@wishknish/knishio-client-ts 0.7.2 → 0.7.6

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.
Files changed (51) hide show
  1. package/dist/index.cjs +2819 -1186
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +378 -142
  4. package/dist/index.d.ts +378 -142
  5. package/dist/index.iife.js +22799 -20747
  6. package/dist/index.iife.js.map +1 -1
  7. package/dist/index.js +2817 -1185
  8. package/dist/index.js.map +1 -1
  9. package/package.json +12 -6
  10. package/src/AuthToken.ts +8 -2
  11. package/src/KnishIOClient.ts +367 -118
  12. package/src/constants.ts +5 -3
  13. package/src/core/Atom.ts +167 -100
  14. package/src/core/AtomMeta.ts +11 -28
  15. package/src/core/Meta.ts +18 -15
  16. package/src/core/Molecule.ts +582 -140
  17. package/src/core/Wallet.ts +19 -24
  18. package/src/index.ts +9 -10
  19. package/src/instance/rules/Rule.ts +128 -19
  20. package/src/libraries/CheckMolecule.ts +88 -1
  21. package/src/libraries/GraphQLClient.ts +17 -22
  22. package/src/libraries/crypto.ts +14 -30
  23. package/src/libraries/strings.ts +26 -25
  24. package/src/mutation/MutationAppendRequest.ts +52 -0
  25. package/src/mutation/MutationCreateRule.ts +2 -2
  26. package/src/mutation/MutationPeering.ts +37 -0
  27. package/src/mutation/MutationRequestAuthorization.ts +3 -3
  28. package/src/query/Query.ts +6 -6
  29. package/src/query/QueryActiveSession.ts +0 -1
  30. package/src/query/QueryAtom.ts +27 -27
  31. package/src/query/QueryContinuId.ts +8 -0
  32. package/src/query/QueryMetaType.ts +1 -1
  33. package/src/query/QueryMetaTypeViaMolecule.ts +221 -0
  34. package/src/query/QueryWalletList.ts +2 -2
  35. package/src/response/Response.ts +17 -1
  36. package/src/response/ResponseAppendRequest.ts +17 -0
  37. package/src/response/ResponseBalance.ts +8 -3
  38. package/src/response/ResponseContinuId.ts +1 -1
  39. package/src/response/ResponseMetaType.ts +32 -19
  40. package/src/response/ResponseMetaTypeViaMolecule.ts +224 -0
  41. package/src/response/ResponsePeering.ts +17 -0
  42. package/src/response/ResponsePolicy.ts +2 -3
  43. package/src/response/ResponseProposeMolecule.ts +0 -1
  44. package/src/response/ResponseRequestAuthorization.ts +32 -2
  45. package/src/response/ResponseRequestAuthorizationGuest.ts +25 -1
  46. package/src/response/ResponseWalletList.ts +1 -1
  47. package/src/schemas/index.ts +12 -1
  48. package/src/types/client.ts +3 -2
  49. package/src/types/graphql.ts +3 -2
  50. package/src/types/guards.ts +18 -5
  51. package/src/types/index.ts +19 -4
package/src/constants.ts CHANGED
@@ -63,7 +63,7 @@ License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
63
63
  * Immutable array of atom isotopes with const assertion
64
64
  * Provides compile-time type safety and runtime immutability
65
65
  */
66
- export const ISOTOPES = ['C', 'V', 'U', 'T', 'M', 'I', 'R', 'B', 'F'] as const
66
+ export const ISOTOPES = ['C', 'V', 'U', 'T', 'M', 'I', 'R', 'B', 'F', 'P', 'A'] as const
67
67
  export type AtomIsotope = typeof ISOTOPES[number]
68
68
 
69
69
  /**
@@ -71,14 +71,16 @@ export type AtomIsotope = typeof ISOTOPES[number]
71
71
  */
72
72
  export const ISOTOPE_DESCRIPTIONS = {
73
73
  C: 'Continue - Position continuation',
74
- V: 'Value - Token value transfer',
74
+ V: 'Value - Token value transfer',
75
75
  U: 'User - User token operations',
76
76
  T: 'Token - Token creation/management',
77
77
  M: 'Meta - Metadata operations',
78
78
  I: 'Identity - Identity operations',
79
79
  R: 'Rule - Policy operations',
80
80
  B: 'Buffer - Buffer token operations',
81
- F: 'Fuse - Token fusion operations'
81
+ F: 'Fuse - Token fusion operations',
82
+ P: 'Peer - Peer registration operations',
83
+ A: 'Append - Append request operations'
82
84
  } as const satisfies Record<AtomIsotope, string>
83
85
 
84
86
  // =============================================================================
package/src/core/Atom.ts CHANGED
@@ -56,8 +56,10 @@ License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
56
56
 
57
57
  import { convertToBase17 } from '@/libraries/crypto'
58
58
  import JsSHA from 'jssha'
59
- import { PROTOCOL_CONFIG } from '@/constants'
59
+ import versions from '@/versions'
60
60
  import { handleIsotope, isWalletAddress, isPosition } from '@/types/guards'
61
+ import Meta from '@/core/Meta'
62
+ import AtomMeta from '@/core/AtomMeta'
61
63
  import type {
62
64
  AtomIsotope,
63
65
  AtomParams,
@@ -87,7 +89,7 @@ export const ATOM_DEFAULTS = {
87
89
  META: [],
88
90
  OTS_FRAGMENT: null,
89
91
  INDEX: null,
90
- VERSION: PROTOCOL_CONFIG.DEFAULT_SDK_VERSION
92
+ VERSION: null
91
93
  } as const satisfies {
92
94
  readonly POSITION: string
93
95
  readonly WALLET_ADDRESS: string
@@ -100,7 +102,7 @@ export const ATOM_DEFAULTS = {
100
102
  readonly META: readonly []
101
103
  readonly OTS_FRAGMENT: null
102
104
  readonly INDEX: null
103
- readonly VERSION: number
105
+ readonly VERSION: null
104
106
  }
105
107
 
106
108
  /**
@@ -119,12 +121,12 @@ export const ATOM_VALIDATION = {
119
121
 
120
122
  export interface AtomMetaData {
121
123
  readonly key: string
122
- readonly value: string | number | boolean | null
123
- readonly [additionalProps: string]: unknown
124
+ readonly value: string | null
125
+ readonly [props: string]: unknown
124
126
  }
125
127
 
126
128
  export interface AtomCreationParams extends AtomParams {
127
- version?: number
129
+ version?: string | number | null | undefined
128
130
  }
129
131
 
130
132
  export interface AtomHashableData {
@@ -139,6 +141,7 @@ export interface AtomHashableData {
139
141
  meta: AtomMetaData[] | null
140
142
  createdAt: string
141
143
  index: number
144
+ version?: string | number | null
142
145
  }
143
146
 
144
147
  // =============================================================================
@@ -150,12 +153,12 @@ export interface AtomHashableData {
150
153
  * Maintains full compatibility with JavaScript SDK implementation
151
154
  */
152
155
  export default class Atom {
153
- // Core properties matching JS SDK exactly
154
- public position: string
155
- public walletAddress: WalletAddress | string
156
- public isotope: AtomIsotope
157
- public token: TokenSlug | string
158
- public value: string | number | null
156
+ // Core properties matching JS SDK exactly (all default to null)
157
+ public position: string | null
158
+ public walletAddress: WalletAddress | string | null
159
+ public isotope: AtomIsotope | null
160
+ public token: TokenSlug | string | null
161
+ public value: string | null
159
162
  public batchId: BatchId | string | null
160
163
  public metaType: MetaType | string | null
161
164
  public metaId: MetaId | string | null
@@ -163,42 +166,45 @@ export default class Atom {
163
166
  public otsFragment: string | null
164
167
  public index: number | null
165
168
  public createdAt: string
166
- public version: number
169
+ public version: string | undefined
167
170
 
168
171
  /**
169
172
  * Create a new Atom instance
170
173
  * Constructor signature matches JavaScript SDK exactly
171
174
  */
172
175
  constructor({
173
- position = ATOM_DEFAULTS.POSITION,
174
- walletAddress = ATOM_DEFAULTS.WALLET_ADDRESS as any,
175
- isotope = ATOM_DEFAULTS.ISOTOPE as AtomIsotope,
176
- token = ATOM_DEFAULTS.TOKEN,
177
- value = ATOM_DEFAULTS.VALUE,
178
- batchId = ATOM_DEFAULTS.BATCH_ID,
179
- metaType = ATOM_DEFAULTS.META_TYPE,
180
- metaId = ATOM_DEFAULTS.META_ID,
176
+ position = null,
177
+ walletAddress = null,
178
+ isotope = null,
179
+ token = null,
180
+ value = null,
181
+ batchId = null,
182
+ metaType = null,
183
+ metaId = null,
181
184
  meta = null,
182
- otsFragment = ATOM_DEFAULTS.OTS_FRAGMENT,
183
- index = ATOM_DEFAULTS.INDEX,
185
+ otsFragment = null,
186
+ index = null,
184
187
  createdAt = null,
185
- version = ATOM_DEFAULTS.VERSION
188
+ version = null
186
189
  }: AtomCreationParams = {}) {
187
190
 
188
- // Use const assertion values with nullish coalescing (2025 pattern)
189
- this.position = position ?? ATOM_DEFAULTS.POSITION
190
- this.walletAddress = walletAddress ?? ATOM_DEFAULTS.WALLET_ADDRESS
191
- this.isotope = isotope ?? ATOM_DEFAULTS.ISOTOPE
192
- this.token = token ?? ATOM_DEFAULTS.TOKEN
193
- this.value = value
191
+ // Match JS SDK constructor exactly
192
+ this.position = position
193
+ this.walletAddress = walletAddress
194
+ this.isotope = isotope
195
+ this.token = token
196
+ this.value = value !== null && value !== undefined ? String(value) : null
194
197
  this.batchId = batchId
195
198
  this.metaType = metaType
196
199
  this.metaId = metaId
197
- this.meta = meta ? [...meta] : [...ATOM_DEFAULTS.META]
200
+ this.meta = meta ? Meta.normalizeMeta(meta) as AtomMetaData[] : []
198
201
  this.otsFragment = otsFragment
199
202
  this.index = index
200
- this.version = version ?? ATOM_DEFAULTS.VERSION
201
- // CRITICAL: Use provided createdAt or generate timestamp in milliseconds as string (Implementation Guide requirement)
203
+ // Match JS SDK: only set version if it exists in the version registry
204
+ if (version !== null && version !== undefined && Object.prototype.hasOwnProperty.call(versions as Record<string, any>, version)) {
205
+ this.version = String(version)
206
+ }
207
+ // Match JS SDK: always generate fresh createdAt (JS SDK has no createdAt parameter)
202
208
  this.createdAt = createdAt || String(+new Date())
203
209
  }
204
210
 
@@ -260,15 +266,17 @@ export default class Atom {
260
266
  return {
261
267
  position: this.position || '',
262
268
  walletAddress: this.walletAddress?.toString() || '',
263
- isotope: this.isotope,
269
+ isotope: (this.isotope || 'C') as AtomIsotope,
264
270
  token: this.token?.toString() || '',
265
271
  value: this.value !== null ? this.value.toString() : null,
266
272
  batchId: this.batchId?.toString() || null,
267
273
  metaType: this.metaType?.toString() || null,
268
274
  metaId: this.metaId?.toString() || null,
269
- meta: this.meta.length > 0 ? [...this.meta] : null,
275
+ // Always return array for meta (server expects Vec<MetaItemInput>, not null)
276
+ meta: this.meta.length > 0 ? [...this.meta] : [],
270
277
  createdAt: this.createdAt,
271
- index: this.index !== null ? this.index : 0
278
+ index: this.index !== null ? this.index : 0,
279
+ version: this.version ?? null
272
280
  }
273
281
  }
274
282
 
@@ -286,8 +294,9 @@ export default class Atom {
286
294
  */
287
295
  public toJSON(options: {
288
296
  includeOtsFragments?: boolean
297
+ includeValidationContext?: boolean
289
298
  validateFields?: boolean
290
- } = {}): AtomHashableData & { otsFragment?: string | null } {
299
+ } = {}): Record<string, unknown> {
291
300
  const {
292
301
  includeOtsFragments = true,
293
302
  validateFields = false
@@ -304,10 +313,22 @@ export default class Atom {
304
313
  }
305
314
  }
306
315
 
307
- // Core atom properties (always included) - use structured data for JSON
308
- const structuredData = this.getStructuredData()
309
- const serialized: AtomHashableData & { otsFragment?: string | null } = {
310
- ...structuredData
316
+ // Core atom properties — matches JavaScript SDK Atom.toJSON() exactly
317
+ // Uses ?? (nullish coalescing) not || (falsy coalescing) to preserve 0/false/"" values
318
+ // No .toString() calls — raw values must match what getHashableValues() hashed
319
+ const serialized: Record<string, unknown> = {
320
+ position: this.position ?? '',
321
+ walletAddress: this.walletAddress ?? '',
322
+ isotope: this.isotope,
323
+ token: this.token ?? '',
324
+ value: this.value,
325
+ batchId: this.batchId,
326
+ metaType: this.metaType,
327
+ metaId: this.metaId,
328
+ meta: this.meta || [],
329
+ index: this.index,
330
+ createdAt: this.createdAt,
331
+ version: this.version
311
332
  }
312
333
 
313
334
  // Optional OTS fragments (can be large, so optional)
@@ -329,8 +350,8 @@ export default class Atom {
329
350
  return new Atom({
330
351
  position: this.position,
331
352
  walletAddress: this.walletAddress as any,
332
- isotope: this.isotope,
333
- token: this.token,
353
+ isotope: this.isotope as AtomIsotope,
354
+ token: this.token as string,
334
355
  value: this.value,
335
356
  batchId: this.batchId,
336
357
  metaType: this.metaType,
@@ -352,6 +373,9 @@ export default class Atom {
352
373
  return false
353
374
  }
354
375
 
376
+ // Null isotope is invalid
377
+ if (!this.isotope) return false
378
+
355
379
  // Exhaustive isotope validation with compile-time completeness
356
380
  return handleIsotope(this.isotope, {
357
381
  V: () => this.value !== null && !isNaN(Number(this.value)), // Value atoms must have numeric value
@@ -362,7 +386,9 @@ export default class Atom {
362
386
  I: () => true, // Identity atoms
363
387
  R: () => true, // Rule atoms
364
388
  B: () => true, // Buffer atoms
365
- F: () => true // Fuse atoms
389
+ F: () => true, // Fuse atoms
390
+ P: () => true, // Peer atoms
391
+ A: () => Boolean(this.metaType && this.metaId) // Append atoms must have metaType and metaId
366
392
  })
367
393
  }
368
394
 
@@ -397,25 +423,67 @@ export default class Atom {
397
423
  */
398
424
  static getUnclaimedProps(): string[] {
399
425
  return [
400
- 'position',
401
- 'walletAddress',
402
- 'isotope',
403
- 'token',
404
- 'value',
405
- 'batchId',
406
- 'metaType',
407
- 'metaId',
408
- 'meta',
409
- 'createdAt'
426
+ 'otsFragment'
410
427
  ]
411
428
  }
412
429
 
413
430
  /**
414
431
  * Create atom from parameters - factory method
415
- * Matches JavaScript SDK Atom.create static method
432
+ * Matches JavaScript SDK Atom.create static method exactly
433
+ * Processes wallet meta, extracts wallet fields, normalizes meta
416
434
  */
417
- static create(params: AtomCreationParams): Atom {
418
- return new Atom(params)
435
+ static create({
436
+ isotope,
437
+ wallet = null,
438
+ value = null,
439
+ metaType = null,
440
+ metaId = null,
441
+ meta = null,
442
+ batchId = null
443
+ }: {
444
+ isotope: AtomIsotope | string
445
+ wallet?: any | null
446
+ value?: string | number | null
447
+ metaType?: string | null
448
+ metaId?: string | null
449
+ meta?: AtomMeta | any[] | Record<string, any> | null
450
+ batchId?: string | null
451
+ }): Atom {
452
+ // If meta object is not passed - create it
453
+ let atomMeta: AtomMeta
454
+ if (!meta) {
455
+ atomMeta = new AtomMeta()
456
+ } else if (meta instanceof AtomMeta) {
457
+ // If meta object is already an instance of AtomMeta - use it
458
+ atomMeta = meta
459
+ } else {
460
+ // Otherwise create from meta
461
+ atomMeta = new AtomMeta(meta)
462
+ }
463
+
464
+ // If wallet has been passed => add related metas
465
+ if (wallet) {
466
+ // Add wallet's meta
467
+ atomMeta.setAtomWallet(wallet)
468
+
469
+ // If batch ID not passed: set it from the wallet
470
+ if (!batchId) {
471
+ batchId = wallet.batchId
472
+ }
473
+ }
474
+
475
+ // Create the final atom
476
+ return new Atom({
477
+ position: wallet ? wallet.position : null,
478
+ walletAddress: wallet ? wallet.address : null,
479
+ isotope: isotope as AtomIsotope,
480
+ token: wallet ? wallet.token : null,
481
+ value,
482
+ batchId,
483
+ metaType,
484
+ metaId,
485
+ meta: atomMeta.get() as any
486
+ })
419
487
  }
420
488
 
421
489
  /**
@@ -506,33 +574,37 @@ export default class Atom {
506
574
  if (!atoms || atoms.length === 0) {
507
575
  return ''
508
576
  }
509
-
577
+
510
578
  // Step 1: Sort atoms by index to ensure deterministic hashing (matches JS SDK)
511
579
  const atomList = Atom.sortAtoms(atoms)
512
- const numberOfAtoms = String(atoms.length)
513
- let hashableValues: string[] = []
514
-
515
- // Step 2: Build hashableValues array exactly like JavaScript SDK
516
- for (const atom of atomList) {
517
- // Add number of atoms (matching JS SDK comment: "Add number of atoms (???)")
518
- hashableValues.push(numberOfAtoms)
519
-
520
- // Add atom's properties - concatenate the array returned by getHashableValues
521
- hashableValues = hashableValues.concat(atom.getHashableValues())
522
- }
523
-
524
- // Step 3: Create molecular hash using SHAKE256 exactly like JS SDK (iterative updates)
525
580
  const molecularSponge = new JsSHA('SHAKE256', 'TEXT')
526
-
527
- // CRITICAL FIX: Use iterative updates like JavaScript, not string concatenation
528
- for (const hashableValue of hashableValues) {
529
- molecularSponge.update(hashableValue) // Match JavaScript SDK exactly
581
+
582
+ // Step 2: Check for versioned hashing (matches JS SDK Atom.hashAtoms lines 365-366)
583
+ const versionRegistry = versions as Record<number | string, any>
584
+ if (atomList.every(atom => atom.version && Object.prototype.hasOwnProperty.call(versionRegistry, atom.version))) {
585
+ // Versioned path: create structured view of each atom and hash as JSON
586
+ molecularSponge.update(JSON.stringify(
587
+ atomList.map(atom => versionRegistry[atom.version!].create(atom).view())
588
+ ))
589
+ } else {
590
+ // Legacy path: field-by-field with incremental SHAKE256 updates
591
+ const numberOfAtoms = String(atoms.length)
592
+ let hashableValues: string[] = []
593
+
594
+ for (const atom of atomList) {
595
+ hashableValues.push(numberOfAtoms)
596
+ hashableValues = hashableValues.concat(atom.getHashableValues())
597
+ }
598
+
599
+ for (const hashableValue of hashableValues) {
600
+ molecularSponge.update(hashableValue)
601
+ }
530
602
  }
531
-
532
- // Step 4: Get hex hash (256 bits = 64 hex chars) and convert to base17
603
+
604
+ // Step 3: Get hex hash (256 bits = 64 hex chars) and convert to base17
533
605
  const hexHash = molecularSponge.getHash('HEX', { outputLen: 256 })
534
-
535
- // Step 5: Convert hex hash to base17 format (Implementation Guide requirement)
606
+
607
+ // Step 4: Convert hex hash to base17 format (Implementation Guide requirement)
536
608
  return convertToBase17(hexHash.toLowerCase())
537
609
  }
538
610
 
@@ -541,10 +613,9 @@ export default class Atom {
541
613
  * Matches JavaScript SDK sortAtoms method
542
614
  */
543
615
  static sortAtoms(atoms: Atom[]): Atom[] {
544
- return [...atoms].sort((a, b) => {
545
- const indexA = a.index !== null ? a.index : 0
546
- const indexB = b.index !== null ? b.index : 0
547
- return indexA - indexB
616
+ return [...atoms].sort((first, second) => {
617
+ // Match JS SDK exactly: first.index < second.index ? -1 : 1
618
+ return first.index! < second.index! ? -1 : 1
548
619
  })
549
620
  }
550
621
 
@@ -553,15 +624,7 @@ export default class Atom {
553
624
  * Matches JavaScript SDK generateNextAtomIndex method
554
625
  */
555
626
  static generateNextAtomIndex(atoms: Atom[]): number {
556
- if (!atoms || atoms.length === 0) {
557
- return 0
558
- }
559
-
560
- const indices = atoms
561
- .map(atom => atom.index !== null ? atom.index : 0)
562
- .filter(index => typeof index === 'number')
563
-
564
- return indices.length > 0 ? Math.max(...indices) + 1 : 0
627
+ return atoms.length
565
628
  }
566
629
 
567
630
  /**
@@ -570,7 +633,7 @@ export default class Atom {
570
633
  */
571
634
  static isotopeFilter(isotopes: AtomIsotope | AtomIsotope[], atoms: Atom[]): Atom[] {
572
635
  const targetIsotopes = Array.isArray(isotopes) ? isotopes : [isotopes]
573
- return atoms.filter(atom => targetIsotopes.includes(atom.isotope))
636
+ return atoms.filter(atom => atom.isotope !== null && targetIsotopes.includes(atom.isotope))
574
637
  }
575
638
 
576
639
  // =============================================================================
@@ -598,7 +661,7 @@ export default class Atom {
598
661
  /**
599
662
  * Check if atom is a specific isotope type
600
663
  */
601
- static isIsotope(atom: Atom, isotope: AtomIsotope): boolean {
664
+ static isIsotope(atom: Atom, isotope: AtomIsotope | null): boolean {
602
665
  return atom.isotope === isotope
603
666
  }
604
667
 
@@ -608,7 +671,9 @@ export default class Atom {
608
671
  static getUniqueIsotopes(atoms: Atom[]): AtomIsotope[] {
609
672
  const isotopes = new Set<AtomIsotope>()
610
673
  for (const atom of atoms) {
611
- isotopes.add(atom.isotope)
674
+ if (atom.isotope !== null) {
675
+ isotopes.add(atom.isotope)
676
+ }
612
677
  }
613
678
  return Array.from(isotopes)
614
679
  }
@@ -627,14 +692,16 @@ export default class Atom {
627
692
  */
628
693
  static groupByIsotope(atoms: Atom[]): Record<AtomIsotope, Atom[]> {
629
694
  const groups: Partial<Record<AtomIsotope, Atom[]>> = {}
630
-
695
+
631
696
  for (const atom of atoms) {
632
- if (!groups[atom.isotope]) {
633
- groups[atom.isotope] = []
697
+ const iso = atom.isotope
698
+ if (iso === null) continue
699
+ if (!groups[iso]) {
700
+ groups[iso] = []
634
701
  }
635
- groups[atom.isotope]!.push(atom)
702
+ groups[iso]!.push(atom)
636
703
  }
637
-
704
+
638
705
  return groups as Record<AtomIsotope, Atom[]>
639
706
  }
640
707
  }
@@ -73,25 +73,9 @@ export default class AtomMeta {
73
73
  * @return This instance for chaining
74
74
  */
75
75
  merge(meta: Record<string, any> | NormalizedMeta[]): AtomMeta {
76
- const normalized = Meta.normalizeMeta(meta)
77
-
78
- // Use Set to avoid duplicates based on key
79
- const existingKeys = new Set(this.meta.map(m => m.key))
80
-
81
- for (const item of normalized) {
82
- if (existingKeys.has(item.key)) {
83
- // Update existing key
84
- const index = this.meta.findIndex(m => m.key === item.key)
85
- if (index !== -1) {
86
- this.meta[index] = item
87
- }
88
- } else {
89
- // Add new key
90
- this.meta.push(item)
91
- existingKeys.add(item.key)
92
- }
93
- }
94
-
76
+ // Match JS SDK exactly: Array.from(new Set([...this.meta, ...Meta.normalizeMeta(meta)]))
77
+ // Set uses reference equality for objects, so it never deduplicates — effectively concatenation
78
+ this.meta = [...this.meta, ...Meta.normalizeMeta(meta)]
95
79
  return this
96
80
  }
97
81
 
@@ -115,23 +99,22 @@ export default class AtomMeta {
115
99
  * @return This instance for chaining
116
100
  */
117
101
  setAtomWallet(wallet: any): AtomMeta {
118
- const walletMeta: Record<string, any> = {
119
- pubkey: wallet.pubkey,
120
- characters: wallet.characters
121
- }
102
+ const walletMeta: Record<string, any> = {}
122
103
 
123
- // Add token units meta key if present
104
+ // Add token units meta key (matches JS SDK exactly — no pubkey/characters)
124
105
  if (wallet.tokenUnits && wallet.tokenUnits.length) {
125
106
  walletMeta.tokenUnits = JSON.stringify(wallet.getTokenUnitsData ? wallet.getTokenUnitsData() : wallet.tokenUnits)
126
107
  }
127
108
 
128
- // Add trade rates meta key if present
129
- if (wallet.tradeRates && Object.keys(wallet.tradeRates).length) {
109
+ // Add trade rates meta key
110
+ if (wallet.tradeRates && wallet.tradeRates.length) {
130
111
  walletMeta.tradeRates = JSON.stringify(wallet.tradeRates)
131
112
  }
132
113
 
133
- // Merge all wallet's metas
134
- this.merge(walletMeta)
114
+ // Merge all wallet's metas (if any)
115
+ if (Object.keys(walletMeta).length > 0) {
116
+ this.merge(walletMeta)
117
+ }
135
118
  return this
136
119
  }
137
120
 
package/src/core/Meta.ts CHANGED
@@ -61,8 +61,8 @@ import type { MetaData } from '@/types'
61
61
 
62
62
  export interface NormalizedMeta {
63
63
  key: string
64
- value: string | number | boolean | null
65
- [additionalProps: string]: unknown
64
+ value: string | null
65
+ [props: string]: unknown
66
66
  }
67
67
 
68
68
  export interface MetaItem {
@@ -95,37 +95,40 @@ export default class Meta {
95
95
  return []
96
96
  }
97
97
 
98
- // Handle array of meta items
98
+ // Handle array of meta items — matches JS SDK exactly
99
99
  if (Array.isArray(meta)) {
100
100
  return meta.map(item => {
101
101
  if (typeof item === 'object' && item !== null && 'key' in item) {
102
102
  return {
103
- ...item,
104
103
  key: String(item.key),
105
- value: item.value as string | number | boolean | null
104
+ value: (item as any).value == null ? null : String((item as any).value)
106
105
  }
107
106
  }
108
-
107
+
109
108
  // Fallback for invalid items
110
109
  return {
111
110
  key: 'unknown',
112
- value: String(item) as string | number | boolean | null
111
+ value: String(item)
113
112
  }
114
113
  })
115
114
  }
116
115
 
117
- // Handle object metadata - convert to array format
116
+ // Handle object metadata - convert to array format (matches JS SDK object path)
118
117
  if (typeof meta === 'object' && meta !== null) {
119
- return Object.entries(meta).map(([key, value]) => ({
120
- key,
121
- value: value as string | number | boolean | null
122
- }))
118
+ const target: NormalizedMeta[] = []
119
+ for (const property in meta) {
120
+ if (Object.prototype.hasOwnProperty.call(meta, property)) {
121
+ const raw = (meta as any)[property]
122
+ target.push({ key: property, value: raw == null ? null : String(raw) })
123
+ }
124
+ }
125
+ return target
123
126
  }
124
127
 
125
128
  // Handle primitive values
126
129
  return [{
127
130
  key: 'value',
128
- value: meta as string | number | boolean | null
131
+ value: String(meta)
129
132
  }]
130
133
  }
131
134
 
@@ -264,7 +267,7 @@ export default class Meta {
264
267
 
265
268
  const newItem: NormalizedMeta = {
266
269
  key,
267
- value: value as string | number | boolean | null
270
+ value: value == null ? null : String(value)
268
271
  }
269
272
 
270
273
  if (existingIndex >= 0) {
@@ -310,7 +313,7 @@ export default class Meta {
310
313
 
311
314
  return Object.entries(jsonData).map(([key, value]) => ({
312
315
  key,
313
- value: value as string | number | boolean | null
316
+ value: value == null ? null : String(value)
314
317
  }))
315
318
  }
316
319