@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.
- package/dist/index.cjs +2819 -1186
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +378 -142
- package/dist/index.d.ts +378 -142
- package/dist/index.iife.js +22799 -20747
- package/dist/index.iife.js.map +1 -1
- package/dist/index.js +2817 -1185
- package/dist/index.js.map +1 -1
- package/package.json +12 -6
- package/src/AuthToken.ts +8 -2
- package/src/KnishIOClient.ts +367 -118
- package/src/constants.ts +5 -3
- package/src/core/Atom.ts +167 -100
- package/src/core/AtomMeta.ts +11 -28
- package/src/core/Meta.ts +18 -15
- package/src/core/Molecule.ts +582 -140
- package/src/core/Wallet.ts +19 -24
- package/src/index.ts +9 -10
- package/src/instance/rules/Rule.ts +128 -19
- package/src/libraries/CheckMolecule.ts +88 -1
- package/src/libraries/GraphQLClient.ts +17 -22
- package/src/libraries/crypto.ts +14 -30
- package/src/libraries/strings.ts +26 -25
- package/src/mutation/MutationAppendRequest.ts +52 -0
- package/src/mutation/MutationCreateRule.ts +2 -2
- package/src/mutation/MutationPeering.ts +37 -0
- package/src/mutation/MutationRequestAuthorization.ts +3 -3
- package/src/query/Query.ts +6 -6
- package/src/query/QueryActiveSession.ts +0 -1
- package/src/query/QueryAtom.ts +27 -27
- package/src/query/QueryContinuId.ts +8 -0
- package/src/query/QueryMetaType.ts +1 -1
- package/src/query/QueryMetaTypeViaMolecule.ts +221 -0
- package/src/query/QueryWalletList.ts +2 -2
- package/src/response/Response.ts +17 -1
- package/src/response/ResponseAppendRequest.ts +17 -0
- package/src/response/ResponseBalance.ts +8 -3
- package/src/response/ResponseContinuId.ts +1 -1
- package/src/response/ResponseMetaType.ts +32 -19
- package/src/response/ResponseMetaTypeViaMolecule.ts +224 -0
- package/src/response/ResponsePeering.ts +17 -0
- package/src/response/ResponsePolicy.ts +2 -3
- package/src/response/ResponseProposeMolecule.ts +0 -1
- package/src/response/ResponseRequestAuthorization.ts +32 -2
- package/src/response/ResponseRequestAuthorizationGuest.ts +25 -1
- package/src/response/ResponseWalletList.ts +1 -1
- package/src/schemas/index.ts +12 -1
- package/src/types/client.ts +3 -2
- package/src/types/graphql.ts +3 -2
- package/src/types/guards.ts +18 -5
- 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
|
|
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:
|
|
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:
|
|
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 |
|
|
123
|
-
readonly [
|
|
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 |
|
|
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:
|
|
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 =
|
|
174
|
-
walletAddress =
|
|
175
|
-
isotope =
|
|
176
|
-
token =
|
|
177
|
-
value =
|
|
178
|
-
batchId =
|
|
179
|
-
metaType =
|
|
180
|
-
metaId =
|
|
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 =
|
|
183
|
-
index =
|
|
185
|
+
otsFragment = null,
|
|
186
|
+
index = null,
|
|
184
187
|
createdAt = null,
|
|
185
|
-
version =
|
|
188
|
+
version = null
|
|
186
189
|
}: AtomCreationParams = {}) {
|
|
187
190
|
|
|
188
|
-
//
|
|
189
|
-
this.position = position
|
|
190
|
-
this.walletAddress = walletAddress
|
|
191
|
-
this.isotope = isotope
|
|
192
|
-
this.token = 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 ? [
|
|
200
|
+
this.meta = meta ? Meta.normalizeMeta(meta) as AtomMetaData[] : []
|
|
198
201
|
this.otsFragment = otsFragment
|
|
199
202
|
this.index = index
|
|
200
|
-
|
|
201
|
-
|
|
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
|
-
|
|
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
|
-
} = {}):
|
|
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
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
|
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
|
-
'
|
|
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(
|
|
418
|
-
|
|
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
|
-
//
|
|
528
|
-
|
|
529
|
-
|
|
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
|
|
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
|
|
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((
|
|
545
|
-
|
|
546
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
633
|
-
|
|
697
|
+
const iso = atom.isotope
|
|
698
|
+
if (iso === null) continue
|
|
699
|
+
if (!groups[iso]) {
|
|
700
|
+
groups[iso] = []
|
|
634
701
|
}
|
|
635
|
-
groups[
|
|
702
|
+
groups[iso]!.push(atom)
|
|
636
703
|
}
|
|
637
|
-
|
|
704
|
+
|
|
638
705
|
return groups as Record<AtomIsotope, Atom[]>
|
|
639
706
|
}
|
|
640
707
|
}
|
package/src/core/AtomMeta.ts
CHANGED
|
@@ -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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
|
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
|
|
129
|
-
if (wallet.tradeRates &&
|
|
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
|
-
|
|
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 |
|
|
65
|
-
[
|
|
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
|
|
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)
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
|
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
|
|
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
|
|
316
|
+
value: value == null ? null : String(value)
|
|
314
317
|
}))
|
|
315
318
|
}
|
|
316
319
|
|