@wishknish/knishio-client-js 0.8.1 → 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.
- package/dist/client.cjs.js +29 -102
- package/dist/client.cjs.js.map +1 -1
- package/dist/client.es.mjs +823 -766
- package/dist/client.es.mjs.map +1 -1
- package/dist/client.iife.js +29 -102
- package/dist/client.iife.js.map +1 -1
- package/package.json +1 -1
- package/src/Atom.js +18 -20
- package/src/KnishIOClient.js +115 -49
- package/src/Molecule.js +78 -68
- package/src/Wallet.js +89 -6
- package/src/index.js +0 -4
- package/src/instance/Rules/Callback.js +1 -0
- package/src/instance/Rules/Meta.js +1 -3
- package/src/instance/Rules/Rule.js +1 -0
- package/src/libraries/strings.js +1 -0
- package/src/libraries/urql/UrqlClientWrapper.js +129 -10
- package/src/mutation/MutationTransferTokens.js +18 -0
- package/src/query/QueryPolicy.js +1 -1
- package/src/response/Response.js +3 -3
- package/src/response/ResponseActiveSession.js +0 -1
- package/src/response/ResponseAtom.js +0 -1
- package/src/response/ResponseAuthorizationGuest.js +0 -1
- package/src/response/ResponseBalance.js +0 -1
- package/src/response/ResponseContinuId.js +0 -1
- package/src/response/ResponseLinkIdentifier.js +0 -1
- package/src/response/ResponseMetaType.js +0 -1
- package/src/response/ResponseMetaTypeViaAtom.js +0 -1
- package/src/response/ResponseMetaTypeViaMolecule.js +0 -1
- package/src/response/ResponsePolicy.js +0 -1
- package/src/response/ResponseQueryActiveSession.js +0 -1
- package/src/response/ResponseWalletBundle.js +0 -1
- package/src/response/ResponseWalletList.js +0 -1
- package/src/query/QueryUserActivity.js +0 -151
- package/src/response/ResponseQueryUserActivity.js +0 -80
package/src/Wallet.js
CHANGED
|
@@ -283,11 +283,11 @@ export default class Wallet {
|
|
|
283
283
|
* Initializes the ML-KEM key pair
|
|
284
284
|
*/
|
|
285
285
|
initializeMLKEM () {
|
|
286
|
-
// Generate a 64-byte (512-bit) seed from the Knish.IO private key
|
|
286
|
+
// Generate a 64-byte (512-bit) seed from the Knish.IO private key
|
|
287
287
|
// Use deterministic approach: generateSecret(key, 128) → 128 hex chars = 64 bytes
|
|
288
|
-
const seedHex = generateSecret(this.key, 128)
|
|
288
|
+
const seedHex = generateSecret(this.key, 128) // 128 hex chars = 64 bytes
|
|
289
289
|
|
|
290
|
-
// Convert the hex string to a Uint8Array
|
|
290
|
+
// Convert the hex string to a Uint8Array
|
|
291
291
|
const seed = new Uint8Array(64)
|
|
292
292
|
for (let i = 0; i < 64; i++) {
|
|
293
293
|
seed[i] = parseInt(seedHex.substr(i * 2, 2), 16)
|
|
@@ -398,6 +398,47 @@ export default class Wallet {
|
|
|
398
398
|
remainderWallet.tokenUnits = remainderTokenUnits
|
|
399
399
|
}
|
|
400
400
|
|
|
401
|
+
/**
|
|
402
|
+
* Split token units across MULTIPLE recipients (WP line 544).
|
|
403
|
+
*
|
|
404
|
+
* The source retains the SENT union (all units leaving), each recipient gets its own subset,
|
|
405
|
+
* and the remainder gets the KEPT units (those not assigned to any recipient). Mirrors
|
|
406
|
+
* splitUnits() but N-way: the source's tokenUnits become the union (not a single recipient's
|
|
407
|
+
* subset) so the source atom carries the full SENT set the validator reads as the authority.
|
|
408
|
+
*
|
|
409
|
+
* @param {array[]} recipientUnitLists - array of unit-id arrays, parallel to recipientWallets
|
|
410
|
+
* @param {Wallet[]} recipientWallets
|
|
411
|
+
* @param {Wallet} remainderWallet
|
|
412
|
+
*/
|
|
413
|
+
splitUnitsMulti (
|
|
414
|
+
recipientUnitLists,
|
|
415
|
+
recipientWallets,
|
|
416
|
+
remainderWallet
|
|
417
|
+
) {
|
|
418
|
+
// The union of all unit ids leaving the source
|
|
419
|
+
const sentIds = new Set()
|
|
420
|
+
recipientUnitLists.forEach(unitList => {
|
|
421
|
+
unitList.forEach(id => sentIds.add(id))
|
|
422
|
+
})
|
|
423
|
+
|
|
424
|
+
// Nothing to split (fungible transfer) — leave token units untouched
|
|
425
|
+
if (sentIds.size === 0) {
|
|
426
|
+
return
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Each recipient gets its own subset of the source's token units
|
|
430
|
+
recipientWallets.forEach((recipientWallet, index) => {
|
|
431
|
+
const ids = recipientUnitLists[index]
|
|
432
|
+
recipientWallet.tokenUnits = this.tokenUnits.filter(tokenUnit => ids.includes(tokenUnit.id))
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
// The remainder keeps everything not sent to any recipient
|
|
436
|
+
remainderWallet.tokenUnits = this.tokenUnits.filter(tokenUnit => !sentIds.has(tokenUnit.id))
|
|
437
|
+
|
|
438
|
+
// The source carries the SENT union (the ownership authority the validator reads)
|
|
439
|
+
this.tokenUnits = this.tokenUnits.filter(tokenUnit => sentIds.has(tokenUnit.id))
|
|
440
|
+
}
|
|
441
|
+
|
|
401
442
|
/**
|
|
402
443
|
* Create a remainder wallet from the source one
|
|
403
444
|
*
|
|
@@ -454,6 +495,17 @@ export default class Wallet {
|
|
|
454
495
|
}
|
|
455
496
|
|
|
456
497
|
async decryptMessage (encryptedData) {
|
|
498
|
+
const decryptedString = await this._mlkemDecryptToString(encryptedData)
|
|
499
|
+
return decryptedString === null ? null : JSON.parse(decryptedString)
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* ML-KEM768 decapsulate + AES-256-GCM decrypt → the RAW decrypted UTF-8 string
|
|
504
|
+
* (no JSON.parse). Shared by {@link decryptMessage} (which JSON.parses the result)
|
|
505
|
+
* and the PQ CipherHash transport ({@link decryptMyMessageML768}, which needs the raw
|
|
506
|
+
* response JSON text). PQ-transport Phase E (cycle 163).
|
|
507
|
+
*/
|
|
508
|
+
async _mlkemDecryptToString (encryptedData) {
|
|
457
509
|
const { cipherText, encryptedMessage } = encryptedData
|
|
458
510
|
|
|
459
511
|
let sharedSecret
|
|
@@ -486,9 +538,8 @@ export default class Wallet {
|
|
|
486
538
|
return null
|
|
487
539
|
}
|
|
488
540
|
|
|
489
|
-
let decryptedString
|
|
490
541
|
try {
|
|
491
|
-
|
|
542
|
+
return new TextDecoder().decode(decryptedUint8)
|
|
492
543
|
} catch (e) {
|
|
493
544
|
console.warn('Wallet::decryptMessage() - Decoding failed', e)
|
|
494
545
|
console.info('Wallet::decryptMessage() - my public key', this.pubkey)
|
|
@@ -497,8 +548,40 @@ export default class Wallet {
|
|
|
497
548
|
console.info('Wallet::decryptMessage() - decrypted Uint8Array', decryptedUint8)
|
|
498
549
|
return null
|
|
499
550
|
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Multi-recipient map key for a public key: `Base64_standard(SHAKE256(pubkey_utf8, 8 bytes))`
|
|
555
|
+
* — matches the validator's `hash_share` and the other SDKs' `hashShare`/`shortHash`.
|
|
556
|
+
* `shake256(pubkey, 64)` = 64 bits = 8 bytes, hex; hex-decode → standard base64. PQ Phase E.
|
|
557
|
+
*/
|
|
558
|
+
hashShare (pubkey) {
|
|
559
|
+
const hex = shake256(pubkey, 64)
|
|
560
|
+
const bytes = Uint8Array.from(hex.match(/.{2}/g).map(b => parseInt(b, 16)))
|
|
561
|
+
return this.serializeKey(bytes)
|
|
562
|
+
}
|
|
500
563
|
|
|
501
|
-
|
|
564
|
+
/**
|
|
565
|
+
* Post-quantum (ML-KEM768) `CipherHash` request envelope: a stringified single-recipient
|
|
566
|
+
* map `{ "<hashShare(recipientPubkey)>": {cipherText, encryptedMessage} }` (object-valued,
|
|
567
|
+
* via {@link encryptMessage}). Matches the Rust validator's CipherHash handler. PQ Phase E.
|
|
568
|
+
*/
|
|
569
|
+
async encryptStringML768 (message, recipientPubkey) {
|
|
570
|
+
const envelope = await this.encryptMessage(message, recipientPubkey)
|
|
571
|
+
return JSON.stringify({ [this.hashShare(recipientPubkey)]: envelope })
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Decrypt a `CipherHash` response map addressed to THIS wallet's ML-KEM pubkey
|
|
576
|
+
* (`hashShare(this.pubkey)`) → the RAW decrypted GraphQL response JSON text (NOT JSON.parsed;
|
|
577
|
+
* it replaces the HTTP response body for the normal parser). `null` if no entry / decrypt fails.
|
|
578
|
+
*/
|
|
579
|
+
async decryptMyMessageML768 (map) {
|
|
580
|
+
const envelope = map[this.hashShare(this.pubkey)]
|
|
581
|
+
if (!envelope) {
|
|
582
|
+
return null
|
|
583
|
+
}
|
|
584
|
+
return this._mlkemDecryptToString(envelope)
|
|
502
585
|
}
|
|
503
586
|
|
|
504
587
|
async encryptWithSharedSecret (message, sharedSecret) {
|
package/src/index.js
CHANGED
|
@@ -91,7 +91,6 @@ import QueryMetaTypeViaAtom from './query/QueryMetaTypeViaAtom.js'
|
|
|
91
91
|
import QueryMetaTypeViaMolecule from './query/QueryMetaTypeViaMolecule.js'
|
|
92
92
|
import QueryPolicy from './query/QueryPolicy.js'
|
|
93
93
|
import QueryToken from './query/QueryToken.js'
|
|
94
|
-
import QueryUserActivity from './query/QueryUserActivity.js'
|
|
95
94
|
import QueryWalletBundle from './query/QueryWalletBundle.js'
|
|
96
95
|
import QueryWalletList from './query/QueryWalletList.js'
|
|
97
96
|
|
|
@@ -142,7 +141,6 @@ import ResponsePeering from './response/ResponsePeering.js'
|
|
|
142
141
|
import ResponsePolicy from './response/ResponsePolicy.js'
|
|
143
142
|
import ResponseProposeMolecule from './response/ResponseProposeMolecule.js'
|
|
144
143
|
import ResponseQueryActiveSession from './response/ResponseQueryActiveSession.js'
|
|
145
|
-
import ResponseQueryUserActivity from './response/ResponseQueryUserActivity.js'
|
|
146
144
|
import ResponseRequestAuthorization from './response/ResponseRequestAuthorization.js'
|
|
147
145
|
import ResponseRequestAuthorizationGuest from './response/ResponseRequestAuthorizationGuest.js'
|
|
148
146
|
import ResponseRequestTokens from './response/ResponseRequestTokens.js'
|
|
@@ -253,7 +251,6 @@ export {
|
|
|
253
251
|
QueryMetaTypeViaMolecule,
|
|
254
252
|
QueryPolicy,
|
|
255
253
|
QueryToken,
|
|
256
|
-
QueryUserActivity,
|
|
257
254
|
QueryWalletBundle,
|
|
258
255
|
QueryWalletList,
|
|
259
256
|
|
|
@@ -298,7 +295,6 @@ export {
|
|
|
298
295
|
ResponsePolicy,
|
|
299
296
|
ResponseProposeMolecule,
|
|
300
297
|
ResponseQueryActiveSession,
|
|
301
|
-
ResponseQueryUserActivity,
|
|
302
298
|
ResponseRequestAuthorization,
|
|
303
299
|
ResponseRequestAuthorizationGuest,
|
|
304
300
|
ResponseRequestTokens,
|
|
@@ -52,6 +52,7 @@ import { isNumeric } from '../../libraries/strings.js'
|
|
|
52
52
|
import { intersect } from '../../libraries/array.js'
|
|
53
53
|
import CodeException from '../../exception/CodeException.js'
|
|
54
54
|
|
|
55
|
+
/* eslint-disable accessor-pairs -- intentional setter-only fluent rule builder; values are read directly via __field, no getter needed */
|
|
55
56
|
export default class Callback {
|
|
56
57
|
/**
|
|
57
58
|
*
|
|
@@ -47,9 +47,7 @@ License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
49
|
export default class Meta {
|
|
50
|
-
constructor ({}) {
|
|
51
|
-
const args = arguments[0]
|
|
52
|
-
|
|
50
|
+
constructor (args = {}) {
|
|
53
51
|
for (const key in args) {
|
|
54
52
|
this[`__${ key }`] = args[key]
|
|
55
53
|
}
|
|
@@ -51,6 +51,7 @@ import Condition from './Condition.js'
|
|
|
51
51
|
import RuleArgumentException from './exception/RuleArgumentException.js'
|
|
52
52
|
import MetaMissingException from '../../exception/MetaMissingException.js'
|
|
53
53
|
|
|
54
|
+
/* eslint-disable accessor-pairs -- intentional setter-only fluent rule builder; values are read directly via __field, no getter needed */
|
|
54
55
|
export default class Rule {
|
|
55
56
|
/**
|
|
56
57
|
*
|
package/src/libraries/strings.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Hex from './Hex.js'
|
|
2
2
|
|
|
3
|
+
/* eslint-disable no-extend-native -- intentional guarded String.prototype polyfill (trim) + SDK camel/snake-case helpers relied on across the codebase */
|
|
3
4
|
if (!String.prototype.trim) {
|
|
4
5
|
String.prototype.trim = function () {
|
|
5
6
|
return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '')
|
|
@@ -7,6 +7,25 @@ import {
|
|
|
7
7
|
import { createClient as createWSClient } from 'graphql-ws'
|
|
8
8
|
import { pipe, map, subscribe } from 'wonka'
|
|
9
9
|
|
|
10
|
+
// PQ-transport Phase E (cycle 163): the post-quantum CipherHash wrapper query. The validator
|
|
11
|
+
// intercepts the `CipherHash` op, decrypts `$Hash`, executes the inner request, and returns the
|
|
12
|
+
// encrypted response in `{ data: { CipherHash: { hash } } }`.
|
|
13
|
+
const CIPHER_HASH_QUERY = 'query ( $Hash: String! ) { CipherHash ( Hash: $Hash ) { hash } }'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Light parse of a GraphQL request body's operation type + root field name, for the CipherHash
|
|
17
|
+
* bypass decision (no full GraphQL parse needed). Operation type = the first query/mutation/
|
|
18
|
+
* subscription keyword (default 'query' for an anonymous `{ ... }`); root field = the first
|
|
19
|
+
* identifier inside the top-level selection set.
|
|
20
|
+
*/
|
|
21
|
+
function parseOperation (query) {
|
|
22
|
+
const typeMatch = (query || '').match(/\b(query|mutation|subscription)\b/i)
|
|
23
|
+
const type = typeMatch ? typeMatch[1].toLowerCase() : 'query'
|
|
24
|
+
const braceIdx = (query || '').indexOf('{')
|
|
25
|
+
const nameMatch = braceIdx >= 0 ? query.slice(braceIdx + 1).match(/[A-Za-z_][A-Za-z0-9_]*/) : null
|
|
26
|
+
return { type, name: nameMatch ? nameMatch[0] : '' }
|
|
27
|
+
}
|
|
28
|
+
|
|
10
29
|
class UrqlClientWrapper {
|
|
11
30
|
constructor ({ serverUri, socket = null, encrypt = false }) {
|
|
12
31
|
this.$__client = this.createUrqlClient({ serverUri, socket, encrypt })
|
|
@@ -44,6 +63,10 @@ class UrqlClientWrapper {
|
|
|
44
63
|
return createClient({
|
|
45
64
|
url: serverUri,
|
|
46
65
|
exchanges,
|
|
66
|
+
// PQ-transport Phase E: when encryption is on, route fetch through the CipherHash
|
|
67
|
+
// wrapper (encrypt the request body to the validator's ML-KEM pubkey, decrypt the
|
|
68
|
+
// response). Undefined → urql uses the global fetch (plaintext).
|
|
69
|
+
...(encrypt ? { fetch: (input, init) => this.cipherFetch(input, init) } : {}),
|
|
47
70
|
fetchOptions: () => ({
|
|
48
71
|
headers: {
|
|
49
72
|
'X-Auth-Token': this.$__authToken
|
|
@@ -54,6 +77,71 @@ class UrqlClientWrapper {
|
|
|
54
77
|
})
|
|
55
78
|
}
|
|
56
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Whether an outgoing GraphQL request body should be wrapped in CipherHash. Bypass (plaintext):
|
|
82
|
+
* introspection `__schema`, `ContinuId`, the `AccessToken` mutation, and the U-isotope
|
|
83
|
+
* `ProposeMolecule` (auth bootstrap — the key exchange itself can't be encrypted). Mirrors the
|
|
84
|
+
* Kotlin/validator bypass set.
|
|
85
|
+
*/
|
|
86
|
+
shouldEncrypt (body) {
|
|
87
|
+
let parsed
|
|
88
|
+
try {
|
|
89
|
+
parsed = JSON.parse(body)
|
|
90
|
+
} catch (e) {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
const { type, name } = parseOperation(parsed.query)
|
|
94
|
+
if (type === 'query' && (name === '__schema' || name === 'ContinuId')) return false
|
|
95
|
+
if (type === 'mutation' && name === 'AccessToken') return false
|
|
96
|
+
if (type === 'mutation' && name === 'ProposeMolecule') {
|
|
97
|
+
const isotope = parsed.variables && parsed.variables.molecule &&
|
|
98
|
+
parsed.variables.molecule.atoms && parsed.variables.molecule.atoms[0] &&
|
|
99
|
+
parsed.variables.molecule.atoms[0].isotope
|
|
100
|
+
if (isotope === 'U') return false
|
|
101
|
+
}
|
|
102
|
+
return true
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Custom `fetch` that wraps a GraphQL request in the ML-KEM CipherHash envelope and decrypts the
|
|
107
|
+
* response (PQ-transport Phase E). Operates on the raw POST body (mirrors Kotlin's
|
|
108
|
+
* encryptBody/decryptBody). Reads the CURRENT client wallet + validator pubkey from auth.
|
|
109
|
+
*/
|
|
110
|
+
async cipherFetch (input, init) {
|
|
111
|
+
const wallet = this.getWallet()
|
|
112
|
+
const serverPubkey = this.getPubKey()
|
|
113
|
+
let encryptedRequest = false
|
|
114
|
+
let requestInit = init
|
|
115
|
+
|
|
116
|
+
if (wallet && serverPubkey && init && typeof init.body === 'string' && this.shouldEncrypt(init.body)) {
|
|
117
|
+
const hashVar = await wallet.encryptStringML768(init.body, serverPubkey)
|
|
118
|
+
requestInit = { ...init, body: JSON.stringify({ query: CIPHER_HASH_QUERY, variables: { Hash: hashVar } }) }
|
|
119
|
+
encryptedRequest = true
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const response = await fetch(input, requestInit)
|
|
123
|
+
if (!encryptedRequest) {
|
|
124
|
+
return response
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Decrypt the CipherHash response back to the inner GraphQL response JSON.
|
|
128
|
+
const text = await response.text()
|
|
129
|
+
const init2 = { status: response.status, statusText: response.statusText, headers: response.headers }
|
|
130
|
+
let parsed
|
|
131
|
+
try {
|
|
132
|
+
parsed = JSON.parse(text)
|
|
133
|
+
} catch (e) {
|
|
134
|
+
return new Response(text, init2)
|
|
135
|
+
}
|
|
136
|
+
const hash = parsed && parsed.data && parsed.data.CipherHash && parsed.data.CipherHash.hash
|
|
137
|
+
if (typeof hash !== 'string') {
|
|
138
|
+
// Plaintext (e.g. a validator-side error response) — pass through unchanged.
|
|
139
|
+
return new Response(text, init2)
|
|
140
|
+
}
|
|
141
|
+
const decrypted = await wallet.decryptMyMessageML768(JSON.parse(hash))
|
|
142
|
+
return new Response(decrypted != null ? decrypted : text, init2)
|
|
143
|
+
}
|
|
144
|
+
|
|
57
145
|
setAuthData ({ token, pubkey, wallet }) {
|
|
58
146
|
this.$__authToken = token
|
|
59
147
|
this.$__pubkey = pubkey
|
|
@@ -67,24 +155,55 @@ class UrqlClientWrapper {
|
|
|
67
155
|
})
|
|
68
156
|
}
|
|
69
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Builds the urql operation options forwarded with a query/mutation.
|
|
160
|
+
*
|
|
161
|
+
* Forwards the requestPolicy (so a long-lived client does not serve stale
|
|
162
|
+
* cache-first reads) and, when the caller supplied a per-query abort signal,
|
|
163
|
+
* the signal too — while re-supplying the X-Auth-Token header. urql REPLACES
|
|
164
|
+
* (not merges) the client-level fetchOptions with any operation-context
|
|
165
|
+
* fetchOptions (createRequestOperation builds the op context as
|
|
166
|
+
* {...baseOpts, ...opts}), so forwarding fetchOptions WITHOUT the header would
|
|
167
|
+
* drop X-Auth-Token and break auth. The header here is byte-identical to the
|
|
168
|
+
* client-level one set in createUrqlClient.
|
|
169
|
+
*
|
|
170
|
+
* @param {object} context
|
|
171
|
+
* @returns {object|undefined}
|
|
172
|
+
*/
|
|
173
|
+
buildRequestOptions (context) {
|
|
174
|
+
if (!context) {
|
|
175
|
+
return undefined
|
|
176
|
+
}
|
|
177
|
+
const opts = {}
|
|
178
|
+
if (context.requestPolicy) {
|
|
179
|
+
opts.requestPolicy = context.requestPolicy
|
|
180
|
+
}
|
|
181
|
+
const callerSignal = context.fetchOptions && context.fetchOptions.signal
|
|
182
|
+
if (callerSignal) {
|
|
183
|
+
// Combine the per-query abort signal with the 60s timeout so either can
|
|
184
|
+
// cancel the request; fall back to the caller signal where AbortSignal.any
|
|
185
|
+
// is unavailable.
|
|
186
|
+
const signal = (typeof AbortSignal !== 'undefined' && typeof AbortSignal.any === 'function')
|
|
187
|
+
? AbortSignal.any([callerSignal, AbortSignal.timeout(60000)])
|
|
188
|
+
: callerSignal
|
|
189
|
+
opts.fetchOptions = {
|
|
190
|
+
headers: { 'X-Auth-Token': this.$__authToken },
|
|
191
|
+
signal
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return Object.keys(opts).length ? opts : undefined
|
|
195
|
+
}
|
|
196
|
+
|
|
70
197
|
async query (request) {
|
|
71
198
|
const { query, variables, context } = request
|
|
72
|
-
|
|
73
|
-
// client does not serve stale cache-first reads. We deliberately do NOT
|
|
74
|
-
// forward the whole context: urql REPLACES (not merges) the client-level
|
|
75
|
-
// fetchOptions with any context.fetchOptions (createRequestOperation builds
|
|
76
|
-
// the op context as {...baseOpts, ...opts}), which would drop the
|
|
77
|
-
// X-Auth-Token header set in createUrqlClient and break authentication.
|
|
78
|
-
const opts = (context && context.requestPolicy) ? { requestPolicy: context.requestPolicy } : undefined
|
|
199
|
+
const opts = this.buildRequestOptions(context)
|
|
79
200
|
const result = await this.$__client.query(query, variables || {}, opts).toPromise()
|
|
80
201
|
return this.formatResponse(result)
|
|
81
202
|
}
|
|
82
203
|
|
|
83
204
|
async mutate (request) {
|
|
84
205
|
const { mutation, variables, context } = request
|
|
85
|
-
|
|
86
|
-
// would clobber the auth-bearing client-level fetchOptions).
|
|
87
|
-
const opts = (context && context.requestPolicy) ? { requestPolicy: context.requestPolicy } : undefined
|
|
206
|
+
const opts = this.buildRequestOptions(context)
|
|
88
207
|
const result = await this.$__client.mutation(mutation, variables || {}, opts).toPromise()
|
|
89
208
|
return this.formatResponse(result)
|
|
90
209
|
}
|
|
@@ -70,6 +70,24 @@ export default class MutationTransferTokens extends MutationProposeMolecule {
|
|
|
70
70
|
this.$__molecule.check(this.$__molecule.sourceWallet)
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Fills the Molecule for a MULTI-recipient transfer (WP line 544)
|
|
75
|
+
*
|
|
76
|
+
* @param {Wallet[]} recipientWallets
|
|
77
|
+
* @param {number[]} amounts - parallel to recipientWallets
|
|
78
|
+
*/
|
|
79
|
+
fillMoleculeMulti ({
|
|
80
|
+
recipientWallets,
|
|
81
|
+
amounts
|
|
82
|
+
}) {
|
|
83
|
+
this.$__molecule.initValues({
|
|
84
|
+
recipientWallets,
|
|
85
|
+
amounts
|
|
86
|
+
})
|
|
87
|
+
this.$__molecule.sign({})
|
|
88
|
+
this.$__molecule.check(this.$__molecule.sourceWallet)
|
|
89
|
+
}
|
|
90
|
+
|
|
73
91
|
/**
|
|
74
92
|
* Builds a Response object out of a JSON string
|
|
75
93
|
*
|
package/src/query/QueryPolicy.js
CHANGED
|
@@ -48,7 +48,7 @@ License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
|
48
48
|
|
|
49
49
|
import Query from './Query.js'
|
|
50
50
|
import ResponsePolicy from '../response/ResponsePolicy.js'
|
|
51
|
-
import { gql } from
|
|
51
|
+
import { gql } from '@urql/core'
|
|
52
52
|
|
|
53
53
|
export default class QueryPolicy extends Query {
|
|
54
54
|
/**
|
package/src/response/Response.js
CHANGED
|
@@ -176,7 +176,7 @@ export default class Response {
|
|
|
176
176
|
/**
|
|
177
177
|
* Enhanced interface methods for standardized response handling
|
|
178
178
|
*/
|
|
179
|
-
|
|
179
|
+
|
|
180
180
|
/**
|
|
181
181
|
* Get error reason (alias for error() to match standardized interface)
|
|
182
182
|
* @return {string|null}
|
|
@@ -247,7 +247,7 @@ export default class Response {
|
|
|
247
247
|
*/
|
|
248
248
|
debug (label = null) {
|
|
249
249
|
const debugPrefix = label ? `[${label}]` : `[${this.constructor.name}]`
|
|
250
|
-
|
|
250
|
+
|
|
251
251
|
if (this.success()) {
|
|
252
252
|
console.debug(`${debugPrefix} Success:`, {
|
|
253
253
|
payload: this.payload(),
|
|
@@ -261,7 +261,7 @@ export default class Response {
|
|
|
261
261
|
rawData: this.$__response
|
|
262
262
|
})
|
|
263
263
|
}
|
|
264
|
-
|
|
264
|
+
|
|
265
265
|
return this
|
|
266
266
|
}
|
|
267
267
|
|
|
@@ -46,7 +46,6 @@ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
|
|
|
46
46
|
License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
|
-
import Query from '../query/Query.js'
|
|
50
49
|
import Response from './Response.js'
|
|
51
50
|
|
|
52
51
|
export default class ResponseActiveSession extends Response {
|
|
@@ -46,7 +46,6 @@ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
|
|
|
46
46
|
License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
|
-
import Query from '../query/Query.js'
|
|
50
49
|
import Response from './Response.js'
|
|
51
50
|
import Dot from '../libraries/Dot.js'
|
|
52
51
|
import InvalidResponseException from '../exception/InvalidResponseException.js'
|
|
@@ -45,7 +45,6 @@ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
|
|
|
45
45
|
|
|
46
46
|
License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
47
47
|
*/
|
|
48
|
-
import Query from '../query/Query.js'
|
|
49
48
|
import Response from './Response.js'
|
|
50
49
|
import ResponseWalletList from './ResponseWalletList.js'
|
|
51
50
|
|
|
@@ -45,7 +45,6 @@ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
|
|
|
45
45
|
|
|
46
46
|
License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
47
47
|
*/
|
|
48
|
-
import Query from '../query/Query.js'
|
|
49
48
|
import Response from './Response.js'
|
|
50
49
|
import Wallet from '../Wallet.js'
|
|
51
50
|
|
|
@@ -45,7 +45,6 @@ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
|
|
|
45
45
|
|
|
46
46
|
License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
47
47
|
*/
|
|
48
|
-
import Query from '../query/Query.js'
|
|
49
48
|
import Response from './Response.js'
|
|
50
49
|
import Dot from '../libraries/Dot.js'
|
|
51
50
|
|
|
@@ -46,7 +46,6 @@ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
|
|
|
46
46
|
License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
|
-
import Query from '../query/Query.js'
|
|
50
49
|
import Response from './Response.js'
|
|
51
50
|
|
|
52
51
|
export default class ResponseMetaTypeViaAtom extends Response {
|
|
@@ -46,7 +46,6 @@ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
|
|
|
46
46
|
License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
|
-
import Query from '../query/Query.js'
|
|
50
49
|
import Response from './Response.js'
|
|
51
50
|
import CheckMolecule from '../libraries/CheckMolecule.js'
|
|
52
51
|
|
|
@@ -46,7 +46,6 @@ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
|
|
|
46
46
|
License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
|
-
import Query from '../query/Query.js'
|
|
50
49
|
import Response from './Response.js'
|
|
51
50
|
|
|
52
51
|
export default class ResponsePolicy extends Response {
|
|
@@ -45,7 +45,6 @@ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
|
|
|
45
45
|
|
|
46
46
|
License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
47
47
|
*/
|
|
48
|
-
import Query from '../query/Query.js'
|
|
49
48
|
import Response from './Response.js'
|
|
50
49
|
import Meta from '../Meta.js'
|
|
51
50
|
|
|
@@ -45,7 +45,6 @@ Please visit https://github.com/WishKnish/KnishIO-Client-JS for information.
|
|
|
45
45
|
|
|
46
46
|
License: https://github.com/WishKnish/KnishIO-Client-JS/blob/master/LICENSE
|
|
47
47
|
*/
|
|
48
|
-
import Query from '../query/Query.js'
|
|
49
48
|
import Response from './Response.js'
|
|
50
49
|
import Wallet from '../Wallet.js'
|
|
51
50
|
import TokenUnit from '../TokenUnit.js'
|