UNPKG

vezgo-sdk-js

Version:

Official Vezgo JS SDK for the Browser & NodeJS

455 lines (454 loc) 15.8 kB
import O from "apisauce"; import S from "jsonwebtoken"; const D = "https://api.vezgo.com", U = "https://connect.vezgo.com", V = "v1", j = `${D}/${V}`, B = () => typeof window < "u" && Object.prototype.toString.call(window) === "[object Window]" && !window.Deno, q = () => typeof global < "u" && Object.prototype.toString.call(global) === "[object global]", x = () => typeof Deno < "u", K = () => q() || x(), M = () => typeof navigator < "u" && navigator.product === "ReactNative"; function G() { const s = "vezgo-connect-widget", t = document.createElement("iframe"); return t.name = s, t.frameBorder = 0, t.allow = "clipboard-read *; clipboard-write *", t.setAttribute("style", [ "width:100%; height:100%;", "position:fixed;", "top:0; left:0; right:0; bottom:0;", "z-index:2147483647;" // max possible z-index ].join(" ")), document.body.appendChild(t), t.style.display = "block", t; } function F({ url: s, token: t, iframe: e }) { const i = document.createElement("form"); i.target = e.name, i.method = "POST", i.action = s, i.style.display = "none"; const r = document.createElement("input"); return r.type = "text", r.name = "token", r.value = t, i.appendChild(r), document.body.appendChild(i), i; } const d = (s = {}) => { const t = new URLSearchParams(); return Object.keys(s).forEach((e) => { t.append(e, s[e]); }), t.toString(); }; class A extends Error { constructor({ message: t, existing_institution_id: e } = {}) { super(t || "This connection is already linked to your account."), this.name = "DuplicateConnectionError", this.existing_institution_id = e; } } function g(s) { if (!s.ok) throw s.status === 409 ? new A(s.data || {}) : s.originalError; } class Q { constructor(t) { this.api = t.userApi; } async getList(t = {}) { let e = "/accounts"; const i = d(t); i && (e = `${e}?${i}`); const r = await this.api.get(e); return g(r), r.data; } async getOne(t, e = {}) { if (!t || typeof t != "string") throw new Error("Please provide a valid Vezgo account id."); let i = `/accounts/${t}`; const r = d(e); r && (i = `${i}?${r}`); const o = await this.api.get(i); return g(o), o.data; } async sync(t) { if (!t || typeof t != "string") throw new Error("Please provide a valid Vezgo account id."); const e = await this.api.post(`/accounts/${t}/sync`, {}); return g(e), e.data; } async getKYCData(t) { if (!t || typeof t != "string") throw new Error("Please provide a valid Vezgo account id."); const e = await this.api.get(`/accounts/${t}/kyc-data`); return e.status === 404 ? null : (g(e), e.data); } async remove(t) { if (!t || typeof t != "string") throw new Error("Please provide a valid Vezgo account id."); const e = await this.api.delete(`/accounts/${t}`); g(e); } } class J { constructor(t) { this.api = t.userApi; } async getList(t = {}) { const { accountId: e, ...i } = t; if (!e || typeof e != "string") throw new Error("Please provide a valid Vezgo account id."); let r = `/accounts/${e}/history`; const o = d(i); o && (r = `${r}?${o}`); const n = await this.api.get(r); if (!n.ok) throw n.originalError; return n.data; } } class Y { constructor(t) { this.api = t.api; } async getList(t = {}) { let e = "/providers"; const i = d(t); i && (e = `${e}?${i}`); const r = await this.api.get(e); if (!r.ok) throw r.originalError; return r.data; } async getOne(t) { if (!t || typeof t != "string") throw new Error("Please provide a valid Vezgo provider id."); const e = await this.api.get(`/providers/${t}`); if (!e.ok) throw e.originalError; return e.data; } } class H { constructor(t) { this.api = t.api, this.clientId = t.config.clientId; } async info() { const t = await this.api.get(`/teams/info?client_id=${this.clientId}`); if (!t.ok) throw t.originalError; return t.data; } } class X { constructor(t) { this.api = t.userApi; } async getList(t = {}) { const { accountId: e, ...i } = t; if (!e || typeof e != "string") throw new Error("Please provide a valid Vezgo account id."); let r = `/accounts/${e}/transactions`; const o = d(i); o && (r = `${r}?${o}`); const n = await this.api.get(r); if (!n.ok) throw n.originalError; return n.data; } async getOne(t = {}) { const { accountId: e, txId: i, ...r } = t; if (!e || typeof e != "string") throw new Error("Please provide a valid Vezgo account id."); if (!i || typeof i != "string") throw new Error("Please provide a valid Vezgo transaction id."); let o = `/accounts/${e}/transactions/${i}`; const n = d(r); n && (o = `${o}?${n}`); const a = await this.api.get(o); if (!a.ok) throw a.originalError; return a.data; } } class Z { constructor(t) { this.api = t.userApi; } async getList(t = {}) { const { accountId: e, ...i } = t; if (!e || typeof e != "string") throw new Error("Please provide a valid Vezgo account id."); let r = `/accounts/${e}/orders`; const o = d(i); o && (r = `${r}?${o}`); const n = await this.api.get(r); if (!n.ok) throw n.originalError; return n.data; } async getOne(t = {}) { const { accountId: e, orderId: i, ...r } = t; if (!e || typeof e != "string") throw new Error("Please provide a valid Vezgo account id."); if (!i || typeof i != "string") throw new Error("Please provide a valid Vezgo order id."); let o = `/accounts/${e}/orders/${i}`; const n = d(r); n && (o = `${o}?${n}`); const a = await this.api.get(o); if (!a.ok) throw a.originalError; return a.data; } } const tt = { accounts: Q, history: J, providers: Y, teams: H, transactions: X, orders: Z }; function b(s, t) { return t.reduce((e, i) => (e[i] = new tt[i](s), e), {}); } const L = "_onConnection", p = "_onError", E = "_onEvent", et = [ "DUPLICATE_CONNECTION", "CLIENT_ID_REQUIRED", "WRONG_CLIENT_ID", "INVALID_ORIGIN", "TOKEN_REQUIRED", "WRONG_REDIRECT_URI", "INVALID_ACCOUNT_ID", "PAGE_NOT_FOUND", "SESSION_EXPIRED", "INVALID_TOKEN" ]; class N { constructor(t) { this.config = { ...t }, this.config.baseURL = this.config.baseURL || j, this.config.connectURL = this.config.connectURL || U; const { clientId: e, secret: i } = this.config; if (this.isBrowser = B(), this.isNodeOrSimilar = K(), this.isReactNative = M(), this.isClient = this.isBrowser || this.isReactNative, !e || typeof e != "string") throw new Error("Please provide a valid Vezgo clientId."); if (this.isNodeOrSimilar && (!i || typeof i != "string")) throw new Error("Please provide a valid Vezgo secret."); if (this.isBrowser) { const r = t.auth || {}; this.config.authEndpoint = this.config.authEndpoint || "/vezgo/auth", this.config.auth = { params: r.params || {}, headers: r.headers || {} }, this.authApi = O.create({ headers: this.config.auth.headers }); } this._token = {}, this._onWidgetMessage = this._onMessage.bind(this), this._widgetOpened = !1, this._widgetActive = !1; } _init() { const { loginName: t, baseURL: e } = this.config; this.api = O.create({ baseURL: e }); const i = b(this, ["providers", "teams"]); return Object.assign(this, i), t ? this.login(t) : this; } login(t) { if (this.isNodeOrSimilar && (!t || typeof t != "string")) throw new Error("Please provide a valid loginName."); const { baseURL: e } = this.config, i = new N({ ...this.config, loginName: null }); i._init(), i.userApi = O.create({ baseURL: e }), i.userApi.addAsyncRequestTransform(async (o) => (o.headers.Authorization = `Bearer ${await i.getToken()}`, o)); const r = b(i, ["accounts", "history", "transactions"]); return Object.assign(i, r), i.config.loginName = t, i; } async getToken(t = {}) { const e = (/* @__PURE__ */ new Date()).valueOf(), { payload: i } = this._token; let { token: r } = this._token; return (!i || e > (i.exp - (t.minimumLifetime || 10)) * 1e3) && (r = await this.fetchToken()), r; } async fetchToken() { const t = await (this.isClient ? this._fetchTokenClient() : this._fetchTokenNode()); if (!t.ok && !t.token) throw t.originalError; const { token: e } = t.data || t, i = S.decode(e); return this._token = { token: e, payload: i }, this._token.token; } _fetchTokenNode() { const { clientId: t, secret: e, loginName: i } = this.config; return this.api.post("/auth/token", { clientId: t, secret: e }, { headers: { loginName: i } }); } _fetchTokenClient() { const { auth: t, authEndpoint: e, authorizer: i } = this.config, { params: r } = t; return typeof i == "function" ? new Promise((o, n) => { i((a, c) => { if (a) { n(a); return; } if (!c || typeof c != "object" || !c.token) { n(new Error('Invalid authorizer result. Expecting `{ token: "the token" }`.')); return; } o(c); }); }) : this.authApi.post(e, r); } getTeam() { return this.teams.info(); } async getConnectData(t = {}) { const { provider: e, disabledProviders: i, accountId: r, state: o, origin: n = this.isBrowser ? window.location.origin : void 0, lang: a, redirectURI: c = this.config.redirectURI, syncNfts: y = !0, providerCategories: l, providers: u, theme: w, providersPerLine: f, features: C, multiWallet: m, hideWalletConnectWallets: v, providersPreferences: P } = t, { clientId: T, connectURL: I } = this.config; let R = e; if (e && !r) { if (!this.cachedProviders) try { this.cachedProviders = await this.providers.getList(); } catch (k) { throw console.error(k), new Error("Failed to fetch providers list."); } const h = this.cachedProviders.find((k) => k.name === e); if (!h) throw new Error("Provider not found."); h.alternate_names && (R = h.alternate_names[h.alternate_names.length - 1]); } const z = await this.getToken({ minimumLifetime: 600 }), _ = { client_id: T, redirect_uri: c, state: o, lang: a || "en", origin: n, sync_nfts: y === !1 ? !1 : void 0, // only pass if it is false demo: this.config.demo ? !0 : void 0, // 'provider' param in priority, skip 'provider_categories' param if 'provider' is set provider_categories: !e && Array.isArray(l) && l.length ? l.join(",") : void 0, // 'provider' param in priority, skip 'providers' param if 'provider' is set providers: !e && Array.isArray(u) && u.length ? u.join(",") : void 0, disabled_providers: i && Array.isArray(i) && i.length ? i.join(",") : void 0, theme: ["light", "dark"].includes(w) ? w : "light", providers_per_line: f && ["1", "2"].includes(f.toString()) ? f.toString() : "2", features: C, multi_wallet: m, hide_wallet_connect_wallets: v, providers_preferences: JSON.stringify(P) }; Object.keys(_).forEach( (h) => [void 0, null, ""].includes(_[h]) && delete _[h] ); const W = new URLSearchParams(_).toString(); let $ = R ? `${I}/connect/${R}` : `${I}/connect`; return r && ($ = `${I}/reconnect/${r}`), { url: `${$}?${W}`, token: z }; } connect(t = {}) { return this._connect(t), this; } reconnect(t, e = {}) { if (!t || typeof t != "string") throw new Error("Please provide a valid accountId."); return this._connect({ accountId: t, ...e }), this; } onConnection(t) { if (typeof t != "function") throw new Error("Callback must be a function."); return this[L] = t.bind(this), this; } onError(t) { if (typeof t != "function") throw new Error("Callback must be a function."); return this[p] = t.bind(this), this; } onEvent(t) { if (typeof t != "function") throw new Error("Callback must be a function."); return this[E] = t.bind(this), this; } _connect(t = {}) { if (!this.isBrowser) throw new Error("Only supported in Browser."); (async () => { try { this._widgetOpened = !0; const { provider: e, providers: i, disabledProviders: r, providerCategories: o, accountId: n, lang: a, theme: c, providersPerLine: y, syncNfts: l, features: u, multiWallet: w, hideWalletConnectWallets: f, providersPreferences: C } = t, { url: m, token: v } = await this.getConnectData({ provider: e, providers: i, disabledProviders: r, providerCategories: o, accountId: n, lang: a, theme: c, providersPerLine: y, syncNfts: l, features: u, multiWallet: w, hideWalletConnectWallets: f, providersPreferences: C }); this.iframe = G(), t.connectionType === "GET" ? this.widget = window.open(`${m}&token=${v}`, this.iframe.name) : (this.widget = window.open("", this.iframe.name), this.form = F({ url: m, token: v, iframe: this.iframe }), this.form.submit()), this.widget.focus(), this._widgetActive = !0, this._addListeners(), this._addWatchers(); } catch { this._closeWidgetWithError(500, "Connection refused"); } })(); } _onMessage({ origin: t, data: e }) { let i = e; try { i = JSON.parse(e); } catch { } if (i.vezgo) { if (t !== this.config.connectURL && !/\.vezgo\.com$/.test(new URL(t).hostname)) throw new Error(`Calling Vezgo from unauthorized origin ${t}`); switch (i.event) { case "success": { this._triggerCallback(L, i.account); break; } case "error": { this._triggerCallback(p, i.error); break; } case "ERROR": { et.includes(i.data && i.data.type) ? this._triggerCallback(p, i.data) : this._triggerCallback(E, i); break; } case "close": { this._closeWidgetWithError(400, "Connection closed"); break; } default: this._triggerCallback(E, i); } } } _addWatchers() { const t = setTimeout(() => { this._closeWidgetWithError(400, "Connection timeout"); }, 6e5), e = setInterval(() => { this._widgetActive ? this.widget.closed && this._closeWidgetWithError(400, "Connection closed") : (this._removeListeners(), clearInterval(e), clearTimeout(t), this._closeWidget()); }, 1e3); } // eslint-disable-next-line camelcase _closeWidgetWithError(t, e) { this._closeWidget(), this._triggerCallback(p, { error_type: t, message: e }); } _closeWidget() { this._widgetActive = !1, this.widget && !this.widget.closed && this.widget.close(), this.iframe && this.iframe.remove(), this.form && this.form.remove(); } _triggerCallback(t, e) { if ([L, p].includes(t)) { this._widgetActive = !1, this._widgetOpened && (this._widgetOpened = !1, this[t] && this[t](e)); return; } if (t === E && this[t]) { const i = e ? e.event : null, r = e ? e.data : null; this[t](i, r); } } _addListeners() { window.addEventListener("message", this._onWidgetMessage, !1); } _removeListeners() { window.removeEventListener("message", this._onWidgetMessage, !1); } } class it { init(t = {}) { return new N(t)._init(); } } const rt = new it(); rt.DuplicateConnectionError = A; export { rt as default };