UNPKG

dappauth

Version:

A Plug-n-Play library for adding UI interface for adding decentralized authentication to your dapp.

1,122 lines (1,098 loc) 210 kB
import bowser from 'bowser'; import BigNumber from 'bignumber.js'; import request from 'request'; import WalletConnectProvider from '@walletconnect/web3-provider'; import Portis from '@portis/web3'; import Fortmatic from 'fortmatic'; import Authereum from 'authereum'; import Squarelink from 'squarelink'; import Torus from '@toruslabs/torus-embed'; import DappkitApi from 'dappkit-sdk'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ 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) { 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) : new P(function (resolve) { resolve(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 (_) 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 noop() { } const identity = x => x; function assign(tar, src) { // @ts-ignore for (const k in src) tar[k] = src[k]; return tar; } function run(fn) { return fn(); } function blank_object() { return Object.create(null); } function run_all(fns) { fns.forEach(run); } function is_function(thing) { return typeof thing === 'function'; } function safe_not_equal(a, b) { return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function'); } function subscribe(store, callback) { const unsub = store.subscribe(callback); return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub; } function get_store_value(store) { let value; subscribe(store, _ => value = _)(); return value; } function component_subscribe(component, store, callback) { component.$$.on_destroy.push(subscribe(store, callback)); } function create_slot(definition, ctx, fn) { if (definition) { const slot_ctx = get_slot_context(definition, ctx, fn); return definition[0](slot_ctx); } } function get_slot_context(definition, ctx, fn) { return definition[1] ? assign({}, assign(ctx.$$scope.ctx, definition[1](fn ? fn(ctx) : {}))) : ctx.$$scope.ctx; } function get_slot_changes(definition, ctx, changed, fn) { return definition[1] ? assign({}, assign(ctx.$$scope.changed || {}, definition[1](fn ? fn(changed) : {}))) : ctx.$$scope.changed || {}; } const is_client = typeof window !== 'undefined'; let now = is_client ? () => window.performance.now() : () => Date.now(); let raf = is_client ? cb => requestAnimationFrame(cb) : noop; const tasks = new Set(); let running = false; function run_tasks() { tasks.forEach(task => { if (!task[0](now())) { tasks.delete(task); task[1](); } }); running = tasks.size > 0; if (running) raf(run_tasks); } function loop(fn) { let task; if (!running) { running = true; raf(run_tasks); } return { promise: new Promise(fulfil => { tasks.add(task = [fn, fulfil]); }), abort() { tasks.delete(task); } }; } function append(target, node) { target.appendChild(node); } function insert(target, node, anchor) { target.insertBefore(node, anchor || null); } function detach(node) { node.parentNode.removeChild(node); } function destroy_each(iterations, detaching) { for (let i = 0; i < iterations.length; i += 1) { if (iterations[i]) iterations[i].d(detaching); } } function element(name) { return document.createElement(name); } function svg_element(name) { return document.createElementNS('http://www.w3.org/2000/svg', name); } function text(data) { return document.createTextNode(data); } function space() { return text(' '); } function empty() { return text(''); } function listen(node, event, handler, options) { node.addEventListener(event, handler, options); return () => node.removeEventListener(event, handler, options); } function attr(node, attribute, value) { if (value == null) node.removeAttribute(attribute); else node.setAttribute(attribute, value); } function children(element) { return Array.from(element.childNodes); } function set_data(text, data) { data = '' + data; if (text.data !== data) text.data = data; } function set_style(node, key, value, important) { node.style.setProperty(key, value, important ? 'important' : ''); } function toggle_class(element, name, toggle) { element.classList[toggle ? 'add' : 'remove'](name); } function custom_event(type, detail) { const e = document.createEvent('CustomEvent'); e.initCustomEvent(type, false, false, detail); return e; } class HtmlTag { constructor(html, anchor = null) { this.e = element('div'); this.a = anchor; this.u(html); } m(target, anchor = null) { for (let i = 0; i < this.n.length; i += 1) { insert(target, this.n[i], anchor); } this.t = target; } u(html) { this.e.innerHTML = html; this.n = Array.from(this.e.childNodes); } p(html) { this.d(); this.u(html); this.m(this.t, this.a); } d() { this.n.forEach(detach); } } let stylesheet; let active = 0; let current_rules = {}; // https://github.com/darkskyapp/string-hash/blob/master/index.js function hash(str) { let hash = 5381; let i = str.length; while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i); return hash >>> 0; } function create_rule(node, a, b, duration, delay, ease, fn, uid = 0) { const step = 16.666 / duration; let keyframes = '{\n'; for (let p = 0; p <= 1; p += step) { const t = a + (b - a) * ease(p); keyframes += p * 100 + `%{${fn(t, 1 - t)}}\n`; } const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`; const name = `__svelte_${hash(rule)}_${uid}`; if (!current_rules[name]) { if (!stylesheet) { const style = element('style'); document.head.appendChild(style); stylesheet = style.sheet; } current_rules[name] = true; stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length); } const animation = node.style.animation || ''; node.style.animation = `${animation ? `${animation}, ` : ``}${name} ${duration}ms linear ${delay}ms 1 both`; active += 1; return name; } function delete_rule(node, name) { node.style.animation = (node.style.animation || '') .split(', ') .filter(name ? anim => anim.indexOf(name) < 0 // remove specific animation : anim => anim.indexOf('__svelte') === -1 // remove all Svelte animations ) .join(', '); if (name && !--active) clear_rules(); } function clear_rules() { raf(() => { if (active) return; let i = stylesheet.cssRules.length; while (i--) stylesheet.deleteRule(i); current_rules = {}; }); } let current_component; function set_current_component(component) { current_component = component; } function get_current_component() { if (!current_component) throw new Error(`Function called outside component initialization`); return current_component; } function onDestroy(fn) { get_current_component().$$.on_destroy.push(fn); } const dirty_components = []; const binding_callbacks = []; const render_callbacks = []; const flush_callbacks = []; const resolved_promise = Promise.resolve(); let update_scheduled = false; function schedule_update() { if (!update_scheduled) { update_scheduled = true; resolved_promise.then(flush); } } function add_render_callback(fn) { render_callbacks.push(fn); } function flush() { const seen_callbacks = new Set(); do { // first, call beforeUpdate functions // and update components while (dirty_components.length) { const component = dirty_components.shift(); set_current_component(component); update(component.$$); } while (binding_callbacks.length) binding_callbacks.pop()(); // then, once components are updated, call // afterUpdate functions. This may cause // subsequent updates... for (let i = 0; i < render_callbacks.length; i += 1) { const callback = render_callbacks[i]; if (!seen_callbacks.has(callback)) { callback(); // ...so guard against infinite loops seen_callbacks.add(callback); } } render_callbacks.length = 0; } while (dirty_components.length); while (flush_callbacks.length) { flush_callbacks.pop()(); } update_scheduled = false; } function update($$) { if ($$.fragment) { $$.update($$.dirty); run_all($$.before_update); $$.fragment.p($$.dirty, $$.ctx); $$.dirty = null; $$.after_update.forEach(add_render_callback); } } let promise; function wait() { if (!promise) { promise = Promise.resolve(); promise.then(() => { promise = null; }); } return promise; } function dispatch(node, direction, kind) { node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`)); } const outroing = new Set(); let outros; function group_outros() { outros = { r: 0, c: [], p: outros // parent group }; } function check_outros() { if (!outros.r) { run_all(outros.c); } outros = outros.p; } function transition_in(block, local) { if (block && block.i) { outroing.delete(block); block.i(local); } } function transition_out(block, local, detach, callback) { if (block && block.o) { if (outroing.has(block)) return; outroing.add(block); outros.c.push(() => { outroing.delete(block); if (callback) { if (detach) block.d(1); callback(); } }); block.o(local); } } const null_transition = { duration: 0 }; function create_in_transition(node, fn, params) { let config = fn(node, params); let running = false; let animation_name; let task; let uid = 0; function cleanup() { if (animation_name) delete_rule(node, animation_name); } function go() { const { delay = 0, duration = 300, easing = identity, tick = noop, css } = config || null_transition; if (css) animation_name = create_rule(node, 0, 1, duration, delay, easing, css, uid++); tick(0, 1); const start_time = now() + delay; const end_time = start_time + duration; if (task) task.abort(); running = true; add_render_callback(() => dispatch(node, true, 'start')); task = loop(now => { if (running) { if (now >= end_time) { tick(1, 0); dispatch(node, true, 'end'); cleanup(); return running = false; } if (now >= start_time) { const t = easing((now - start_time) / duration); tick(t, 1 - t); } } return running; }); } let started = false; return { start() { if (started) return; delete_rule(node); if (is_function(config)) { config = config(); wait().then(go); } else { go(); } }, invalidate() { started = false; }, end() { if (running) { cleanup(); running = false; } } }; } function create_bidirectional_transition(node, fn, params, intro) { let config = fn(node, params); let t = intro ? 0 : 1; let running_program = null; let pending_program = null; let animation_name = null; function clear_animation() { if (animation_name) delete_rule(node, animation_name); } function init(program, duration) { const d = program.b - t; duration *= Math.abs(d); return { a: t, b: program.b, d, duration, start: program.start, end: program.start + duration, group: program.group }; } function go(b) { const { delay = 0, duration = 300, easing = identity, tick = noop, css } = config || null_transition; const program = { start: now() + delay, b }; if (!b) { // @ts-ignore todo: improve typings program.group = outros; outros.r += 1; } if (running_program) { pending_program = program; } else { // if this is an intro, and there's a delay, we need to do // an initial tick and/or apply CSS animation immediately if (css) { clear_animation(); animation_name = create_rule(node, t, b, duration, delay, easing, css); } if (b) tick(0, 1); running_program = init(program, duration); add_render_callback(() => dispatch(node, b, 'start')); loop(now => { if (pending_program && now > pending_program.start) { running_program = init(pending_program, duration); pending_program = null; dispatch(node, running_program.b, 'start'); if (css) { clear_animation(); animation_name = create_rule(node, t, running_program.b, running_program.duration, 0, easing, config.css); } } if (running_program) { if (now >= running_program.end) { tick(t = running_program.b, 1 - t); dispatch(node, running_program.b, 'end'); if (!pending_program) { // we're done if (running_program.b) { // intro — we can tidy up immediately clear_animation(); } else { // outro — needs to be coordinated if (!--running_program.group.r) run_all(running_program.group.c); } } running_program = null; } else if (now >= running_program.start) { const p = now - running_program.start; t = running_program.a + running_program.d * easing(p / running_program.duration); tick(t, 1 - t); } } return !!(running_program || pending_program); }); } } return { run(b) { if (is_function(config)) { wait().then(() => { // @ts-ignore config = config(); go(b); }); } else { go(b); } }, end() { clear_animation(); running_program = pending_program = null; } }; } function mount_component(component, target, anchor) { const { fragment, on_mount, on_destroy, after_update } = component.$$; fragment.m(target, anchor); // onMount happens before the initial afterUpdate add_render_callback(() => { const new_on_destroy = on_mount.map(run).filter(is_function); if (on_destroy) { on_destroy.push(...new_on_destroy); } else { // Edge case - component was destroyed immediately, // most likely as a result of a binding initialising run_all(new_on_destroy); } component.$$.on_mount = []; }); after_update.forEach(add_render_callback); } function destroy_component(component, detaching) { if (component.$$.fragment) { run_all(component.$$.on_destroy); component.$$.fragment.d(detaching); // TODO null out other refs, including component.$$ (but need to // preserve final state?) component.$$.on_destroy = component.$$.fragment = null; component.$$.ctx = {}; } } function make_dirty(component, key) { if (!component.$$.dirty) { dirty_components.push(component); schedule_update(); component.$$.dirty = blank_object(); } component.$$.dirty[key] = true; } function init(component, options, instance, create_fragment, not_equal, prop_names) { const parent_component = current_component; set_current_component(component); const props = options.props || {}; const $$ = component.$$ = { fragment: null, ctx: null, // state props: prop_names, update: noop, not_equal, bound: blank_object(), // lifecycle on_mount: [], on_destroy: [], before_update: [], after_update: [], context: new Map(parent_component ? parent_component.$$.context : []), // everything else callbacks: blank_object(), dirty: null }; let ready = false; $$.ctx = instance ? instance(component, props, (key, ret, value = ret) => { if ($$.ctx && not_equal($$.ctx[key], $$.ctx[key] = value)) { if ($$.bound[key]) $$.bound[key](value); if (ready) make_dirty(component, key); } return ret; }) : props; $$.update(); ready = true; run_all($$.before_update); $$.fragment = create_fragment($$.ctx); if (options.target) { if (options.hydrate) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion $$.fragment.l(children(options.target)); } else { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion $$.fragment.c(); } if (options.intro) transition_in(component.$$.fragment); mount_component(component, options.target, options.anchor); flush(); } set_current_component(parent_component); } class SvelteComponent { $destroy() { destroy_component(this, 1); this.$destroy = noop; } $on(type, callback) { const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = [])); callbacks.push(callback); return () => { const index = callbacks.indexOf(callback); if (index !== -1) callbacks.splice(index, 1); }; } $set() { // overridden by instance, if it has props } } const subscriber_queue = []; /** * Creates a `Readable` store that allows reading by subscription. * @param value initial value * @param {StartStopNotifier}start start and stop notifications for subscriptions */ function readable(value, start) { return { subscribe: writable(value, start).subscribe, }; } /** * Create a `Writable` store that allows both updating and reading by subscription. * @param {*=}value initial value * @param {StartStopNotifier=}start start and stop notifications for subscriptions */ function writable(value, start = noop) { let stop; const subscribers = []; function set(new_value) { if (safe_not_equal(value, new_value)) { value = new_value; if (stop) { // store is ready const run_queue = !subscriber_queue.length; for (let i = 0; i < subscribers.length; i += 1) { const s = subscribers[i]; s[1](); subscriber_queue.push(s, value); } if (run_queue) { for (let i = 0; i < subscriber_queue.length; i += 2) { subscriber_queue[i][0](subscriber_queue[i + 1]); } subscriber_queue.length = 0; } } } } function update(fn) { set(fn(value)); } function subscribe(run, invalidate = noop) { const subscriber = [run, invalidate]; subscribers.push(subscriber); if (subscribers.length === 1) { stop = start(set) || noop; } run(value); return () => { const index = subscribers.indexOf(subscriber); if (index !== -1) { subscribers.splice(index, 1); } if (subscribers.length === 0) { stop(); stop = null; } }; } return { set, update, subscribe }; } /** * Derived value store by synchronizing one or more readable stores and * applying an aggregation function over its input values. * @param {Stores} stores input stores * @param {function(Stores=, function(*)=):*}fn function callback that aggregates the values * @param {*=}initial_value when used asynchronously */ function derived(stores, fn, initial_value) { const single = !Array.isArray(stores); const stores_array = single ? [stores] : stores; const auto = fn.length < 2; return readable(initial_value, (set) => { let inited = false; const values = []; let pending = 0; let cleanup = noop; const sync = () => { if (pending) { return; } cleanup(); const result = fn(single ? values[0] : values, set); if (auto) { set(result); } else { cleanup = is_function(result) ? result : noop; } }; const unsubscribers = stores_array.map((store, i) => store.subscribe((value) => { values[i] = value; pending &= ~(1 << i); if (inited) { sync(); } }, () => { pending |= (1 << i); })); inited = true; sync(); return function stop() { run_all(unsubscribers); cleanup(); }; }); } var extensionInstallMessage = function (helpers) { var currentWallet = helpers.currentWallet, selectedWallet = helpers.selectedWallet; if (currentWallet) { return "\n <p style=\"font-size: 0.889rem; font-family: 'Montserrat', sans-serif; margin: 0.889rem 0;\">\n We have detected that you already have\n <b>" + currentWallet + "</b>\n installed. If you would prefer to use\n <b>" + selectedWallet + "</b>\n instead, then click below to install.\n </p>\n <p style=\"font-size: 0.889rem; font-family: 'Montserrat', sans-serif; margin: 0.889rem 0;\">\n <b>Tip:</b>\n If you already have " + selectedWallet + " installed, check your\n browser extension settings to make sure that you have it enabled\n and that you have disabled any other browser extension wallets.\n <span\n class=\"bn-onboard-clickable\"\n style=\"color: #4a90e2;\"\n onclick=\"window.location.reload();\">\n Then refresh the page.\n </span>\n </p>\n "; } else { return "\n <p style=\"font-size: 0.889rem; font-family: 'Montserrat', sans-serif; margin: 0.889rem 0;\">\n You'll need to install <b>" + selectedWallet + "</b> to continue. Install\n the extension and then\n <span\n class=\"bn-clickable\"\n style=\"color: #4a90e2;\"\n onclick={window.location.reload();}>\n refresh the page.\n </span>\n </p>\n "; } }; var mobileWalletInstallMessage = function (helpers) { var selectedWallet = helpers.selectedWallet; return "\n <p style=\"font-size: 0.889rem;\">\n You'll need to install <b>" + selectedWallet + "</b> to continue. Click below to install and then load this Dapp with <b>" + selectedWallet + "</b>.\n </p>\n "; }; var metamaskIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAoCAMAAACl6XjsAAABfVBMVEVHcEx/Rh2ARx2ESiLwiCLMu67cfCagZDOddlJ+Rx7pgiPlfyPshSN/Rxx+Rh2CSB6ASB2JTR7gkkl1SCbQciPUwLLMu6+BSB5/Rx2DSR5+RxzefR3ogCPlfiPGuLHhfiP2jCTvhyN/Rx3nfyPfo2/lfCTIuK7kfyP2jCPkfiPuhSTFtKjogSThfCR/Rx5+Rx3lfiPeeiTDs6koIR2DSh/ifCajWx6qYCDckVOBSR7jfiTyiCOYYTXLcCKpXiHEs6fDs6fCsKYjHBwhHx8iHR0iICB1a2ZyaGIiHyCPTx7ogSTlfyTwhyOASB7ziSTngCTrgyT2jCTthCT1iyPuhCX4jSSESh5/Rx6ITR/+kSTYbyDheSLjfSPBaiPacSDdcyCvYSK0ZCGTVSPGcSblhi/ngSPqgSTdu56mXSDaeSP6jiPmfSD5jSQcGhvimFdqUj/TbSJARUsyQE6tbDLOeyzZx7nayr7hsog7Nza/raDjjUF/VTjFtKhKNCB0amRMd0DeAAAASnRSTlMAe/oOkv4TAwgrpnA9n1n9vkYfHPv+xu2r9mgN6uI4Us5ji/n9Ln7G7pO61/K35ZXYiUji5s21zMnb0/r5aMipm2UkYjSGnPy0/l1QcU4AAALOSURBVHhehdJXXxpNFAbwBYIgoICCIKhgi91ETe/9fZ3ZXui92bvp5bPnzCwzK79c+Fxws3/mOXN2BSe+0Tnh1oBKTI7eqvypSUnaHP4XDIVeRn1cucKSJIUj4wMF6cVgYDr2KsrVXE4imUx6mEmHgoH786ZZ3b3H/usZAWW7R3fsAFFNhCrVwmaKdY4ylZdaqEgjI4yxUm7mpAjvjABjbt/QIIZJ1MF+Pu+eY3MMuwEwl2sfEidiBcdaeUl6yrcEkzks38IWMBnG2gUVTrIljSco4LUNGZxRaeZASW4X63Q5hznHyTGqpAfRwU5+WKGtaxC1SQsSKb+tfOyeTHWRDEyuNGhpf7me5EBjoYowFoEZ+gFx7pH+FYaTA0qBfSG6ErI2KcxZJMxVDhSkS1sV4twuNls0wVi4CYpEJ6yHwXEmpHJ5OxJTGNHhMLjH/BP0uQp2GpTwVhHY+orAExLt9ChxWhFWprYcFihaNKLDegZt7U4FuRpbPtbssONgRNECVjm6wYJFrR+5XK/VavVa9byO4L3qpWqMl/qznGlipV46b5xdturYIK//54sND7sAR3SnlfbZxeVFFYkw3MHV9dIQv8CAQ7qlXl+1kUoO78mMsQvwXiRbh8VjEenEqat9NlvUBmLJol2v6jDe89U0Vb7sDQa7k/UjxZSp04mjpw1ewBBRuV6qVbCCRFmzNNE0rOVZP2EZE9F0u10F10qQsr1hVTQ0WTSs7KwP2NA0wjxlUHWCmJRlo5jNELdlYidQaR92RINRp1P4vfPxnSAszis3XLkMD3Gn8+P0dGHh697e3vdvJyf/f4CrLqm8xFx/+IQ+jH/+QgK/wHbek9ZZwhSkq1MbwUW/f+buRJyIfn79+e/TuGBfomfi6UBmjH3NIL19Ffd6J2YEmhX92UqGbpEHzlzzeuNxL6ht9lmG0g5w5PbrtbWJN2/HyGB/AYd1QUewqrrRAAAAAElFTkSuQmCC"; var metamaskIcon2x = "data:image/png;base64,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"; function metamask() { return { name: "MetaMask", iconSrc: metamaskIcon, iconSrcSet: metamaskIcon2x, wallet: function (helpers) { var getProviderName = helpers.getProviderName, createModernProviderInterface = helpers.createModernProviderInterface, createLegacyProviderInterface = helpers.createLegacyProviderInterface; var provider = window.ethereum || (window.web3 && window.web3.currentProvider); return { provider: provider, interface: provider && getProviderName(provider) === "MetaMask" ? typeof provider.enable === "function" ? createModernProviderInterface(provider) : createLegacyProviderInterface(provider) : null }; }, link: "https://metamask.io/", installMessage: extensionInstallMessage }; } function createModernProviderInterface(provider) { provider.autoRefreshOnNetworkChange = false; return { address: { get: function () { return Promise.resolve(provider.selectedAddress || null); } // METAMASK BUG NEEDS TO BE FIXED FOR CHROME: https://github.com/MetaMask/metamask-extension/issues/7101 // onChange: func => { // // give the initial value if it exists // if (provider.selectedAddress) { // func(provider.selectedAddress) // } // provider.on("accountsChanged", accounts => func(accounts[0])) // } }, network: { onChange: function (func) { // give the initial value if it exists if (provider.networkVersion) { func(provider.networkVersion); } provider.on("networkChanged", func); } }, balance: { get: function () { return new Promise(function (resolve) { if (!provider.selectedAddress) { resolve(null); return; } provider.sendAsync({ method: "eth_getBalance", params: [provider.selectedAddress, "latest"], id: 1 }, function (e, res) { resolve(new BigNumber(res.result).toString(10)); }); }); } }, connect: function () { return new Promise(function (resolve, reject) { provider .enable() .then(resolve) .catch(function () { return reject({ message: "This dapp needs access to your account information." }); }); }); }, name: getProviderName(provider) || "unknown" }; } function createLegacyProviderInterface(provider) { return { address: { get: function () { return Promise.resolve(provider._address || provider.address); } }, network: { get: function () { return Promise.resolve(provider._chainId || provider.chainId); } }, balance: { get: function () { return new Promise(function (resolve) { provider.sendAsync({ method: "eth_getBalance", params: [provider._address, "latest"] }, function (e, res) { resolve(new BigNumber(res.result).toString(10)); }); }); } }, name: getProviderName(provider) || "unknown" }; } function getProviderName(provider) { if (!provider) return; if (provider.isMetaMask) { return "MetaMask"; } if (provider.isDapper) { return "Dapper"; } if (provider.isWalletConnect) { return "WalletConnect"; } if (provider.isTrust) { return "Trust"; } if (provider.isCoinbaseWallet) { return "Coinbase"; } if (provider.isToshi) { return "Toshi"; } if (provider.isCipher) { return "Cipher"; } if (provider.host && provider.host.indexOf("localhost") !== -1) { return "localhost"; } } function networkName(id) { switch (id) { case 1: return "mainnet"; case 3: return "ropsten"; case 4: return "rinkeby"; case 5: return "goerli"; case 42: return "kovan"; default: return "local"; } } function networkToId(network) { switch (network) { case "mainnet": return 1; case "ropsten": return 3; case "rinkeby": return 4; case "goerli": return 5; case "kovan": return 42; default: return 0; } } function wait$1(time) { return new Promise(function (resolve) { return setTimeout(resolve, time); }); } function makeQuerablePromise(promise) { var isResolved = false; var isRejected = false; promise.then(function (v) { isResolved = true; return v; }, function (e) { isRejected = true; throw e; }); promise.isFulfilled = function () { return isResolved || isRejected; }; promise.isResolved = function () { return isResolved; }; promise.isRejected = function () { return isRejected; }; return promise; } function getDeviceInfo() { var browser = bowser.getParser(window.navigator.userAgent); var name = browser.getOS().name; var type = browser.getPlatform().type; return { isMobile: type !== 'desktop', os: name }; } function registerUser(allowAuthAnalytics, projectId, method, address, networkId) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: console.log("ANALYTICS LOG: ", allowAuthAnalytics, projectId, method, address, networkId); if (!allowAuthAnalytics) return [3 /*break*/, 2]; console.log("allowAuthAnalytics: ", allowAuthAnalytics); return [4 /*yield*/, request.post('https://dappkit.io:6969/api/beta-v0/user', { form: { projectId: projectId, method: method, address: address, networkId: networkId, device: window.navigator.userAgent } })]; case 1: _a.sent(); _a.label = 2; case 2: return [2 /*return*/]; } }); }); } var dapperIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAABKVBMVEVHcEzf2eXn0enj2+fh3ebf3ebvy+/g2OXk1+ng3ubi3ujh3efh4Ojg4Onh3+ji3+nq1O3g5evg3ObnxdntsM7woMT1ibn5fLPh2efk0uL7cKz/XqD/Vpv/WJz/UZj/Wp39aKff3uf/WZ3/Y6Psvdf/hbf/n8b/qcz/ebD/lMD/bqn/4O3//v//////xdz/8vj/ttTm3+39+P3s3fvjy/jcvvb/6fLp1/qubuuJKuKhVuiCH+DNpfKTPOR/GeD/1ebp2u2oYuqEIeD38P3x5vzBkPC3fe2nYumlXuj3lcbs1vHu1vPy0/T6icCcTeb0z/X5qtv3vOn1zfX2xvD2zff5oNT1zvf0zPTxyvH1zfXzyvP1zfb0zPT4s+P1zPXty+30zPTzy/P0zPQJmk/TAAAAY3RSTlMACTBHZIhYIxOn3ez07sX3d+248fP2+Po77/z///////6r///x////////////////7v//////////////////7///////////9u3ycPj/7fPw8+/u9NlWocav16fytVe6sWDohgwWAAADF0lEQVR4AXSPtdrkRhAAq3tmpF3pp2OOLjIzw6v45Rw5MT6AU1Po1OEx/gvC6fau9hhKWN9XQ8LzyBYkx955jufC2Zi2GWzLxsxfHZaWdHJTwEPWdfaXQznsk0GEkenD6OgqvxiWdS/EfiYbAN/QFgzSjv5ceP5YJU5bnFRcLcg69+jJ6+2TcNdZVY8UmSeYhya0FtZTGQA0qxSzwoM+d04NFOOYz7UjIMCsMClKDbxM9i4P3fBoRgmyF1/ZodSdxexTeD4rIQZeiQx0lP0UZk1nNHnQ7O7R2WG+MxWVbIagc6VKwQoVcR+UDJjti6GyCtmyL3ThQqqsmKlWKrAtV6pYXUgGUemPgzV5rG8Eqa8ehxhOIEVMahIrG22/tBSLkN3rscd6Pbag4dTRMs2VOsY4GlA0e2UuixhTB8OBdGW4suhVIzdiVVMXRbIe3H3/nJVVoXQATRSvGYtw9H7neS+nfY9DdA1FzHHFPMaIE07vr5IMy4OrK23hgc+QNlNadep0PIlJKRlideZUUgbjY7itn8InhyOqJZuya5PCzqDp1kun4h8QhcN/6NlRTguCTx0bAww5ZE+rCukCh9oxkQ04Gh4ZtdBtP18rVPRH3JzRAXTqJN8Yk/k93LYJCgS57tg0Fdre9LHaWLOzHjf7lF2YLZ/yW31Ie23sW6rjh2myvdi0JOvYEtMAdDcDw8MH59oFXt0fhzJtjVuQbFn0o4CS+JSwzKc0catP6veboCvb2k1P89VtspRAHJKMbMqhSF6txrYfA9rfndWnGuYPj1eqqKTQx0QUgdB3IfraswRAaZpFuR6EABbUIAJSeEY3bU/iEYGNqQJ4MwKawJY9QFbVzBN0AxPf7jRt/oTXY+WYoI66+VhGeR3+ZiANP+nvGeRTM15DjhGscr1ZG8R3LYTAywTzTwKw8MC/HwxCceG/2CuA+YQwMdhXDsx/GyM2zjuIX2v7JwEKdvRA5sPTDQyH3xsCfCdrY4sbewsm9lmCIjCU+oMxhZTz/xf4A+7t3yCCFamU5Fr2A1HicvyKXY7d00D3ghkAxraU/JeFj1kAAAAASUVORK5CYII="; var dapperIcon2x = "data:image/png;base64,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"; function dapper(allowAuthAnalytics, projectId) { return function () { var _this = this; return { name: "Dapper", iconSrc: dapperIcon, iconSrcSet: dapperIcon2x, wallet: function (helpers) { var getProviderName = helpers.getProviderName, BigNumber = helpers.BigNumber; var provider = window.ethereum; return { provider: provider, interface: provider && getProviderName(provider) === "Dapper" ? { name: "Dapper", connect: provider.enable, address: { get: function () { return Promise.resolve(provider.cachedResults.eth_coinbase.result); } }, network: { get: function () { return Promise.resolve(provider.cachedResults.net_version.result); } }, balance: { get: function () { return new Promise(function (resolve) { if (!provider.cachedResults.eth_coinbase.result) { resolve(null); return; } provider.sendAsync({ method: "eth_getBalance", params: [ provider.cachedResults.eth_coinbase.result, "latest" ], id: 1 }, function (e, res) { return __awaiter(_this, void 0, void 0, function () { var _a, _b; return __generator(this, function (_c) { switch (_c.label) { case 0: _a = registerUser; _b = [allowAuthAnalytics, projectId, 'dapper']; return [4 /*yield*/, provider.cachedResults.eth_coinbase.result]; case 1: return [4 /*yield*/, _a.apply(void 0, _b.concat([_c.sent(), provider.cachedResults.net_version.result]))]; case 2: _c.sent(); resolve(BigNumber(res.result).toString(10)); return [2 /*return*/]; } }); }); }); }); } } } : null }; }, link: "https://www.meetdapper.com/", installMessage: extensionInstallMessage }; }; } var walletConnectIcon = "data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI1IiB2aWV3Qm94PSIwIDAgNDAgMjUiIHdpZHRoPSI0MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtOC4xOTE4MDU3MiA0LjgzNDE2ODE2YzYuNTIxNDk2NTgtNi4zODUwODg4NCAxNy4wOTQ5MzE1OC02LjM4NTA4ODg0IDIzLjYxNjQyNzg4IDBsLjc4NDg3MjcuNzY4NDU1NjVjLjMyNjA3NDguMzE5MjU0NDIuMzI2MDc0OC44MzY4NjgxNiAwIDEuMTU2MTIyNzJsLTIuNjg0ODkyNyAyLjYyODczMzc0Yy0uMTYzMDM3NS4xNTk2MjczNC0uNDI3MzczMy4xNTk2MjczNC0uNTkwNDEwOCAwbC0xLjA4MDA3NzktMS4wNTc0ODYzOWMtNC41NDk1NTg5LTQuNDU0Mzk3NTYtMTEuOTI1ODUxNC00LjQ1NDM5NzU2LTE2LjQ3NTQxMDUgMGwtMS4xNTY2NzQxIDEuMTMyNDgwNjhjLS4xNjMwMzc2LjE1OTYyNzIxLS40MjczNzM1LjE1OTYyNzIxLS41OTA0MTA4IDBsLTIuNjg0ODkyNjMtMi42Mjg3MzM3NWMtLjMyNjA3NDgzLS4zMTkyNTQ1Ni0uMzI2MDc0ODMtLjgzNjg2ODI5IDAtMS4xNTYxMjI3MnptMjkuMTY5MDM5NDggNS40MzY0OTkzNCAyLjM4OTU1OTYgMi4zMzk1ODYyYy4zMjYwNzMyLjMxOTI1My4zMjYwNzUxLjgzNjg2MzYuMDAwMDA0MSAxLjE1NjExODdsLTEwLjc3NDY4OTQgMTAuNTQ5NDg0NWMtLjMyNjA3MjYuMzE5MjU2OC0uODU0NzQ0My4zMTkyNjA0LTEuMTgwODIxNC4wMDAwMDgzLS4wMDAwMDEzLS4wMDAwMDEzLS4wMDAwMDI5LS4wMDAwMDI5LS4wMDAwMDQyLS4wMDAwMDQzbC03LjY0NzIxOTEtNy40ODcyNzYyYy0uMDgxNTE4Ny0uMDc5ODEzNi0uMjEzNjg2Ny0uMDc5ODEzNi0uMjk1MjA1MyAwLS4wMDAwMDA2LjAwMDAwMDUtLjAwMDAwMS4wMDAwMDEtLjAwMDAwMTUuMDAwMDAxNGwtNy42NDcwNTYyIDcuNDg3MjcwOGMtLjMyNjA3MTUuMzE5MjU3Ni0uODU0NzQzNC4zMTkyNjMtMS4xODA4MjE1LjAwMDAxMTYtLjAwMDAwMTktLjAwMDAwMTgtLjAwMDAwMzktLjAwMDAwMzctLjAwMDAwNTktLjAwMDAwNThsLTEwLjc3NDk4OTMtMTAuNTQ5NjI0N2MtLjMyNjA3NDY5LS4zMTkyNTQ0LS4zMjYwNzQ2OS0uODM2ODY4MiAwLTEuMTU2MTIyNmwyLjM4OTU2Mzk1LTIuMzM5NTgyM2MuMzI2MDc0Ny0uMzE5MjU0NDYuODU0NzQ2NTItLjMxOTI1NDQ2IDEuMTgwODIxMzYgMGw3LjY0NzMzMDI5IDcuNDg3MzgwOWMuMDgxNTE4OC4wNzk4MTM2LjIxMzY4NjYuMDc5ODEzNi4yOTUyMDU0IDAgLjAwMDAwMTItLjAwMDAwMTIuMDAwMDAyMy0uMDAwMDAyMy4wMDAwMDM1LS4wMDAwMDMybDcuNjQ2OTQ3MS03LjQ4NzM3NzdjLjMyNjA2NzMtLjMxOT