@defuse-protocol/one-click-sdk-typescript
Version:
TypeScript SDK for 1Click API
558 lines (548 loc) • 18.6 kB
JavaScript
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
};