UNPKG

@spindl-xyz/attribution-lite

Version:
1,000 lines (971 loc) 38.9 kB
(function(factory) { typeof define === "function" && define.amd ? define(factory) : factory(); })((function() { "use strict"; var CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; var ENTROPY = 32; function legacy() { var str = ""; for (var i = 0; i < ENTROPY; i++) { str += CHARSET.charAt(Math.floor(Math.random() * CHARSET.length)); } return str; } function generateRandomString() { if (typeof window === "undefined" || typeof crypto === "undefined" || typeof crypto.getRandomValues === "undefined") { return legacy(); } var values = crypto.getRandomValues(new Uint8Array(ENTROPY)); return Array.from(values, (function(value) { return CHARSET[value % CHARSET.length]; })).join(""); } function getGlobal() { if (typeof self !== "undefined") { return self; } if (typeof window !== "undefined") { return window; } return undefined; } function parseHashParams(hash) { if (hash === "") return undefined; var paramsStartIndex = hash.indexOf("?"); if (paramsStartIndex < 0 || paramsStartIndex >= hash.length - 1) return undefined; var params = hash.substring(paramsStartIndex + 1); var hashIndex = params.indexOf("#"); if (hashIndex >= 0) { params = params.substring(0, hashIndex); } return new URLSearchParams(params); } function getUrlSearchParams() { if (typeof window === "undefined") { return; } var _a = new URL(window === null || window === void 0 ? void 0 : window.location.href), searchParams = _a.searchParams, hash = _a.hash; var hashParams = parseHashParams(hash); if (hashParams) { hashParams.forEach((function(value, key) { if (!searchParams.has(key)) { searchParams.append(key, value); } })); } return searchParams; } var __assign = function() { __assign = Object.assign || function __assign(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); }; function __awaiter(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()); })); } function __generator(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 (g && (g = 0, op[0] && (_ = 0)), _) 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 }; } } function __values(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function() { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; var defaultOptions = { sdkKey: "", api: "https://api.spindl.xyz/v1", host: "https://spindl.link", maxRetries: 3, debugMode: false }; function createConfigPlugin(initialConfig) { var _a, _b; var _config = __assign(__assign(__assign({}, defaultOptions), initialConfig), { sdkKey: (_b = (_a = initialConfig.sdkKey) !== null && _a !== void 0 ? _a : initialConfig.API_KEY) !== null && _b !== void 0 ? _b : defaultOptions.sdkKey }); function setConfig(updates) { var _a, _b; var sdkKey = (_b = (_a = updates.API_KEY) !== null && _a !== void 0 ? _a : updates.sdkKey) !== null && _b !== void 0 ? _b : _config.sdkKey; _config = __assign(__assign(__assign({}, _config), updates), { sdkKey: sdkKey }); } function getConfig() { return _config; } return { setConfig: setConfig, getConfig: getConfig }; } function createHttpClientPlugin(configPlugin, logger) { function send(options) { return __awaiter(this, void 0, void 0, (function() { var response, e_1; return __generator(this, (function(_a) { switch (_a.label) { case 0: _a.trys.push([ 0, 2, , 3 ]); return [ 4, fetch(options.url, options) ]; case 1: response = _a.sent(); if (!response.ok) { logger.error("request failed with http code:", response.status); return [ 2, undefined ]; } return [ 2, response ]; case 2: e_1 = _a.sent(); if (e_1.message === "Failed to fetch") { return [ 2, { stopRetry: true } ]; } logger.error("request failed", e_1); return [ 2, undefined ]; case 3: return [ 2 ]; } })); })); } function retryRequest(request) { return __awaiter(this, void 0, void 0, (function() { var i, response; return __generator(this, (function(_a) { switch (_a.label) { case 0: i = 0; _a.label = 1; case 1: if (!(i < configPlugin.getConfig().maxRetries)) return [ 3, 4 ]; return [ 4, request() ]; case 2: response = _a.sent(); if ((response === null || response === void 0 ? void 0 : response.stopRetry) === true) { return [ 2 ]; } if (response === null || response === void 0 ? void 0 : response.ok) { return [ 2, response ]; } _a.label = 3; case 3: i++; return [ 3, 1 ]; case 4: return [ 2, undefined ]; } })); })); } function retrySend(options) { return __awaiter(this, void 0, void 0, (function() { var sendRequest; return __generator(this, (function(_a) { sendRequest = function() { return send(options); }; return [ 2, retryRequest(sendRequest) ]; })); })); } return { send: send, retrySend: retrySend, retryRequest: retryRequest }; } var LogPrefix = "Spindl SDK"; function createLoggerPlugin(configPlugin) { function info() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (configPlugin.getConfig().debugMode) { console.log.apply(console, __spreadArray([ "[".concat(LogPrefix, "]") ], __read(args), false)); } } function warn() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (configPlugin.getConfig().debugMode) { console.warn.apply(console, __spreadArray([ "[".concat(LogPrefix, "]") ], __read(args), false)); } } function error() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } console.error.apply(console, __spreadArray([ "[".concat(LogPrefix, "]") ], __read(args), false)); } return { info: info, warn: warn, error: error }; } var isWindow = typeof window === "object"; var getSourceUrl = function() { var _a; return isWindow ? (_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.href : undefined; }; var gerReferrer = function() { var _a; return isWindow ? (_a = window === null || window === void 0 ? void 0 : window.document) === null || _a === void 0 ? void 0 : _a.referrer : undefined; }; function createPageViewPlugin(beacon) { var autoPageTrackInitialized = false; function pageView() { var globalThis = getGlobal(); if (typeof globalThis === "undefined" || typeof document === "undefined" || typeof location === "undefined") { return; } var sourceUrl = getSourceUrl(); var referrer = gerReferrer(); return beacon.sendBeacon({ type: "PAGE_VIEW", data: { sourceUrl: sourceUrl, referrer: referrer } }); } function enableAutoPageViews(props) { var _a = (props || {}).trackReplaceState, trackReplaceState = _a === void 0 ? false : _a; var globalThis = getGlobal(); if (typeof globalThis === "undefined" || typeof history === "undefined" || autoPageTrackInitialized === true) { return function() {}; } autoPageTrackInitialized = true; pageView(); var track = function() { return pageView(); }; var pushState = history.pushState; var replaceState = history.replaceState; if (pushState && replaceState) { history.pushState = function(data, unused, url) { pushState.call(this, data, unused, url); track(); }; history.replaceState = function(data, unused, url) { replaceState.call(this, data, unused, url); if (trackReplaceState) { track(); } }; addEventListener("popstate", track); } return function() { if (pushState) { history.pushState = pushState; history.replaceState = replaceState; removeEventListener("popstate", track); } }; } return { pageView: pageView, enableAutoPageViews: enableAutoPageViews }; } var createReferrerCodePlugin = function() { var globalThis = getGlobal(); if (typeof globalThis === "undefined" || typeof localStorage === "undefined") { return { getValue: function() { return {}; } }; } var REFERRER_CODE_KEY = "spindl_referrer_code"; var referrerCode = localStorage.getItem(REFERRER_CODE_KEY) || ""; function getValue() { return __awaiter(this, void 0, void 0, (function() { var urlParams, newReferrerCode; return __generator(this, (function(_a) { urlParams = getUrlSearchParams(); newReferrerCode = urlParams.get("ref"); if (newReferrerCode && newReferrerCode !== referrerCode) { referrerCode = newReferrerCode; localStorage.setItem(REFERRER_CODE_KEY, referrerCode); } if (!referrerCode) { return [ 2, {} ]; } return [ 2, { referrerCode: referrerCode } ]; })); })); } return { getValue: getValue }; }; function createSdkPlugin(initialConfig, version) { var configPlugin = createConfigPlugin(initialConfig); var logger = createLoggerPlugin(configPlugin); var http = createHttpClientPlugin(configPlugin, logger); return __assign(__assign({}, configPlugin), { http: http, logger: logger, version: version }); } var createSessionIdPlugin = function() { var globalThis = getGlobal(); if (typeof globalThis === "undefined" || typeof sessionStorage === "undefined") { return { getValue: function() { return {}; } }; } var SESSION_ID_KEY = "spindl_session_id"; var sessionId = sessionStorage.getItem(SESSION_ID_KEY) || ""; if (!sessionId) { sessionId = generateRandomString(); sessionStorage.setItem(SESSION_ID_KEY, sessionId); } function getValue() { return { sessionId: sessionId }; } return { getValue: getValue }; }; var StorageNoop = { length: 0, clear: function() {}, getItem: function(key) { return null; }, key: function(index) { return null; }, removeItem: function(key) {}, setItem: function(key, value) {} }; function createBeaconPlugin(sdk, metadata) { var _a; var globalThis = getGlobal(); var storage; if (typeof globalThis === "undefined" || typeof sessionStorage === "undefined") { storage = StorageNoop; } else { storage = sessionStorage; } var REQUEST_ID_KEY = "spindl_request_id"; var reqId = parseInt((_a = storage.getItem(REQUEST_ID_KEY)) !== null && _a !== void 0 ? _a : "0"); function getRequestId() { var updatedValue = reqId + 1; storage.setItem(REQUEST_ID_KEY, updatedValue.toString()); return reqId++; } function sendBeacon(beacon) { return __awaiter(this, void 0, void 0, (function() { var headers, meta, reqId, payload, response; return __generator(this, (function(_a) { switch (_a.label) { case 0: headers = { "X-API-Key": sdk.getConfig().sdkKey }; return [ 4, metadata.getMetadata() ]; case 1: meta = _a.sent(); reqId = getRequestId(); payload = __assign(__assign({}, beacon), { metadata: __assign(__assign({ version: sdk.version }, meta), { reqId: reqId }) }); return [ 4, sdk.http.retrySend({ url: "".concat(sdk.getConfig().host, "/events"), headers: __assign(__assign({}, headers), { "content-type": "application/json" }), method: "POST", credentials: "include", body: JSON.stringify(payload) }) ]; case 2: response = _a.sent(); if (response) { sdk.logger.info("sent ".concat(payload.type)); } return [ 2, Boolean(response) ]; } })); })); } return { sendBeacon: sendBeacon }; } function createWalletConnectsPlugin(beacon) { function attribute(address) { var sourceUrl = getSourceUrl(); var referrer = gerReferrer(); return beacon.sendBeacon({ type: "WALLET_CONNECTED", data: { address: address, sourceUrl: sourceUrl, referrer: referrer } }); } function enableAutoWalletConnects() { var _a; var connectedAddress; var provider = (window === null || window === void 0 ? void 0 : window.ethereum) || ((_a = window.web3) === null || _a === void 0 ? void 0 : _a.currentProvider); var listener = function() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var accounts = args[0]; if (accounts.length > 0 && accounts[0] !== connectedAddress) { attribute(accounts[0]); connectedAddress = accounts[0]; } else { connectedAddress = undefined; } }; provider === null || provider === void 0 ? void 0 : provider.on("accountsChanged", listener); addEventListener("load", (function(event) { var _a, _b, _c; var selectedAddress = ((_a = window === null || window === void 0 ? void 0 : window.ethereum) === null || _a === void 0 ? void 0 : _a.selectedAddress) || ((_c = (_b = window.web3) === null || _b === void 0 ? void 0 : _b.currentProvider) === null || _c === void 0 ? void 0 : _c.selectedAddress); if (selectedAddress && connectedAddress !== selectedAddress) { connectedAddress = selectedAddress; attribute(selectedAddress); } })); return function() { if (provider) { provider.removeListener("accountsChanged", listener); } }; } return { attribute: attribute, enableAutoWalletConnects: enableAutoWalletConnects }; } function createReferralApiPlugin(sdk, metadata) { function getReferrerAttribution(address) { return __awaiter(this, void 0, void 0, (function() { var url, meta, response, body; return __generator(this, (function(_a) { switch (_a.label) { case 0: url = new URL("".concat(sdk.getConfig().api, "/referrer-attribution/").concat(address)); return [ 4, metadata.getMetadata() ]; case 1: meta = _a.sent(); if (typeof meta.referrerCode === "string") { url.searchParams.set("ref", meta.referrerCode); } return [ 4, sdk.http.send({ url: url.toString(), headers: { "X-API-Key": sdk.getConfig().sdkKey }, method: "GET" }) ]; case 2: response = _a.sent(); if (!(response === null || response === void 0 ? void 0 : response.ok)) { sdk.logger.error("request failed with http code:", response.status); return [ 2, undefined ]; } return [ 4, response.json() ]; case 3: body = _a.sent(); return [ 2, body.attribution ]; } })); })); } function getReferrerHistory(address) { return __awaiter(this, void 0, void 0, (function() { var url, response, body; return __generator(this, (function(_a) { switch (_a.label) { case 0: url = new URL("".concat(sdk.getConfig().api, "/referrals/history/").concat(address)); return [ 4, sdk.http.send({ url: url.toString(), headers: { "X-API-Key": sdk.getConfig().sdkKey }, method: "GET" }) ]; case 1: response = _a.sent(); if (!(response === null || response === void 0 ? void 0 : response.ok)) { sdk.logger.error("request failed with http code:", response.status); return [ 2, undefined ]; } return [ 4, response.json() ]; case 2: body = _a.sent(); return [ 2, body.items ]; } })); })); } function getReferrerStats(address) { return __awaiter(this, void 0, void 0, (function() { var url, response, body; return __generator(this, (function(_a) { switch (_a.label) { case 0: url = new URL("".concat(sdk.getConfig().api, "/referrals/stats/").concat(address)); return [ 4, sdk.http.send({ url: url.toString(), headers: { "X-API-Key": sdk.getConfig().sdkKey }, method: "GET" }) ]; case 1: response = _a.sent(); if (!(response === null || response === void 0 ? void 0 : response.ok)) { sdk.logger.error("request failed with http code:", response.status); return [ 2, undefined ]; } return [ 4, response.json() ]; case 2: body = _a.sent(); return [ 2, body ]; } })); })); } function createReferrerCode(address, code) { return __awaiter(this, void 0, void 0, (function() { var response, body; return __generator(this, (function(_a) { switch (_a.label) { case 0: return [ 4, sdk.http.send({ url: "".concat(sdk.getConfig().api, "/referrer-codes"), headers: { "X-API-Key": sdk.getConfig().sdkKey, "content-type": "application/json" }, method: "POST", body: JSON.stringify({ address: address, code: code }) }) ]; case 1: response = _a.sent(); if (!response.ok) { sdk.logger.error("request failed with http code:", response.status); return [ 2, undefined ]; } return [ 4, response.json() ]; case 2: body = _a.sent(); return [ 2, body.code ]; } })); })); } function validateReferrerCode(slug) { return typeof slug === "string" && /^([a-z0-9_]){4,20}$/.test(slug); } function checkReferrerCode(code) { return __awaiter(this, void 0, void 0, (function() { var response, body; return __generator(this, (function(_a) { switch (_a.label) { case 0: return [ 4, sdk.http.send({ url: "".concat(sdk.getConfig().api, "/referrer-codes/check-availability"), headers: { "X-API-Key": sdk.getConfig().sdkKey, "content-type": "application/json" }, method: "POST", body: JSON.stringify({ code: code }) }) ]; case 1: response = _a.sent(); if (!response.ok) { sdk.logger.error("request failed with http code:", response.status); return [ 2, false ]; } return [ 4, response.json() ]; case 2: body = _a.sent(); return [ 2, body.available ]; } })); })); } function getReferrerCodes(filter) { if (filter === void 0) { filter = {}; } return __awaiter(this, void 0, void 0, (function() { var url, response; return __generator(this, (function(_a) { switch (_a.label) { case 0: url = new URL("".concat(sdk.getConfig().api, "/referrer-codes")); if (filter.address) { url.searchParams.set("address", filter.address); } if (filter.code) { url.searchParams.set("code", filter.code); } return [ 4, sdk.http.send({ url: url.toString(), headers: { "X-API-Key": sdk.getConfig().sdkKey }, method: "GET" }) ]; case 1: response = _a.sent(); if (!response.ok) { sdk.logger.error("request failed with http code:", response.status); return [ 2, [] ]; } return [ 2, response.json() ]; } })); })); } function getReferrerCode(address) { return __awaiter(this, void 0, void 0, (function() { var referrerCodes; return __generator(this, (function(_a) { switch (_a.label) { case 0: if (!address) return [ 2 ]; return [ 4, getReferrerCodes({ address: address }) ]; case 1: referrerCodes = _a.sent(); if (referrerCodes === null || referrerCodes === void 0 ? void 0 : referrerCodes.length) { return [ 2, referrerCodes[0].code ]; } return [ 2 ]; } })); })); } function getReferrerAddress(code) { return __awaiter(this, void 0, void 0, (function() { var referrerCodes; return __generator(this, (function(_a) { switch (_a.label) { case 0: if (!code) return [ 2 ]; return [ 4, getReferrerCodes({ code: code }) ]; case 1: referrerCodes = _a.sent(); if (referrerCodes === null || referrerCodes === void 0 ? void 0 : referrerCodes.length) { return [ 2, referrerCodes[0].address ]; } return [ 2 ]; } })); })); } return { getReferrerAttribution: getReferrerAttribution, getReferrerStats: getReferrerStats, getReferrerHistory: getReferrerHistory, createReferrerCode: createReferrerCode, validateReferrerCode: validateReferrerCode, checkReferrerCode: checkReferrerCode, getReferrerCode: getReferrerCode, getReferrerAddress: getReferrerAddress }; } var createTimestampPlugin = function() { function getValue() { return { ts: (new Date).getTime() }; } return { getValue: getValue }; }; var createRestrictedPlugin = function() { function getValue() { return { restricted: true }; } return { getValue: getValue }; }; function createCustomEventsPlugin(beacon) { function track(name, properties, identityProps) { var sourceUrl = getSourceUrl(); return beacon.sendBeacon({ type: "CUSTOM", data: { name: name, properties: properties, sourceUrl: sourceUrl }, identity: identityProps }); } return { track: track }; } function createMetadataPlugin(plugins) { var factories = plugins.map((function(plugin) { return plugin(); })); function getMetadata() { return __awaiter(this, void 0, void 0, (function() { var tuples, result, tuples_1, tuples_1_1, tuple; var e_1, _a; return __generator(this, (function(_b) { switch (_b.label) { case 0: return [ 4, Promise.all(factories.map((function(factory) { return factory.getValue(); }))) ]; case 1: tuples = _b.sent(); result = {}; try { for (tuples_1 = __values(tuples), tuples_1_1 = tuples_1.next(); !tuples_1_1.done; tuples_1_1 = tuples_1.next()) { tuple = tuples_1_1.value; Object.assign(result, tuple); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (tuples_1_1 && !tuples_1_1.done && (_a = tuples_1.return)) _a.call(tuples_1); } finally { if (e_1) throw e_1.error; } } return [ 2, result ]; } })); })); } return { getMetadata: getMetadata }; } var _a, _b, _c; var VERSION = "1.8.1"; var sdk = createSdkPlugin({ sdkKey: "" }, VERSION); var metadata = createMetadataPlugin([ createSessionIdPlugin, createReferrerCodePlugin, createTimestampPlugin, createRestrictedPlugin ]); var beacon = createBeaconPlugin(sdk, metadata); var pageView = (_a = createPageViewPlugin(beacon), _a.pageView), enableAutoPageViews = _a.enableAutoPageViews; var attribute = (_b = createWalletConnectsPlugin(beacon), _b.attribute), enableAutoWalletConnects = _b.enableAutoWalletConnects; var checkReferrerCode = (_c = createReferralApiPlugin(sdk, metadata), _c.checkReferrerCode), createReferrerCode = _c.createReferrerCode, getReferrerAddress = _c.getReferrerAddress, getReferrerAttribution = _c.getReferrerAttribution, getReferrerHistory = _c.getReferrerHistory, getReferrerStats = _c.getReferrerStats, getReferrerCode = _c.getReferrerCode, validateReferrerCode = _c.validateReferrerCode; var track = createCustomEventsPlugin(beacon).track; function configure(initialConfig) { sdk.setConfig(initialConfig); } var client = Object.freeze({ __proto__: null, attribute: attribute, checkReferrerCode: checkReferrerCode, configure: configure, createReferrerCode: createReferrerCode, enableAutoPageViews: enableAutoPageViews, enableAutoWalletConnects: enableAutoWalletConnects, getReferrerAddress: getReferrerAddress, getReferrerAttribution: getReferrerAttribution, getReferrerCode: getReferrerCode, getReferrerHistory: getReferrerHistory, getReferrerStats: getReferrerStats, pageView: pageView, track: track, validateReferrerCode: validateReferrerCode }); module.exports = client; })); //# sourceMappingURL=attribution.development.js.map