@wishknish/knishio-client-ts 0.8.3 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5053,9 +5053,19 @@ var KnishIO = (function (exports) {
5053
5053
  });
5054
5054
 
5055
5055
  // src/exception/StackableUnitDecimalsException.ts
5056
+ var StackableUnitDecimalsException, StackableUnitDecimalsException_default;
5056
5057
  var init_StackableUnitDecimalsException = __esm({
5057
5058
  "src/exception/StackableUnitDecimalsException.ts"() {
5058
5059
  init_BaseException();
5060
+ StackableUnitDecimalsException = class extends exports.BaseException {
5061
+ /**
5062
+ * Constructor using proper error type
5063
+ */
5064
+ constructor(message = "Stackable tokens with unit IDs cannot have decimal places!") {
5065
+ super("STACKABLE_UNIT_DECIMALS_ERROR", message);
5066
+ }
5067
+ };
5068
+ StackableUnitDecimalsException_default = StackableUnitDecimalsException;
5059
5069
  }
5060
5070
  });
5061
5071
 
@@ -21334,9 +21344,6 @@ ${operationTypes.join("\n")}
21334
21344
  }
21335
21345
  }
21336
21346
  function generateBundleHash(secret, _source = null) {
21337
- if (!secret || secret.length === 0) {
21338
- throw new Error("Secret is required for bundle hash generation");
21339
- }
21340
21347
  const hash = shake256(secret, CRYPTO_CONSTANTS.BUNDLE_HASH_LENGTH * 4);
21341
21348
  return hash;
21342
21349
  }
@@ -22749,8 +22756,7 @@ ${operationTypes.join("\n")}
22749
22756
  "Batch",
22750
22757
  "ActiveSession",
22751
22758
  "Policy",
22752
- "Token",
22753
- "UserActivity"
22759
+ "Token"
22754
22760
  ];
22755
22761
  function createLookup(values) {
22756
22762
  return values.reduce((acc, value2) => {
@@ -23832,6 +23838,29 @@ ${operationTypes.join("\n")}
23832
23838
  }
23833
23839
  remainderWallet.tokenUnits = remainderTokenUnits;
23834
23840
  }
23841
+ /**
23842
+ * Split token units across MULTIPLE recipients (N-way sibling of splitUnits).
23843
+ *
23844
+ * The source retains the SENT union (all units leaving), each recipient gets its own
23845
+ * subset, and the remainder keeps the KEPT units (those not assigned to any recipient).
23846
+ * recipientUnitLists is parallel to recipientWallets. No-op when no units are sent.
23847
+ *
23848
+ * @param recipientUnitLists - per-recipient arrays of token unit IDs (parallel to recipientWallets)
23849
+ * @param recipientWallets - destination wallets
23850
+ * @param remainderWallet - wallet to receive the KEPT units
23851
+ */
23852
+ splitUnitsMulti(recipientUnitLists, recipientWallets, remainderWallet) {
23853
+ const sentIds = new Set(recipientUnitLists.flat());
23854
+ if (sentIds.size === 0) {
23855
+ return;
23856
+ }
23857
+ recipientWallets.forEach((recipientWallet, i4) => {
23858
+ const ids = recipientUnitLists[i4] ?? [];
23859
+ recipientWallet.tokenUnits = this.tokenUnits.filter((tokenUnit) => ids.includes(tokenUnit.id));
23860
+ });
23861
+ remainderWallet.tokenUnits = this.tokenUnits.filter((tokenUnit) => !sentIds.has(tokenUnit.id));
23862
+ this.tokenUnits = this.tokenUnits.filter((tokenUnit) => sentIds.has(tokenUnit.id));
23863
+ }
23835
23864
  /**
23836
23865
  * Get token units data
23837
23866
  * Stub for compatibility
@@ -23878,6 +23907,15 @@ ${operationTypes.join("\n")}
23878
23907
  };
23879
23908
  }
23880
23909
  async decryptMessage(encryptedData) {
23910
+ const decryptedString = await this._mlkemDecryptToString(encryptedData);
23911
+ return decryptedString === null ? null : JSON.parse(decryptedString);
23912
+ }
23913
+ /**
23914
+ * ML-KEM768 decapsulate + AES-256-GCM decrypt → the RAW decrypted UTF-8 string (no JSON.parse).
23915
+ * Shared by {@link decryptMessage} (which JSON.parses the result) and the PQ CipherHash transport
23916
+ * ({@link decryptMyMessageML768}, which needs the raw response JSON text). PQ-transport Phase E.
23917
+ */
23918
+ async _mlkemDecryptToString(encryptedData) {
23881
23919
  const { cipherText, encryptedMessage } = encryptedData;
23882
23920
  let sharedSecret;
23883
23921
  try {
@@ -23906,9 +23944,8 @@ ${operationTypes.join("\n")}
23906
23944
  console.info("Wallet::decryptMessage() - deserialized encrypted message", deserializedEncryptedMessage);
23907
23945
  return null;
23908
23946
  }
23909
- let decryptedString;
23910
23947
  try {
23911
- decryptedString = new TextDecoder().decode(decryptedUint8);
23948
+ return new TextDecoder().decode(decryptedUint8);
23912
23949
  } catch (e4) {
23913
23950
  console.warn("Wallet::decryptMessage() - Decoding failed", e4);
23914
23951
  console.info("Wallet::decryptMessage() - my public key", this.pubkey);
@@ -23917,7 +23954,40 @@ ${operationTypes.join("\n")}
23917
23954
  console.info("Wallet::decryptMessage() - decrypted Uint8Array", decryptedUint8);
23918
23955
  return null;
23919
23956
  }
23920
- return JSON.parse(decryptedString);
23957
+ }
23958
+ /**
23959
+ * Canonical cross-SDK hashShare for a public key: standard base64 of SHAKE256(pubkey_utf8, 8 bytes)
23960
+ * — byte-matches the validator's hash_share and the JS/Kotlin/PHP hashShare. `shake256(pubkey, 64)`
23961
+ * = 64 bits = 8 bytes (hex) → hex-decode → standard base64 via serializeKey. PQ-transport Phase E.
23962
+ */
23963
+ hashShare(pubkey) {
23964
+ const hex = shake256(pubkey, 64);
23965
+ const bytes = new Uint8Array(hex.length / 2);
23966
+ for (let i4 = 0; i4 < bytes.length; i4++) {
23967
+ bytes[i4] = parseInt(hex.substr(i4 * 2, 2), 16);
23968
+ }
23969
+ return this.serializeKey(bytes);
23970
+ }
23971
+ /**
23972
+ * Post-quantum (ML-KEM768) CipherHash request envelope: a stringified single-recipient map
23973
+ * `{ "<hashShare(recipientPubkey)>": {cipherText, encryptedMessage} }` (object-valued, via
23974
+ * {@link encryptMessage}). Matches the Rust validator's CipherHash handler. PQ-transport Phase E.
23975
+ */
23976
+ async encryptStringML768(message, recipientPubkey) {
23977
+ const envelope = await this.encryptMessage(message, recipientPubkey);
23978
+ return JSON.stringify({ [this.hashShare(recipientPubkey)]: envelope });
23979
+ }
23980
+ /**
23981
+ * Decrypt a CipherHash response map addressed to THIS wallet's ML-KEM pubkey
23982
+ * (`hashShare(this.pubkey)`) → the RAW decrypted GraphQL response JSON text (NOT JSON.parsed;
23983
+ * it replaces the HTTP response body for the normal parser). `null` if no entry / decrypt fails.
23984
+ */
23985
+ async decryptMyMessageML768(map2) {
23986
+ const envelope = map2[this.hashShare(this.pubkey)];
23987
+ if (!envelope) {
23988
+ return null;
23989
+ }
23990
+ return this._mlkemDecryptToString(envelope);
23921
23991
  }
23922
23992
  // =============================================================================
23923
23993
  // SYMMETRIC ENCRYPTION HELPERS (AES-GCM with shared secret)
@@ -25220,6 +25290,46 @@ ${operationTypes.join("\n")}
25220
25290
  }));
25221
25291
  return this;
25222
25292
  }
25293
+ /**
25294
+ * Initialize a MULTI-recipient V-type molecule: one source debits its FULL balance to fund
25295
+ * N recipients (each its own amount + stackable units) plus a remainder back to the sender.
25296
+ * Multi-recipient sibling of initValue (WP line 544: fund multiple recipients with one
25297
+ * transaction). recipientWallets is parallel to amounts.
25298
+ */
25299
+ initValues({
25300
+ recipientWallets,
25301
+ amounts
25302
+ }) {
25303
+ if (!this.sourceWallet) {
25304
+ throw new Error("Source wallet required for value transfer");
25305
+ }
25306
+ const total = amounts.reduce((sum, amount) => sum + amount, 0);
25307
+ if (Number(this.sourceWallet.balance) - total < 0) {
25308
+ throw new BalanceInsufficientException();
25309
+ }
25310
+ this.addAtom(Atom.create({
25311
+ isotope: "V",
25312
+ wallet: this.sourceWallet,
25313
+ value: -Number(this.sourceWallet.balance)
25314
+ }));
25315
+ recipientWallets.forEach((recipientWallet, i4) => {
25316
+ this.addAtom(Atom.create({
25317
+ isotope: "V",
25318
+ wallet: recipientWallet,
25319
+ value: amounts[i4],
25320
+ metaType: "walletBundle",
25321
+ metaId: recipientWallet.bundle
25322
+ }));
25323
+ });
25324
+ this.addAtom(Atom.create({
25325
+ isotope: "V",
25326
+ wallet: this.remainderWallet,
25327
+ value: Number(this.sourceWallet.balance) - total,
25328
+ metaType: "walletBundle",
25329
+ metaId: this.remainderWallet.bundle
25330
+ }));
25331
+ return this;
25332
+ }
25223
25333
  /**
25224
25334
  * Sign the molecule with one-time signature
25225
25335
  * Matches JavaScript SDK sign method
@@ -25977,7 +26087,7 @@ ${operationTypes.join("\n")}
25977
26087
  * @param debug Enable debug logging
25978
26088
  * @returns 0 if equal, 1 if value1 > value2, -1 if value1 < value2
25979
26089
  */
25980
- static cmp(value1, value2, debug = false) {
26090
+ static cmp(value1, value2, _debug = false) {
25981
26091
  const val1 = _Decimal.val(value1) * MULTIPLIER;
25982
26092
  const val2 = _Decimal.val(value2) * MULTIPLIER;
25983
26093
  if (Math.abs(val1 - val2) < 1) {
@@ -28418,6 +28528,14 @@ ${operationTypes.join("\n")}
28418
28528
 
28419
28529
  // src/libraries/GraphQLClient.ts
28420
28530
  var import_graphql_ws = __toESM(require_dist());
28531
+ var CIPHER_HASH_QUERY = "query ( $Hash: String! ) { CipherHash ( Hash: $Hash ) { hash } }";
28532
+ function parseOperation(query) {
28533
+ const typeMatch = (query || "").match(/\b(query|mutation|subscription)\b/i);
28534
+ const type2 = typeMatch?.[1]?.toLowerCase() ?? "query";
28535
+ const braceIdx = (query || "").indexOf("{");
28536
+ const nameMatch = braceIdx >= 0 ? query.slice(braceIdx + 1).match(/[A-Za-z_][A-Za-z0-9_]*/) : null;
28537
+ return { type: type2, name: nameMatch?.[0] ?? "" };
28538
+ }
28421
28539
  var GraphQLClient = class {
28422
28540
  $__client;
28423
28541
  $__authToken = "";
@@ -28463,6 +28581,10 @@ ${operationTypes.join("\n")}
28463
28581
  return Q3({
28464
28582
  url: serverUri,
28465
28583
  exchanges,
28584
+ // PQ-transport Phase E: when encryption is on, route fetch through the CipherHash wrapper
28585
+ // (encrypt the request body to the validator's ML-KEM pubkey, decrypt the response).
28586
+ // Omitted → urql uses the global fetch (plaintext).
28587
+ ...this.cipherLink ? { fetch: ((input, init) => this.cipherFetch(input, init)) } : {},
28466
28588
  fetchOptions: () => ({
28467
28589
  headers: {
28468
28590
  "X-Auth-Token": this.$__authToken
@@ -28472,6 +28594,62 @@ ${operationTypes.join("\n")}
28472
28594
  })
28473
28595
  });
28474
28596
  }
28597
+ /**
28598
+ * Whether an outgoing GraphQL request body should be wrapped in CipherHash. Bypass (plaintext):
28599
+ * introspection `__schema`, `ContinuId`, the `AccessToken` mutation, and the U-isotope
28600
+ * `ProposeMolecule` (auth bootstrap — the key exchange itself can't be encrypted). Mirrors the
28601
+ * Kotlin/PHP/validator bypass set.
28602
+ */
28603
+ shouldEncrypt(body) {
28604
+ let parsed;
28605
+ try {
28606
+ parsed = JSON.parse(body);
28607
+ } catch (e4) {
28608
+ return false;
28609
+ }
28610
+ const { type: type2, name: name2 } = parseOperation(parsed.query);
28611
+ if (type2 === "query" && (name2 === "__schema" || name2 === "ContinuId")) return false;
28612
+ if (type2 === "mutation" && name2 === "AccessToken") return false;
28613
+ if (type2 === "mutation" && name2 === "ProposeMolecule") {
28614
+ const isotope = parsed.variables?.molecule?.atoms?.[0]?.isotope;
28615
+ if (isotope === "U") return false;
28616
+ }
28617
+ return true;
28618
+ }
28619
+ /**
28620
+ * Custom `fetch` that wraps a GraphQL request in the ML-KEM CipherHash envelope and decrypts the
28621
+ * response (PQ-transport Phase E). Operates on the raw POST body (mirrors the JS/Kotlin transform).
28622
+ * Reads the CURRENT client wallet + validator pubkey from auth.
28623
+ */
28624
+ async cipherFetch(input, init) {
28625
+ const wallet = this.$__wallet;
28626
+ const serverPubkey = this.$__pubkey;
28627
+ let encryptedRequest = false;
28628
+ let requestInit = init;
28629
+ if (wallet && serverPubkey && init && typeof init.body === "string" && this.shouldEncrypt(init.body)) {
28630
+ const hashVar = await wallet.encryptStringML768(init.body, serverPubkey);
28631
+ requestInit = { ...init, body: JSON.stringify({ query: CIPHER_HASH_QUERY, variables: { Hash: hashVar } }) };
28632
+ encryptedRequest = true;
28633
+ }
28634
+ const response = await fetch(input, requestInit);
28635
+ if (!encryptedRequest) {
28636
+ return response;
28637
+ }
28638
+ const text = await response.text();
28639
+ const init2 = { status: response.status, statusText: response.statusText, headers: response.headers };
28640
+ let parsed;
28641
+ try {
28642
+ parsed = JSON.parse(text);
28643
+ } catch (e4) {
28644
+ return new Response(text, init2);
28645
+ }
28646
+ const hash = parsed?.data?.CipherHash?.hash;
28647
+ if (typeof hash !== "string") {
28648
+ return new Response(text, init2);
28649
+ }
28650
+ const decrypted = await wallet.decryptMyMessageML768(JSON.parse(hash));
28651
+ return new Response(decrypted != null ? decrypted : text, init2);
28652
+ }
28475
28653
  setAuthData({
28476
28654
  token,
28477
28655
  pubkey,
@@ -28766,8 +28944,8 @@ ${operationTypes.join("\n")}
28766
28944
  * Returns a Response object
28767
28945
  */
28768
28946
  createResponse(json) {
28769
- const Response2 = (init_Response(), __toCommonJS(Response_exports)).default;
28770
- return new Response2({
28947
+ const Response3 = (init_Response(), __toCommonJS(Response_exports)).default;
28948
+ return new Response3({
28771
28949
  query: this,
28772
28950
  json
28773
28951
  });
@@ -28837,8 +29015,8 @@ ${operationTypes.join("\n")}
28837
29015
  } catch (error2) {
28838
29016
  if (error2.name === "AbortError") {
28839
29017
  this.knishIOClient.log("warn", "Query was cancelled");
28840
- const Response2 = (init_Response(), __toCommonJS(Response_exports)).default;
28841
- return new Response2({
29018
+ const Response3 = (init_Response(), __toCommonJS(Response_exports)).default;
29019
+ return new Response3({
28842
29020
  query: this,
28843
29021
  json: { data: null, errors: [{ message: "Query was cancelled" }] }
28844
29022
  });
@@ -28882,8 +29060,8 @@ ${operationTypes.join("\n")}
28882
29060
  } catch (error2) {
28883
29061
  if (error2.name === "AbortError") {
28884
29062
  this.knishIOClient.log("warn", "Mutation was cancelled");
28885
- const Response2 = (init_Response(), __toCommonJS(Response_exports)).default;
28886
- return new Response2({
29063
+ const Response3 = (init_Response(), __toCommonJS(Response_exports)).default;
29064
+ return new Response3({
28887
29065
  query: this,
28888
29066
  json: { data: null, errors: [{ message: "Mutation was cancelled" }] }
28889
29067
  });
@@ -29822,6 +30000,89 @@ ${operationTypes.join("\n")}
29822
30000
 
29823
30001
  // src/response/ResponseBalance.ts
29824
30002
  init_Response();
30003
+
30004
+ // src/core/TokenUnit.ts
30005
+ var TokenUnit = class _TokenUnit {
30006
+ id;
30007
+ name;
30008
+ metas;
30009
+ /**
30010
+ * Create new TokenUnit instance
30011
+ * Matches JavaScript SDK constructor signature exactly
30012
+ */
30013
+ constructor(id, name2, metas) {
30014
+ this.id = id;
30015
+ this.name = name2;
30016
+ this.metas = metas || {};
30017
+ }
30018
+ /**
30019
+ * Create TokenUnit from GraphQL response data
30020
+ * Matches JavaScript SDK createFromGraphQL method exactly
30021
+ */
30022
+ static createFromGraphQL(data) {
30023
+ let metas = data.metas || {};
30024
+ if (Array.isArray(metas) && metas.length) {
30025
+ try {
30026
+ metas = JSON.parse(metas);
30027
+ if (!metas) {
30028
+ metas = {};
30029
+ }
30030
+ } catch (error2) {
30031
+ metas = {};
30032
+ }
30033
+ }
30034
+ return new _TokenUnit(
30035
+ data.id,
30036
+ data.name,
30037
+ metas
30038
+ );
30039
+ }
30040
+ /**
30041
+ * Create TokenUnit from database array data
30042
+ * Matches JavaScript SDK createFromDB method exactly
30043
+ */
30044
+ static createFromDB(data) {
30045
+ return new _TokenUnit(
30046
+ data[0],
30047
+ data[1],
30048
+ data.length > 2 ? data[2] : {}
30049
+ );
30050
+ }
30051
+ /**
30052
+ * Get fragment zone from metadata
30053
+ * Matches JavaScript SDK getFragmentZone method exactly
30054
+ */
30055
+ getFragmentZone() {
30056
+ return this.metas.fragmentZone || null;
30057
+ }
30058
+ /**
30059
+ * Get fused token units from metadata
30060
+ * Matches JavaScript SDK getFusedTokenUnits method exactly
30061
+ */
30062
+ getFusedTokenUnits() {
30063
+ return this.metas.fusedTokenUnits || null;
30064
+ }
30065
+ /**
30066
+ * Convert to data array format
30067
+ * Matches JavaScript SDK toData method exactly
30068
+ */
30069
+ toData() {
30070
+ return [this.id, this.name, this.metas];
30071
+ }
30072
+ /**
30073
+ * Convert to GraphQL response format
30074
+ * Matches JavaScript SDK toGraphQLResponse method exactly
30075
+ */
30076
+ toGraphQLResponse() {
30077
+ return {
30078
+ id: this.id,
30079
+ name: this.name,
30080
+ metas: JSON.stringify(this.metas)
30081
+ };
30082
+ }
30083
+ };
30084
+
30085
+ // src/response/ResponseBalance.ts
29825
30086
  var ResponseBalance = class _ResponseBalance extends exports.Response {
29826
30087
  /**
29827
30088
  * Class constructor
@@ -29884,6 +30145,11 @@ ${operationTypes.join("\n")}
29884
30145
  wallet.tokenSupply = data.token.supply;
29885
30146
  wallet.tokenFungibility = data.token.fungibility;
29886
30147
  }
30148
+ if (data.tokenUnits && data.tokenUnits.length) {
30149
+ for (const tokenUnitData of data.tokenUnits) {
30150
+ wallet.tokenUnits.push(TokenUnit.createFromGraphQL(tokenUnitData));
30151
+ }
30152
+ }
29887
30153
  if (data.tradeRates && data.tradeRates.length) {
29888
30154
  for (const tradeRate of data.tradeRates) {
29889
30155
  wallet.tradeRates[tradeRate.tokenSlug] = tradeRate.amount;
@@ -29943,89 +30209,6 @@ ${operationTypes.join("\n")}
29943
30209
 
29944
30210
  // src/response/ResponseWalletList.ts
29945
30211
  init_Response();
29946
-
29947
- // src/core/TokenUnit.ts
29948
- var TokenUnit = class _TokenUnit {
29949
- id;
29950
- name;
29951
- metas;
29952
- /**
29953
- * Create new TokenUnit instance
29954
- * Matches JavaScript SDK constructor signature exactly
29955
- */
29956
- constructor(id, name2, metas) {
29957
- this.id = id;
29958
- this.name = name2;
29959
- this.metas = metas || {};
29960
- }
29961
- /**
29962
- * Create TokenUnit from GraphQL response data
29963
- * Matches JavaScript SDK createFromGraphQL method exactly
29964
- */
29965
- static createFromGraphQL(data) {
29966
- let metas = data.metas || {};
29967
- if (Array.isArray(metas) && metas.length) {
29968
- try {
29969
- metas = JSON.parse(metas);
29970
- if (!metas) {
29971
- metas = {};
29972
- }
29973
- } catch (error2) {
29974
- metas = {};
29975
- }
29976
- }
29977
- return new _TokenUnit(
29978
- data.id,
29979
- data.name,
29980
- metas
29981
- );
29982
- }
29983
- /**
29984
- * Create TokenUnit from database array data
29985
- * Matches JavaScript SDK createFromDB method exactly
29986
- */
29987
- static createFromDB(data) {
29988
- return new _TokenUnit(
29989
- data[0],
29990
- data[1],
29991
- data.length > 2 ? data[2] : {}
29992
- );
29993
- }
29994
- /**
29995
- * Get fragment zone from metadata
29996
- * Matches JavaScript SDK getFragmentZone method exactly
29997
- */
29998
- getFragmentZone() {
29999
- return this.metas.fragmentZone || null;
30000
- }
30001
- /**
30002
- * Get fused token units from metadata
30003
- * Matches JavaScript SDK getFusedTokenUnits method exactly
30004
- */
30005
- getFusedTokenUnits() {
30006
- return this.metas.fusedTokenUnits || null;
30007
- }
30008
- /**
30009
- * Convert to data array format
30010
- * Matches JavaScript SDK toData method exactly
30011
- */
30012
- toData() {
30013
- return [this.id, this.name, this.metas];
30014
- }
30015
- /**
30016
- * Convert to GraphQL response format
30017
- * Matches JavaScript SDK toGraphQLResponse method exactly
30018
- */
30019
- toGraphQLResponse() {
30020
- return {
30021
- id: this.id,
30022
- name: this.name,
30023
- metas: JSON.stringify(this.metas)
30024
- };
30025
- }
30026
- };
30027
-
30028
- // src/response/ResponseWalletList.ts
30029
30212
  var ResponseWalletList = class _ResponseWalletList extends exports.Response {
30030
30213
  /**
30031
30214
  * Class constructor
@@ -30963,133 +31146,6 @@ ${operationTypes.join("\n")}
30963
31146
  }
30964
31147
  };
30965
31148
 
30966
- // src/response/ResponseQueryUserActivity.ts
30967
- init_Response();
30968
- var ResponseQueryUserActivity = class extends exports.Response {
30969
- /**
30970
- * Constructor
30971
- */
30972
- constructor({
30973
- query,
30974
- json
30975
- }) {
30976
- super({
30977
- query,
30978
- json,
30979
- dataKey: "data.UserActivity"
30980
- });
30981
- }
30982
- /**
30983
- * Returns processed user activity data
30984
- */
30985
- payload() {
30986
- const data = JSON.parse(JSON.stringify(this.data()));
30987
- if (data.instances) {
30988
- for (const datum of data.instances) {
30989
- if (datum.jsonData) {
30990
- datum.jsonData = JSON.parse(datum.jsonData);
30991
- }
30992
- }
30993
- }
30994
- return data;
30995
- }
30996
- };
30997
-
30998
- // src/query/QueryUserActivity.ts
30999
- var QueryUserActivity = class extends Query {
31000
- /**
31001
- * Constructor
31002
- */
31003
- constructor(graphQLClient, knishIOClient) {
31004
- super(graphQLClient, knishIOClient);
31005
- this.$__query = gql`
31006
- query UserActivity(
31007
- $bundleHash: String
31008
- $metaType: String
31009
- $metaId: String
31010
- $ipAddress: String
31011
- $browser: String
31012
- $osCpu: String
31013
- $resolution: String
31014
- $timeZone: String
31015
- $countBy: [CountByUserActivity]
31016
- $interval: span
31017
- ) {
31018
- UserActivity(
31019
- bundleHash: $bundleHash
31020
- metaType: $metaType
31021
- metaId: $metaId
31022
- ipAddress: $ipAddress
31023
- browser: $browser
31024
- osCpu: $osCpu
31025
- resolution: $resolution
31026
- timeZone: $timeZone
31027
- countBy: $countBy
31028
- interval: $interval
31029
- ) {
31030
- createdAt
31031
- bundleHash
31032
- metaType
31033
- metaId
31034
- instances {
31035
- bundleHash
31036
- metaType
31037
- metaId
31038
- jsonData
31039
- createdAt
31040
- updatedAt
31041
- }
31042
- instanceCount {
31043
- ...SubFields
31044
- ...Recursive
31045
- }
31046
- }
31047
- }
31048
-
31049
- fragment SubFields on InstanceCountType {
31050
- id
31051
- count
31052
- }
31053
-
31054
- fragment Recursive on InstanceCountType {
31055
- instances {
31056
- ...SubFields
31057
- instances {
31058
- ...SubFields
31059
- instances {
31060
- ...SubFields
31061
- instances {
31062
- ...SubFields
31063
- instances {
31064
- ...SubFields
31065
- instances {
31066
- ...SubFields
31067
- instances {
31068
- ...SubFields
31069
- instances {
31070
- ...SubFields
31071
- }
31072
- }
31073
- }
31074
- }
31075
- }
31076
- }
31077
- }
31078
- }
31079
- }
31080
- `;
31081
- }
31082
- /**
31083
- * Returns a Response object
31084
- */
31085
- createResponse(json) {
31086
- return new ResponseQueryUserActivity({
31087
- query: this,
31088
- json
31089
- });
31090
- }
31091
- };
31092
-
31093
31149
  // src/query/QueryToken.ts
31094
31150
  init_Response();
31095
31151
  var QueryToken = class extends Query {
@@ -31931,6 +31987,20 @@ ${operationTypes.join("\n")}
31931
31987
  this.$__molecule.sign({});
31932
31988
  this.$__molecule.check(this.$__molecule.sourceWallet);
31933
31989
  }
31990
+ /**
31991
+ * Fills the Molecule for a MULTI-recipient transfer (one source funds N recipients)
31992
+ */
31993
+ fillMoleculeMulti({
31994
+ recipientWallets,
31995
+ amounts
31996
+ }) {
31997
+ this.$__molecule.initValues({
31998
+ recipientWallets,
31999
+ amounts
32000
+ });
32001
+ this.$__molecule.sign({});
32002
+ this.$__molecule.check(this.$__molecule.sourceWallet);
32003
+ }
31934
32004
  /**
31935
32005
  * Builds a Response object out of a JSON object
31936
32006
  * Matches JavaScript SDK createResponse method signature exactly
@@ -31991,7 +32061,8 @@ ${operationTypes.join("\n")}
31991
32061
  bundle: this.$__molecule.bundle,
31992
32062
  token,
31993
32063
  batchId
31994
- })(this.$__molecule).initShadowWalletClaim(wallet);
32064
+ });
32065
+ this.$__molecule.initShadowWalletClaim(wallet);
31995
32066
  this.$__molecule.sign({});
31996
32067
  this.$__molecule.check();
31997
32068
  }
@@ -33251,6 +33322,75 @@ ${operationTypes.join("\n")}
33251
33322
  });
33252
33323
  return await this.executeQuery(query);
33253
33324
  }
33325
+ /**
33326
+ * Fund N recipients from a single source in ONE molecule (multi-recipient sibling of
33327
+ * transferToken). Each recipient gets its own subset of stackable units (or a fungible
33328
+ * amount); a remainder returns the rest to the sender. Conserves:
33329
+ * -balance + Σamounts + (balance - Σ) === 0.
33330
+ *
33331
+ * @param token - token slug
33332
+ * @param recipients - destinations (bundleHash + units OR amount + optional batchId)
33333
+ * @param sourceWallet - optional pre-resolved source (defaults to the client's own wallet)
33334
+ */
33335
+ async transferTokens({
33336
+ token,
33337
+ recipients,
33338
+ sourceWallet = null
33339
+ }) {
33340
+ const amounts = recipients.map((recipient) => {
33341
+ const unitCount = recipient.units ? recipient.units.length : 0;
33342
+ if (unitCount > 0) {
33343
+ if (recipient.amount !== null && recipient.amount !== void 0 && recipient.amount > 0) {
33344
+ throw new StackableUnitAmountException_default();
33345
+ }
33346
+ return unitCount;
33347
+ }
33348
+ return recipient.amount ?? 0;
33349
+ });
33350
+ const total = amounts.reduce((sum, amount) => sum + amount, 0);
33351
+ if (sourceWallet === null) {
33352
+ sourceWallet = await this.querySourceWallet({
33353
+ token,
33354
+ amount: total
33355
+ });
33356
+ }
33357
+ if (sourceWallet === null || Decimal.cmp(Number(sourceWallet.balance), total) < 0) {
33358
+ throw new exports.TransferBalanceException();
33359
+ }
33360
+ const recipientWallets = recipients.map((recipient) => {
33361
+ const recipientWallet = Wallet.create({
33362
+ bundle: recipient.bundleHash,
33363
+ token
33364
+ });
33365
+ if (recipient.batchId !== null && recipient.batchId !== void 0) {
33366
+ recipientWallet.batchId = recipient.batchId;
33367
+ } else {
33368
+ recipientWallet.initBatchId({ sourceWallet });
33369
+ }
33370
+ return recipientWallet;
33371
+ });
33372
+ const remainderWallet = sourceWallet.createRemainder(this.getSecret());
33373
+ if (recipients.some((recipient) => recipient.units && recipient.units.length > 0)) {
33374
+ sourceWallet.splitUnitsMulti(
33375
+ recipients.map((recipient) => recipient.units ?? []),
33376
+ recipientWallets,
33377
+ remainderWallet
33378
+ );
33379
+ }
33380
+ const molecule = await this.createMolecule({
33381
+ sourceWallet,
33382
+ remainderWallet
33383
+ });
33384
+ const query = await this.createMoleculeMutation({
33385
+ mutationClass: MutationTransferTokens,
33386
+ molecule
33387
+ });
33388
+ query.fillMoleculeMulti({
33389
+ recipientWallets,
33390
+ amounts
33391
+ });
33392
+ return await this.executeQuery(query);
33393
+ }
33254
33394
  /**
33255
33395
  * Request authorization token (guest or profile)
33256
33396
  *
@@ -33707,36 +33847,6 @@ ${operationTypes.join("\n")}
33707
33847
  metaId
33708
33848
  });
33709
33849
  }
33710
- /**
33711
- * Query user activity
33712
- */
33713
- async queryUserActivity({
33714
- bundleHash,
33715
- metaType,
33716
- metaId,
33717
- ipAddress = null,
33718
- browser = null,
33719
- osCpu = null,
33720
- resolution = null,
33721
- timeZone = null,
33722
- countBy = null,
33723
- interval = null
33724
- }) {
33725
- const query = this.createQuery(QueryUserActivity);
33726
- const variables = {
33727
- bundleHash,
33728
- metaType,
33729
- metaId
33730
- };
33731
- if (ipAddress !== null) variables.ipAddress = ipAddress;
33732
- if (browser !== null) variables.browser = browser;
33733
- if (osCpu !== null) variables.osCpu = osCpu;
33734
- if (resolution !== null) variables.resolution = resolution;
33735
- if (timeZone !== null) variables.timeZone = timeZone;
33736
- if (countBy !== null) variables.countBy = countBy;
33737
- if (interval !== null) variables.interval = interval;
33738
- return this.executeQuery(query, variables);
33739
- }
33740
33850
  /**
33741
33851
  * Query token information
33742
33852
  */
@@ -33845,9 +33955,27 @@ ${operationTypes.join("\n")}
33845
33955
  amount = null,
33846
33956
  meta = null,
33847
33957
  batchId = null,
33848
- units: _units = null
33958
+ units = null
33849
33959
  }) {
33850
33960
  this.log("info", `KnishIOClient::createToken() - Creating token ${token}...`);
33961
+ const tokenMeta = meta || {};
33962
+ const fungibility = tokenMeta.fungibility;
33963
+ let resolvedAmount = amount ?? 0;
33964
+ if (fungibility === "stackable") {
33965
+ tokenMeta.batchId = batchId || generateBatchId({});
33966
+ }
33967
+ if ((fungibility === "stackable" || fungibility === "nonfungible" || fungibility === "non-fungible") && units && units.length > 0) {
33968
+ if (Number(tokenMeta.decimals ?? 0) > 0) {
33969
+ throw new StackableUnitDecimalsException_default();
33970
+ }
33971
+ if (Number(amount ?? 0) > 0) {
33972
+ throw new StackableUnitAmountException_default();
33973
+ }
33974
+ resolvedAmount = units.length;
33975
+ tokenMeta.splittable = "1";
33976
+ tokenMeta.decimals = "0";
33977
+ tokenMeta.tokenUnits = JSON.stringify(units);
33978
+ }
33851
33979
  const mutation = await this.createMoleculeMutation({ mutationClass: MutationCreateToken });
33852
33980
  const recipientWallet = new Wallet({
33853
33981
  secret: this.getSecret(),
@@ -33857,8 +33985,8 @@ ${operationTypes.join("\n")}
33857
33985
  });
33858
33986
  await mutation.fillMolecule({
33859
33987
  recipientWallet,
33860
- amount: amount ?? 0,
33861
- meta
33988
+ amount: resolvedAmount,
33989
+ meta: tokenMeta
33862
33990
  });
33863
33991
  const response = await this.executeQuery(mutation);
33864
33992
  if (!response) {
@@ -34299,8 +34427,12 @@ ${operationTypes.join("\n")}
34299
34427
  mutationClass: MutationRequestAuthorization,
34300
34428
  molecule
34301
34429
  });
34430
+ const authMeta = { encrypt: encrypt ? "true" : "false" };
34431
+ if (wallet.pubkey) {
34432
+ authMeta.walletPubkey = wallet.pubkey;
34433
+ }
34302
34434
  mutation.fillMolecule({
34303
- meta: { encrypt: encrypt ? "true" : "false" }
34435
+ meta: authMeta
34304
34436
  });
34305
34437
  const response = await this.executeQuery(mutation);
34306
34438
  if (!response) {