@wishknish/knishio-client-ts 0.7.4 → 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 (43) hide show
  1. package/dist/index.cjs +2670 -1039
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +336 -105
  4. package/dist/index.d.ts +336 -105
  5. package/dist/index.iife.js +22097 -20047
  6. package/dist/index.iife.js.map +1 -1
  7. package/dist/index.js +2667 -1040
  8. package/dist/index.js.map +1 -1
  9. package/package.json +10 -4
  10. package/src/AuthToken.ts +8 -2
  11. package/src/KnishIOClient.ts +306 -50
  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 +8 -0
  19. package/src/instance/rules/Rule.ts +128 -19
  20. package/src/libraries/CheckMolecule.ts +88 -1
  21. package/src/libraries/crypto.ts +14 -30
  22. package/src/libraries/strings.ts +26 -25
  23. package/src/mutation/MutationAppendRequest.ts +52 -0
  24. package/src/mutation/MutationCreateRule.ts +2 -2
  25. package/src/mutation/MutationPeering.ts +37 -0
  26. package/src/mutation/MutationRequestAuthorization.ts +3 -3
  27. package/src/query/QueryActiveSession.ts +0 -1
  28. package/src/query/QueryContinuId.ts +8 -0
  29. package/src/query/QueryMetaTypeViaMolecule.ts +221 -0
  30. package/src/query/QueryWalletList.ts +2 -2
  31. package/src/response/ResponseAppendRequest.ts +17 -0
  32. package/src/response/ResponseBalance.ts +8 -3
  33. package/src/response/ResponseContinuId.ts +1 -1
  34. package/src/response/ResponseMetaType.ts +32 -19
  35. package/src/response/ResponseMetaTypeViaMolecule.ts +224 -0
  36. package/src/response/ResponsePeering.ts +17 -0
  37. package/src/response/ResponsePolicy.ts +2 -3
  38. package/src/response/ResponseProposeMolecule.ts +0 -1
  39. package/src/response/ResponseRequestAuthorization.ts +32 -2
  40. package/src/response/ResponseRequestAuthorizationGuest.ts +25 -1
  41. package/src/response/ResponseWalletList.ts +1 -1
  42. package/src/types/guards.ts +18 -5
  43. package/src/types/index.ts +3 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wishknish/knishio-client-ts",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "productName": "Knish.IO TypeScript SDK Client",
5
5
  "description": "TypeScript implementation of the Knish.IO SDK to consume Knish.IO GraphQL APIs with enhanced type safety.",
6
6
  "license": "GPL-3.0-or-later",
@@ -58,24 +58,30 @@
58
58
  "fips-203"
59
59
  ],
60
60
  "dependencies": {
61
- "@noble/post-quantum": "^0.5.2",
61
+ "@noble/post-quantum": "^0.5.4",
62
62
  "@thumbmarkjs/thumbmarkjs": "^0.19.1",
63
63
  "@urql/core": "^5.2.0",
64
64
  "graphql": "^16.11.0",
65
- "graphql-ws": "^6.0.6",
65
+ "graphql-ws": "^6.0.7",
66
66
  "isomorphic-fetch": "^3.0.0",
67
67
  "jssha": "^3.3.1",
68
+ "tslib": "^2.8.1",
68
69
  "wonka": "^6.3.5",
69
70
  "zod": "^3.23.8"
70
71
  },
71
72
  "devDependencies": {
72
73
  "@types/isomorphic-fetch": "^0.0.39",
74
+ "@types/jest": "^30.0.0",
73
75
  "@types/jssha": "^3.0.0",
74
76
  "@types/node": "^22.8.1",
77
+ "@types/pg": "^8.10.0",
75
78
  "@typescript-eslint/eslint-plugin": "^8.15.0",
76
79
  "@typescript-eslint/parser": "^8.15.0",
77
80
  "eslint": "^9.16.0",
81
+ "jest": "^30.2.0",
82
+ "pg": "^8.11.0",
78
83
  "prettier": "^3.4.2",
84
+ "ts-jest": "^29.4.6",
79
85
  "tsup": "^8.3.5",
80
86
  "tsx": "^4.20.5",
81
87
  "typescript": "^5.6.3",
@@ -109,7 +115,7 @@
109
115
  "README.md",
110
116
  "LICENSE"
111
117
  ],
112
- "packageManager": "yarn@4.10.3",
118
+ "packageManager": "yarn@4.6.0",
113
119
  "engines": {
114
120
  "node": ">=18.0.0"
115
121
  }
package/src/AuthToken.ts CHANGED
@@ -162,12 +162,18 @@ export default class AuthToken {
162
162
  return this.$__encrypt
163
163
  }
164
164
 
165
+ /**
166
+ * Get expire interval in milliseconds (matching JS SDK pattern)
167
+ */
168
+ getExpireInterval(): number {
169
+ return (this.$__expiresAt * 1000) - Date.now()
170
+ }
171
+
165
172
  /**
166
173
  * Check if token is expired
167
174
  */
168
175
  isExpired(): boolean {
169
- const now = Math.floor(Date.now() / 1000)
170
- return now >= this.$__expiresAt
176
+ return !this.$__expiresAt || this.getExpireInterval() < 0
171
177
  }
172
178
 
173
179
  /**
@@ -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
@@ -140,6 +146,7 @@ export default class KnishIOClient {
140
146
  private $__logging: boolean = false
141
147
  private $__authTokenObjects: Record<string, AuthToken | null> = {}
142
148
  private $__authToken: AuthToken | null = null
149
+ private $__authInProcess: boolean = false
143
150
  private $__remainderWallet: Wallet | null = null
144
151
  private lastMoleculeQuery: Mutation | null = null
145
152
  private abortControllers: Map<string, AbortController> = new Map()
@@ -331,6 +338,10 @@ export default class KnishIOClient {
331
338
  } else {
332
339
  this.$__uris = uri
333
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
+ }
334
345
  }
335
346
 
336
347
  /**
@@ -403,7 +414,8 @@ export default class KnishIOClient {
403
414
  }
404
415
 
405
416
  /**
406
- * 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
407
419
  */
408
420
  async createMolecule({
409
421
  secret = null,
@@ -429,19 +441,29 @@ export default class KnishIOClient {
429
441
  this.lastMoleculeQuery.response()?.success()
430
442
  ) {
431
443
  sourceWallet = this.getRemainderWallet()
444
+ this.log('info', `KnishIOClient::createMolecule() - Using carry-forward remainder wallet at position ${sourceWallet?.position?.substring(0, 16)}...`)
432
445
  }
433
446
 
434
447
  // Unable to use last remainder wallet; Figure out what wallet to use:
435
448
  if (!sourceWallet) {
436
- // Get source wallet
437
449
  sourceWallet = await this.getSourceWallet()
438
450
  }
439
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
+
440
461
  return new Molecule({
441
462
  secret,
442
- bundle,
443
463
  sourceWallet,
444
- remainderWallet
464
+ remainderWallet: this.getRemainderWallet()!,
465
+ cellSlug: this.getCellSlug(),
466
+ version: this.getServerSdkVersion()
445
467
  })
446
468
  }
447
469
 
@@ -477,7 +499,8 @@ export default class KnishIOClient {
477
499
  */
478
500
  async executeQuery(query: Query | Mutation, variables: Record<string, any> | null = null): Promise<Response | null> {
479
501
  // Check and refresh authorization token if needed
480
- if (this.$__authToken && this.$__authToken.isExpired()) {
502
+ // Guard with $__authInProcess to prevent recursive auth refresh
503
+ if (this.$__authToken && this.$__authToken.isExpired() && !this.$__authInProcess) {
481
504
  this.log('info', 'KnishIOClient::executeQuery() - Access token is expired. Getting new one...')
482
505
  await this.requestAuthToken({
483
506
  secret: this.$__secret,
@@ -511,16 +534,29 @@ export default class KnishIOClient {
511
534
  }
512
535
 
513
536
  /**
514
- * 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
515
540
  */
516
541
  async getSourceWallet(): Promise<Wallet> {
517
- // For now, create a new wallet with the current secret
518
- // In full implementation, this would query the ledger
519
- return Wallet.create({
520
- secret: this.getSecret(),
521
- bundle: this.getBundle(),
522
- token: 'USER'
523
- })
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
524
560
  }
525
561
 
526
562
  /**
@@ -566,7 +602,7 @@ export default class KnishIOClient {
566
602
  }
567
603
 
568
604
  // Do you have enough tokens?
569
- if (sourceWallet === null || Decimal.cmp(sourceWallet.balance, amount) < 0) {
605
+ if (sourceWallet === null || Decimal.cmp(Number(sourceWallet.balance), amount) < 0) {
570
606
  throw new TransferBalanceException()
571
607
  }
572
608
 
@@ -615,13 +651,18 @@ export default class KnishIOClient {
615
651
  }
616
652
 
617
653
  /**
618
- * 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
619
660
  */
620
661
  async requestAuthToken({
621
- secret: _secret = null,
622
- seed: _seed = null,
623
- cellSlug: _cellSlug = null,
624
- encrypt: _encrypt = false
662
+ secret = null,
663
+ seed = null,
664
+ cellSlug = null,
665
+ encrypt = false
625
666
  }: {
626
667
  secret?: string | null
627
668
  seed?: string | null
@@ -630,12 +671,52 @@ export default class KnishIOClient {
630
671
  } = {}): Promise<Response | null> {
631
672
  // SDK versions 2 and below do not utilize an authorization token
632
673
  if (this.$__serverSdkVersion < 3) {
633
- 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...')
634
675
  return null
635
676
  }
636
677
 
637
- // For now, return null - full implementation would handle authorization
638
- 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
639
720
  }
640
721
 
641
722
  /**
@@ -756,7 +837,7 @@ export default class KnishIOClient {
756
837
 
757
838
  // Do you have enough tokens?
758
839
  const amountNum = typeof amount === 'string' ? Number(amount) : amount
759
- if (sourceWallet === null || Decimal.cmp(sourceWallet.balance || 0, amountNum) < 0) {
840
+ if (sourceWallet === null || Decimal.cmp(Number(sourceWallet.balance || 0), amountNum) < 0) {
760
841
  throw new TransferBalanceException()
761
842
  }
762
843
 
@@ -786,7 +867,7 @@ export default class KnishIOClient {
786
867
 
787
868
  const response = await this.executeQuery(walletQuery, {
788
869
  bundleHash: bundle || this.getBundle(),
789
- tokenSlug: token,
870
+ token,
790
871
  unspent
791
872
  })
792
873
 
@@ -851,6 +932,7 @@ export default class KnishIOClient {
851
932
  count = null,
852
933
  countBy = null,
853
934
  throughAtom = true,
935
+ throughMolecule = false,
854
936
  values = null,
855
937
  keys = null,
856
938
  atomValues = null
@@ -866,6 +948,7 @@ export default class KnishIOClient {
866
948
  count?: number | null
867
949
  countBy?: string | null
868
950
  throughAtom?: boolean | null
951
+ throughMolecule?: boolean | null
869
952
  values?: any[] | null
870
953
  keys?: string[] | null
871
954
  atomValues?: any[] | null
@@ -875,10 +958,26 @@ export default class KnishIOClient {
875
958
  let query: Query
876
959
  let variables: Record<string, any>
877
960
 
878
- if (throughAtom) {
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) {
879
978
  query = this.createQuery(QueryMetaTypeViaAtom)
880
979
  variables = QueryMetaTypeViaAtom.createVariables({
881
- metaType,
980
+ metaType: metaType,
882
981
  metaId,
883
982
  key,
884
983
  value,
@@ -894,7 +993,7 @@ export default class KnishIOClient {
894
993
  } else {
895
994
  query = this.createQuery(QueryMetaType)
896
995
  variables = QueryMetaType.createVariables({
897
- metaType,
996
+ metaType: metaType,
898
997
  metaId,
899
998
  key,
900
999
  value,
@@ -910,6 +1009,34 @@ export default class KnishIOClient {
910
1009
  return this.executeQuery(query, variables) as Promise<Response>
911
1010
  }
912
1011
 
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()
1036
+ }
1037
+ return response
1038
+ }
1039
+
913
1040
  /**
914
1041
  * Query cascading meta instances for batchId
915
1042
  */
@@ -1281,7 +1408,7 @@ export default class KnishIOClient {
1281
1408
  const recipientWallet = new Wallet({
1282
1409
  secret: this.getSecret(),
1283
1410
  bundle: this.getBundle(),
1284
- token: token.toUpperCase(),
1411
+ token,
1285
1412
  batchId: batchId as any
1286
1413
  })
1287
1414
 
@@ -1327,7 +1454,7 @@ export default class KnishIOClient {
1327
1454
 
1328
1455
  // Initialize the request tokens mutation
1329
1456
  await mutation.fillMolecule({
1330
- token: token.toUpperCase(),
1457
+ token,
1331
1458
  amount: amount ?? 0,
1332
1459
  metaType: to || '',
1333
1460
  metaId: to || '',
@@ -1369,14 +1496,22 @@ export default class KnishIOClient {
1369
1496
  })
1370
1497
  }
1371
1498
 
1499
+ // Create molecule with the source wallet (same pattern as transferToken)
1500
+ const molecule = await this.createMolecule({
1501
+ sourceWallet
1502
+ })
1503
+
1372
1504
  // Create a transfer to null address (burn)
1373
- const mutation = await this.createMoleculeMutation({ mutationClass: MutationTransferTokens })
1505
+ const mutation = await this.createMoleculeMutation({
1506
+ mutationClass: MutationTransferTokens,
1507
+ molecule
1508
+ })
1374
1509
 
1375
1510
  // Create recipient wallet for burn address
1376
1511
  const recipientWallet = new Wallet({
1377
1512
  secret: this.getSecret(),
1378
1513
  bundle: '0000000000000000000000000000000000000000000000000000000000000000',
1379
- token: token.toUpperCase()
1514
+ token
1380
1515
  })
1381
1516
 
1382
1517
  await mutation.fillMolecule({
@@ -1461,7 +1596,7 @@ export default class KnishIOClient {
1461
1596
  const newWallet = new Wallet({
1462
1597
  secret: this.getSecret(),
1463
1598
  bundle: this.getBundle(),
1464
- token: token.toUpperCase()
1599
+ token
1465
1600
  })
1466
1601
 
1467
1602
  // Initialize the create wallet mutation
@@ -1516,7 +1651,7 @@ export default class KnishIOClient {
1516
1651
 
1517
1652
  // Initialize the claim shadow wallet mutation
1518
1653
  await mutation.fillMolecule({
1519
- token: token.toUpperCase() as TokenSlug,
1654
+ token: token as TokenSlug,
1520
1655
  batchId: shadowWallet.batchId
1521
1656
  })
1522
1657
 
@@ -1587,14 +1722,20 @@ export default class KnishIOClient {
1587
1722
  }): Promise<Response> {
1588
1723
  this.log('info', `KnishIOClient::createMeta() - Creating metadata for ${metaType}:${metaId}...`)
1589
1724
 
1590
- // Create the molecule mutation
1591
- 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
+ })
1592
1733
 
1593
1734
  // Initialize the create meta mutation
1594
1735
  await mutation.fillMolecule({
1595
- metaType: metaType.toUpperCase(),
1736
+ metaType,
1596
1737
  metaId,
1597
- meta,
1738
+ meta: meta || {},
1598
1739
  policy
1599
1740
  })
1600
1741
 
@@ -1624,12 +1765,18 @@ export default class KnishIOClient {
1624
1765
  }): Promise<Response> {
1625
1766
  this.log('info', `KnishIOClient::createRule() - Creating rule for ${metaType}:${metaId}...`)
1626
1767
 
1627
- // Create the molecule mutation
1628
- 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
+ })
1629
1776
 
1630
1777
  // Initialize the create rule mutation
1631
1778
  await mutation.fillMolecule({
1632
- metaType: metaType.toUpperCase() as MetaType,
1779
+ metaType: metaType as MetaType,
1633
1780
  metaId: metaId as MetaId,
1634
1781
  rule,
1635
1782
  policy
@@ -1764,10 +1911,10 @@ export default class KnishIOClient {
1764
1911
  // Create the mutation (extends Mutation directly, not MutationProposeMolecule)
1765
1912
  const mutation = this.createQuery(MutationActiveSession)
1766
1913
 
1767
- // Execute with variables
1914
+ // Execute with variables (bundleHash matches GraphQL variable name)
1768
1915
  const response = await this.executeQuery(mutation, {
1769
- bundle: bundle || this.getBundle(),
1770
- metaType: metaType.toUpperCase(),
1916
+ bundleHash: bundle || this.getBundle(),
1917
+ metaType,
1771
1918
  metaId,
1772
1919
  ipAddress,
1773
1920
  browser,
@@ -1909,6 +2056,7 @@ export default class KnishIOClient {
1909
2056
 
1910
2057
  /**
1911
2058
  * Request profile authentication token
2059
+ * Matches JavaScript SDK requestProfileAuthToken implementation
1912
2060
  */
1913
2061
  async requestProfileAuthToken({
1914
2062
  secret,
@@ -1916,27 +2064,58 @@ export default class KnishIOClient {
1916
2064
  }: {
1917
2065
  secret: string
1918
2066
  encrypt?: boolean
1919
- }): Promise<Response> {
2067
+ }): Promise<ResponseRequestAuthorization> {
1920
2068
  this.log('info', 'KnishIOClient::requestProfileAuthToken() - Requesting profile auth token...')
1921
2069
 
1922
2070
  // Set the secret
1923
2071
  this.setSecret(secret)
1924
2072
 
1925
- // Create the molecule mutation
1926
- 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
+ })
1927
2090
 
1928
2091
  // Initialize the profile auth mutation
1929
- await mutation.fillMolecule({
2092
+ mutation.fillMolecule({
1930
2093
  meta: { encrypt: encrypt ? 'true' : 'false' }
1931
2094
  })
1932
2095
 
1933
2096
  // Execute the mutation
1934
- const response = await this.executeQuery(mutation)
2097
+ const response = await this.executeQuery(mutation) as ResponseRequestAuthorization
1935
2098
 
1936
2099
  if (!response) {
1937
2100
  throw new CodeException('Profile auth token request failed')
1938
2101
  }
1939
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
+
1940
2119
  // Handle encryption if needed
1941
2120
  if (encrypt) {
1942
2121
  this.switchEncryption(true)
@@ -1945,6 +2124,83 @@ export default class KnishIOClient {
1945
2124
  return response
1946
2125
  }
1947
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
+
1948
2204
  // =============================================================================
1949
2205
  // LEGACY/DEPRECATED METHODS
1950
2206
  // =============================================================================