@joeywallet/wallet-sdk 0.2.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/LICENSE +21 -0
- package/README.md +705 -0
- package/dist/client.d.ts +55 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +224 -0
- package/dist/client.js.map +1 -0
- package/dist/detect.d.ts +45 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +238 -0
- package/dist/detect.js.map +1 -0
- package/dist/errors.d.ts +75 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +120 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/mutation.d.ts +46 -0
- package/dist/mutation.d.ts.map +1 -0
- package/dist/mutation.js +67 -0
- package/dist/mutation.js.map +1 -0
- package/dist/provider.d.ts +159 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +142 -0
- package/dist/provider.js.map +1 -0
- package/dist/react.d.ts +76 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +225 -0
- package/dist/react.js.map +1 -0
- package/dist/types.d.ts +391 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +38 -0
- package/dist/types.js.map +1 -0
- package/dist/vanilla.d.ts +58 -0
- package/dist/vanilla.d.ts.map +1 -0
- package/dist/vanilla.js +161 -0
- package/dist/vanilla.js.map +1 -0
- package/package.json +70 -0
- package/src/client.ts +342 -0
- package/src/detect.ts +278 -0
- package/src/errors.ts +133 -0
- package/src/index.ts +97 -0
- package/src/mutation.ts +109 -0
- package/src/provider.ts +229 -0
- package/src/react.ts +375 -0
- package/src/types.ts +440 -0
- package/src/vanilla.ts +239 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vanilla.js","sourceRoot":"","sources":["../src/vanilla.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@joeywallet/wallet-sdk",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Dependency-free TypeScript SDK for the Joey Wallet browser extension (XLS-72d / Wallet Standard).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/Joey-Wallet/joey-wallet-sdk#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Joey-Wallet/joey-wallet-sdk.git",
|
|
10
|
+
"directory": "packages/sdk"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Joey-Wallet/joey-wallet-sdk/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"sideEffects": false,
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./react": {
|
|
25
|
+
"types": "./dist/react.d.ts",
|
|
26
|
+
"import": "./dist/react.js"
|
|
27
|
+
},
|
|
28
|
+
"./vanilla": {
|
|
29
|
+
"types": "./dist/vanilla.d.ts",
|
|
30
|
+
"import": "./dist/vanilla.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"src",
|
|
36
|
+
"LICENSE",
|
|
37
|
+
"README.md"
|
|
38
|
+
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"react": ">=18"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"react": {
|
|
50
|
+
"optional": true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/react": "19.0.2",
|
|
55
|
+
"react": "19.0.0",
|
|
56
|
+
"typescript": "5.7.2",
|
|
57
|
+
"xrpl": "4.2.5"
|
|
58
|
+
},
|
|
59
|
+
"keywords": [
|
|
60
|
+
"xrpl",
|
|
61
|
+
"wallet",
|
|
62
|
+
"joey",
|
|
63
|
+
"xls-72d",
|
|
64
|
+
"wallet-standard"
|
|
65
|
+
],
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "tsc -p tsconfig.json",
|
|
68
|
+
"ts:check": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json"
|
|
69
|
+
}
|
|
70
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The typed API a dapp actually calls.
|
|
3
|
+
*
|
|
4
|
+
* Every method resolves a value or rejects with a {@link JoeyRpcError}. There is
|
|
5
|
+
* deliberately no `{ type, result }` envelope: an envelope forces a branch at
|
|
6
|
+
* every call site, and a promise rejection is what a JS developer already writes
|
|
7
|
+
* `try`/`catch` around.
|
|
8
|
+
*
|
|
9
|
+
* Event payloads are normalised here rather than passed through raw. The
|
|
10
|
+
* provider forwards whatever the background sent, which is the right choice for
|
|
11
|
+
* a protocol layer and the wrong one for a dapp — a listener should not have to
|
|
12
|
+
* guess whether `accountsChanged` carried an array, an object with an
|
|
13
|
+
* `accounts` key, or a list of bare address strings.
|
|
14
|
+
*/
|
|
15
|
+
import { JOEY_ERROR_CODES, JoeyRpcError } from './errors.js'
|
|
16
|
+
import {
|
|
17
|
+
JOEY_RPC_METHODS,
|
|
18
|
+
invoke,
|
|
19
|
+
subscribe,
|
|
20
|
+
type JoeyInjectedProvider,
|
|
21
|
+
type JoeyProviderEventName,
|
|
22
|
+
type JoeyRequestArguments,
|
|
23
|
+
type JoeyRpcMethod,
|
|
24
|
+
} from './provider.js'
|
|
25
|
+
import {
|
|
26
|
+
isJoeyChain,
|
|
27
|
+
networkIdForChain,
|
|
28
|
+
type AnyTransaction,
|
|
29
|
+
type ConnectParams,
|
|
30
|
+
type ConnectResult,
|
|
31
|
+
type JoeyAccount,
|
|
32
|
+
type JoeyChain,
|
|
33
|
+
type JoeyEventListener,
|
|
34
|
+
type JoeyEventName,
|
|
35
|
+
type JoeyNetwork,
|
|
36
|
+
type SignAndSubmitTransactionResult,
|
|
37
|
+
type SignInParams,
|
|
38
|
+
type SignInResult,
|
|
39
|
+
type SignTransactionBulkParams,
|
|
40
|
+
type SignTransactionForParams,
|
|
41
|
+
type SignTransactionParams,
|
|
42
|
+
type SignTransactionResult,
|
|
43
|
+
type TransactionLike,
|
|
44
|
+
} from './types.js'
|
|
45
|
+
|
|
46
|
+
export interface Joey {
|
|
47
|
+
/** The raw injected object, for anything this SDK version does not model. */
|
|
48
|
+
readonly provider: JoeyInjectedProvider
|
|
49
|
+
/** Version of the injected surface, when the provider reports one. */
|
|
50
|
+
readonly version: string | undefined
|
|
51
|
+
/** Reverse-DNS identity, `xyz.joeywallet`. */
|
|
52
|
+
readonly rdns: string | undefined
|
|
53
|
+
/** Granted addresses, read synchronously. `[]` until the user connects. */
|
|
54
|
+
readonly accounts: readonly string[]
|
|
55
|
+
/** The chain the wallet is on, or `null` before the first connect. */
|
|
56
|
+
readonly chain: JoeyChain | null
|
|
57
|
+
|
|
58
|
+
/** Synchronous. True once the user has granted this origin an account. */
|
|
59
|
+
isConnected(): boolean
|
|
60
|
+
|
|
61
|
+
connect(params?: ConnectParams): Promise<ConnectResult>
|
|
62
|
+
disconnect(): Promise<void>
|
|
63
|
+
/** Granted addresses. `[]` for an origin with no grant — never an error. */
|
|
64
|
+
getAccounts(): Promise<string[]>
|
|
65
|
+
getNetwork(): Promise<JoeyNetwork>
|
|
66
|
+
|
|
67
|
+
signTransaction<TTx extends TransactionLike = AnyTransaction>(
|
|
68
|
+
params: SignTransactionParams<TTx>,
|
|
69
|
+
): Promise<SignTransactionResult>
|
|
70
|
+
|
|
71
|
+
signAndSubmitTransaction<TTx extends TransactionLike = AnyTransaction>(
|
|
72
|
+
params: SignTransactionParams<TTx>,
|
|
73
|
+
): Promise<SignAndSubmitTransactionResult>
|
|
74
|
+
|
|
75
|
+
/** Add one signature to a multisigned transaction. */
|
|
76
|
+
signTransactionFor<TTx extends TransactionLike = AnyTransaction>(
|
|
77
|
+
params: SignTransactionForParams<TTx>,
|
|
78
|
+
): Promise<SignTransactionResult>
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* One approval, up to `MAX_BULK_TRANSACTIONS` transactions, signed in order.
|
|
82
|
+
*
|
|
83
|
+
* Resolves with one entry per transaction, in the order you sent them.
|
|
84
|
+
* `engine_result` is present only when you asked for `submit: true` — with
|
|
85
|
+
* `submit: false` nothing is broadcast, so there is no engine result to give.
|
|
86
|
+
*
|
|
87
|
+
* A batch that fails part way *rejects*, and the error's `data` is a
|
|
88
|
+
* {@link SignTransactionBulkFailure} carrying every signed blob and which
|
|
89
|
+
* index stopped it. Read that rather than re-prompting the user.
|
|
90
|
+
*/
|
|
91
|
+
signTransactionBulk<TTx extends TransactionLike = AnyTransaction>(
|
|
92
|
+
params: SignTransactionBulkParams<TTx>,
|
|
93
|
+
): Promise<SignAndSubmitTransactionResult[]>
|
|
94
|
+
|
|
95
|
+
signIn(params?: SignInParams): Promise<SignInResult>
|
|
96
|
+
|
|
97
|
+
/** Escape hatch for a method the wallet added after this SDK was published. */
|
|
98
|
+
request<TResult = unknown>(args: JoeyRequestArguments): Promise<TResult>
|
|
99
|
+
|
|
100
|
+
on<K extends JoeyEventName>(event: K, listener: JoeyEventListener<K>): () => void
|
|
101
|
+
off<K extends JoeyEventName>(event: K, listener: JoeyEventListener<K>): void
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* --------------------------------------------------------------- normalising */
|
|
105
|
+
|
|
106
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
107
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Read an account list out of whatever the wallet sent.
|
|
112
|
+
*
|
|
113
|
+
* Accepts a bare array, `{ accounts: [...] }`, and entries that are either
|
|
114
|
+
* address strings or objects — the shapes the provider and the background
|
|
115
|
+
* between them can produce.
|
|
116
|
+
*/
|
|
117
|
+
export function readAccounts(value: unknown): JoeyAccount[] {
|
|
118
|
+
const source = Array.isArray(value) ? value : isRecord(value) ? value.accounts : undefined
|
|
119
|
+
if (!Array.isArray(source)) return []
|
|
120
|
+
|
|
121
|
+
const out: JoeyAccount[] = []
|
|
122
|
+
for (const entry of source) {
|
|
123
|
+
if (typeof entry === 'string') {
|
|
124
|
+
out.push({ address: entry })
|
|
125
|
+
continue
|
|
126
|
+
}
|
|
127
|
+
if (!isRecord(entry) || typeof entry.address !== 'string') continue
|
|
128
|
+
const account: JoeyAccount = { address: entry.address }
|
|
129
|
+
if (typeof entry.publicKey === 'string') account.publicKey = entry.publicKey
|
|
130
|
+
if (typeof entry.label === 'string') account.label = entry.label
|
|
131
|
+
out.push(account)
|
|
132
|
+
}
|
|
133
|
+
return out
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function readChain(value: unknown): JoeyChain | null {
|
|
137
|
+
if (isJoeyChain(value)) return value
|
|
138
|
+
if (!isRecord(value)) return null
|
|
139
|
+
return isJoeyChain(value.chain) ? value.chain : null
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function readNetwork(value: unknown): JoeyNetwork | null {
|
|
143
|
+
const chain = readChain(value)
|
|
144
|
+
if (chain === null) return null
|
|
145
|
+
const record = isRecord(value) ? value : {}
|
|
146
|
+
return {
|
|
147
|
+
chain,
|
|
148
|
+
networkId:
|
|
149
|
+
typeof record.networkId === 'number' ? record.networkId : (networkIdForChain(chain) ?? 0),
|
|
150
|
+
name: typeof record.name === 'string' ? record.name : chain,
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* -------------------------------------------------------------------- client */
|
|
155
|
+
|
|
156
|
+
/** Wrap a raw injected provider in the typed API. */
|
|
157
|
+
export function createJoeyClient(provider: JoeyInjectedProvider): Joey {
|
|
158
|
+
/**
|
|
159
|
+
* Unsubscribe functions, keyed by the exact listener the caller handed us.
|
|
160
|
+
*
|
|
161
|
+
* Needed because the SDK subscribes a *wrapper* that normalises the payload,
|
|
162
|
+
* so the provider never sees the caller's own function.
|
|
163
|
+
*
|
|
164
|
+
* The value is a stack, not a single function, because a listener may be
|
|
165
|
+
* registered more than once and each registration is a separate subscription
|
|
166
|
+
* on the provider. Storing one function per listener silently dropped the
|
|
167
|
+
* earlier registration's unsubscriber: `off()` then removed the newest, the
|
|
168
|
+
* oldest kept firing, and nothing the dapp could call would ever remove it.
|
|
169
|
+
* A React effect that re-subscribes on a dependency change and unsubscribes
|
|
170
|
+
* on cleanup does exactly this, in that order, on every render — so the leak
|
|
171
|
+
* compounds. Each `off()` removes one registration, newest first, which is
|
|
172
|
+
* what `addEventListener`-shaped APIs do.
|
|
173
|
+
*/
|
|
174
|
+
const unsubscribers = new Map<JoeyEventName, Map<unknown, Array<() => void>>>()
|
|
175
|
+
|
|
176
|
+
const call = async <TResult>(method: JoeyRpcMethod, params?: unknown): Promise<TResult> => {
|
|
177
|
+
try {
|
|
178
|
+
return await invoke<TResult>(provider, method, params)
|
|
179
|
+
} catch (cause) {
|
|
180
|
+
throw JoeyRpcError.from(cause)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Drop one specific registration, wherever it sits in the stack. */
|
|
185
|
+
const release = (
|
|
186
|
+
event: JoeyEventName,
|
|
187
|
+
listener: unknown,
|
|
188
|
+
unsubscribe: () => void,
|
|
189
|
+
): void => {
|
|
190
|
+
const forEvent = unsubscribers.get(event)
|
|
191
|
+
const stack = forEvent?.get(listener)
|
|
192
|
+
if (stack === undefined) return
|
|
193
|
+
const at = stack.lastIndexOf(unsubscribe)
|
|
194
|
+
if (at === -1) return
|
|
195
|
+
stack.splice(at, 1)
|
|
196
|
+
if (stack.length === 0) forEvent?.delete(listener)
|
|
197
|
+
unsubscribe()
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const normalise: {
|
|
201
|
+
[K in JoeyEventName]: (payload: unknown) => Parameters<JoeyEventListener<K>>[0]
|
|
202
|
+
} = {
|
|
203
|
+
connect: (payload) => ({ accounts: readAccounts(payload), chain: readChain(payload) }),
|
|
204
|
+
disconnect: (payload) =>
|
|
205
|
+
isRecord(payload) && typeof payload.reason === 'string' ? { reason: payload.reason } : {},
|
|
206
|
+
accountsChanged: (payload) => readAccounts(payload),
|
|
207
|
+
networkChanged: (payload) => readNetwork(payload),
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const client: Joey = {
|
|
211
|
+
provider,
|
|
212
|
+
version: typeof provider.version === 'string' ? provider.version : undefined,
|
|
213
|
+
rdns: typeof provider.rdns === 'string' ? provider.rdns : undefined,
|
|
214
|
+
|
|
215
|
+
get accounts() {
|
|
216
|
+
return provider.accounts ?? []
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
get chain() {
|
|
220
|
+
return provider.chain ?? null
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
isConnected() {
|
|
224
|
+
if (typeof provider.isConnected === 'function') return provider.isConnected()
|
|
225
|
+
return (provider.accounts ?? []).length > 0
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
async connect(params) {
|
|
229
|
+
const result = await call<unknown>(JOEY_RPC_METHODS.connect, params ?? {})
|
|
230
|
+
const record = isRecord(result) ? result : {}
|
|
231
|
+
const chain = readChain(record)
|
|
232
|
+
return {
|
|
233
|
+
accounts: readAccounts(record),
|
|
234
|
+
chain,
|
|
235
|
+
networkId:
|
|
236
|
+
typeof record.networkId === 'number'
|
|
237
|
+
? record.networkId
|
|
238
|
+
: chain === null
|
|
239
|
+
? null
|
|
240
|
+
: networkIdForChain(chain),
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
async disconnect() {
|
|
245
|
+
await call<unknown>(JOEY_RPC_METHODS.disconnect, {})
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
async getAccounts() {
|
|
249
|
+
const result = await call<unknown>(JOEY_RPC_METHODS.getAccounts, {})
|
|
250
|
+
// The provider answers with bare addresses; the background may answer with
|
|
251
|
+
// account objects. Both collapse to addresses here.
|
|
252
|
+
return readAccounts(result).map((account) => account.address)
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
async getNetwork() {
|
|
256
|
+
const result = await call<unknown>(JOEY_RPC_METHODS.getNetwork, {})
|
|
257
|
+
const network = readNetwork(result)
|
|
258
|
+
if (network === null) {
|
|
259
|
+
throw new JoeyRpcError(
|
|
260
|
+
JOEY_ERROR_CODES.UNRECOGNIZED_CHAIN,
|
|
261
|
+
'The wallet reported a chain this SDK does not recognise.',
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
return network
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
signTransaction(params) {
|
|
268
|
+
return call<SignTransactionResult>(JOEY_RPC_METHODS.signTransaction, params)
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
signAndSubmitTransaction(params) {
|
|
272
|
+
return call<SignAndSubmitTransactionResult>(
|
|
273
|
+
JOEY_RPC_METHODS.signAndSubmitTransaction,
|
|
274
|
+
params,
|
|
275
|
+
)
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
signTransactionFor(params) {
|
|
279
|
+
return call<SignTransactionResult>(JOEY_RPC_METHODS.signTransactionFor, params)
|
|
280
|
+
},
|
|
281
|
+
|
|
282
|
+
signTransactionBulk(params) {
|
|
283
|
+
return call<SignAndSubmitTransactionResult[]>(
|
|
284
|
+
JOEY_RPC_METHODS.signTransactionBulk,
|
|
285
|
+
params,
|
|
286
|
+
)
|
|
287
|
+
},
|
|
288
|
+
|
|
289
|
+
signIn(params) {
|
|
290
|
+
return call<SignInResult>(JOEY_RPC_METHODS.signIn, params ?? {})
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
async request(args) {
|
|
294
|
+
try {
|
|
295
|
+
return await provider.request(args)
|
|
296
|
+
} catch (cause) {
|
|
297
|
+
throw JoeyRpcError.from(cause)
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
on(event, listener) {
|
|
302
|
+
const wrapped = (payload: unknown): void => {
|
|
303
|
+
;(listener as (value: unknown) => void)(normalise[event](payload))
|
|
304
|
+
}
|
|
305
|
+
const unsubscribe = subscribe(
|
|
306
|
+
provider,
|
|
307
|
+
event as JoeyProviderEventName,
|
|
308
|
+
wrapped as (payload: never) => void,
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
let forEvent = unsubscribers.get(event)
|
|
312
|
+
if (forEvent === undefined) {
|
|
313
|
+
forEvent = new Map()
|
|
314
|
+
unsubscribers.set(event, forEvent)
|
|
315
|
+
}
|
|
316
|
+
const stack = forEvent.get(listener)
|
|
317
|
+
if (stack === undefined) forEvent.set(listener, [unsubscribe])
|
|
318
|
+
else stack.push(unsubscribe)
|
|
319
|
+
|
|
320
|
+
// The returned function removes *this* registration, once. Calling it
|
|
321
|
+
// twice must not take a sibling registration down with it.
|
|
322
|
+
let released = false
|
|
323
|
+
return () => {
|
|
324
|
+
if (released) return
|
|
325
|
+
released = true
|
|
326
|
+
release(event, listener, unsubscribe)
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
off(event, listener) {
|
|
331
|
+
const stack = unsubscribers.get(event)?.get(listener)
|
|
332
|
+
const unsubscribe = stack?.pop()
|
|
333
|
+
if (unsubscribe === undefined) return
|
|
334
|
+
unsubscribe()
|
|
335
|
+
if (stack !== undefined && stack.length === 0) {
|
|
336
|
+
unsubscribers.get(event)?.delete(listener)
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return Object.freeze(client)
|
|
342
|
+
}
|