@keetanetwork/anchor 0.0.2 → 0.0.5

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 (45) hide show
  1. package/client/index.d.ts +6 -0
  2. package/client/index.d.ts.map +1 -1
  3. package/client/index.js +7 -0
  4. package/client/index.js.map +1 -1
  5. package/lib/error.d.ts +14 -0
  6. package/lib/error.d.ts.map +1 -0
  7. package/lib/error.js +38 -0
  8. package/lib/error.js.map +1 -0
  9. package/lib/resolver.d.ts +159 -60
  10. package/lib/resolver.d.ts.map +1 -1
  11. package/lib/resolver.js +3519 -384
  12. package/lib/resolver.js.map +1 -1
  13. package/lib/utils/brand.d.ts +12 -0
  14. package/lib/utils/brand.d.ts.map +1 -0
  15. package/lib/utils/brand.js +2 -0
  16. package/lib/utils/brand.js.map +1 -0
  17. package/lib/utils/never.d.ts +4 -0
  18. package/lib/utils/never.d.ts.map +1 -1
  19. package/lib/utils/never.js.map +1 -1
  20. package/lib/utils/signing.d.ts +17 -0
  21. package/lib/utils/signing.d.ts.map +1 -0
  22. package/lib/utils/signing.js +73 -0
  23. package/lib/utils/signing.js.map +1 -0
  24. package/lib/utils/url.d.ts +2 -0
  25. package/lib/utils/url.d.ts.map +1 -0
  26. package/lib/utils/url.js +8 -0
  27. package/lib/utils/url.js.map +1 -0
  28. package/npm-shrinkwrap.json +21 -14
  29. package/package.json +6 -4
  30. package/services/fx/client.d.ts +137 -0
  31. package/services/fx/client.d.ts.map +1 -0
  32. package/services/fx/client.js +519 -0
  33. package/services/fx/client.js.map +1 -0
  34. package/services/fx/common.d.ts +133 -0
  35. package/services/fx/common.d.ts.map +1 -0
  36. package/services/fx/common.js +45 -0
  37. package/services/fx/common.js.map +1 -0
  38. package/services/fx/server.d.ts +77 -0
  39. package/services/fx/server.d.ts.map +1 -0
  40. package/services/fx/server.js +693 -0
  41. package/services/fx/server.js.map +1 -0
  42. package/services/kyc/client.d.ts +1 -1
  43. package/services/kyc/client.d.ts.map +1 -1
  44. package/services/kyc/client.js +7 -53
  45. package/services/kyc/client.js.map +1 -1
@@ -0,0 +1,519 @@
1
+ import * as __typia_transform__assertGuard from "typia/lib/internal/_assertGuard.js";
2
+ import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';
3
+ import { createAssert, createIs } from 'typia';
4
+ import { Decimal } from 'decimal.js';
5
+ import { getDefaultResolver } from '../../config.js';
6
+ import { Buffer } from '../../lib/utils/buffer.js';
7
+ import crypto from '../../lib/utils/crypto.js';
8
+ import { validateURL } from '../../lib/utils/url.js';
9
+ import { createSwapRequest } from './common.js';
10
+ import { KeetaAnchorUserError } from '../../lib/error.js';
11
+ function typedFxServiceEntries(obj) {
12
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
13
+ return Object.entries(obj);
14
+ }
15
+ const KeetaFXAnchorClientAccessToken = Symbol('KeetaFXAnchorClientAccessToken');
16
+ const assertKeetaNetTokenPublicKeyString = (() => { const __is = input => "string" === typeof input && (RegExp(/^keeta_am(.*)/).test(input) || RegExp(/^keeta_an(.*)/).test(input) || RegExp(/^keeta_ao(.*)/).test(input) || RegExp(/^keeta_ap(.*)/).test(input) || RegExp(/^tyblocks_am(.*)/).test(input) || RegExp(/^tyblocks_an(.*)/).test(input) || RegExp(/^tyblocks_ao(.*)/).test(input) || RegExp(/^tyblocks_ap(.*)/).test(input)); let _errorFactory; return (input, errorFactory) => {
17
+ if (false === __is(input)) {
18
+ _errorFactory = errorFactory;
19
+ ((input, _path, _exceptionable = true) => "string" === typeof input && (RegExp(/^keeta_am(.*)/).test(input) || RegExp(/^keeta_an(.*)/).test(input) || RegExp(/^keeta_ao(.*)/).test(input) || RegExp(/^keeta_ap(.*)/).test(input) || RegExp(/^tyblocks_am(.*)/).test(input) || RegExp(/^tyblocks_an(.*)/).test(input) || RegExp(/^tyblocks_ao(.*)/).test(input) || RegExp(/^tyblocks_ap(.*)/).test(input)) || __typia_transform__assertGuard._assertGuard(true, {
20
+ method: "createAssert",
21
+ path: _path + "",
22
+ expected: "(`keeta_am${string}` | `keeta_an${string}` | `keeta_ao${string}` | `keeta_ap${string}` | `tyblocks_am${string}` | `tyblocks_an${string}` | `tyblocks_ao${string}` | `tyblocks_ap${string}`)",
23
+ value: input
24
+ }, _errorFactory))(input, "$input", true);
25
+ }
26
+ return input;
27
+ }; })();
28
+ async function getEndpoints(resolver, request, _ignored_account) {
29
+ const criteria = {};
30
+ if (request.from !== undefined) {
31
+ criteria.inputCurrencyCode = request.from;
32
+ }
33
+ if (request.to !== undefined) {
34
+ criteria.outputCurrencyCode = request.to;
35
+ }
36
+ const response = await resolver.lookup('fx', {
37
+ ...criteria
38
+ // kycProviders: 'TODO' XXX:TODO
39
+ });
40
+ if (response === undefined) {
41
+ return (null);
42
+ }
43
+ const serviceInfoPromises = Object.entries(response).map(async function ([id, serviceInfo]) {
44
+ const operations = await serviceInfo.operations('object');
45
+ const operationsFunctions = {};
46
+ for (const [key, operation] of Object.entries(operations)) {
47
+ if (operation === undefined) {
48
+ continue;
49
+ }
50
+ Object.defineProperty(operationsFunctions, key, {
51
+ get: async function () {
52
+ const url = await operation('string');
53
+ return (function (params) {
54
+ let substitutedURL = url;
55
+ for (const [paramKey, paramValue] of Object.entries(params ?? {})) {
56
+ substitutedURL = substitutedURL.replace(`{${paramKey}}`, encodeURIComponent(paramValue));
57
+ }
58
+ return (validateURL(substitutedURL));
59
+ });
60
+ },
61
+ enumerable: true,
62
+ configurable: true
63
+ });
64
+ }
65
+ const fromInfo = await serviceInfo.from('array');
66
+ const allFrom = await Promise.all(fromInfo.map(async function (fromFn) {
67
+ const from = await fromFn('object');
68
+ const currencyCodes = await Promise.all((await from.currencyCodes('array')).map(async (currencyCode) => {
69
+ const code = await currencyCode('string');
70
+ return (assertKeetaNetTokenPublicKeyString(code));
71
+ }));
72
+ const to = await Promise.all((await from.to('array')).map(async (currencyCode) => {
73
+ const code = await currencyCode('string');
74
+ return (assertKeetaNetTokenPublicKeyString(code));
75
+ }));
76
+ const kycProvidersEntry = (await from.kycProviders?.('array'))?.map(async (providerFn) => {
77
+ const provider = await providerFn('string');
78
+ return (provider);
79
+ });
80
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
81
+ let kycProviders = {};
82
+ if (kycProvidersEntry && kycProvidersEntry.length > 0) {
83
+ kycProviders = { kycProviders: await Promise.all(kycProvidersEntry) };
84
+ }
85
+ return ({ currencyCodes, to, ...kycProviders });
86
+ }));
87
+ return ([
88
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
89
+ id,
90
+ {
91
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
92
+ operations: operationsFunctions,
93
+ from: allFrom
94
+ }
95
+ ]);
96
+ });
97
+ if (serviceInfoPromises.length === 0) {
98
+ return (null);
99
+ }
100
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
101
+ const retval = Object.fromEntries(await Promise.all(serviceInfoPromises));
102
+ return (retval);
103
+ }
104
+ const isKeetaFXAnchorEstimateResponse = (() => { const _io0 = input => true === input.ok && ("object" === typeof input.estimate && null !== input.estimate && _io1(input.estimate)); const _io1 = input => "object" === typeof input.request && null !== input.request && _io2(input.request) && "string" === typeof input.convertedAmount && ("object" === typeof input.expectedCost && null !== input.expectedCost && _io3(input.expectedCost)); const _io2 = input => "string" === typeof input.from && (RegExp(/^keeta_am(.*)/).test(input.from) || RegExp(/^keeta_an(.*)/).test(input.from) || RegExp(/^keeta_ao(.*)/).test(input.from) || RegExp(/^keeta_ap(.*)/).test(input.from) || RegExp(/^tyblocks_am(.*)/).test(input.from) || RegExp(/^tyblocks_an(.*)/).test(input.from) || RegExp(/^tyblocks_ao(.*)/).test(input.from) || RegExp(/^tyblocks_ap(.*)/).test(input.from)) && ("string" === typeof input.to && (RegExp(/^keeta_am(.*)/).test(input.to) || RegExp(/^keeta_an(.*)/).test(input.to) || RegExp(/^keeta_ao(.*)/).test(input.to) || RegExp(/^keeta_ap(.*)/).test(input.to) || RegExp(/^tyblocks_am(.*)/).test(input.to) || RegExp(/^tyblocks_an(.*)/).test(input.to) || RegExp(/^tyblocks_ao(.*)/).test(input.to) || RegExp(/^tyblocks_ap(.*)/).test(input.to))) && "string" === typeof input.amount && ("from" === input.affinity || "to" === input.affinity); const _io3 = input => "string" === typeof input.min && "string" === typeof input.max && ("string" === typeof input.token && (RegExp(/^keeta_am(.*)/).test(input.token) || RegExp(/^keeta_an(.*)/).test(input.token) || RegExp(/^keeta_ao(.*)/).test(input.token) || RegExp(/^keeta_ap(.*)/).test(input.token) || RegExp(/^tyblocks_am(.*)/).test(input.token) || RegExp(/^tyblocks_an(.*)/).test(input.token) || RegExp(/^tyblocks_ao(.*)/).test(input.token) || RegExp(/^tyblocks_ap(.*)/).test(input.token))); const _io4 = input => false === input.ok && "string" === typeof input.error; const _iu0 = input => (() => {
105
+ if (true === input.ok)
106
+ return _io0(input);
107
+ else if (false === input.ok)
108
+ return _io4(input);
109
+ else
110
+ return false;
111
+ })(); return input => "object" === typeof input && null !== input && _iu0(input); })();
112
+ const isKeetaFXAnchorQuoteResponse = (() => { const _io0 = input => true === input.ok && ("object" === typeof input.quote && null !== input.quote && _io1(input.quote)); const _io1 = input => "object" === typeof input.request && null !== input.request && _io2(input.request) && "string" === typeof input.account && "string" === typeof input.convertedAmount && ("object" === typeof input.cost && null !== input.cost && _io3(input.cost)) && ("object" === typeof input.signed && null !== input.signed && _io4(input.signed)); const _io2 = input => "string" === typeof input.from && (RegExp(/^keeta_am(.*)/).test(input.from) || RegExp(/^keeta_an(.*)/).test(input.from) || RegExp(/^keeta_ao(.*)/).test(input.from) || RegExp(/^keeta_ap(.*)/).test(input.from) || RegExp(/^tyblocks_am(.*)/).test(input.from) || RegExp(/^tyblocks_an(.*)/).test(input.from) || RegExp(/^tyblocks_ao(.*)/).test(input.from) || RegExp(/^tyblocks_ap(.*)/).test(input.from)) && ("string" === typeof input.to && (RegExp(/^keeta_am(.*)/).test(input.to) || RegExp(/^keeta_an(.*)/).test(input.to) || RegExp(/^keeta_ao(.*)/).test(input.to) || RegExp(/^keeta_ap(.*)/).test(input.to) || RegExp(/^tyblocks_am(.*)/).test(input.to) || RegExp(/^tyblocks_an(.*)/).test(input.to) || RegExp(/^tyblocks_ao(.*)/).test(input.to) || RegExp(/^tyblocks_ap(.*)/).test(input.to))) && "string" === typeof input.amount && ("from" === input.affinity || "to" === input.affinity); const _io3 = input => "string" === typeof input.amount && ("string" === typeof input.token && (RegExp(/^keeta_am(.*)/).test(input.token) || RegExp(/^keeta_an(.*)/).test(input.token) || RegExp(/^keeta_ao(.*)/).test(input.token) || RegExp(/^keeta_ap(.*)/).test(input.token) || RegExp(/^tyblocks_am(.*)/).test(input.token) || RegExp(/^tyblocks_an(.*)/).test(input.token) || RegExp(/^tyblocks_ao(.*)/).test(input.token) || RegExp(/^tyblocks_ap(.*)/).test(input.token))); const _io4 = input => "string" === typeof input.nonce && "string" === typeof input.timestamp && "string" === typeof input.signature; const _io5 = input => false === input.ok && "string" === typeof input.error; const _iu0 = input => (() => {
113
+ if (true === input.ok)
114
+ return _io0(input);
115
+ else if (false === input.ok)
116
+ return _io5(input);
117
+ else
118
+ return false;
119
+ })(); return input => "object" === typeof input && null !== input && _iu0(input); })();
120
+ const isKeetaFXAnchorExchangeResponse = (() => { const _io0 = input => "string" === typeof input.exchangeID && true === input.ok; const _io1 = input => "string" === typeof input.exchangeID && false === input.ok && "string" === typeof input.error; const _iu0 = input => (() => {
121
+ if (true === input.ok)
122
+ return _io0(input);
123
+ else if (false === input.ok)
124
+ return _io1(input);
125
+ else
126
+ return false;
127
+ })(); return input => "object" === typeof input && null !== input && _iu0(input); })();
128
+ class KeetaFXAnchorBase {
129
+ logger;
130
+ client;
131
+ constructor(config) {
132
+ this.client = config.client;
133
+ this.logger = config.logger;
134
+ }
135
+ }
136
+ class KeetaFXAnchorProviderBase extends KeetaFXAnchorBase {
137
+ serviceInfo;
138
+ providerID;
139
+ conversion;
140
+ parent;
141
+ constructor(serviceInfo, providerID, conversion, parent) {
142
+ const parentPrivate = parent._internals(KeetaFXAnchorClientAccessToken);
143
+ super(parentPrivate);
144
+ this.serviceInfo = serviceInfo;
145
+ this.providerID = providerID;
146
+ this.conversion = conversion;
147
+ this.parent = parent;
148
+ }
149
+ async getEstimate() {
150
+ const serviceURL = await this.serviceInfo.operations.getEstimate;
151
+ if (serviceURL !== undefined) {
152
+ const estimateURL = serviceURL();
153
+ const requestInformation = await fetch(estimateURL, {
154
+ method: 'POST',
155
+ headers: {
156
+ 'Content-Type': 'application/json',
157
+ 'Accept': 'application/json'
158
+ },
159
+ body: JSON.stringify({
160
+ request: this.conversion
161
+ })
162
+ });
163
+ const requestInformationJSON = await requestInformation.json();
164
+ if (!isKeetaFXAnchorEstimateResponse(requestInformationJSON)) {
165
+ throw (new Error(`Invalid response from FX estimate service: ${JSON.stringify(requestInformationJSON)}`));
166
+ }
167
+ if (!requestInformationJSON.ok) {
168
+ throw (new Error(`FX estimate request failed: ${requestInformationJSON.error}`));
169
+ }
170
+ this.logger?.debug(`FX estimate request successful, to provider ${estimateURL} for ${JSON.stringify(this.conversion)}`);
171
+ return (requestInformationJSON.estimate);
172
+ }
173
+ else {
174
+ throw (new Error('Service getEstimate does not exist'));
175
+ }
176
+ }
177
+ /**
178
+ * Get a quote from the provider. If an estimate is provided, it will
179
+ * be used to validate the quote is within the tolerance range.
180
+ *
181
+ * @param estimate An optional estimate to validate the quote against
182
+ * @param tolerance The tolerance, in percentage points, to allow the
183
+ * quote to vary from the estimate. For example, a
184
+ * tolerance of 1.0 allows the quote to be 100% more
185
+ * or less than the estimate. The default is 0.10
186
+ * (10%).
187
+ * @returns A promise that resolves to the quote response
188
+ */
189
+ async getQuote(estimate, tolerance = 0.1) {
190
+ const serviceURL = (await this.serviceInfo.operations.getQuote)();
191
+ const requestInformation = await fetch(serviceURL, {
192
+ method: 'POST',
193
+ headers: {
194
+ 'Content-Type': 'application/json',
195
+ 'Accept': 'application/json'
196
+ },
197
+ body: JSON.stringify({
198
+ request: this.conversion
199
+ })
200
+ });
201
+ const requestInformationJSON = await requestInformation.json();
202
+ if (!isKeetaFXAnchorQuoteResponse(requestInformationJSON)) {
203
+ throw (new Error(`Invalid response from FX quote service: ${JSON.stringify(requestInformationJSON)}`));
204
+ }
205
+ if (!requestInformationJSON.ok) {
206
+ throw (new Error(`FX quote request failed: ${requestInformationJSON.error}`));
207
+ }
208
+ if (estimate !== undefined && tolerance !== undefined) {
209
+ const quoteAmount = new Decimal(requestInformationJSON.quote.convertedAmount);
210
+ const estimateAmount = new Decimal(estimate.convertedAmount);
211
+ const variation = Math.abs(quoteAmount.dividedBy(estimateAmount).toNumber() - 1);
212
+ if (variation > tolerance) {
213
+ throw (new Error(`FX Quote amount: ${requestInformationJSON.quote.convertedAmount} differs more than tolerance limit: ${tolerance} from estimate`));
214
+ }
215
+ }
216
+ this.logger?.debug(`FX quote request successful, to provider ${serviceURL} for ${JSON.stringify(this.conversion)}`);
217
+ return (requestInformationJSON.quote);
218
+ }
219
+ async createExchange(quote, block) {
220
+ let swapBlock = block;
221
+ if (swapBlock === undefined) {
222
+ /* Liquidity Provider that will complete the swap */
223
+ const liquidityProvider = KeetaNetLib.Account.fromPublicKeyString(quote.account);
224
+ /* Assume affinity is 'from' and assign appropriate variables */
225
+ let sendAmount = BigInt(quote.request.amount);
226
+ let receiveAmount = BigInt(quote.convertedAmount);
227
+ /* If affinity is 'to' then reverse amounts */
228
+ if (quote.request.affinity === 'to') {
229
+ sendAmount = BigInt(quote.convertedAmount);
230
+ receiveAmount = BigInt(quote.request.amount);
231
+ }
232
+ const from = { account: this.client.account, token: KeetaNetLib.Account.fromPublicKeyString(quote.request.from), amount: sendAmount };
233
+ const to = { account: liquidityProvider, token: KeetaNetLib.Account.fromPublicKeyString(quote.request.to), amount: receiveAmount };
234
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
235
+ swapBlock = await createSwapRequest(this.client, from, to);
236
+ }
237
+ if (swapBlock == undefined) {
238
+ throw (new Error('User Swap Block is undefined'));
239
+ }
240
+ const serviceURL = (await this.serviceInfo.operations.createExchange)();
241
+ const requestInformation = await fetch(serviceURL, {
242
+ method: 'POST',
243
+ headers: {
244
+ 'Content-Type': 'application/json',
245
+ 'Accept': 'application/json'
246
+ },
247
+ body: JSON.stringify({
248
+ request: {
249
+ quote: quote,
250
+ block: Buffer.from(swapBlock.toBytes()).toString('base64')
251
+ }
252
+ })
253
+ });
254
+ const requestInformationJSON = await requestInformation.json();
255
+ if (!isKeetaFXAnchorExchangeResponse(requestInformationJSON)) {
256
+ throw (new Error(`Invalid response from FX exchange service: ${JSON.stringify(requestInformationJSON)}`));
257
+ }
258
+ if (!requestInformationJSON.ok) {
259
+ throw (new Error(`FX exchange request failed: ${requestInformationJSON.error}`));
260
+ }
261
+ this.logger?.debug(`FX exchange request successful, to provider ${serviceURL} for ${swapBlock.hash.toString()}`);
262
+ return ({ exchangeID: requestInformationJSON.exchangeID });
263
+ }
264
+ async getExchangeStatus(exchangeID) {
265
+ const serviceURL = (await this.serviceInfo.operations.getExchangeStatus)({ exchangeID });
266
+ const requestInformation = await fetch(serviceURL, {
267
+ method: 'GET',
268
+ headers: {
269
+ 'Accept': 'application/json'
270
+ }
271
+ });
272
+ const requestInformationJSON = await requestInformation.json();
273
+ if (!isKeetaFXAnchorExchangeResponse(requestInformationJSON)) {
274
+ throw (new Error(`Invalid response from FX exchange status service: ${JSON.stringify(requestInformationJSON)}`));
275
+ }
276
+ if (!requestInformationJSON.ok) {
277
+ throw (new Error(`FX exchange status failed: ${requestInformationJSON.error}`));
278
+ }
279
+ this.logger?.debug(`FX exchange status request successful, to provider ${serviceURL} for ${exchangeID}`);
280
+ return ({ exchangeID: requestInformationJSON.exchangeID });
281
+ }
282
+ /** @internal */
283
+ _internals(accessToken) {
284
+ if (accessToken !== KeetaFXAnchorClientAccessToken) {
285
+ throw (new Error('invalid access token'));
286
+ }
287
+ return ({
288
+ parent: this.parent
289
+ });
290
+ }
291
+ }
292
+ /*
293
+ * Various classes for the state machine:
294
+ * Estimate(optional) -> Quote(optional) -> Exchange -> ExchangeStatus
295
+ */
296
+ class KeetaFXAnchorExchangeWithProvider {
297
+ provider;
298
+ exchange;
299
+ constructor(provider, exchange) {
300
+ this.provider = provider;
301
+ this.exchange = exchange;
302
+ }
303
+ async getExchangeStatus() {
304
+ /* XXX:TODO: This should return something useful -- right now it just returns the exchange ID... */
305
+ return (await this.provider.getExchangeStatus(this.exchange.exchangeID));
306
+ }
307
+ }
308
+ class KeetaFXAnchorQuoteWithProvider {
309
+ provider;
310
+ quote;
311
+ constructor(provider, quote) {
312
+ this.provider = provider;
313
+ this.quote = quote;
314
+ }
315
+ async createExchange(block) {
316
+ const exchange = await this.provider.createExchange(this.quote, block);
317
+ return (new KeetaFXAnchorExchangeWithProvider(this.provider, exchange));
318
+ }
319
+ }
320
+ class KeetaFXAnchorEstimateWithProvider {
321
+ provider;
322
+ estimate;
323
+ constructor(provider, estimate) {
324
+ this.provider = provider;
325
+ this.estimate = estimate;
326
+ }
327
+ async getQuote(tolerance) {
328
+ const quote = await this.provider.getQuote(this.estimate, tolerance);
329
+ return (new KeetaFXAnchorQuoteWithProvider(this.provider, quote));
330
+ }
331
+ }
332
+ class KeetaFXAnchorClient extends KeetaFXAnchorBase {
333
+ resolver;
334
+ id;
335
+ #signer;
336
+ #account;
337
+ constructor(client, config = {}) {
338
+ super({ client, logger: config.logger });
339
+ this.resolver = config.resolver ?? getDefaultResolver(client, config);
340
+ this.id = config.id ?? crypto.randomUUID();
341
+ if (config.signer) {
342
+ this.#signer = config.signer;
343
+ }
344
+ else if ('signer' in client && client.signer !== null) {
345
+ this.#signer = client.signer;
346
+ }
347
+ else if ('account' in client && client.account.hasPrivateKey) {
348
+ this.#signer = client.account;
349
+ }
350
+ else {
351
+ throw (new Error('KeetaFXAnchorClient requires a Signer or a UserClient with an associated Signer'));
352
+ }
353
+ if (config.account) {
354
+ this.#account = config.account;
355
+ }
356
+ else if ('account' in client) {
357
+ this.#account = client.account;
358
+ }
359
+ else {
360
+ throw (new Error('KeetaFXAnchorClient requires an Account or a UserClient with an associated Account'));
361
+ }
362
+ }
363
+ async canonicalizeConversionTokens(input) {
364
+ let from = {};
365
+ if (input.from !== undefined) {
366
+ let fromToken;
367
+ if (KeetaNetLib.Account.isInstance(input.from) && input.from.isToken()) {
368
+ fromToken = input.from.publicKeyString.get();
369
+ }
370
+ else {
371
+ const tokenLookup = await this.resolver.lookupToken(input.from);
372
+ if (tokenLookup === null) {
373
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
374
+ throw (new Error(`Could not convert from: ${input.from} to a token address`));
375
+ }
376
+ fromToken = tokenLookup.token;
377
+ }
378
+ from = { from: fromToken };
379
+ }
380
+ let to = {};
381
+ if (input.to !== undefined) {
382
+ let toToken;
383
+ if (KeetaNetLib.Account.isInstance(input.to) && input.to.isToken()) {
384
+ toToken = input.to.publicKeyString.get();
385
+ }
386
+ else {
387
+ const tokenLookup = await this.resolver.lookupToken(input.to);
388
+ if (tokenLookup === null) {
389
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
390
+ throw (new Error(`Could not convert to: ${input.to} to a token address`));
391
+ }
392
+ toToken = tokenLookup.token;
393
+ }
394
+ to = { to: toToken };
395
+ }
396
+ return ({ ...from, ...to });
397
+ }
398
+ async canonicalizeConversionInput(input) {
399
+ const amount = new Decimal(input.amount);
400
+ if (amount.isNaN() || amount.lte(0)) {
401
+ throw (new Error('invalid amount'));
402
+ }
403
+ const { from, to } = await this.canonicalizeConversionTokens(input);
404
+ if (from === undefined || to === undefined) {
405
+ throw (new Error('From and To are both required for a conversion'));
406
+ }
407
+ return ({
408
+ from,
409
+ to,
410
+ amount: amount.toString(),
411
+ affinity: input.affinity
412
+ });
413
+ }
414
+ async listPossibleConversions(input, options = {}) {
415
+ if (input.from !== undefined && input.to !== undefined) {
416
+ throw (new KeetaAnchorUserError('Only one of from or two should be provided'));
417
+ }
418
+ if (input.from === undefined && input.to === undefined) {
419
+ throw (new KeetaAnchorUserError('At least one of from or two should be provided'));
420
+ }
421
+ const conversion = await this.canonicalizeConversionTokens(input);
422
+ const account = options.account ?? this.#account;
423
+ const providerEndpoints = await getEndpoints(this.resolver, conversion, account);
424
+ if (providerEndpoints === null) {
425
+ return (null);
426
+ }
427
+ const conversions = new Set();
428
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
429
+ for (const [_ignored_providerID, serviceInfo] of typedFxServiceEntries(providerEndpoints)) {
430
+ for (const conversionPair of serviceInfo.from) {
431
+ if (conversion.from !== undefined) {
432
+ if (conversionPair.currencyCodes.includes(conversion.from)) {
433
+ conversionPair.to.forEach((token) => {
434
+ if (conversion.from !== token) {
435
+ conversions.add(token);
436
+ }
437
+ });
438
+ }
439
+ }
440
+ else if (conversion.to !== undefined) {
441
+ if (conversionPair.to.includes(conversion.to)) {
442
+ conversionPair.currencyCodes.forEach((token) => {
443
+ if (conversion.to !== token) {
444
+ conversions.add(token);
445
+ }
446
+ });
447
+ }
448
+ }
449
+ }
450
+ }
451
+ ;
452
+ return ({ conversions: [...conversions] });
453
+ }
454
+ async getBaseProvidersForConversion(request, options = {}) {
455
+ const conversion = await this.canonicalizeConversionInput(request);
456
+ const account = options.account ?? this.#account;
457
+ const providerEndpoints = await getEndpoints(this.resolver, conversion, account);
458
+ if (providerEndpoints === null) {
459
+ return (null);
460
+ }
461
+ const providers = typedFxServiceEntries(providerEndpoints).map(([providerID, serviceInfo]) => {
462
+ return (new KeetaFXAnchorProviderBase(serviceInfo, providerID, conversion, this));
463
+ });
464
+ return (providers);
465
+ }
466
+ async getEstimates(request, options = {}) {
467
+ const estimateProviders = await this.getBaseProvidersForConversion(request, options);
468
+ if (estimateProviders === null) {
469
+ return (null);
470
+ }
471
+ const estimates = await Promise.allSettled(estimateProviders.map(async (provider) => {
472
+ const estimate = await provider.getEstimate();
473
+ return (new KeetaFXAnchorEstimateWithProvider(provider, estimate));
474
+ }));
475
+ const results = estimates.filter(function (result) {
476
+ return (result.status === 'fulfilled');
477
+ }).map(function (result) {
478
+ return (result.value);
479
+ });
480
+ if (results.length === 0) {
481
+ return (null);
482
+ }
483
+ return (results);
484
+ }
485
+ async getQuotes(request, options = {}) {
486
+ const estimateProviders = await this.getBaseProvidersForConversion(request, options);
487
+ if (estimateProviders === null) {
488
+ return (null);
489
+ }
490
+ const quotes = await Promise.allSettled(estimateProviders.map(async (provider) => {
491
+ const quote = await provider.getQuote();
492
+ return (new KeetaFXAnchorQuoteWithProvider(provider, quote));
493
+ }));
494
+ const results = quotes.filter(function (result) {
495
+ return (result.status === 'fulfilled');
496
+ }).map(function (result) {
497
+ return (result.value);
498
+ });
499
+ if (results.length === 0) {
500
+ return (null);
501
+ }
502
+ return (results);
503
+ }
504
+ /** @internal */
505
+ _internals(accessToken) {
506
+ if (accessToken !== KeetaFXAnchorClientAccessToken) {
507
+ throw (new Error('invalid access token'));
508
+ }
509
+ return ({
510
+ resolver: this.resolver,
511
+ logger: this.logger,
512
+ client: this.client,
513
+ signer: this.#signer,
514
+ account: this.#account
515
+ });
516
+ }
517
+ }
518
+ export default KeetaFXAnchorClient;
519
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/services/fx/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';\nimport { createAssert, createIs } from 'typia';\nimport { Decimal } from 'decimal.js';\n\nimport { getDefaultResolver } from '../../config.js';\n\nimport type {\n\tUserClient as KeetaNetUserClient\n} from '@keetanetwork/keetanet-client';\nimport type { Logger } from '../../lib/log/index.ts';\nimport type Resolver from '../../lib/resolver.ts';\nimport type { ServiceMetadata, ServiceSearchCriteria } from '../../lib/resolver.ts';\nimport { Buffer } from '../../lib/utils/buffer.js';\nimport crypto from '../../lib/utils/crypto.js';\nimport { validateURL } from '../../lib/utils/url.js';\nimport type { BrandedString } from '../../lib/utils/brand.ts';\nimport type {\n\tConversionInput,\n\tConversionInputCanonical,\n\tKeetaFXAnchorEstimate,\n\tKeetaFXAnchorEstimateResponse,\n\tKeetaFXAnchorExchange,\n\tKeetaFXAnchorExchangeResponse,\n\tKeetaFXAnchorQuote,\n\tKeetaFXAnchorQuoteResponse,\n\tKeetaNetTokenPublicKeyString\n} from './common.ts';\nimport { createSwapRequest } from './common.js';\nimport { KeetaAnchorUserError } from '../../lib/error.js';\n\n/**\n * An opaque type that represents a provider ID.\n */\ntype ProviderID = BrandedString<'FXProviderID'>;\n\ntype AccountOptions = {\n\t/**\n\t * The account to use for signing requests. If not provided, the\n\t * account associated with the provided client will be used. If there\n\t * is no account associated with the client, an error occurs.\n\t */\n\tsigner?: InstanceType<typeof KeetaNetLib.Account>;\n\t/**\n\t * Account to perform changes on. If not provided, the account\n\t * associated with the provided client will be used. If there is no\n\t * account associated with the client, an error occurs.\n\t */\n\taccount?: InstanceType<typeof KeetaNetLib.Account>;\n};\n\n/**\n * The configuration options for the FX Anchor client.\n */\nexport type KeetaFXAnchorClientConfig = {\n\t/**\n\t * The ID of the client. This is used to identify the client in logs.\n\t * If not provided, a random ID will be generated.\n\t */\n\tid?: string;\n\t/**\n\t * The logger to use for logging messages. If not provided, no logging\n\t * will be done.\n\t */\n\tlogger?: Logger;\n\t/**\n\t * The resolver to use for resolving FX Anchor services. If not\n\t * provided, a default resolver will be created using the provided\n\t * client and network (if the network is also not provided and the\n\t * client is not a UserClient, an error occurs).\n\t */\n\tresolver?: Resolver;\n\t/**\n\t * The account to use for signing requests. If not provided, the\n\t * account associated with the provided client will be used. If there\n\t * is no account associated with the client, an error occurs.\n\t */\n\tsigner?: InstanceType<typeof KeetaNetLib.Account>;\n\t/**\n\t * Account to perform changes on. If not provided, the account\n\t * associated with the provided client will be used. If there is no\n\t * account associated with the client, an error occurs.\n\t */\n\taccount?: InstanceType<typeof KeetaNetLib.Account>;\n} & Omit<NonNullable<Parameters<typeof getDefaultResolver>[1]>, 'client'> & AccountOptions;\n\nfunction typedFxServiceEntries<T extends object>(obj: T): [keyof T, T[keyof T]][] {\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\treturn(Object.entries(obj) as [keyof T, T[keyof T]][]);\n}\n\ntype KeetaFXAnchorOperations = {\n\t[operation in keyof NonNullable<ServiceMetadata['services']['fx']>[string]['operations']]: (params?: { [key: string]: string; }) => URL;\n};\n\ntype KeetaFXServiceInfo = {\n\toperations: {\n\t\t[operation in keyof KeetaFXAnchorOperations]: Promise<KeetaFXAnchorOperations[operation]>;\n\t},\n\tfrom: NonNullable<ServiceMetadata['services']['fx']>[string]['from'];\n}\n\ntype GetEndpointsResult = {\n\t[providerID: ProviderID]: KeetaFXServiceInfo;\n};\n\nconst KeetaFXAnchorClientAccessToken = Symbol('KeetaFXAnchorClientAccessToken');\n\nconst assertKeetaNetTokenPublicKeyString = createAssert<KeetaNetTokenPublicKeyString>();\nasync function getEndpoints(resolver: Resolver, request: Partial<Pick<ConversionInputCanonical, 'from' | 'to'>>, _ignored_account: InstanceType<typeof KeetaNetLib.Account>): Promise<GetEndpointsResult | null> {\n\tconst criteria: ServiceSearchCriteria<'fx'> = {};\n\tif (request.from !== undefined) {\n\t\tcriteria.inputCurrencyCode = request.from;\n\t}\n\tif (request.to !== undefined) {\n\t\tcriteria.outputCurrencyCode = request.to;\n\t}\n\n\tconst response = await resolver.lookup('fx', {\n\t\t...criteria\n\t\t// kycProviders: 'TODO' XXX:TODO\n\t});\n\n\tif (response === undefined) {\n\t\treturn(null);\n\t}\n\n\tconst serviceInfoPromises = Object.entries(response).map(async function([id, serviceInfo]): Promise<[ProviderID, KeetaFXServiceInfo]> {\n\t\tconst operations = await serviceInfo.operations('object');\n\t\tconst operationsFunctions: Partial<KeetaFXServiceInfo['operations']> = {};\n\t\tfor (const [key, operation] of Object.entries(operations)) {\n\t\t\tif (operation === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tObject.defineProperty(operationsFunctions, key, {\n\t\t\t\tget: async function() {\n\t\t\t\t\tconst url = await operation('string');\n\t\t\t\t\treturn(function(params?: { [key: string]: string; }): URL {\n\t\t\t\t\t\tlet substitutedURL = url;\n\t\t\t\t\t\tfor (const [paramKey, paramValue] of Object.entries(params ?? {})) {\n\t\t\t\t\t\t\tsubstitutedURL = substitutedURL.replace(`{${paramKey}}`, encodeURIComponent(paramValue));\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(validateURL(substitutedURL));\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true\n\t\t\t});\n\t\t}\n\n\t\tconst fromInfo = await serviceInfo.from('array');\n\t\tconst allFrom = await Promise.all(fromInfo.map(async function(fromFn) {\n\t\t\tconst from = await fromFn('object');\n\n\t\t\tconst currencyCodes = await Promise.all((await from.currencyCodes('array')).map(async (currencyCode) => {\n\t\t\t\tconst code = await currencyCode('string');\n\t\t\t\treturn(assertKeetaNetTokenPublicKeyString(code));\n\t\t\t}));\n\n\t\t\tconst to = await Promise.all((await from.to('array')).map(async (currencyCode) => {\n\t\t\t\tconst code = await currencyCode('string');\n\t\t\t\treturn(assertKeetaNetTokenPublicKeyString(code));\n\t\t\t}));\n\n\t\t\tconst kycProvidersEntry = (await from.kycProviders?.('array'))?.map(async (providerFn) => {\n\t\t\t\tconst provider = await providerFn('string');\n\t\t\t\treturn(provider);\n\t\t\t});\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-empty-object-type\n\t\t\tlet kycProviders: { kycProviders: string[] } | {} = {};\n\t\t\tif (kycProvidersEntry && kycProvidersEntry.length > 0) {\n\t\t\t\tkycProviders = { kycProviders: await Promise.all(kycProvidersEntry) }\n\t\t\t}\n\n\t\t\treturn({ currencyCodes, to, ...kycProviders });\n\t\t}));\n\t\treturn([\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tid as unknown as ProviderID,\n\t\t\t{\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\t\toperations: operationsFunctions as KeetaFXServiceInfo['operations'],\n\t\t\t\tfrom: allFrom\n\t\t\t}\n\t\t]);\n\t});\n\n\tif (serviceInfoPromises.length === 0) {\n\t\treturn(null);\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\tconst retval = Object.fromEntries(await Promise.all(serviceInfoPromises)) satisfies GetEndpointsResult as GetEndpointsResult;\n\n\treturn(retval);\n}\n\nconst isKeetaFXAnchorEstimateResponse = createIs<KeetaFXAnchorEstimateResponse>();\nconst isKeetaFXAnchorQuoteResponse = createIs<KeetaFXAnchorQuoteResponse>();\nconst isKeetaFXAnchorExchangeResponse = createIs<KeetaFXAnchorExchangeResponse>();\n\ninterface KeetaFXAnchorBaseConfig {\n\tclient: KeetaNetUserClient;\n\tlogger?: Logger | undefined;\n}\n\nclass KeetaFXAnchorBase {\n\tprotected readonly logger?: Logger | undefined;\n\tprotected readonly client: KeetaNetUserClient;\n\n\tconstructor(config: KeetaFXAnchorBaseConfig) {\n\t\tthis.client = config.client;\n\t\tthis.logger = config.logger;\n\t}\n}\n\nclass KeetaFXAnchorProviderBase extends KeetaFXAnchorBase {\n\treadonly serviceInfo: KeetaFXServiceInfo;\n\treadonly providerID: ProviderID;\n\treadonly conversion: ConversionInputCanonical;\n\tprivate readonly parent: KeetaFXAnchorClient;\n\n\tconstructor(serviceInfo: KeetaFXServiceInfo, providerID: ProviderID, conversion: ConversionInputCanonical, parent: KeetaFXAnchorClient) {\n\t\tconst parentPrivate = parent._internals(KeetaFXAnchorClientAccessToken);\n\t\tsuper(parentPrivate);\n\n\t\tthis.serviceInfo = serviceInfo;\n\t\tthis.providerID = providerID;\n\t\tthis.conversion = conversion;\n\t\tthis.parent = parent;\n\t}\n\n\tasync getEstimate(): Promise<KeetaFXAnchorEstimate> {\n\t\tconst serviceURL = await this.serviceInfo.operations.getEstimate;\n\t\tif (serviceURL !== undefined) {\n\t\t\tconst estimateURL = serviceURL();\n\t\t\tconst requestInformation = await fetch(estimateURL, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t'Accept': 'application/json'\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\trequest: this.conversion\n\t\t\t\t})\n\t\t\t});\n\n\t\t\tconst requestInformationJSON: unknown = await requestInformation.json();\n\t\t\tif (!isKeetaFXAnchorEstimateResponse(requestInformationJSON)) {\n\t\t\t\tthrow(new Error(`Invalid response from FX estimate service: ${JSON.stringify(requestInformationJSON)}`));\n\t\t\t}\n\n\t\t\tif (!requestInformationJSON.ok) {\n\t\t\t\tthrow(new Error(`FX estimate request failed: ${requestInformationJSON.error}`));\n\t\t\t}\n\n\t\t\tthis.logger?.debug(`FX estimate request successful, to provider ${estimateURL} for ${JSON.stringify(this.conversion)}`);\n\t\t\treturn(requestInformationJSON.estimate);\n\t\t} else {\n\t\t\tthrow(new Error('Service getEstimate does not exist'));\n\t\t}\n\t}\n\n\t/**\n\t * Get a quote from the provider. If an estimate is provided, it will\n\t * be used to validate the quote is within the tolerance range.\n\t *\n\t * @param estimate An optional estimate to validate the quote against\n\t * @param tolerance The tolerance, in percentage points, to allow the\n\t * quote to vary from the estimate. For example, a\n\t * tolerance of 1.0 allows the quote to be 100% more\n\t * or less than the estimate. The default is 0.10\n\t * (10%).\n\t * @returns A promise that resolves to the quote response\n\t */\n\tasync getQuote(estimate?: KeetaFXAnchorEstimate, tolerance: number = 0.1): Promise<KeetaFXAnchorQuote> {\n\t\tconst serviceURL = (await this.serviceInfo.operations.getQuote)();\n\t\tconst requestInformation = await fetch(serviceURL, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t'Accept': 'application/json'\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\trequest: this.conversion\n\t\t\t})\n\t\t});\n\n\t\tconst requestInformationJSON: unknown = await requestInformation.json();\n\t\tif (!isKeetaFXAnchorQuoteResponse(requestInformationJSON)) {\n\t\t\tthrow(new Error(`Invalid response from FX quote service: ${JSON.stringify(requestInformationJSON)}`));\n\t\t}\n\n\t\tif (!requestInformationJSON.ok) {\n\t\t\tthrow(new Error(`FX quote request failed: ${requestInformationJSON.error}`));\n\t\t}\n\n\t\tif (estimate !== undefined && tolerance !== undefined) {\n\t\t\tconst quoteAmount = new Decimal(requestInformationJSON.quote.convertedAmount);\n\t\t\tconst estimateAmount = new Decimal(estimate.convertedAmount);\n\t\t\tconst variation = Math.abs(quoteAmount.dividedBy(estimateAmount).toNumber() - 1);\n\t\t\tif (variation > tolerance) {\n\t\t\t\tthrow(new Error(`FX Quote amount: ${requestInformationJSON.quote.convertedAmount} differs more than tolerance limit: ${tolerance} from estimate`));\n\t\t\t}\n\t\t}\n\n\t\tthis.logger?.debug(`FX quote request successful, to provider ${serviceURL} for ${JSON.stringify(this.conversion)}`);\n\t\treturn(requestInformationJSON.quote);\n\t}\n\n\tasync createExchange(quote: KeetaFXAnchorQuote, block?: InstanceType<typeof KeetaNetLib.Block>): Promise<KeetaFXAnchorExchange> {\n\t\tlet swapBlock = block;\n\t\tif (swapBlock === undefined) {\n\t\t\t/* Liquidity Provider that will complete the swap */\n\t\t\tconst liquidityProvider = KeetaNetLib.Account.fromPublicKeyString(quote.account);\n\n\t\t\t/* Assume affinity is 'from' and assign appropriate variables */\n\t\t\tlet sendAmount = BigInt(quote.request.amount);\n\t\t\tlet receiveAmount = BigInt(quote.convertedAmount);\n\n\t\t\t/* If affinity is 'to' then reverse amounts */\n\t\t\tif (quote.request.affinity === 'to') {\n\t\t\t\tsendAmount = BigInt(quote.convertedAmount);\n\t\t\t\treceiveAmount = BigInt(quote.request.amount);\n\t\t\t}\n\n\t\t\tconst from = { account: this.client.account, token: KeetaNetLib.Account.fromPublicKeyString(quote.request.from), amount: sendAmount };\n\t\t\tconst to = { account: liquidityProvider, token: KeetaNetLib.Account.fromPublicKeyString(quote.request.to), amount: receiveAmount };\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\tswapBlock = await createSwapRequest(this.client, from, to);\n\t\t}\n\n\t\tif (swapBlock == undefined) {\n\t\t\tthrow(new Error('User Swap Block is undefined'));\n\t\t}\n\n\t\tconst serviceURL = (await this.serviceInfo.operations.createExchange)();\n\t\tconst requestInformation = await fetch(serviceURL, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t'Accept': 'application/json'\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\trequest: {\n\t\t\t\t\tquote: quote,\n\t\t\t\t\tblock: Buffer.from(swapBlock.toBytes()).toString('base64')\n\t\t\t\t}\n\t\t\t})\n\t\t});\n\n\t\tconst requestInformationJSON: unknown = await requestInformation.json();\n\t\tif (!isKeetaFXAnchorExchangeResponse(requestInformationJSON)) {\n\t\t\tthrow(new Error(`Invalid response from FX exchange service: ${JSON.stringify(requestInformationJSON)}`));\n\t\t}\n\n\t\tif (!requestInformationJSON.ok) {\n\t\t\tthrow(new Error(`FX exchange request failed: ${requestInformationJSON.error}`));\n\t\t}\n\n\t\tthis.logger?.debug(`FX exchange request successful, to provider ${serviceURL} for ${swapBlock.hash.toString()}`);\n\t\treturn({ exchangeID: requestInformationJSON.exchangeID });\n\t}\n\n\tasync getExchangeStatus(exchangeID: string): Promise<KeetaFXAnchorExchange> {\n\t\tconst serviceURL = (await this.serviceInfo.operations.getExchangeStatus)({ exchangeID });\n\t\tconst requestInformation = await fetch(serviceURL, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: {\n\t\t\t\t'Accept': 'application/json'\n\t\t\t}\n\t\t});\n\n\t\tconst requestInformationJSON: unknown = await requestInformation.json();\n\t\tif (!isKeetaFXAnchorExchangeResponse(requestInformationJSON)) {\n\t\t\tthrow(new Error(`Invalid response from FX exchange status service: ${JSON.stringify(requestInformationJSON)}`));\n\t\t}\n\n\t\tif (!requestInformationJSON.ok) {\n\t\t\tthrow(new Error(`FX exchange status failed: ${requestInformationJSON.error}`));\n\t\t}\n\n\t\tthis.logger?.debug(`FX exchange status request successful, to provider ${serviceURL} for ${exchangeID}`);\n\t\treturn({ exchangeID: requestInformationJSON.exchangeID });\n\t}\n\n\t/** @internal */\n\t_internals(accessToken: symbol) {\n\t\tif (accessToken !== KeetaFXAnchorClientAccessToken) {\n\t\t\tthrow(new Error('invalid access token'));\n\t\t}\n\n\t\treturn({\n\t\t\tparent: this.parent\n\t\t});\n\n\t}\n}\n\n/*\n * Various classes for the state machine:\n * Estimate(optional) -> Quote(optional) -> Exchange -> ExchangeStatus\n */\nclass KeetaFXAnchorExchangeWithProvider {\n\tprivate readonly provider: KeetaFXAnchorProviderBase;\n\treadonly exchange: KeetaFXAnchorExchange\n\n\tconstructor(provider: KeetaFXAnchorProviderBase, exchange: KeetaFXAnchorExchange) {\n\t\tthis.provider = provider;\n\t\tthis.exchange = exchange;\n\t}\n\n\tasync getExchangeStatus(): Promise<KeetaFXAnchorExchange> {\n\t\t/* XXX:TODO: This should return something useful -- right now it just returns the exchange ID... */\n\t\treturn(await this.provider.getExchangeStatus(this.exchange.exchangeID));\n\t}\n}\n\nclass KeetaFXAnchorQuoteWithProvider {\n\tprivate readonly provider: KeetaFXAnchorProviderBase;\n\treadonly quote: KeetaFXAnchorQuote;\n\n\tconstructor(provider: KeetaFXAnchorProviderBase, quote: KeetaFXAnchorQuote) {\n\t\tthis.provider = provider;\n\t\tthis.quote = quote;\n\t}\n\n\tasync createExchange(block?: InstanceType<typeof KeetaNetLib.Block>): Promise<KeetaFXAnchorExchangeWithProvider> {\n\t\tconst exchange = await this.provider.createExchange(this.quote, block);\n\t\treturn(new KeetaFXAnchorExchangeWithProvider(this.provider, exchange));\n\t}\n}\n\nclass KeetaFXAnchorEstimateWithProvider {\n\tprivate readonly provider: KeetaFXAnchorProviderBase;\n\treadonly estimate: KeetaFXAnchorEstimate;\n\n\tconstructor(provider: KeetaFXAnchorProviderBase, estimate: KeetaFXAnchorEstimate) {\n\t\tthis.provider = provider;\n\t\tthis.estimate = estimate;\n\t}\n\n\tasync getQuote(tolerance?: number): Promise<KeetaFXAnchorQuoteWithProvider> {\n\t\tconst quote = await this.provider.getQuote(this.estimate, tolerance);\n\t\treturn(new KeetaFXAnchorQuoteWithProvider(this.provider, quote));\n\t}\n}\n\nclass KeetaFXAnchorClient extends KeetaFXAnchorBase {\n\treadonly resolver: Resolver;\n\treadonly id: string;\n\treadonly #signer: InstanceType<typeof KeetaNetLib.Account>;\n\treadonly #account: InstanceType<typeof KeetaNetLib.Account>;\n\n\tconstructor(client: KeetaNetUserClient, config: KeetaFXAnchorClientConfig = {}) {\n\t\tsuper({ client, logger: config.logger });\n\t\tthis.resolver = config.resolver ?? getDefaultResolver(client, config);\n\t\tthis.id = config.id ?? crypto.randomUUID();\n\n\t\tif (config.signer) {\n\t\t\tthis.#signer = config.signer;\n\t\t} else if ('signer' in client && client.signer !== null) {\n\t\t\tthis.#signer = client.signer;\n\t\t} else if ('account' in client && client.account.hasPrivateKey) {\n\t\t\tthis.#signer = client.account;\n\t\t} else {\n\t\t\tthrow(new Error('KeetaFXAnchorClient requires a Signer or a UserClient with an associated Signer'));\n\t\t}\n\n\t\tif (config.account) {\n\t\t\tthis.#account = config.account;\n\t\t} else if ('account' in client) {\n\t\t\tthis.#account = client.account;\n\t\t} else {\n\t\t\tthrow(new Error('KeetaFXAnchorClient requires an Account or a UserClient with an associated Account'));\n\t\t}\n\t}\n\n\tprivate async canonicalizeConversionTokens(input: Partial<ConversionInput>): Promise<Partial<Pick<ConversionInputCanonical, 'from' | 'to'>>> {\n\t\tlet from = {}\n\t\tif (input.from !== undefined) {\n\t\t\tlet fromToken: KeetaNetTokenPublicKeyString;\n\t\t\tif (KeetaNetLib.Account.isInstance(input.from) && input.from.isToken()) {\n\t\t\t\tfromToken = input.from.publicKeyString.get();\n\t\t\t} else {\n\t\t\t\tconst tokenLookup = await this.resolver.lookupToken(input.from);\n\t\t\t\tif (tokenLookup === null) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-base-to-string\n\t\t\t\t\tthrow(new Error(`Could not convert from: ${input.from} to a token address`));\n\t\t\t\t}\n\t\t\t\tfromToken = tokenLookup.token;\n\t\t\t}\n\t\t\tfrom = { from: fromToken };\n\t\t}\n\n\t\tlet to = {};\n\t\tif (input.to !== undefined) {\n\t\t\tlet toToken: KeetaNetTokenPublicKeyString;\n\t\t\tif (KeetaNetLib.Account.isInstance(input.to) && input.to.isToken()) {\n\t\t\t\ttoToken = input.to.publicKeyString.get();\n\t\t\t} else {\n\t\t\t\tconst tokenLookup = await this.resolver.lookupToken(input.to);\n\t\t\t\tif (tokenLookup === null) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-base-to-string\n\t\t\t\t\tthrow(new Error(`Could not convert to: ${input.to} to a token address`));\n\t\t\t\t}\n\t\t\t\ttoToken = tokenLookup.token;\n\t\t\t}\n\t\t\tto = { to: toToken };\n\t\t}\n\t\treturn({ ...from, ...to });\n\t}\n\n\tprivate async canonicalizeConversionInput(input: ConversionInput): Promise<ConversionInputCanonical> {\n\t\tconst amount = new Decimal(input.amount);\n\t\tif (amount.isNaN() || amount.lte(0)) {\n\t\t\tthrow(new Error('invalid amount'));\n\t\t}\n\n\t\tconst { from, to } = await this.canonicalizeConversionTokens(input);\n\n\t\tif (from === undefined || to === undefined) {\n\t\t\tthrow(new Error('From and To are both required for a conversion'));\n\t\t}\n\n\t\treturn({\n\t\t\tfrom,\n\t\t\tto,\n\t\t\tamount: amount.toString(),\n\t\t\taffinity: input.affinity\n\t\t});\n\t}\n\n\tasync listPossibleConversions(input: Partial<Pick<ConversionInput, 'from' | 'to'>>, options: AccountOptions = {}): Promise<{ conversions: KeetaNetTokenPublicKeyString[] } | null> {\n\t\tif (input.from !== undefined && input.to !== undefined) {\n\t\t\tthrow(new KeetaAnchorUserError('Only one of from or two should be provided'));\n\t\t}\n\t\tif (input.from === undefined && input.to === undefined) {\n\t\t\tthrow(new KeetaAnchorUserError('At least one of from or two should be provided'));\n\t\t}\n\t\tconst conversion = await this.canonicalizeConversionTokens(input);\n\t\tconst account = options.account ?? this.#account;\n\t\tconst providerEndpoints = await getEndpoints(this.resolver, conversion, account);\n\t\tif (providerEndpoints === null) {\n\t\t\treturn(null);\n\t\t}\n\n\t\tconst conversions = new Set<KeetaNetTokenPublicKeyString>();\n\t\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t\tfor (const [_ignored_providerID, serviceInfo] of typedFxServiceEntries(providerEndpoints)) {\n\t\t\tfor (const conversionPair of serviceInfo.from) {\n\t\t\t\tif (conversion.from !== undefined) {\n\t\t\t\t\tif (conversionPair.currencyCodes.includes(conversion.from)) {\n\t\t\t\t\t\tconversionPair.to.forEach((token) => {\n\t\t\t\t\t\t\tif (conversion.from !== token) {\n\t\t\t\t\t\t\t\tconversions.add(token);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if (conversion.to !== undefined) {\n\t\t\t\t\tif (conversionPair.to.includes(conversion.to)) {\n\t\t\t\t\t\tconversionPair.currencyCodes.forEach((token) => {\n\t\t\t\t\t\t\tif (conversion.to !== token) {\n\t\t\t\t\t\t\t\tconversions.add(token);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\treturn({ conversions: [...conversions] });\n\t}\n\n\tasync getBaseProvidersForConversion(request: ConversionInput, options: AccountOptions = {}): Promise<KeetaFXAnchorProviderBase[] | null> {\n\t\tconst conversion = await this.canonicalizeConversionInput(request);\n\t\tconst account = options.account ?? this.#account;\n\t\tconst providerEndpoints = await getEndpoints(this.resolver, conversion, account);\n\t\tif (providerEndpoints === null) {\n\t\t\treturn(null);\n\t\t}\n\n\t\tconst providers = typedFxServiceEntries(providerEndpoints).map(([providerID, serviceInfo]) => {\n\t\t\treturn(new KeetaFXAnchorProviderBase(serviceInfo, providerID, conversion, this));\n\t\t});\n\n\t\treturn(providers);\n\t}\n\n\tasync getEstimates(request: ConversionInput, options: AccountOptions = {}): Promise<KeetaFXAnchorEstimateWithProvider[] | null> {\n\t\tconst estimateProviders = await this.getBaseProvidersForConversion(request, options);\n\t\tif (estimateProviders === null) {\n\t\t\treturn(null);\n\t\t}\n\n\t\tconst estimates = await Promise.allSettled(estimateProviders.map(async (provider) => {\n\t\t\tconst estimate = await provider.getEstimate();\n\n\t\t\treturn(new KeetaFXAnchorEstimateWithProvider(provider, estimate));\n\t\t}));\n\n\t\tconst results = estimates.filter(function(result) {\n\t\t\treturn(result.status === 'fulfilled');\n\t\t}).map(function(result) {\n\t\t\treturn(result.value);\n\t\t});\n\n\t\tif (results.length === 0) {\n\t\t\treturn(null);\n\t\t}\n\n\t\treturn(results);\n\t}\n\n\tasync getQuotes(request: ConversionInput, options: AccountOptions = {}): Promise<KeetaFXAnchorQuoteWithProvider[] | null> {\n\t\tconst estimateProviders = await this.getBaseProvidersForConversion(request, options);\n\t\tif (estimateProviders === null) {\n\t\t\treturn(null);\n\t\t}\n\n\t\tconst quotes = await Promise.allSettled(estimateProviders.map(async (provider) => {\n\t\t\tconst quote = await provider.getQuote();\n\n\t\t\treturn(new KeetaFXAnchorQuoteWithProvider(provider, quote));\n\t\t}));\n\n\t\tconst results = quotes.filter(function(result) {\n\t\t\treturn(result.status === 'fulfilled');\n\t\t}).map(function(result) {\n\t\t\treturn(result.value);\n\t\t});\n\n\t\tif (results.length === 0) {\n\t\t\treturn(null);\n\t\t}\n\n\t\treturn(results);\n\t}\n\n\t/** @internal */\n\t_internals(accessToken: symbol) {\n\t\tif (accessToken !== KeetaFXAnchorClientAccessToken) {\n\t\t\tthrow(new Error('invalid access token'));\n\t\t}\n\n\t\treturn({\n\t\t\tresolver: this.resolver,\n\t\t\tlogger: this.logger,\n\t\t\tclient: this.client,\n\t\t\tsigner: this.#signer,\n\t\t\taccount: this.#account\n\t\t});\n\n\t}\n}\n\nexport default KeetaFXAnchorClient;\n"]}