UNPKG

gemsdkbeta

Version:

JavaScript SDK for the GEM swap

498 lines 23.9 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.OpenSeaAPI = void 0; require("isomorphic-unfetch"); var QueryString = require("query-string"); var axios_1 = require("axios"); var types_1 = require("./types"); var utils_1 = require("./utils/utils"); var constants_1 = require("./constants"); var OpenSeaAPI = /** @class */ (function () { /** * Create an instance of the OpenSea API * @param config OpenSeaAPIConfig for setting up the API, including an optional API key, network name, and base URL * @param logger Optional function for logging debug strings before and after requests are made */ function OpenSeaAPI(config, logger) { /** * Page size to use for fetching orders */ this.pageSize = 20; this.apiKey = config.apiKey; switch (config.networkName) { case types_1.Network.Rinkeby: this.apiBaseUrl = config.apiBaseUrl || constants_1.API_BASE_RINKEBY; this.hostUrl = constants_1.SITE_HOST_RINKEBY; break; case types_1.Network.Main: default: this.apiBaseUrl = config.apiBaseUrl || constants_1.API_BASE_MAINNET; this.hostUrl = constants_1.SITE_HOST_MAINNET; break; } // Debugging: default to nothing this.logger = logger || (function (arg) { return arg; }); } /** * Send an order to the orderbook. * Throws when the order is invalid. * IN NEXT VERSION: change order input to Order type * @param order Order JSON to post to the orderbook * @param retries Number of times to retry if the service is unavailable for any reason */ OpenSeaAPI.prototype.postOrder = function (order, retries) { if (retries === void 0) { retries = 2; } return __awaiter(this, void 0, void 0, function () { var json, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 4]); return [4 /*yield*/, this.post(constants_1.ORDERBOOK_PATH + "/orders/post/", order)]; case 1: json = (_a.sent()); return [3 /*break*/, 4]; case 2: error_1 = _a.sent(); // @ts-ignore _throwOrContinue(error_1, retries); return [4 /*yield*/, utils_1.delay(3000)]; case 3: _a.sent(); return [2 /*return*/, this.postOrder(order, retries - 1)]; case 4: return [2 /*return*/, utils_1.orderFromJSON(json)]; } }); }); }; /** * Create a whitelist entry for an asset to prevent others from buying. * Buyers will have to have verified at least one of the emails * on an asset in order to buy. * This will throw a 403 if the given API key isn't allowed to create whitelist entries for this contract or asset. * @param tokenAddress Address of the asset's contract * @param tokenId The asset's token ID * @param email The email allowed to buy. */ OpenSeaAPI.prototype.postAssetWhitelist = function (tokenAddress, tokenId, email) { return __awaiter(this, void 0, void 0, function () { var json; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.post(constants_1.API_PATH + "/asset/" + tokenAddress + "/" + tokenId + "/whitelist/", { email: email, })]; case 1: json = _a.sent(); return [2 /*return*/, !!json.success]; } }); }); }; /** * Get an order from the orderbook, throwing if none is found. * @param query Query to use for getting orders. A subset of parameters * on the `OrderJSON` type is supported */ OpenSeaAPI.prototype.getOrder = function (query) { return __awaiter(this, void 0, void 0, function () { var result, orderJSON, json, json; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.get(constants_1.ORDERBOOK_PATH + "/orders/", __assign({ limit: 1 }, query))]; case 1: result = _a.sent(); if (constants_1.ORDERBOOK_VERSION == 0) { json = result; orderJSON = json[0]; } else { json = result; orderJSON = json.orders[0]; } if (!orderJSON) { throw new Error("Not found: no matching order found"); } return [2 /*return*/, utils_1.orderFromJSON(orderJSON)]; } }); }); }; /** * Get a list of orders from the orderbook, returning the page of orders * and the count of total orders found. * @param query Query to use for getting orders. A subset of parameters * on the `OrderJSON` type is supported * @param page Page number, defaults to 1. Can be overridden by * `limit` and `offset` attributes from OrderQuery */ OpenSeaAPI.prototype.getOrders = function (query, page) { if (query === void 0) { query = {}; } if (page === void 0) { page = 1; } return __awaiter(this, void 0, void 0, function () { var result, json, json; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.get(constants_1.ORDERBOOK_PATH + "/orders/", __assign({ limit: this.pageSize, offset: (page - 1) * this.pageSize }, query))]; case 1: result = _a.sent(); if (constants_1.ORDERBOOK_VERSION == 0) { json = result; return [2 /*return*/, { orders: json.map(function (j) { return utils_1.orderFromJSON(j); }), count: json.length, }]; } else { json = result; return [2 /*return*/, { orders: json.orders.map(function (j) { return utils_1.orderFromJSON(j); }), count: json.count, }]; } return [2 /*return*/]; } }); }); }; /** * Fetch an asset from the API, throwing if none is found * @param tokenAddress Address of the asset's contract * @param tokenId The asset's token ID, or null if ERC-20 * @param retries Number of times to retry if the service is unavailable for any reason */ OpenSeaAPI.prototype.getAsset = function (_a, retries) { var tokenAddress = _a.tokenAddress, tokenId = _a.tokenId; if (retries === void 0) { retries = 1; } return __awaiter(this, void 0, void 0, function () { var json, error_2; return __generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 2, , 4]); return [4 /*yield*/, this.get(constants_1.API_PATH + "/asset/" + tokenAddress + "/" + (tokenId || 0) + "/")]; case 1: json = _b.sent(); return [3 /*break*/, 4]; case 2: error_2 = _b.sent(); // @ts-ignore _throwOrContinue(error_2, retries); return [4 /*yield*/, utils_1.delay(3000)]; case 3: _b.sent(); return [2 /*return*/, this.getAsset({ tokenAddress: tokenAddress, tokenId: tokenId }, retries - 1)]; case 4: return [2 /*return*/, utils_1.assetFromJSON(json)]; } }); }); }; /** * Fetch list of assets from the API, returning the page of assets and the count of total assets * @param query Query to use for getting orders. A subset of parameters on the `OpenSeaAssetJSON` type is supported * @param page Page number, defaults to 1. Can be overridden by * `limit` and `offset` attributes from OpenSeaAssetQuery */ OpenSeaAPI.prototype.getAssets = function (query, page) { if (query === void 0) { query = {}; } if (page === void 0) { page = 1; } return __awaiter(this, void 0, void 0, function () { var json, error_3; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 4]); return [4 /*yield*/, this.get(constants_1.API_PATH + "/assets/", __assign({ limit: this.pageSize, offset: (page - 1) * this.pageSize }, query))]; case 1: json = _a.sent(); return [3 /*break*/, 4]; case 2: error_3 = _a.sent(); // @ts-ignore _throwOrContinue(error_3, retries); return [4 /*yield*/, utils_1.delay(3000)]; case 3: _a.sent(); return [2 /*return*/, this.getAssets(query, page)]; case 4: return [2 /*return*/, { assets: json.assets.map(function (j) { return utils_1.assetFromJSON(j); }), estimatedCount: json.estimated_count, }]; } }); }); }; /** * Fetch list of fungible tokens from the API matching paramters * @param query Query to use for getting orders. A subset of parameters on the `OpenSeaAssetJSON` type is supported * @param page Page number, defaults to 1. Can be overridden by * `limit` and `offset` attributes from OpenSeaFungibleTokenQuery * @param retries Number of times to retry if the service is unavailable for any reason */ OpenSeaAPI.prototype.getPaymentTokens = function (query, page, retries) { if (query === void 0) { query = {}; } if (page === void 0) { page = 1; } if (retries === void 0) { retries = 1; } return __awaiter(this, void 0, void 0, function () { var json, error_4; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 4]); return [4 /*yield*/, this.get(constants_1.API_PATH + "/tokens/", __assign(__assign({}, query), { limit: this.pageSize, offset: (page - 1) * this.pageSize }))]; case 1: json = _a.sent(); return [3 /*break*/, 4]; case 2: error_4 = _a.sent(); // @ts-ignore _throwOrContinue(error_4, retries); return [4 /*yield*/, utils_1.delay(3000)]; case 3: _a.sent(); return [2 /*return*/, this.getPaymentTokens(query, page, retries - 1)]; case 4: return [2 /*return*/, { tokens: json.map(function (t) { return utils_1.tokenFromJSON(t); }), }]; } }); }); }; /** * Fetch an bundle from the API, return null if it isn't found * @param slug The bundle's identifier */ OpenSeaAPI.prototype.getBundle = function (_a) { var slug = _a.slug; return __awaiter(this, void 0, void 0, function () { var json; return __generator(this, function (_b) { switch (_b.label) { case 0: return [4 /*yield*/, this.get(constants_1.API_PATH + "/bundle/" + slug + "/")]; case 1: json = _b.sent(); return [2 /*return*/, json ? utils_1.assetBundleFromJSON(json) : null]; } }); }); }; /** * Fetch list of bundles from the API, returning the page of bundles and the count of total bundles * @param query Query to use for getting orders. A subset of parameters on the `OpenSeaAssetBundleJSON` type is supported * @param page Page number, defaults to 1. Can be overridden by * `limit` and `offset` attributes from OpenSeaAssetBundleQuery */ OpenSeaAPI.prototype.getBundles = function (query, page) { if (query === void 0) { query = {}; } if (page === void 0) { page = 1; } return __awaiter(this, void 0, void 0, function () { var json; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, this.get(constants_1.API_PATH + "/bundles/", __assign(__assign({}, query), { limit: this.pageSize, offset: (page - 1) * this.pageSize }))]; case 1: json = _a.sent(); return [2 /*return*/, { bundles: json.bundles.map(function (j) { return utils_1.assetBundleFromJSON(j); }), estimatedCount: json.estimated_count, }]; } }); }); }; /** * Get JSON data from API, sending auth token in headers * @param apiPath Path to URL endpoint under API * @param query Data to send. Will be stringified using QueryString */ OpenSeaAPI.prototype.get = function (apiPath, query) { if (query === void 0) { query = {}; } return __awaiter(this, void 0, void 0, function () { var qs, url, response; return __generator(this, function (_a) { switch (_a.label) { case 0: qs = QueryString.stringify(query); url = apiPath + "?" + qs; return [4 /*yield*/, this._fetch(url)]; case 1: response = _a.sent(); return [2 /*return*/, response]; } }); }); }; /** * POST JSON data to API, sending auth token in headers * @param apiPath Path to URL endpoint under API * @param body Data to send. Will be JSON.stringified * @param opts RequestInit opts, similar to Fetch API. If it contains * a body, it won't be stringified. */ OpenSeaAPI.prototype.post = function (apiPath, body, opts) { if (opts === void 0) { opts = {}; } return __awaiter(this, void 0, void 0, function () { var fetchOpts, response; return __generator(this, function (_a) { switch (_a.label) { case 0: fetchOpts = __assign({ method: "POST", body: body ? JSON.stringify(body) : undefined, headers: { Accept: "application/json", "Content-Type": "application/json", } }, opts); return [4 /*yield*/, this._fetch(apiPath, fetchOpts)]; case 1: response = _a.sent(); return [2 /*return*/, response]; } }); }); }; /** * PUT JSON data to API, sending auth token in headers * @param apiPath Path to URL endpoint under API * @param body Data to send * @param opts RequestInit opts, similar to Fetch API. If it contains * a body, it won't be stringified. */ OpenSeaAPI.prototype.put = function (apiPath, body, opts) { if (opts === void 0) { opts = {}; } return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, this.post(apiPath, body, __assign({ method: "PUT" }, opts))]; }); }); }; /** * Get from an API Endpoint, sending auth token in headers * @param apiPath Path to URL endpoint under API * @param opts RequestInit opts, similar to Fetch API */ OpenSeaAPI.prototype._fetch = function (apiPath, opts) { if (opts === void 0) { opts = {}; } return __awaiter(this, void 0, void 0, function () { var response; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, axios_1.default.post("https://gem-public-api.herokuapp.com/fetchMethod", { apiPath: apiPath, opts: opts, apiBaseUrl: this.apiBaseUrl, })]; case 1: response = _a.sent(); return [2 /*return*/, response.data]; } }); }); }; OpenSeaAPI.prototype._handleApiResponse = function (response) { return __awaiter(this, void 0, void 0, function () { var result, errorMessage, _a; return __generator(this, function (_b) { switch (_b.label) { case 0: if (response.ok) { this.logger("Got success: " + response.status); return [2 /*return*/, response]; } _b.label = 1; case 1: _b.trys.push([1, 3, , 4]); return [4 /*yield*/, response.text()]; case 2: result = _b.sent(); result = JSON.parse(result); return [3 /*break*/, 4]; case 3: _a = _b.sent(); return [3 /*break*/, 4]; case 4: this.logger("Got error " + response.status + ": " + JSON.stringify(result)); switch (response.status) { case 400: errorMessage = result && result.errors ? result.errors.join(", ") : "Invalid request: " + JSON.stringify(result); break; case 401: case 403: errorMessage = "Unauthorized. Full message was '" + JSON.stringify(result) + "'"; break; case 404: errorMessage = "Not found. Full message was '" + JSON.stringify(result) + "'"; break; case 500: errorMessage = "Internal server error. OpenSea has been alerted, but if the problem persists please contact us via Discord: https://discord.gg/ga8EJbv - full message was " + JSON.stringify(result); break; case 503: errorMessage = "Service unavailable. Please try again in a few minutes. If the problem persists please contact us via Discord: https://discord.gg/ga8EJbv - full message was " + JSON.stringify(result); break; default: errorMessage = "Message: " + JSON.stringify(result); break; } throw new Error("API Error " + response.status + ": " + errorMessage); } }); }); }; return OpenSeaAPI; }()); exports.OpenSeaAPI = OpenSeaAPI; function _throwOrContinue(error, retries) { var isUnavailable = !!error.message && (error.message.includes("503") || error.message.includes("429")); if (retries <= 0 || !isUnavailable) { throw error; } } //# sourceMappingURL=api.js.map