UNPKG

@yoroi/swap

Version:
243 lines (239 loc) 7.11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.steelswapApiMaker = exports.parseSteelswapError = void 0; var _common = require("@yoroi/common"); var _types = require("@yoroi/types"); var _immer = require("immer"); var _transformers = require("./transformers"); const steelswapApiMaker = config => { const { address, network, request = _common.fetchData } = config; if (network !== _types.Chain.Network.Mainnet) return new Proxy({}, { get() { return () => Promise.resolve((0, _immer.freeze)({ tag: 'left', error: { status: -3, message: 'Steelswap api only works on mainnet' } }, true)); } }); const headers = { 'Content-Type': 'application/json', 'Accept': 'application/json', 'token': 'yoroi-xEwoVRkAcYSn4fgxsx5kS2ZJRBxPzAe15GyyG8FZVJEgn7e9UHfVZ07FwUBUAbmM' }; const baseUrl = baseUrls[network]; const transformers = (0, _transformers.transformersMaker)({ ...config }); const api = (0, _immer.freeze)({ async tokens() { const response = await request({ method: 'get', url: `${baseUrl}${apiPaths.tokens}`, headers }); if ((0, _common.isLeft)(response)) return parseSteelswapError(response); return (0, _immer.freeze)({ tag: 'right', value: { status: response.value.status, data: transformers.tokens.response(response.value.data) } }, true); }, async orders() { const requestBody = { addresses: [address], txType: ['swap'], page: 0, pageSize: 100, isFloat: true }; const response = await request({ method: 'post', url: `${baseUrl}${apiPaths.orders}`, headers, data: requestBody }); if ((0, _common.isLeft)(response)) return parseSteelswapError(response); try { return (0, _immer.freeze)({ tag: 'right', value: { status: 200, data: transformers.orders.response(response.value.data).sort(({ lastUpdate: A, placedAt: A2 }, { lastUpdate: B, placedAt: B2 }) => (B ?? B2 ?? 0) - (A ?? A2 ?? 0)) } }, true); } catch (e) { return (0, _immer.freeze)({ tag: 'left', error: { status: -3, message: 'Failed to transform orders', responseData: response.value.data } }, true); } }, async limitOptions() { return (0, _immer.freeze)({ tag: 'left', error: { status: -3, message: 'Limit options not supported', responseData: null } }, true); }, async estimate(body) { // Reject limit estimates (wantedPrice) - not supported if (body.wantedPrice !== undefined) { return (0, _immer.freeze)({ tag: 'left', error: { status: -1, message: 'Steelswap Aggregator only supports market', responseData: null } }); } const requestBody = transformers.estimate.request(body); const response = await request({ method: 'post', url: `${baseUrl}${apiPaths.estimate}`, headers, data: requestBody }); if ((0, _common.isLeft)(response)) return parseSteelswapError(response); try { return (0, _immer.freeze)({ tag: 'right', value: { status: response.value.status, data: transformers.estimate.response(response.value.data) } }, true); } catch (e) { return (0, _immer.freeze)({ tag: 'left', error: { status: -3, message: 'No liquidity pools satisfy the estimate requirements', responseData: response.value.data } }, true); } }, async create(body) { const requestBody = transformers.create.request(body); const response = await request({ method: 'post', url: `${baseUrl}${apiPaths.create}`, headers, data: requestBody }); if ((0, _common.isLeft)(response)) return parseSteelswapError(response); // Make an estimate call to get the swap details (build endpoint doesn't return splits) const estimateRequest = { amountIn: body.amountIn, tokenIn: body.tokenIn, tokenOut: body.tokenOut, slippage: body.slippage ?? 0, blockedProtocols: body.blockedProtocols, protocol: body.protocol }; const estimateResponse = await this.estimate(estimateRequest); // If estimate fails, return the create response with minimal data if ((0, _common.isLeft)(estimateResponse)) { return (0, _immer.freeze)({ tag: 'right', value: { status: response.value.status, data: transformers.create.response(response.value.data) } }, true); } // Merge the CBOR from create with the estimate data const estimateData = estimateResponse.value.data; const mergedData = { ...estimateData, cbor: response.value.data.tx, aggregator: _types.Swap.Aggregator.Steelswap, totalInput: estimateData.totalInput ?? body.amountIn }; return (0, _immer.freeze)({ tag: 'right', value: { status: response.value.status, data: mergedData } }, true); }, async cancel(body) { const requestBody = transformers.cancel.request(body); const response = await request({ method: 'post', url: `${baseUrl}${apiPaths.cancel}`, headers, data: requestBody }); if ((0, _common.isLeft)(response)) return parseSteelswapError(response); return (0, _immer.freeze)({ tag: 'right', value: { status: response.value.status, data: transformers.cancel.response(response.value.data) } }, true); } }, true); return api; }; exports.steelswapApiMaker = steelswapApiMaker; const parseSteelswapError = ({ tag, error }) => { const responseData = error.responseData; let message = 'Steelswap API error'; if (responseData) { if (typeof responseData.detail === 'string') { message = responseData.detail; } else if (Array.isArray(responseData.detail)) { message = responseData.detail.map(err => `${err.loc.join('.')}: ${err.msg}`).join('; '); } } return (0, _immer.freeze)({ tag, error: { ...error, message } }, true); }; exports.parseSteelswapError = parseSteelswapError; const baseUrls = (0, _immer.freeze)({ [_types.Chain.Network.Mainnet]: 'https://yoroi.steelswap.io' }); const apiPaths = (0, _immer.freeze)({ tokens: '/tokens/list/', orders: '/wallet/history/', estimate: '/swap/estimate/', create: '/swap/build/', cancel: '/swap/cancel/' }); //# sourceMappingURL=api-maker.js.map