@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
@@ -49,7 +49,8 @@ License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
49
49
  import Decimal from '@/libraries/Decimal'
50
50
  import GraphQLClient from '@/libraries/GraphQLClient'
51
51
  import {
52
- generateBundleHash
52
+ generateBundleHash,
53
+ generateSecret
53
54
  } from '@/libraries/crypto'
54
55
  import Molecule from '@/core/Molecule'
55
56
  import Wallet from '@/core/Wallet'
@@ -57,6 +58,7 @@ import AuthToken from '@/AuthToken'
57
58
  import Query from '@/query/Query'
58
59
  import Mutation from '@/mutation/Mutation'
59
60
  import Response from '@/response/Response'
61
+ import ResponseRequestAuthorization from '@/response/ResponseRequestAuthorization'
60
62
 
61
63
  // 2025 TypeScript: Zod validation integration
62
64
  import {
@@ -81,6 +83,7 @@ import QueryActiveSession from '@/query/QueryActiveSession'
81
83
  import QueryUserActivity from '@/query/QueryUserActivity'
82
84
  import QueryToken from '@/query/QueryToken'
83
85
  import QueryMetaTypeViaAtom from '@/query/QueryMetaTypeViaAtom'
86
+ import QueryMetaTypeViaMolecule from '@/query/QueryMetaTypeViaMolecule'
84
87
 
85
88
  // Mutation imports
86
89
  import MutationCreateToken from '@/mutation/MutationCreateToken'
@@ -97,6 +100,8 @@ import MutationWithdrawBufferToken from '@/mutation/MutationWithdrawBufferToken'
97
100
  import MutationRequestAuthorization from '@/mutation/MutationRequestAuthorization'
98
101
  import MutationRequestAuthorizationGuest from '@/mutation/MutationRequestAuthorizationGuest'
99
102
  import MutationLinkIdentifier from '@/mutation/MutationLinkIdentifier'
103
+ import MutationPeering from '@/mutation/MutationPeering'
104
+ import MutationAppendRequest from '@/mutation/MutationAppendRequest'
100
105
 
101
106
  // Subscribe imports
102
107
  import CreateMoleculeSubscribe from '@/subscribe/CreateMoleculeSubscribe'
@@ -110,7 +115,8 @@ import {
110
115
  UnauthenticatedException,
111
116
  TransferBalanceException,
112
117
  WalletShadowException,
113
- StackableUnitAmountException
118
+ StackableUnitAmountException,
119
+ AuthorizationRejectedException
114
120
  } from '@/exception'
115
121
 
116
122
  // Type imports
@@ -121,7 +127,8 @@ import type {
121
127
  CellSlug,
122
128
  MetaType,
123
129
  MetaId,
124
- BatchId
130
+ BatchId,
131
+ MetaFilter
125
132
  } from '@/types'
126
133
 
127
134
  /**
@@ -139,6 +146,7 @@ export default class KnishIOClient {
139
146
  private $__logging: boolean = false
140
147
  private $__authTokenObjects: Record<string, AuthToken | null> = {}
141
148
  private $__authToken: AuthToken | null = null
149
+ private $__authInProcess: boolean = false
142
150
  private $__remainderWallet: Wallet | null = null
143
151
  private lastMoleculeQuery: Mutation | null = null
144
152
  private abortControllers: Map<string, AbortController> = new Map()
@@ -330,6 +338,10 @@ export default class KnishIOClient {
330
338
  } else {
331
339
  this.$__uris = uri
332
340
  }
341
+ // Update the underlying GraphQL client's URI
342
+ if (this.$__client && 'setUri' in this.$__client) {
343
+ (this.$__client as any).setUri(this.getRandomUri())
344
+ }
333
345
  }
334
346
 
335
347
  /**
@@ -402,7 +414,8 @@ export default class KnishIOClient {
402
414
  }
403
415
 
404
416
  /**
405
- * Creates a new molecule for a transaction
417
+ * Instantiates a new Molecule and prepares this client session to operate on it
418
+ * Matches JavaScript SDK createMolecule implementation
406
419
  */
407
420
  async createMolecule({
408
421
  secret = null,
@@ -428,19 +441,29 @@ export default class KnishIOClient {
428
441
  this.lastMoleculeQuery.response()?.success()
429
442
  ) {
430
443
  sourceWallet = this.getRemainderWallet()
444
+ this.log('info', `KnishIOClient::createMolecule() - Using carry-forward remainder wallet at position ${sourceWallet?.position?.substring(0, 16)}...`)
431
445
  }
432
446
 
433
447
  // Unable to use last remainder wallet; Figure out what wallet to use:
434
448
  if (!sourceWallet) {
435
- // Get source wallet
436
449
  sourceWallet = await this.getSourceWallet()
437
450
  }
438
451
 
452
+ // Set the remainder wallet for the next transaction (always USER token for ContinuID)
453
+ this.setRemainderWallet(remainderWallet || Wallet.create({
454
+ secret: secret!,
455
+ bundle,
456
+ token: 'USER',
457
+ batchId: sourceWallet!.batchId,
458
+ characters: sourceWallet!.characters
459
+ }))
460
+
439
461
  return new Molecule({
440
462
  secret,
441
- bundle,
442
463
  sourceWallet,
443
- remainderWallet
464
+ remainderWallet: this.getRemainderWallet()!,
465
+ cellSlug: this.getCellSlug(),
466
+ version: this.getServerSdkVersion()
444
467
  })
445
468
  }
446
469
 
@@ -476,7 +499,8 @@ export default class KnishIOClient {
476
499
  */
477
500
  async executeQuery(query: Query | Mutation, variables: Record<string, any> | null = null): Promise<Response | null> {
478
501
  // Check and refresh authorization token if needed
479
- if (this.$__authToken && this.$__authToken.isExpired()) {
502
+ // Guard with $__authInProcess to prevent recursive auth refresh
503
+ if (this.$__authToken && this.$__authToken.isExpired() && !this.$__authInProcess) {
480
504
  this.log('info', 'KnishIOClient::executeQuery() - Access token is expired. Getting new one...')
481
505
  await this.requestAuthToken({
482
506
  secret: this.$__secret,
@@ -510,16 +534,29 @@ export default class KnishIOClient {
510
534
  }
511
535
 
512
536
  /**
513
- * Gets source wallet - basic implementation
537
+ * Retrieves this session's wallet used for signing the next Molecule
538
+ * Queries ContinuID from the server to get the authoritative position
539
+ * Matches JavaScript SDK getSourceWallet implementation
514
540
  */
515
541
  async getSourceWallet(): Promise<Wallet> {
516
- // For now, create a new wallet with the current secret
517
- // In full implementation, this would query the ledger
518
- return Wallet.create({
519
- secret: this.getSecret(),
520
- bundle: this.getBundle(),
521
- token: 'USER'
522
- })
542
+ // Match JavaScript SDK exactly: no try/catch, errors propagate
543
+ let sourceWallet: Wallet | null = (await this.queryContinuId({
544
+ bundle: this.getBundle()
545
+ }))?.payload() as Wallet | null
546
+
547
+ if (!sourceWallet) {
548
+ sourceWallet = new Wallet({
549
+ secret: this.getSecret()
550
+ })
551
+ } else {
552
+ sourceWallet.key = Wallet.generateKey({
553
+ secret: this.getSecret(),
554
+ token: sourceWallet.token,
555
+ position: sourceWallet.position!
556
+ })
557
+ }
558
+
559
+ return sourceWallet
523
560
  }
524
561
 
525
562
  /**
@@ -565,7 +602,7 @@ export default class KnishIOClient {
565
602
  }
566
603
 
567
604
  // Do you have enough tokens?
568
- if (sourceWallet === null || Decimal.cmp(sourceWallet.balance, amount) < 0) {
605
+ if (sourceWallet === null || Decimal.cmp(Number(sourceWallet.balance), amount) < 0) {
569
606
  throw new TransferBalanceException()
570
607
  }
571
608
 
@@ -614,13 +651,18 @@ export default class KnishIOClient {
614
651
  }
615
652
 
616
653
  /**
617
- * Request authorization token
654
+ * Request authorization token (guest or profile)
655
+ *
656
+ * @param secret - User secret for profile auth (null for guest)
657
+ * @param seed - Seed to generate secret (alternative to secret)
658
+ * @param cellSlug - Cell slug for scoped access
659
+ * @param encrypt - Whether to use encryption
618
660
  */
619
661
  async requestAuthToken({
620
- secret: _secret = null,
621
- seed: _seed = null,
622
- cellSlug: _cellSlug = null,
623
- encrypt: _encrypt = false
662
+ secret = null,
663
+ seed = null,
664
+ cellSlug = null,
665
+ encrypt = false
624
666
  }: {
625
667
  secret?: string | null
626
668
  seed?: string | null
@@ -629,12 +671,52 @@ export default class KnishIOClient {
629
671
  } = {}): Promise<Response | null> {
630
672
  // SDK versions 2 and below do not utilize an authorization token
631
673
  if (this.$__serverSdkVersion < 3) {
632
- this.log('warn', 'KnishIOClient::authorize() - Server SDK version does not require an authorization...')
674
+ this.log('warn', 'KnishIOClient::requestAuthToken() - Server SDK version does not require authorization...')
633
675
  return null
634
676
  }
635
677
 
636
- // For now, return null - full implementation would handle authorization
637
- return null
678
+ // Generate a secret from the seed if provided
679
+ if (secret === null && seed) {
680
+ secret = generateSecret(seed)
681
+ }
682
+
683
+ // Set cell slug if provided
684
+ if (cellSlug) {
685
+ this.setCellSlug(cellSlug)
686
+ }
687
+
688
+ // Auth in process...
689
+ this.$__authInProcess = true
690
+
691
+ // Auth token response
692
+ let response: Response
693
+
694
+ // Authorized user (profile auth with secret)
695
+ if (secret) {
696
+ response = await this.requestProfileAuthToken({
697
+ secret,
698
+ encrypt
699
+ })
700
+ } else {
701
+ // Guest auth (no secret)
702
+ response = await this.requestGuestAuthToken({
703
+ cellSlug: cellSlug || this.getCellSlug(),
704
+ encrypt
705
+ })
706
+ }
707
+
708
+ // Log success
709
+ if (this.$__authToken) {
710
+ this.log('info', `KnishIOClient::requestAuthToken() - Successfully retrieved auth token...`)
711
+ }
712
+
713
+ // Handle encryption if needed
714
+ this.switchEncryption(encrypt)
715
+
716
+ // Auth process is stopped
717
+ this.$__authInProcess = false
718
+
719
+ return response
638
720
  }
639
721
 
640
722
  /**
@@ -755,7 +837,7 @@ export default class KnishIOClient {
755
837
 
756
838
  // Do you have enough tokens?
757
839
  const amountNum = typeof amount === 'string' ? Number(amount) : amount
758
- if (sourceWallet === null || Decimal.cmp(sourceWallet.balance || 0, amountNum) < 0) {
840
+ if (sourceWallet === null || Decimal.cmp(Number(sourceWallet.balance || 0), amountNum) < 0) {
759
841
  throw new TransferBalanceException()
760
842
  }
761
843
 
@@ -785,7 +867,7 @@ export default class KnishIOClient {
785
867
 
786
868
  const response = await this.executeQuery(walletQuery, {
787
869
  bundleHash: bundle || this.getBundle(),
788
- tokenSlug: token,
870
+ token,
789
871
  unspent
790
872
  })
791
873
 
@@ -849,7 +931,8 @@ export default class KnishIOClient {
849
931
  queryArgs = null,
850
932
  count = null,
851
933
  countBy = null,
852
- throughAtom = null,
934
+ throughAtom = true,
935
+ throughMolecule = false,
853
936
  values = null,
854
937
  keys = null,
855
938
  atomValues = null
@@ -860,11 +943,12 @@ export default class KnishIOClient {
860
943
  value?: string | null
861
944
  latest?: boolean | null
862
945
  fields?: string[] | null
863
- filter?: string | null
946
+ filter?: MetaFilter[] | null
864
947
  queryArgs?: Record<string, any> | null
865
948
  count?: number | null
866
949
  countBy?: string | null
867
950
  throughAtom?: boolean | null
951
+ throughMolecule?: boolean | null
868
952
  values?: any[] | null
869
953
  keys?: string[] | null
870
954
  atomValues?: any[] | null
@@ -872,50 +956,85 @@ export default class KnishIOClient {
872
956
  this.log('info', `KnishIOClient::queryMeta() - Querying metaType: ${metaType}, metaId: ${metaId}...`)
873
957
 
874
958
  let query: Query
875
-
876
- if (throughAtom === true) {
959
+ let variables: Record<string, any>
960
+
961
+ if (throughMolecule) {
962
+ query = this.createQuery(QueryMetaTypeViaMolecule)
963
+ variables = QueryMetaTypeViaMolecule.createVariables({
964
+ metaType: metaType,
965
+ metaId,
966
+ key,
967
+ value,
968
+ latest,
969
+ filter,
970
+ queryArgs,
971
+ countBy,
972
+ values,
973
+ keys,
974
+ atomValues,
975
+ cellSlug: this.getCellSlug()
976
+ })
977
+ } else if (throughAtom) {
877
978
  query = this.createQuery(QueryMetaTypeViaAtom)
979
+ variables = QueryMetaTypeViaAtom.createVariables({
980
+ metaType: metaType,
981
+ metaId,
982
+ key,
983
+ value,
984
+ latest,
985
+ filter,
986
+ queryArgs,
987
+ countBy,
988
+ values,
989
+ keys,
990
+ atomValues,
991
+ cellSlug: this.getCellSlug()
992
+ })
878
993
  } else {
879
994
  query = this.createQuery(QueryMetaType)
995
+ variables = QueryMetaType.createVariables({
996
+ metaType: metaType,
997
+ metaId,
998
+ key,
999
+ value,
1000
+ latest,
1001
+ filter,
1002
+ queryArgs,
1003
+ count,
1004
+ countBy,
1005
+ cellSlug: this.getCellSlug()
1006
+ })
880
1007
  }
881
1008
 
882
- const variables: Record<string, any> = {
883
- metaType: metaType.toUpperCase(),
884
- metaId
885
- }
1009
+ return this.executeQuery(query, variables) as Promise<Response>
1010
+ }
886
1011
 
887
- if (filter !== null) {
888
- variables.filter = filter
889
- }
890
- if (latest !== null) {
891
- variables.latest = latest
892
- }
893
- if (key !== null) {
894
- variables.key = key
895
- }
896
- if (value !== null) {
897
- variables.value = value
898
- }
899
- if (queryArgs !== null) {
900
- variables.queryArgs = queryArgs
901
- }
902
- if (count !== null) {
903
- variables.count = count
904
- }
905
- if (countBy !== null) {
906
- variables.countBy = countBy
907
- }
908
- if (values !== null) {
909
- variables.values = values
910
- }
911
- if (keys !== null) {
912
- variables.keys = keys
913
- }
914
- if (atomValues !== null) {
915
- variables.atomValues = atomValues
1012
+ /**
1013
+ * Queries meta assets and verifies cryptographic integrity of associated molecules.
1014
+ * Forces throughMolecule=true to ensure molecule data is available for verification.
1015
+ * Returns the same response as queryMeta(), with an additional `integrity` field on the payload.
1016
+ */
1017
+ async queryMetaVerified(params: {
1018
+ metaType: MetaType | string
1019
+ metaId?: MetaId | string | null
1020
+ key?: string | null
1021
+ value?: string | null
1022
+ latest?: boolean | null
1023
+ fields?: string[] | null
1024
+ filter?: MetaFilter[] | null
1025
+ queryArgs?: Record<string, any> | null
1026
+ count?: number | null
1027
+ countBy?: string | null
1028
+ values?: any[] | null
1029
+ keys?: string[] | null
1030
+ atomValues?: any[] | null
1031
+ }): Promise<Response> {
1032
+ const response = await this.queryMeta({ ...params, throughMolecule: true })
1033
+ const payload = response.payload()
1034
+ if (payload && typeof (response as any).verifyIntegrity === 'function') {
1035
+ payload.integrity = (response as any).verifyIntegrity()
916
1036
  }
917
-
918
- return this.executeQuery(query, variables) as Promise<Response>
1037
+ return response
919
1038
  }
920
1039
 
921
1040
  /**
@@ -1008,42 +1127,43 @@ export default class KnishIOClient {
1008
1127
  metaId?: string | null
1009
1128
  indexes?: number[] | null
1010
1129
  index?: number | null
1011
- filter?: string | null
1130
+ filter?: MetaFilter[] | null
1012
1131
  latest?: boolean | null
1013
1132
  queryArgs?: Record<string, any> | null
1014
1133
  } = {}): Promise<Response> {
1134
+ this.log('info', 'KnishIOClient::queryAtom() - Querying atom instances')
1135
+
1015
1136
  const query = this.createQuery(QueryAtom)
1016
1137
 
1017
- const variables: Record<string, any> = {}
1018
-
1019
- // Add all non-null parameters to variables
1020
- if (molecularHashes !== null) variables.molecularHashes = molecularHashes
1021
- if (molecularHash !== null) variables.molecularHash = molecularHash
1022
- if (bundleHashes !== null) variables.bundleHashes = bundleHashes
1023
- if (bundleHash !== null) variables.bundleHash = bundleHash
1024
- if (positions !== null) variables.positions = positions
1025
- if (position !== null) variables.position = position
1026
- if (walletAddresses !== null) variables.walletAddresses = walletAddresses
1027
- if (walletAddress !== null) variables.walletAddress = walletAddress
1028
- if (isotopes !== null) variables.isotopes = isotopes
1029
- if (isotope !== null) variables.isotope = isotope
1030
- if (tokenSlugs !== null) variables.tokenSlugs = tokenSlugs
1031
- if (tokenSlug !== null) variables.tokenSlug = tokenSlug
1032
- if (cellSlugs !== null) variables.cellSlugs = cellSlugs
1033
- if (cellSlug !== null) variables.cellSlug = cellSlug
1034
- if (batchIds !== null) variables.batchIds = batchIds
1035
- if (batchId !== null) variables.batchId = batchId
1036
- if (values !== null) variables.values = values
1037
- if (value !== null) variables.value = value
1038
- if (metaTypes !== null) variables.metaTypes = metaTypes
1039
- if (metaType !== null) variables.metaType = metaType
1040
- if (metaIds !== null) variables.metaIds = metaIds
1041
- if (metaId !== null) variables.metaId = metaId
1042
- if (indexes !== null) variables.indexes = indexes
1043
- if (index !== null) variables.index = index
1044
- if (filter !== null) variables.filter = filter
1045
- if (latest !== null) variables.latest = latest
1046
- if (queryArgs !== null) variables.queryArgs = queryArgs
1138
+ const variables = QueryAtom.createVariables({
1139
+ molecularHashes,
1140
+ molecularHash,
1141
+ bundleHashes,
1142
+ bundleHash,
1143
+ positions,
1144
+ position,
1145
+ walletAddresses,
1146
+ walletAddress,
1147
+ isotopes,
1148
+ isotope,
1149
+ tokenSlugs,
1150
+ tokenSlug,
1151
+ cellSlugs,
1152
+ cellSlug,
1153
+ batchIds,
1154
+ batchId,
1155
+ values,
1156
+ value,
1157
+ metaTypes,
1158
+ metaType,
1159
+ metaIds,
1160
+ metaId,
1161
+ indexes,
1162
+ index,
1163
+ filter,
1164
+ latest,
1165
+ queryArgs
1166
+ })
1047
1167
 
1048
1168
  return this.executeQuery(query, variables) as Promise<Response>
1049
1169
  }
@@ -1288,7 +1408,7 @@ export default class KnishIOClient {
1288
1408
  const recipientWallet = new Wallet({
1289
1409
  secret: this.getSecret(),
1290
1410
  bundle: this.getBundle(),
1291
- token: token.toUpperCase(),
1411
+ token,
1292
1412
  batchId: batchId as any
1293
1413
  })
1294
1414
 
@@ -1334,7 +1454,7 @@ export default class KnishIOClient {
1334
1454
 
1335
1455
  // Initialize the request tokens mutation
1336
1456
  await mutation.fillMolecule({
1337
- token: token.toUpperCase(),
1457
+ token,
1338
1458
  amount: amount ?? 0,
1339
1459
  metaType: to || '',
1340
1460
  metaId: to || '',
@@ -1376,14 +1496,22 @@ export default class KnishIOClient {
1376
1496
  })
1377
1497
  }
1378
1498
 
1499
+ // Create molecule with the source wallet (same pattern as transferToken)
1500
+ const molecule = await this.createMolecule({
1501
+ sourceWallet
1502
+ })
1503
+
1379
1504
  // Create a transfer to null address (burn)
1380
- const mutation = await this.createMoleculeMutation({ mutationClass: MutationTransferTokens })
1505
+ const mutation = await this.createMoleculeMutation({
1506
+ mutationClass: MutationTransferTokens,
1507
+ molecule
1508
+ })
1381
1509
 
1382
1510
  // Create recipient wallet for burn address
1383
1511
  const recipientWallet = new Wallet({
1384
1512
  secret: this.getSecret(),
1385
1513
  bundle: '0000000000000000000000000000000000000000000000000000000000000000',
1386
- token: token.toUpperCase()
1514
+ token
1387
1515
  })
1388
1516
 
1389
1517
  await mutation.fillMolecule({
@@ -1468,7 +1596,7 @@ export default class KnishIOClient {
1468
1596
  const newWallet = new Wallet({
1469
1597
  secret: this.getSecret(),
1470
1598
  bundle: this.getBundle(),
1471
- token: token.toUpperCase()
1599
+ token
1472
1600
  })
1473
1601
 
1474
1602
  // Initialize the create wallet mutation
@@ -1523,7 +1651,7 @@ export default class KnishIOClient {
1523
1651
 
1524
1652
  // Initialize the claim shadow wallet mutation
1525
1653
  await mutation.fillMolecule({
1526
- token: token.toUpperCase() as TokenSlug,
1654
+ token: token as TokenSlug,
1527
1655
  batchId: shadowWallet.batchId
1528
1656
  })
1529
1657
 
@@ -1594,14 +1722,20 @@ export default class KnishIOClient {
1594
1722
  }): Promise<Response> {
1595
1723
  this.log('info', `KnishIOClient::createMeta() - Creating metadata for ${metaType}:${metaId}...`)
1596
1724
 
1597
- // Create the molecule mutation
1598
- const mutation = await this.createMoleculeMutation({ mutationClass: MutationCreateMeta })
1725
+ // Create the molecule mutation — let createMolecule() handle sourceWallet via
1726
+ // carry-forward (remainder wallet from prior mutation) or server fallback
1727
+ const mutation = await this.createMoleculeMutation({
1728
+ mutationClass: MutationCreateMeta,
1729
+ molecule: await this.createMolecule({
1730
+ secret: this.getSecret()
1731
+ })
1732
+ })
1599
1733
 
1600
1734
  // Initialize the create meta mutation
1601
1735
  await mutation.fillMolecule({
1602
- metaType: metaType.toUpperCase(),
1736
+ metaType,
1603
1737
  metaId,
1604
- meta,
1738
+ meta: meta || {},
1605
1739
  policy
1606
1740
  })
1607
1741
 
@@ -1631,12 +1765,18 @@ export default class KnishIOClient {
1631
1765
  }): Promise<Response> {
1632
1766
  this.log('info', `KnishIOClient::createRule() - Creating rule for ${metaType}:${metaId}...`)
1633
1767
 
1634
- // Create the molecule mutation
1635
- const mutation = await this.createMoleculeMutation({ mutationClass: MutationCreateRule })
1768
+ // Create the molecule mutation — let createMolecule() handle sourceWallet via
1769
+ // carry-forward (remainder wallet from prior mutation) or server fallback
1770
+ const mutation = await this.createMoleculeMutation({
1771
+ mutationClass: MutationCreateRule,
1772
+ molecule: await this.createMolecule({
1773
+ secret: this.getSecret()
1774
+ })
1775
+ })
1636
1776
 
1637
1777
  // Initialize the create rule mutation
1638
1778
  await mutation.fillMolecule({
1639
- metaType: metaType.toUpperCase() as MetaType,
1779
+ metaType: metaType as MetaType,
1640
1780
  metaId: metaId as MetaId,
1641
1781
  rule,
1642
1782
  policy
@@ -1771,10 +1911,10 @@ export default class KnishIOClient {
1771
1911
  // Create the mutation (extends Mutation directly, not MutationProposeMolecule)
1772
1912
  const mutation = this.createQuery(MutationActiveSession)
1773
1913
 
1774
- // Execute with variables
1914
+ // Execute with variables (bundleHash matches GraphQL variable name)
1775
1915
  const response = await this.executeQuery(mutation, {
1776
- bundle: bundle || this.getBundle(),
1777
- metaType: metaType.toUpperCase(),
1916
+ bundleHash: bundle || this.getBundle(),
1917
+ metaType,
1778
1918
  metaId,
1779
1919
  ipAddress,
1780
1920
  browser,
@@ -1916,6 +2056,7 @@ export default class KnishIOClient {
1916
2056
 
1917
2057
  /**
1918
2058
  * Request profile authentication token
2059
+ * Matches JavaScript SDK requestProfileAuthToken implementation
1919
2060
  */
1920
2061
  async requestProfileAuthToken({
1921
2062
  secret,
@@ -1923,27 +2064,58 @@ export default class KnishIOClient {
1923
2064
  }: {
1924
2065
  secret: string
1925
2066
  encrypt?: boolean
1926
- }): Promise<Response> {
2067
+ }): Promise<ResponseRequestAuthorization> {
1927
2068
  this.log('info', 'KnishIOClient::requestProfileAuthToken() - Requesting profile auth token...')
1928
2069
 
1929
2070
  // Set the secret
1930
2071
  this.setSecret(secret)
1931
2072
 
1932
- // Create the molecule mutation
1933
- const mutation = await this.createMoleculeMutation({ mutationClass: MutationRequestAuthorization })
2073
+ // Generate a signing wallet with AUTH token (matching JavaScript SDK)
2074
+ const wallet = new Wallet({
2075
+ secret,
2076
+ token: 'AUTH'
2077
+ })
2078
+
2079
+ // Create a molecule with the AUTH wallet as source
2080
+ const molecule = await this.createMolecule({
2081
+ secret,
2082
+ sourceWallet: wallet
2083
+ })
2084
+
2085
+ // Create the mutation with this specific molecule
2086
+ const mutation = await this.createMoleculeMutation({
2087
+ mutationClass: MutationRequestAuthorization,
2088
+ molecule
2089
+ })
1934
2090
 
1935
2091
  // Initialize the profile auth mutation
1936
- await mutation.fillMolecule({
2092
+ mutation.fillMolecule({
1937
2093
  meta: { encrypt: encrypt ? 'true' : 'false' }
1938
2094
  })
1939
2095
 
1940
2096
  // Execute the mutation
1941
- const response = await this.executeQuery(mutation)
2097
+ const response = await this.executeQuery(mutation) as ResponseRequestAuthorization
1942
2098
 
1943
2099
  if (!response) {
1944
2100
  throw new CodeException('Profile auth token request failed')
1945
2101
  }
1946
2102
 
2103
+ // Did the authorization molecule get accepted?
2104
+ if (response.success()) {
2105
+ // Create & set an auth token from the response data
2106
+ const authToken = AuthToken.create({
2107
+ token: response.token(),
2108
+ expiresAt: response.expiresAt(),
2109
+ encrypt: String(response.encrypt()) === 'true',
2110
+ pubkey: response.pubKey()
2111
+ }, wallet)
2112
+ this.setAuthToken(authToken)
2113
+ } else {
2114
+ throw new AuthorizationRejectedException(
2115
+ `KnishIOClient::requestProfileAuthToken() - Authorization attempt rejected by ledger. Reason: ${response.reason()}`
2116
+ )
2117
+ }
2118
+
1947
2119
  // Handle encryption if needed
1948
2120
  if (encrypt) {
1949
2121
  this.switchEncryption(true)
@@ -1952,6 +2124,83 @@ export default class KnishIOClient {
1952
2124
  return response
1953
2125
  }
1954
2126
 
2127
+ // =============================================================================
2128
+ // MUTATION METHODS - PEERING & APPEND REQUEST
2129
+ // =============================================================================
2130
+
2131
+ /**
2132
+ * Register a peer node via P-isotope
2133
+ * Matches JavaScript SDK registerPeer implementation exactly
2134
+ */
2135
+ async registerPeer({ host }: { host: string }): Promise<Response> {
2136
+ this.log('info', `KnishIOClient::registerPeer() - Registering peer at ${host}...`)
2137
+
2138
+ // Create the molecule mutation — let createMolecule() handle sourceWallet via
2139
+ // carry-forward (remainder wallet from prior mutation) or server fallback
2140
+ const mutation = await this.createMoleculeMutation({
2141
+ mutationClass: MutationPeering,
2142
+ molecule: await this.createMolecule({
2143
+ secret: this.getSecret()
2144
+ })
2145
+ })
2146
+
2147
+ // Fill the molecule with peering data
2148
+ mutation.fillMolecule({ host })
2149
+
2150
+ // Execute the mutation
2151
+ const response = await this.executeQuery(mutation)
2152
+
2153
+ if (!response) {
2154
+ throw new CodeException('Peer registration failed')
2155
+ }
2156
+
2157
+ return response
2158
+ }
2159
+
2160
+ /**
2161
+ * Submit an append request via A-isotope
2162
+ * Matches JavaScript SDK appendRequest implementation exactly
2163
+ */
2164
+ async appendRequest({
2165
+ metaType,
2166
+ metaId,
2167
+ action,
2168
+ meta = {}
2169
+ }: {
2170
+ metaType: string
2171
+ metaId: string
2172
+ action: string
2173
+ meta?: Record<string, any>
2174
+ }): Promise<Response> {
2175
+ this.log('info', `KnishIOClient::appendRequest() - Submitting append request for ${metaType}:${metaId}...`)
2176
+
2177
+ // Create the molecule mutation — let createMolecule() handle sourceWallet via
2178
+ // carry-forward (remainder wallet from prior mutation) or server fallback
2179
+ const mutation = await this.createMoleculeMutation({
2180
+ mutationClass: MutationAppendRequest,
2181
+ molecule: await this.createMolecule({
2182
+ secret: this.getSecret()
2183
+ })
2184
+ })
2185
+
2186
+ // Fill the molecule with append request data
2187
+ mutation.fillMolecule({
2188
+ metaType,
2189
+ metaId,
2190
+ action,
2191
+ meta
2192
+ })
2193
+
2194
+ // Execute the mutation
2195
+ const response = await this.executeQuery(mutation)
2196
+
2197
+ if (!response) {
2198
+ throw new CodeException('Append request failed')
2199
+ }
2200
+
2201
+ return response
2202
+ }
2203
+
1955
2204
  // =============================================================================
1956
2205
  // LEGACY/DEPRECATED METHODS
1957
2206
  // =============================================================================