UNPKG

@defuse-protocol/one-click-sdk-typescript

Version:
558 lines (548 loc) 18.6 kB
var __typeError = (msg) => { throw TypeError(msg); }; var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); // src/core/ApiError.ts var ApiError = class extends Error { constructor(request2, response, message) { super(message); this.name = "ApiError"; this.url = response.url; this.status = response.status; this.statusText = response.statusText; this.body = response.body; this.request = request2; } }; // src/core/CancelablePromise.ts var CancelError = class extends Error { constructor(message) { super(message); this.name = "CancelError"; } get isCancelled() { return true; } }; var _isResolved, _isRejected, _isCancelled, _cancelHandlers, _promise, _resolve, _reject; var CancelablePromise = class { constructor(executor) { __privateAdd(this, _isResolved); __privateAdd(this, _isRejected); __privateAdd(this, _isCancelled); __privateAdd(this, _cancelHandlers); __privateAdd(this, _promise); __privateAdd(this, _resolve); __privateAdd(this, _reject); __privateSet(this, _isResolved, false); __privateSet(this, _isRejected, false); __privateSet(this, _isCancelled, false); __privateSet(this, _cancelHandlers, []); __privateSet(this, _promise, new Promise((resolve2, reject) => { __privateSet(this, _resolve, resolve2); __privateSet(this, _reject, reject); const onResolve = (value) => { if (__privateGet(this, _isResolved) || __privateGet(this, _isRejected) || __privateGet(this, _isCancelled)) { return; } __privateSet(this, _isResolved, true); if (__privateGet(this, _resolve)) __privateGet(this, _resolve).call(this, value); }; const onReject = (reason) => { if (__privateGet(this, _isResolved) || __privateGet(this, _isRejected) || __privateGet(this, _isCancelled)) { return; } __privateSet(this, _isRejected, true); if (__privateGet(this, _reject)) __privateGet(this, _reject).call(this, reason); }; const onCancel = (cancelHandler) => { if (__privateGet(this, _isResolved) || __privateGet(this, _isRejected) || __privateGet(this, _isCancelled)) { return; } __privateGet(this, _cancelHandlers).push(cancelHandler); }; Object.defineProperty(onCancel, "isResolved", { get: () => __privateGet(this, _isResolved) }); Object.defineProperty(onCancel, "isRejected", { get: () => __privateGet(this, _isRejected) }); Object.defineProperty(onCancel, "isCancelled", { get: () => __privateGet(this, _isCancelled) }); return executor(onResolve, onReject, onCancel); })); } get [Symbol.toStringTag]() { return "Cancellable Promise"; } then(onFulfilled, onRejected) { return __privateGet(this, _promise).then(onFulfilled, onRejected); } catch(onRejected) { return __privateGet(this, _promise).catch(onRejected); } finally(onFinally) { return __privateGet(this, _promise).finally(onFinally); } cancel() { if (__privateGet(this, _isResolved) || __privateGet(this, _isRejected) || __privateGet(this, _isCancelled)) { return; } __privateSet(this, _isCancelled, true); if (__privateGet(this, _cancelHandlers).length) { try { for (const cancelHandler of __privateGet(this, _cancelHandlers)) { cancelHandler(); } } catch (error) { console.warn("Cancellation threw an error", error); return; } } __privateGet(this, _cancelHandlers).length = 0; if (__privateGet(this, _reject)) __privateGet(this, _reject).call(this, new CancelError("Request aborted")); } get isCancelled() { return __privateGet(this, _isCancelled); } }; _isResolved = new WeakMap(); _isRejected = new WeakMap(); _isCancelled = new WeakMap(); _cancelHandlers = new WeakMap(); _promise = new WeakMap(); _resolve = new WeakMap(); _reject = new WeakMap(); // src/core/OpenAPI.ts var OpenAPI = { BASE: "https://1click.chaindefuser.com", VERSION: "0.1.10", WITH_CREDENTIALS: false, CREDENTIALS: "include", TOKEN: void 0, USERNAME: void 0, PASSWORD: void 0, HEADERS: void 0, ENCODE_PATH: void 0 }; // src/models/GetExecutionStatusResponse.ts var GetExecutionStatusResponse; ((GetExecutionStatusResponse2) => { let status; ((status2) => { status2["KNOWN_DEPOSIT_TX"] = "KNOWN_DEPOSIT_TX"; status2["PENDING_DEPOSIT"] = "PENDING_DEPOSIT"; status2["INCOMPLETE_DEPOSIT"] = "INCOMPLETE_DEPOSIT"; status2["PROCESSING"] = "PROCESSING"; status2["SUCCESS"] = "SUCCESS"; status2["REFUNDED"] = "REFUNDED"; status2["FAILED"] = "FAILED"; })(status = GetExecutionStatusResponse2.status || (GetExecutionStatusResponse2.status = {})); })(GetExecutionStatusResponse || (GetExecutionStatusResponse = {})); // src/models/QuoteRequest.ts var QuoteRequest; ((QuoteRequest2) => { let depositMode; ((depositMode2) => { depositMode2["SIMPLE"] = "SIMPLE"; depositMode2["MEMO"] = "MEMO"; })(depositMode = QuoteRequest2.depositMode || (QuoteRequest2.depositMode = {})); let swapType; ((swapType2) => { swapType2["EXACT_INPUT"] = "EXACT_INPUT"; swapType2["EXACT_OUTPUT"] = "EXACT_OUTPUT"; swapType2["FLEX_INPUT"] = "FLEX_INPUT"; })(swapType = QuoteRequest2.swapType || (QuoteRequest2.swapType = {})); let depositType; ((depositType2) => { depositType2["ORIGIN_CHAIN"] = "ORIGIN_CHAIN"; depositType2["INTENTS"] = "INTENTS"; })(depositType = QuoteRequest2.depositType || (QuoteRequest2.depositType = {})); let refundType; ((refundType2) => { refundType2["ORIGIN_CHAIN"] = "ORIGIN_CHAIN"; refundType2["INTENTS"] = "INTENTS"; })(refundType = QuoteRequest2.refundType || (QuoteRequest2.refundType = {})); let recipientType; ((recipientType2) => { recipientType2["DESTINATION_CHAIN"] = "DESTINATION_CHAIN"; recipientType2["INTENTS"] = "INTENTS"; })(recipientType = QuoteRequest2.recipientType || (QuoteRequest2.recipientType = {})); })(QuoteRequest || (QuoteRequest = {})); // src/models/SubmitDepositTxResponse.ts var SubmitDepositTxResponse; ((SubmitDepositTxResponse2) => { let status; ((status2) => { status2["KNOWN_DEPOSIT_TX"] = "KNOWN_DEPOSIT_TX"; status2["PENDING_DEPOSIT"] = "PENDING_DEPOSIT"; status2["INCOMPLETE_DEPOSIT"] = "INCOMPLETE_DEPOSIT"; status2["PROCESSING"] = "PROCESSING"; status2["SUCCESS"] = "SUCCESS"; status2["REFUNDED"] = "REFUNDED"; status2["FAILED"] = "FAILED"; })(status = SubmitDepositTxResponse2.status || (SubmitDepositTxResponse2.status = {})); })(SubmitDepositTxResponse || (SubmitDepositTxResponse = {})); // src/models/TokenResponse.ts var TokenResponse; ((TokenResponse2) => { let blockchain; ((blockchain2) => { blockchain2["NEAR"] = "near"; blockchain2["ETH"] = "eth"; blockchain2["BASE"] = "base"; blockchain2["ARB"] = "arb"; blockchain2["BTC"] = "btc"; blockchain2["SOL"] = "sol"; blockchain2["TON"] = "ton"; blockchain2["DOGE"] = "doge"; blockchain2["XRP"] = "xrp"; blockchain2["ZEC"] = "zec"; blockchain2["GNOSIS"] = "gnosis"; blockchain2["BERA"] = "bera"; blockchain2["BSC"] = "bsc"; blockchain2["POL"] = "pol"; blockchain2["TRON"] = "tron"; blockchain2["SUI"] = "sui"; blockchain2["OP"] = "op"; blockchain2["AVAX"] = "avax"; blockchain2["CARDANO"] = "cardano"; })(blockchain = TokenResponse2.blockchain || (TokenResponse2.blockchain = {})); })(TokenResponse || (TokenResponse = {})); // src/core/request.ts import axios from "axios"; import FormData from "form-data"; var isDefined = (value) => { return value !== void 0 && value !== null; }; var isString = (value) => { return typeof value === "string"; }; var isStringWithValue = (value) => { return isString(value) && value !== ""; }; var isBlob = (value) => { return typeof value === "object" && typeof value.type === "string" && typeof value.stream === "function" && typeof value.arrayBuffer === "function" && typeof value.constructor === "function" && typeof value.constructor.name === "string" && /^(Blob|File)$/.test(value.constructor.name) && /^(Blob|File)$/.test(value[Symbol.toStringTag]); }; var isFormData = (value) => { return value instanceof FormData; }; var isSuccess = (status) => { return status >= 200 && status < 300; }; var base64 = (str) => { try { return btoa(str); } catch (err) { return Buffer.from(str).toString("base64"); } }; var getQueryString = (params) => { const qs = []; const append = (key, value) => { qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`); }; const process = (key, value) => { if (isDefined(value)) { if (Array.isArray(value)) { value.forEach((v) => { process(key, v); }); } else if (typeof value === "object") { Object.entries(value).forEach(([k, v]) => { process(`${key}[${k}]`, v); }); } else { append(key, value); } } }; Object.entries(params).forEach(([key, value]) => { process(key, value); }); if (qs.length > 0) { return `?${qs.join("&")}`; } return ""; }; var getUrl = (config, options) => { const encoder = config.ENCODE_PATH || encodeURI; const path = options.url.replace("{api-version}", config.VERSION).replace(/{(.*?)}/g, (substring, group) => { if (options.path?.hasOwnProperty(group)) { return encoder(String(options.path[group])); } return substring; }); const url = `${config.BASE}${path}`; if (options.query) { return `${url}${getQueryString(options.query)}`; } return url; }; var getFormData = (options) => { if (options.formData) { const formData = new FormData(); const process = (key, value) => { if (isString(value) || isBlob(value)) { formData.append(key, value); } else { formData.append(key, JSON.stringify(value)); } }; Object.entries(options.formData).filter(([_, value]) => isDefined(value)).forEach(([key, value]) => { if (Array.isArray(value)) { value.forEach((v) => process(key, v)); } else { process(key, value); } }); return formData; } return void 0; }; var resolve = async (options, resolver) => { if (typeof resolver === "function") { return resolver(options); } return resolver; }; var getHeaders = async (config, options, formData) => { const [token, username, password, additionalHeaders] = await Promise.all([ resolve(options, config.TOKEN), resolve(options, config.USERNAME), resolve(options, config.PASSWORD), resolve(options, config.HEADERS) ]); const formHeaders = typeof formData?.getHeaders === "function" && formData?.getHeaders() || {}; const headers = Object.entries({ Accept: "application/json", ...additionalHeaders, ...options.headers, ...formHeaders }).filter(([_, value]) => isDefined(value)).reduce((headers2, [key, value]) => ({ ...headers2, [key]: String(value) }), {}); if (isStringWithValue(token)) { headers["Authorization"] = `Bearer ${token}`; } if (isStringWithValue(username) && isStringWithValue(password)) { const credentials = base64(`${username}:${password}`); headers["Authorization"] = `Basic ${credentials}`; } if (options.body !== void 0) { if (options.mediaType) { headers["Content-Type"] = options.mediaType; } else if (isBlob(options.body)) { headers["Content-Type"] = options.body.type || "application/octet-stream"; } else if (isString(options.body)) { headers["Content-Type"] = "text/plain"; } else if (!isFormData(options.body)) { headers["Content-Type"] = "application/json"; } } return headers; }; var getRequestBody = (options) => { if (options.body) { return options.body; } return void 0; }; var sendRequest = async (config, options, url, body, formData, headers, onCancel, axiosClient) => { const source = axios.CancelToken.source(); const requestConfig = { url, headers, data: body ?? formData, method: options.method, withCredentials: config.WITH_CREDENTIALS, withXSRFToken: config.CREDENTIALS === "include" ? config.WITH_CREDENTIALS : false, cancelToken: source.token }; onCancel(() => source.cancel("The user aborted a request.")); try { return await axiosClient.request(requestConfig); } catch (error) { const axiosError = error; if (axiosError.response) { return axiosError.response; } throw error; } }; var getResponseHeader = (response, responseHeader) => { if (responseHeader) { const content = response.headers[responseHeader]; if (isString(content)) { return content; } } return void 0; }; var getResponseBody = (response) => { if (response.status !== 204) { return response.data; } return void 0; }; var catchErrorCodes = (options, result) => { const errors = { 400: "Bad Request", 401: "Unauthorized", 403: "Forbidden", 404: "Not Found", 500: "Internal Server Error", 502: "Bad Gateway", 503: "Service Unavailable", ...options.errors }; const error = errors[result.status]; if (error) { throw new ApiError(options, result, error); } if (!result.ok) { const errorStatus = result.status ?? "unknown"; const errorStatusText = result.statusText ?? "unknown"; const errorBody = (() => { try { return JSON.stringify(result.body, null, 2); } catch (e) { return void 0; } })(); throw new ApiError( options, result, `Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}` ); } }; var request = (config, options, axiosClient = axios) => { return new CancelablePromise(async (resolve2, reject, onCancel) => { try { const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); const headers = await getHeaders(config, options, formData); if (!onCancel.isCancelled) { const response = await sendRequest(config, options, url, body, formData, headers, onCancel, axiosClient); const responseBody = getResponseBody(response); const responseHeader = getResponseHeader(response, options.responseHeader); const result = { url, ok: isSuccess(response.status), status: response.status, statusText: response.statusText, body: responseHeader ?? responseBody }; catchErrorCodes(options, result); resolve2(result.body); } } catch (error) { reject(error); } }); }; // src/services/OneClickService.ts var OneClickService = class { /** * Get supported tokens * Retrieves a list of tokens currently supported by the 1Click API for asset swaps. * * Each token entry includes its blockchain, contract address (if available), price in USD, and other metadata such as symbol and decimals. * @returns TokenResponse * @throws ApiError */ static getTokens() { return request(OpenAPI, { method: "GET", url: "/v0/tokens" }); } /** * Request a swap quote * Generates a swap quote based on input parameters such as the assets, amount, slippage tolerance, and recipient/refund information. * * Returns pricing details, estimated time, and a unique **deposit address** to which tokens must be transferred to initiate the swap. * * You can set the `dry` parameter to `true` to simulate the quote request **without generating a deposit address** or initiating the swap process. This is useful for previewing swap parameters or validating input data without committing to an actual swap. * * This endpoint is the first required step in the swap process. * @param requestBody * @returns QuoteResponse * @throws ApiError */ static getQuote(requestBody) { return request(OpenAPI, { method: "POST", url: "/v0/quote", body: requestBody, mediaType: "application/json", errors: { 400: `Bad Request - Invalid input data`, 401: `Unauthorized - JWT token is invalid` } }); } /** * Check swap execution status * Retrieves the current status of a swap using the unique deposit address from the quote, if quote response included deposit memo, it is required as well. * * The response includes the state of the swap (e.g., pending, processing, success, refunded) and any associated swap and transaction details. * @param depositAddress * @param depositMemo * @returns GetExecutionStatusResponse * @throws ApiError */ static getExecutionStatus(depositAddress, depositMemo) { return request(OpenAPI, { method: "GET", url: "/v0/status", query: { "depositAddress": depositAddress, "depositMemo": depositMemo }, errors: { 401: `Unauthorized - JWT token is invalid`, 404: `Deposit address not found` } }); } /** * Submit deposit transaction hash * Optionally notifies the 1Click service that a deposit has been sent to the specified address, using the blockchain transaction hash. * * This step can speed up swap processing by allowing the system to preemptively verify the deposit. * @param requestBody * @returns SubmitDepositTxResponse * @throws ApiError */ static submitDepositTx(requestBody) { return request(OpenAPI, { method: "POST", url: "/v0/deposit/submit", body: requestBody, mediaType: "application/json", errors: { 400: `Bad Request - Invalid input data`, 401: `Unauthorized - JWT token is invalid` } }); } }; export { ApiError, CancelError, CancelablePromise, GetExecutionStatusResponse, OneClickService, OpenAPI, QuoteRequest, SubmitDepositTxResponse, TokenResponse };