@olympex-io/olympex-sdk 0.1.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/index.js ADDED
@@ -0,0 +1,863 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ OlympexConfigError: () => OlympexConfigError,
34
+ OlympexDomainError: () => OlympexDomainError,
35
+ OlympexGraphQLError: () => OlympexGraphQLError,
36
+ OlympexNetworkError: () => OlympexNetworkError,
37
+ OlympexNotImplementedError: () => OlympexNotImplementedError,
38
+ OlympexSdkError: () => OlympexSdkError,
39
+ createAccount: () => createAccount,
40
+ createConsoleLogger: () => createConsoleLogger,
41
+ getVersion: () => getVersion,
42
+ initialize: () => initialize
43
+ });
44
+ module.exports = __toCommonJS(index_exports);
45
+
46
+ // src/errors/base-error.ts
47
+ var OlympexSdkError = class extends Error {
48
+ code;
49
+ metadata;
50
+ constructor(message, code = "OLYMPEX_SDK_ERROR", metadata) {
51
+ super(message);
52
+ this.name = new.target.name;
53
+ this.code = code;
54
+ this.metadata = metadata;
55
+ }
56
+ };
57
+
58
+ // src/errors/graphql-error.ts
59
+ var OlympexGraphQLError = class extends OlympexSdkError {
60
+ constructor(message, metadata) {
61
+ super(message, "OLYMPEX_GRAPHQL_ERROR", metadata);
62
+ }
63
+ };
64
+
65
+ // src/errors/network-error.ts
66
+ var OlympexNetworkError = class extends OlympexSdkError {
67
+ constructor(message, metadata) {
68
+ super(message, "OLYMPEX_NETWORK_ERROR", metadata);
69
+ }
70
+ };
71
+
72
+ // src/errors/redact.ts
73
+ var SENSITIVE_KEY_PATTERN = /api[-_]?key|authorization|cookie|token|secret|password/i;
74
+ function isPlainObject(value) {
75
+ return typeof value === "object" && value !== null && !Array.isArray(value);
76
+ }
77
+ function redact(value) {
78
+ if (Array.isArray(value)) {
79
+ return value.map((item) => redact(item));
80
+ }
81
+ if (!isPlainObject(value)) {
82
+ return value;
83
+ }
84
+ return Object.fromEntries(
85
+ Object.entries(value).map(([key, entry]) => [
86
+ key,
87
+ SENSITIVE_KEY_PATTERN.test(key) ? "<REDACTED>" : redact(entry)
88
+ ])
89
+ );
90
+ }
91
+
92
+ // src/client/request-signing.ts
93
+ var import_crypto = __toESM(require("crypto"));
94
+ function generateBodySignature(body) {
95
+ const hashBuffer = import_crypto.default.createHash("sha256").update(body).digest();
96
+ return hashBuffer.toString("base64url");
97
+ }
98
+ function getTimestamp() {
99
+ return Math.floor(Date.now() / 1e3).toString();
100
+ }
101
+ function generateNonce() {
102
+ return import_crypto.default.randomBytes(12).toString("hex");
103
+ }
104
+ function sign({ message, secret }) {
105
+ return import_crypto.default.createHmac("sha256", secret).update(message).digest("hex");
106
+ }
107
+ function buildSignedHeaders({
108
+ apiKey,
109
+ apiSecret,
110
+ passphrase,
111
+ body,
112
+ timestamp,
113
+ nonce
114
+ }) {
115
+ const bodyHash = generateBodySignature(body);
116
+ const resolvedTimestamp = timestamp ?? getTimestamp();
117
+ const resolvedNonce = nonce ?? generateNonce();
118
+ const message = `${resolvedTimestamp}
119
+ ${resolvedNonce}
120
+ ${bodyHash}`;
121
+ const headerData = Buffer.from(message).toString("base64");
122
+ return {
123
+ "x-api-key-id": apiKey,
124
+ "x-value-info": headerData,
125
+ "x-passphrase": passphrase,
126
+ "x-signature": sign({ message, secret: apiSecret })
127
+ };
128
+ }
129
+
130
+ // src/client/graphql-client.ts
131
+ var OlympexGraphQLClient = class {
132
+ apiKey;
133
+ apiSecret;
134
+ passphrase;
135
+ endpoint;
136
+ headers;
137
+ logger;
138
+ timeoutMs;
139
+ constructor(options) {
140
+ this.apiKey = options.apiKey;
141
+ this.apiSecret = options.apiSecret;
142
+ this.passphrase = options.passphrase;
143
+ this.endpoint = options.endpoint;
144
+ this.headers = options.headers ?? {};
145
+ this.logger = options.logger;
146
+ this.timeoutMs = options.timeoutMs;
147
+ }
148
+ async request(document, variables) {
149
+ const controller = new AbortController();
150
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
151
+ try {
152
+ this.logger?.log(
153
+ "debug",
154
+ "Sending Olympex GraphQL request",
155
+ redact({
156
+ endpoint: this.endpoint,
157
+ variables
158
+ })
159
+ );
160
+ const bodyToFetch = JSON.stringify({ query: document, variables });
161
+ const signedHeaders = buildSignedHeaders({
162
+ apiKey: this.apiKey,
163
+ apiSecret: this.apiSecret,
164
+ body: bodyToFetch,
165
+ passphrase: this.passphrase
166
+ });
167
+ const response = await fetch(this.endpoint, {
168
+ body: bodyToFetch,
169
+ headers: {
170
+ accept: "application/json",
171
+ "content-type": "application/json",
172
+ ...this.headers,
173
+ ...signedHeaders
174
+ },
175
+ method: "POST",
176
+ signal: controller.signal
177
+ });
178
+ let body;
179
+ try {
180
+ body = await response.json();
181
+ } catch {
182
+ this.logger?.log(
183
+ "error",
184
+ "Olympex GraphQL response was not valid JSON",
185
+ redact({
186
+ contentType: response.headers.get("content-type") ?? void 0,
187
+ endpoint: this.endpoint,
188
+ status: response.status
189
+ })
190
+ );
191
+ throw new OlympexNetworkError("GraphQL response was not valid JSON", {
192
+ contentType: response.headers.get("content-type") ?? void 0,
193
+ status: response.status,
194
+ statusText: response.statusText
195
+ });
196
+ }
197
+ if (!response.ok) {
198
+ this.logger?.log(
199
+ "error",
200
+ "Olympex GraphQL request failed with HTTP status",
201
+ redact({
202
+ endpoint: this.endpoint,
203
+ status: response.status,
204
+ statusText: response.statusText
205
+ })
206
+ );
207
+ throw new OlympexNetworkError(`GraphQL request failed with status ${response.status}`, {
208
+ status: response.status,
209
+ statusText: response.statusText
210
+ });
211
+ }
212
+ if (body?.errors?.length) {
213
+ const firstError = body.errors[0];
214
+ this.logger?.log(
215
+ "warn",
216
+ "Olympex GraphQL response contains errors",
217
+ redact({
218
+ endpoint: this.endpoint,
219
+ errorCount: body.errors.length,
220
+ extensions: firstError?.extensions,
221
+ firstMessage: firstError?.message
222
+ })
223
+ );
224
+ throw new OlympexGraphQLError(body.errors[0]?.message ?? "GraphQL request failed", {
225
+ errors: body.errors.map((error) => ({
226
+ extensions: error.extensions,
227
+ message: error.message,
228
+ path: error.path
229
+ }))
230
+ });
231
+ }
232
+ if (!body?.data) {
233
+ throw new OlympexGraphQLError("GraphQL response did not include data");
234
+ }
235
+ return body.data;
236
+ } catch (error) {
237
+ if (error instanceof OlympexGraphQLError || error instanceof OlympexNetworkError) {
238
+ throw error;
239
+ }
240
+ const errorName = error instanceof Error ? error.name : "UnknownError";
241
+ const errorMessage = error instanceof Error ? error.message : "Unknown network error";
242
+ this.logger?.log(
243
+ "error",
244
+ "Olympex GraphQL network failure",
245
+ redact({
246
+ endpoint: this.endpoint,
247
+ errorMessage,
248
+ errorName
249
+ })
250
+ );
251
+ throw new OlympexNetworkError(errorMessage);
252
+ } finally {
253
+ clearTimeout(timeout);
254
+ }
255
+ }
256
+ };
257
+
258
+ // src/errors/config-error.ts
259
+ var OlympexConfigError = class extends OlympexSdkError {
260
+ constructor(message, metadata) {
261
+ super(message, "OLYMPEX_CONFIG_ERROR", metadata);
262
+ }
263
+ };
264
+
265
+ // src/fees/validation.ts
266
+ var import_ethers = require("ethers");
267
+
268
+ // src/fees/constants.ts
269
+ var FEE_BPS_MIN = 0;
270
+ var FEE_BPS_MAX = 100;
271
+
272
+ // src/fees/validation.ts
273
+ function validateFeeOptions(fees) {
274
+ if (!fees) {
275
+ return;
276
+ }
277
+ if (fees.feeBps !== void 0) {
278
+ if (!Number.isFinite(fees.feeBps) || fees.feeBps < FEE_BPS_MIN || fees.feeBps > FEE_BPS_MAX) {
279
+ throw new OlympexConfigError(`feeBps must be between ${FEE_BPS_MIN} and ${FEE_BPS_MAX}`);
280
+ }
281
+ }
282
+ if (fees.feeRecipient !== void 0 && !(0, import_ethers.isAddress)(fees.feeRecipient)) {
283
+ throw new OlympexConfigError("feeRecipient must be a valid Ethereum address");
284
+ }
285
+ }
286
+
287
+ // src/config/backend-url.ts
288
+ var DEFAULT_BACKEND_URL = "https://back.olympex.io/graphql";
289
+ var BACKEND_URL_ENV = "OLYMPEX_BACKEND_URL";
290
+ var GRAPHQL_PATH = "/graphql";
291
+ function readBackendUrlEnv() {
292
+ const raw = process.env[BACKEND_URL_ENV];
293
+ if (raw === void 0) {
294
+ return void 0;
295
+ }
296
+ const trimmed = raw.trim();
297
+ return trimmed.length > 0 ? trimmed : void 0;
298
+ }
299
+ function validateBackendUrl(url) {
300
+ let parsed;
301
+ try {
302
+ parsed = new URL(url);
303
+ } catch {
304
+ throw new OlympexConfigError(`Invalid ${BACKEND_URL_ENV}: ${url}`);
305
+ }
306
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
307
+ throw new OlympexConfigError(`Invalid ${BACKEND_URL_ENV}: ${url}`);
308
+ }
309
+ if (parsed.search || parsed.hash) {
310
+ throw new OlympexConfigError(`Invalid ${BACKEND_URL_ENV}: ${url}`);
311
+ }
312
+ const pathname = parsed.pathname.replace(/\/$/, "") || "/";
313
+ if (pathname !== "/" && pathname !== GRAPHQL_PATH) {
314
+ throw new OlympexConfigError(`Invalid ${BACKEND_URL_ENV}: ${url}`);
315
+ }
316
+ return parsed;
317
+ }
318
+ function normalizeBase(baseUrl) {
319
+ return baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
320
+ }
321
+ function toGraphqlEndpoint(url) {
322
+ const parsed = validateBackendUrl(url);
323
+ const pathname = parsed.pathname.replace(/\/$/, "") || "/";
324
+ if (pathname === GRAPHQL_PATH) {
325
+ return `${parsed.origin}${GRAPHQL_PATH}`;
326
+ }
327
+ return `${parsed.origin}${GRAPHQL_PATH}`;
328
+ }
329
+ function resolveBackendBaseUrl() {
330
+ const configured = readBackendUrlEnv();
331
+ const candidate = configured ?? DEFAULT_BACKEND_URL;
332
+ return toGraphqlEndpoint(candidate);
333
+ }
334
+ function getGraphqlEndpoint() {
335
+ return normalizeBase(resolveBackendBaseUrl());
336
+ }
337
+ function getRestBaseUrl() {
338
+ const graphqlEndpoint = normalizeBase(resolveBackendBaseUrl());
339
+ if (graphqlEndpoint.endsWith(GRAPHQL_PATH)) {
340
+ return graphqlEndpoint.slice(0, -GRAPHQL_PATH.length);
341
+ }
342
+ return graphqlEndpoint;
343
+ }
344
+
345
+ // src/methods/account.ts
346
+ var CREATE_ACCOUNT_PATH = "/api/v1/accounts";
347
+ function extractCredentials(payload) {
348
+ if (!payload || typeof payload !== "object") {
349
+ return null;
350
+ }
351
+ const directPayload = payload;
352
+ const candidatePayloads = [directPayload];
353
+ if (directPayload.data !== void 0) {
354
+ candidatePayloads.push(directPayload.data);
355
+ }
356
+ for (const candidate of candidatePayloads) {
357
+ if (!candidate || typeof candidate !== "object") {
358
+ continue;
359
+ }
360
+ const values = candidate;
361
+ if (typeof values.apiKey === "string" && typeof values.secretKey === "string") {
362
+ return {
363
+ apiKey: values.apiKey,
364
+ secretKey: values.secretKey
365
+ };
366
+ }
367
+ }
368
+ return null;
369
+ }
370
+ function parseResponseMessage(payload) {
371
+ if (!payload || typeof payload !== "object") {
372
+ return void 0;
373
+ }
374
+ const maybeMessage = payload.message;
375
+ return typeof maybeMessage === "string" ? maybeMessage : void 0;
376
+ }
377
+ async function createAccount({
378
+ name,
379
+ password
380
+ }) {
381
+ const normalizedName = name.trim();
382
+ const normalizedPassword = password.trim();
383
+ if (!normalizedName) {
384
+ throw new OlympexConfigError("name is required");
385
+ }
386
+ if (!normalizedPassword) {
387
+ throw new OlympexConfigError("password is required");
388
+ }
389
+ const endpoint = `${getRestBaseUrl()}${CREATE_ACCOUNT_PATH}`;
390
+ const response = await fetch(endpoint, {
391
+ body: JSON.stringify({ name: normalizedName, password: normalizedPassword }),
392
+ headers: {
393
+ accept: "application/json",
394
+ "content-type": "application/json"
395
+ },
396
+ method: "POST"
397
+ });
398
+ let responseBody;
399
+ try {
400
+ responseBody = await response.json();
401
+ } catch {
402
+ throw new OlympexNetworkError("createAccount response was not valid JSON", {
403
+ contentType: response.headers.get("content-type") ?? void 0,
404
+ endpoint,
405
+ status: response.status,
406
+ statusText: response.statusText
407
+ });
408
+ }
409
+ if (!response.ok) {
410
+ throw new OlympexNetworkError(`createAccount request failed with status ${response.status}`, {
411
+ endpoint,
412
+ responseMessage: parseResponseMessage(responseBody),
413
+ status: response.status,
414
+ statusText: response.statusText
415
+ });
416
+ }
417
+ const credentials = extractCredentials(responseBody);
418
+ if (!credentials) {
419
+ throw new OlympexNetworkError("createAccount response did not include credentials", {
420
+ endpoint,
421
+ status: response.status
422
+ });
423
+ }
424
+ return credentials;
425
+ }
426
+
427
+ // src/methods/get-version.ts
428
+ var VERSION = "0.0.0";
429
+ function getVersion() {
430
+ return VERSION;
431
+ }
432
+
433
+ // src/errors/domain-error.ts
434
+ var OlympexDomainError = class extends OlympexSdkError {
435
+ constructor(message, metadata) {
436
+ super(message, "OLYMPEX_DOMAIN_ERROR", metadata);
437
+ }
438
+ };
439
+
440
+ // src/client/domain-response.ts
441
+ function requireSuccessfulDomainResponse(response, payloadName) {
442
+ if (response === null || response === void 0) {
443
+ throw new OlympexDomainError(`Missing ${payloadName} response`);
444
+ }
445
+ if (response.success === false) {
446
+ throw new OlympexDomainError(response.message ?? `${payloadName} failed`, {
447
+ code: response.code,
448
+ success: response.success
449
+ });
450
+ }
451
+ return response;
452
+ }
453
+ function requirePayload(payload, payloadName) {
454
+ if (payload === null || payload === void 0) {
455
+ throw new OlympexDomainError(`Missing ${payloadName} payload`);
456
+ }
457
+ return payload;
458
+ }
459
+
460
+ // src/fees/defaults.ts
461
+ function resolveFeeOptions(callFees, clientDefaultFees) {
462
+ if (!callFees && !clientDefaultFees) {
463
+ return void 0;
464
+ }
465
+ return {
466
+ ...clientDefaultFees,
467
+ ...callFees
468
+ };
469
+ }
470
+
471
+ // src/fees/serialize.ts
472
+ function serializeFeeOptions(fees) {
473
+ if (!fees) {
474
+ return void 0;
475
+ }
476
+ const serialized = {};
477
+ if (fees.feeBps !== void 0) {
478
+ serialized.feeBps = fees.feeBps;
479
+ }
480
+ if (fees.feeRecipient !== void 0) {
481
+ serialized.feeRecipient = fees.feeRecipient;
482
+ }
483
+ return Object.keys(serialized).length > 0 ? serialized : void 0;
484
+ }
485
+ function mergeParamsWithFees(params, fees) {
486
+ const serialized = serializeFeeOptions(fees);
487
+ if (!serialized) {
488
+ return params;
489
+ }
490
+ return {
491
+ ...params,
492
+ ...serialized
493
+ };
494
+ }
495
+
496
+ // src/graphql/operations.ts
497
+ var GET_ENABLED_CHAINS = (
498
+ /* GraphQL */
499
+ `
500
+ query GetEnabledChains {
501
+ getEnabledChains {
502
+ chainIds
503
+ }
504
+ }
505
+ `
506
+ );
507
+ var GET_QUOTE = (
508
+ /* GraphQL */
509
+ `
510
+ query GetQuote($getQuoteParams: QuoteInput!) {
511
+ getQuote(params: $getQuoteParams) {
512
+ outAmount
513
+ estimatedGas
514
+ aggregatorId
515
+ aggregatorOrder
516
+ market {
517
+ dexName
518
+ swapAmount
519
+ dexImageURL
520
+ }
521
+ routes {
522
+ percentage
523
+ subRoutes {
524
+ from
525
+ to
526
+ dexes {
527
+ name
528
+ percentage
529
+ }
530
+ }
531
+ }
532
+ dataFeeTransaction {
533
+ effectiveGasPrice
534
+ nativePrice
535
+ transactionFee
536
+ transactionFeeInUSD
537
+ tokenPrice
538
+ transactionFeeInTokenIn
539
+ valueToApprove
540
+ }
541
+ gasMultiplier
542
+ }
543
+ }
544
+ `
545
+ );
546
+ var GET_QUOTE_SWAP = (
547
+ /* GraphQL */
548
+ `
549
+ mutation GetQuoteSwap($getQuoteSwapParams: QuoteSwapInput!) {
550
+ getQuoteSwap(params: $getQuoteSwapParams) {
551
+ code
552
+ message
553
+ quoteSwap {
554
+ data
555
+ estimatedGas
556
+ minOutAmount
557
+ outAmount
558
+ value
559
+ approveTransaction
560
+ }
561
+ success
562
+ }
563
+ }
564
+ `
565
+ );
566
+ var GET_CROSS_CHAIN_QUOTE = (
567
+ /* GraphQL */
568
+ `
569
+ query GetCrossChainQuote($params: CrossChainQuoteInput!) {
570
+ getCrossChainQuote(params: $params) {
571
+ code
572
+ message
573
+ success
574
+ crossChainQuote {
575
+ aggregatorId
576
+ estimatedGas
577
+ estimatedTime
578
+ estimateCostInUSD
579
+ fromTokenAmount
580
+ toTokenAmount
581
+ minimumReceived
582
+ bridgeInfo {
583
+ icon
584
+ displayName
585
+ }
586
+ middlewareRoute {
587
+ chainFrom {
588
+ fromAsset {
589
+ address
590
+ decimals
591
+ symbol
592
+ }
593
+ toAsset {
594
+ address
595
+ decimals
596
+ symbol
597
+ }
598
+ }
599
+ chainTo {
600
+ fromAsset {
601
+ address
602
+ decimals
603
+ symbol
604
+ }
605
+ toAsset {
606
+ address
607
+ decimals
608
+ symbol
609
+ }
610
+ }
611
+ }
612
+ }
613
+ }
614
+ }
615
+ `
616
+ );
617
+ var GET_CROSS_CHAIN_SWAP = (
618
+ /* GraphQL */
619
+ `
620
+ mutation GetCrossChainSwap($params: CrossChainSwapInput!) {
621
+ getCrossChainSwap(params: $params) {
622
+ code
623
+ message
624
+ success
625
+ crossChainSwap {
626
+ calldata
627
+ value
628
+ approveTransaction
629
+ dexHash
630
+ }
631
+ }
632
+ }
633
+ `
634
+ );
635
+ var GET_CROSS_CHAIN_TX_STATUS = (
636
+ /* GraphQL */
637
+ `
638
+ query GetCrossChainTxStatus($hash: String!, $chainId: String!, $dexHash: String!) {
639
+ getCrossChainTxStatus(txHash: $hash, chainId: $chainId, dexHash: $dexHash) {
640
+ message
641
+ success
642
+ txStatus {
643
+ toChainId
644
+ fromChainId
645
+ detailStatus
646
+ status
647
+ }
648
+ }
649
+ }
650
+ `
651
+ );
652
+
653
+ // src/methods/quote.ts
654
+ function createQuoteMethod(graphqlClient, defaultFees, logger) {
655
+ return async function quote(input) {
656
+ const fees = resolveFeeOptions(input.fees, defaultFees);
657
+ validateFeeOptions(fees);
658
+ if (input.mode === "single-chain") {
659
+ logger?.log(
660
+ "info",
661
+ "Olympex quote requested",
662
+ redact({
663
+ chainId: input.params.chainId,
664
+ mode: "single-chain"
665
+ })
666
+ );
667
+ const data2 = await graphqlClient.request(
668
+ GET_QUOTE,
669
+ {
670
+ getQuoteParams: mergeParamsWithFees(input.params, fees)
671
+ }
672
+ );
673
+ return {
674
+ mode: "single-chain",
675
+ quote: requirePayload(data2.getQuote, "getQuote")
676
+ };
677
+ }
678
+ logger?.log(
679
+ "info",
680
+ "Olympex quote requested",
681
+ redact({
682
+ fromChainId: input.params.fromChainId,
683
+ mode: "cross-chain",
684
+ toChainId: input.params.toChainId
685
+ })
686
+ );
687
+ const data = await graphqlClient.request(
688
+ GET_CROSS_CHAIN_QUOTE,
689
+ {
690
+ params: mergeParamsWithFees(input.params, fees)
691
+ }
692
+ );
693
+ const response = requireSuccessfulDomainResponse(data.getCrossChainQuote, "getCrossChainQuote");
694
+ return {
695
+ mode: "cross-chain",
696
+ quote: requirePayload(response.crossChainQuote, "crossChainQuote")
697
+ };
698
+ };
699
+ }
700
+
701
+ // src/methods/support-chain.ts
702
+ function createSupportChainMethod(graphqlClient) {
703
+ return async function supportChain(chainId) {
704
+ const data = await graphqlClient.request(
705
+ GET_ENABLED_CHAINS,
706
+ {}
707
+ );
708
+ const enabledChains = requirePayload(data.getEnabledChains, "getEnabledChains");
709
+ return enabledChains.chainIds.includes(String(chainId));
710
+ };
711
+ }
712
+
713
+ // src/methods/swap.ts
714
+ function createSwapMethod(graphqlClient, defaultFees, logger) {
715
+ return async function swap(input) {
716
+ const fees = resolveFeeOptions(input.fees, defaultFees);
717
+ validateFeeOptions(fees);
718
+ if (input.mode === "single-chain") {
719
+ logger?.log(
720
+ "info",
721
+ "Olympex swap requested",
722
+ redact({
723
+ chainId: input.params.chainId,
724
+ mode: "single-chain"
725
+ })
726
+ );
727
+ const data2 = await graphqlClient.request(
728
+ GET_QUOTE_SWAP,
729
+ {
730
+ getQuoteSwapParams: mergeParamsWithFees(input.params, fees)
731
+ }
732
+ );
733
+ const response2 = requireSuccessfulDomainResponse(data2.getQuoteSwap, "getQuoteSwap");
734
+ return {
735
+ mode: "single-chain",
736
+ swap: requirePayload(response2.quoteSwap, "quoteSwap")
737
+ };
738
+ }
739
+ logger?.log(
740
+ "info",
741
+ "Olympex swap requested",
742
+ redact({
743
+ fromChainId: input.params.fromChainId,
744
+ mode: "cross-chain",
745
+ toChainId: input.params.toChainId
746
+ })
747
+ );
748
+ const data = await graphqlClient.request(
749
+ GET_CROSS_CHAIN_SWAP,
750
+ {
751
+ params: mergeParamsWithFees(input.params, fees)
752
+ }
753
+ );
754
+ const response = requireSuccessfulDomainResponse(data.getCrossChainSwap, "getCrossChainSwap");
755
+ return {
756
+ mode: "cross-chain",
757
+ swap: requirePayload(response.crossChainSwap, "crossChainSwap")
758
+ };
759
+ };
760
+ }
761
+
762
+ // src/methods/tx-status.ts
763
+ function createTxStatusMethod(graphqlClient) {
764
+ return async function txStatus(input) {
765
+ const data = await graphqlClient.request(
766
+ GET_CROSS_CHAIN_TX_STATUS,
767
+ input
768
+ );
769
+ const response = requireSuccessfulDomainResponse(
770
+ data.getCrossChainTxStatus,
771
+ "getCrossChainTxStatus"
772
+ );
773
+ return requirePayload(response.txStatus, "txStatus");
774
+ };
775
+ }
776
+
777
+ // src/config/initialize.ts
778
+ var DEFAULT_TIMEOUT_MS = 3e4;
779
+ function initialize(options) {
780
+ const apiKey = options.apiKey.trim();
781
+ const apiSecret = options.apiSecret.trim();
782
+ const passphrase = options.passphrase.trim();
783
+ if (!apiKey) {
784
+ throw new OlympexConfigError("apiKey is required");
785
+ }
786
+ if (!apiSecret) {
787
+ throw new OlympexConfigError("apiSecret is required");
788
+ }
789
+ if (!passphrase) {
790
+ throw new OlympexConfigError("passphrase is required");
791
+ }
792
+ validateFeeOptions(options.defaultFees);
793
+ const graphqlClient = new OlympexGraphQLClient({
794
+ apiKey,
795
+ apiSecret,
796
+ endpoint: getGraphqlEndpoint(),
797
+ headers: options.headers,
798
+ logger: options.logger,
799
+ passphrase,
800
+ timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS
801
+ });
802
+ return {
803
+ apiKey,
804
+ createAccount,
805
+ getVersion,
806
+ quote: createQuoteMethod(graphqlClient, options.defaultFees, options.logger),
807
+ supportChain: createSupportChainMethod(graphqlClient),
808
+ swap: createSwapMethod(graphqlClient, options.defaultFees, options.logger),
809
+ txStatus: createTxStatusMethod(graphqlClient)
810
+ };
811
+ }
812
+
813
+ // src/logging/console-logger.ts
814
+ var LEVEL_RANK = {
815
+ debug: 10,
816
+ info: 20,
817
+ warn: 30,
818
+ error: 40
819
+ };
820
+ function createConsoleLogger(options = {}) {
821
+ const minRank = LEVEL_RANK[options.minLevel ?? "info"];
822
+ const target = (level) => {
823
+ const method = globalThis.console[level];
824
+ return typeof method === "function" ? method.bind(globalThis.console) : globalThis.console.log.bind(globalThis.console);
825
+ };
826
+ return Object.freeze({
827
+ log(level, message, metadata) {
828
+ if (LEVEL_RANK[level] < minRank) {
829
+ return;
830
+ }
831
+ try {
832
+ const write = target(level);
833
+ if (metadata === void 0) {
834
+ write(message);
835
+ } else {
836
+ write(message, metadata);
837
+ }
838
+ } catch {
839
+ }
840
+ }
841
+ });
842
+ }
843
+
844
+ // src/errors/not-implemented-error.ts
845
+ var OlympexNotImplementedError = class extends OlympexSdkError {
846
+ constructor(message, metadata) {
847
+ super(message, "OLYMPEX_NOT_IMPLEMENTED", metadata);
848
+ }
849
+ };
850
+ // Annotate the CommonJS export names for ESM import in node:
851
+ 0 && (module.exports = {
852
+ OlympexConfigError,
853
+ OlympexDomainError,
854
+ OlympexGraphQLError,
855
+ OlympexNetworkError,
856
+ OlympexNotImplementedError,
857
+ OlympexSdkError,
858
+ createAccount,
859
+ createConsoleLogger,
860
+ getVersion,
861
+ initialize
862
+ });
863
+ //# sourceMappingURL=index.js.map