vezgo-sdk-js
Version:
Official Vezgo JS SDK for the Browser & NodeJS
455 lines (454 loc) • 15.8 kB
JavaScript
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
};