UNPKG

@tronweb3/tronwallet-adapter-tronlink

Version:

Wallet adapter for TronLink Wallet extension and TronLink app.

1,211 lines (1,119 loc) 82.9 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global["@tronweb3/tronwallet-adapter-tronlink"] = factory()); })(this, (function () { 'use strict'; function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var cjs$1 = {}; var adapter$1 = {}; var cjs = {}; var adapter = {}; var eventemitter3 = {exports: {}}; var hasRequiredEventemitter3; function requireEventemitter3 () { if (hasRequiredEventemitter3) return eventemitter3.exports; hasRequiredEventemitter3 = 1; (function (module) { var has = Object.prototype.hasOwnProperty , prefix = '~'; /** * Constructor to create a storage for our `EE` objects. * An `Events` instance is a plain object whose properties are event names. * * @constructor * @private */ function Events() {} // // We try to not inherit from `Object.prototype`. In some engines creating an // instance in this way is faster than calling `Object.create(null)` directly. // If `Object.create(null)` is not supported we prefix the event names with a // character to make sure that the built-in object properties are not // overridden or used as an attack vector. // if (Object.create) { Events.prototype = Object.create(null); // // This hack is needed because the `__proto__` property is still inherited in // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5. // if (!new Events().__proto__) prefix = false; } /** * Representation of a single event listener. * * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} [once=false] Specify if the listener is a one-time listener. * @constructor * @private */ function EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; } /** * Add a listener for a given event. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} once Specify if the listener is a one-time listener. * @returns {EventEmitter} * @private */ function addListener(emitter, event, fn, context, once) { if (typeof fn !== 'function') { throw new TypeError('The listener must be a function'); } var listener = new EE(fn, context || emitter, once) , evt = prefix ? prefix + event : event; if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); else emitter._events[evt] = [emitter._events[evt], listener]; return emitter; } /** * Clear event by name. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} evt The Event name. * @private */ function clearEvent(emitter, evt) { if (--emitter._eventsCount === 0) emitter._events = new Events(); else delete emitter._events[evt]; } /** * Minimal `EventEmitter` interface that is molded against the Node.js * `EventEmitter` interface. * * @constructor * @public */ function EventEmitter() { this._events = new Events(); this._eventsCount = 0; } /** * Return an array listing the events for which the emitter has registered * listeners. * * @returns {Array} * @public */ EventEmitter.prototype.eventNames = function eventNames() { var names = [] , events , name; if (this._eventsCount === 0) return names; for (name in (events = this._events)) { if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); } if (Object.getOwnPropertySymbols) { return names.concat(Object.getOwnPropertySymbols(events)); } return names; }; /** * Return the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Array} The registered listeners. * @public */ EventEmitter.prototype.listeners = function listeners(event) { var evt = prefix ? prefix + event : event , handlers = this._events[evt]; if (!handlers) return []; if (handlers.fn) return [handlers.fn]; for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) { ee[i] = handlers[i].fn; } return ee; }; /** * Return the number of listeners listening to a given event. * * @param {(String|Symbol)} event The event name. * @returns {Number} The number of listeners. * @public */ EventEmitter.prototype.listenerCount = function listenerCount(event) { var evt = prefix ? prefix + event : event , listeners = this._events[evt]; if (!listeners) return 0; if (listeners.fn) return 1; return listeners.length; }; /** * Calls each of the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Boolean} `true` if the event had listeners, else `false`. * @public */ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return false; var listeners = this._events[evt] , len = arguments.length , args , i; if (listeners.fn) { if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); switch (len) { case 1: return listeners.fn.call(listeners.context), true; case 2: return listeners.fn.call(listeners.context, a1), true; case 3: return listeners.fn.call(listeners.context, a1, a2), true; case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; } for (i = 1, args = new Array(len -1); i < len; i++) { args[i - 1] = arguments[i]; } listeners.fn.apply(listeners.context, args); } else { var length = listeners.length , j; for (i = 0; i < length; i++) { if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); switch (len) { case 1: listeners[i].fn.call(listeners[i].context); break; case 2: listeners[i].fn.call(listeners[i].context, a1); break; case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; default: if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { args[j - 1] = arguments[j]; } listeners[i].fn.apply(listeners[i].context, args); } } } return true; }; /** * Add a listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.on = function on(event, fn, context) { return addListener(this, event, fn, context, false); }; /** * Add a one-time listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.once = function once(event, fn, context) { return addListener(this, event, fn, context, true); }; /** * Remove the listeners of a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn Only remove the listeners that match this function. * @param {*} context Only remove the listeners that have this context. * @param {Boolean} once Only remove one-time listeners. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return this; if (!fn) { clearEvent(this, evt); return this; } var listeners = this._events[evt]; if (listeners.fn) { if ( listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context) ) { clearEvent(this, evt); } } else { for (var i = 0, events = [], length = listeners.length; i < length; i++) { if ( listeners[i].fn !== fn || (once && !listeners[i].once) || (context && listeners[i].context !== context) ) { events.push(listeners[i]); } } // // Reset the array, or remove it completely if we have no more listeners. // if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; else clearEvent(this, evt); } return this; }; /** * Remove all listeners, or those of the specified event. * * @param {(String|Symbol)} [event] The event name. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { var evt; if (event) { evt = prefix ? prefix + event : event; if (this._events[evt]) clearEvent(this, evt); } else { this._events = new Events(); this._eventsCount = 0; } return this; }; // // Alias methods names because people roll like that. // EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.addListener = EventEmitter.prototype.on; // // Expose the prefix. // EventEmitter.prefixed = prefix; // // Allow `EventEmitter` to be imported as module namespace. // EventEmitter.EventEmitter = EventEmitter; // // Expose the module. // { module.exports = EventEmitter; } } (eventemitter3)); return eventemitter3.exports; } var typedData = {}; var errors = {}; var hasRequiredErrors; function requireErrors () { if (hasRequiredErrors) return errors; hasRequiredErrors = 1; Object.defineProperty(errors, "__esModule", { value: true }); errors.WalletSignTypedDataError = errors.WalletGetNetworkError = errors.WalletSwitchChainError = errors.WalletWindowClosedError = errors.WalletWalletLoadError = errors.WalletSignTransactionError = errors.WalletSignMessageError = errors.WalletDisconnectionError = errors.WalletConnectionError = errors.WalletDisconnectedError = errors.WalletNotSelectedError = errors.WalletNotFoundError = errors.WalletError = void 0; class WalletError extends Error { constructor(message, error) { super(message); this.error = error; } } errors.WalletError = WalletError; /** * Occurs when wallet is not installed. */ class WalletNotFoundError extends WalletError { constructor(message, error) { super(message || 'The wallet is not found.', error); this.name = 'WalletNotFoundError'; } } errors.WalletNotFoundError = WalletNotFoundError; /** * Occurs when connect to a wallet but there is no wallet selected. */ class WalletNotSelectedError extends WalletError { constructor() { super(...arguments); this.name = 'WalletNotSelectedError'; this.message = 'No wallet is selected. Please select a wallet.'; } } errors.WalletNotSelectedError = WalletNotSelectedError; /** * Occurs when wallet is disconnected. * Used by some wallets which won't connect automatically when call `signMessage()` or `signTransaction()`. */ class WalletDisconnectedError extends WalletError { constructor() { super(...arguments); this.name = 'WalletDisconnectedError'; this.message = 'The wallet is disconnected. Please connect first.'; } } errors.WalletDisconnectedError = WalletDisconnectedError; /** * Occurs when try to connect a wallet. */ class WalletConnectionError extends WalletError { constructor() { super(...arguments); this.name = 'WalletConnectionError'; } } errors.WalletConnectionError = WalletConnectionError; /** * Occurs when try to disconnect a wallet. */ class WalletDisconnectionError extends WalletError { constructor() { super(...arguments); this.name = 'WalletDisconnectionError'; } } errors.WalletDisconnectionError = WalletDisconnectionError; /** * Occurs when call `signMessage()`. */ class WalletSignMessageError extends WalletError { constructor() { super(...arguments); this.name = 'WalletSignMessageError'; } } errors.WalletSignMessageError = WalletSignMessageError; /** * Occurs when call `signTransaction()`. */ class WalletSignTransactionError extends WalletError { constructor() { super(...arguments); this.name = 'WalletSignTransactionError'; } } errors.WalletSignTransactionError = WalletSignTransactionError; /** * Occurs when load wallet */ class WalletWalletLoadError extends WalletError { constructor() { super(...arguments); this.name = 'WalletWalletLoadError'; } } errors.WalletWalletLoadError = WalletWalletLoadError; /** * Occurs when walletconnect QR window is closed. */ class WalletWindowClosedError extends WalletError { constructor(message, error) { super(message || 'The QR window is closed.', error); this.name = 'WalletWindowClosedError'; } } errors.WalletWindowClosedError = WalletWindowClosedError; /** * Occurs when request wallet to switch chain. */ class WalletSwitchChainError extends WalletError { constructor() { super(...arguments); this.name = 'WalletSwitchChainError'; } } errors.WalletSwitchChainError = WalletSwitchChainError; /** * Occurs when get network infomation. */ class WalletGetNetworkError extends WalletError { constructor() { super(...arguments); this.name = 'WalletGetNetworkError'; } } errors.WalletGetNetworkError = WalletGetNetworkError; /** * Occurs when call `signTypedData()`. */ class WalletSignTypedDataError extends WalletError { constructor() { super(...arguments); this.name = 'WalletSignTypedDataError'; } } errors.WalletSignTypedDataError = WalletSignTypedDataError; return errors; } var hasRequiredTypedData; function requireTypedData () { if (hasRequiredTypedData) return typedData; hasRequiredTypedData = 1; Object.defineProperty(typedData, "__esModule", { value: true }); typedData.normalizeAndValidateTypedData = normalizeAndValidateTypedData; const errors_js_1 = requireErrors(); function isPlainObject(value) { return typeof value === 'object' && value !== null && !Array.isArray(value); } /** * Validate a TypedData payload and return a normalized copy safe to pass to wallets. * * Current normalization: convert `domain.chainId` from string to number (some wallets, * e.g. TronLink, require a numeric chainId). * * Throws {@link WalletSignTypedDataError} if the payload is not a valid TypedData object. */ function normalizeAndValidateTypedData(typedData) { if (!isPlainObject(typedData)) { throw new errors_js_1.WalletSignTypedDataError('typedData must be an object.'); } if (!isPlainObject(typedData.domain)) { throw new errors_js_1.WalletSignTypedDataError('typedData.domain must be an object.'); } if (!isPlainObject(typedData.types)) { throw new errors_js_1.WalletSignTypedDataError('typedData.types must be an object.'); } if (!isPlainObject(typedData.message)) { throw new errors_js_1.WalletSignTypedDataError('typedData.message must be an object.'); } const { chainId } = typedData.domain; if (typeof chainId === 'string') { const parsed = Number(chainId); if (!Number.isFinite(parsed)) { throw new errors_js_1.WalletSignTypedDataError(`Invalid domain.chainId: ${chainId}.`); } return Object.assign(Object.assign({}, typedData), { domain: Object.assign(Object.assign({}, typedData.domain), { chainId: parsed }) }); } return typedData; } return typedData; } var types$1 = {}; var hasRequiredTypes$1; function requireTypes$1 () { if (hasRequiredTypes$1) return types$1; hasRequiredTypes$1 = 1; Object.defineProperty(types$1, "__esModule", { value: true }); types$1.TIP6963RequestProviderEventName = types$1.TIP6963AnnounceProviderEventName = types$1.ChainNetwork = types$1.NetworkType = types$1.AdapterState = types$1.WalletReadyState = void 0; /** * Wallet ready state. */ var WalletReadyState; (function (WalletReadyState) { /** * Adapter will start to check if wallet exists after adapter instance is created. */ WalletReadyState["Loading"] = "Loading"; /** * When checking ends and wallet is not found, readyState will be NotFound. */ WalletReadyState["NotFound"] = "NotFound"; /** * When checking ends and wallet is found, readyState will be Found. */ WalletReadyState["Found"] = "Found"; })(WalletReadyState || (types$1.WalletReadyState = WalletReadyState = {})); /** * Adapter state */ var AdapterState; (function (AdapterState) { /** * If adapter is checking the wallet, the state is Loading. */ AdapterState["Loading"] = "Loading"; /** * If wallet is not installed, the state is NotFound. */ AdapterState["NotFound"] = "NotFound"; /** * If wallet is installed but is not connected to current Dapp, the state is Disconnected. */ AdapterState["Disconnect"] = "Disconnected"; /** * Wallet is connected to current Dapp. */ AdapterState["Connected"] = "Connected"; })(AdapterState || (types$1.AdapterState = AdapterState = {})); var NetworkType; (function (NetworkType) { NetworkType["Mainnet"] = "Mainnet"; NetworkType["Shasta"] = "Shasta"; NetworkType["Nile"] = "Nile"; /** * When use custom node */ NetworkType["Unknown"] = "Unknown"; })(NetworkType || (types$1.NetworkType = NetworkType = {})); var ChainNetwork; (function (ChainNetwork) { ChainNetwork["Mainnet"] = "Mainnet"; ChainNetwork["Shasta"] = "Shasta"; ChainNetwork["Nile"] = "Nile"; })(ChainNetwork || (types$1.ChainNetwork = ChainNetwork = {})); types$1.TIP6963AnnounceProviderEventName = 'TIP6963:announceProvider'; types$1.TIP6963RequestProviderEventName = 'TIP6963:requestProvider'; return types$1; } var hasRequiredAdapter$1; function requireAdapter$1 () { if (hasRequiredAdapter$1) return adapter; hasRequiredAdapter$1 = 1; var __importDefault = (adapter && adapter.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(adapter, "__esModule", { value: true }); adapter.Adapter = adapter.EventEmitter = void 0; const eventemitter3_1 = __importDefault(requireEventemitter3()); adapter.EventEmitter = eventemitter3_1.default; const typedData_js_1 = requireTypedData(); const types_js_1 = requireTypes$1(); class Adapter extends eventemitter3_1.default { get connected() { return this.state === types_js_1.AdapterState.Connected; } /** * Some wallets such as TronLink don't support disconnect() method. */ disconnect() { console.info("The current adapter doesn't support disconnect by DApp."); return Promise.resolve(); } // eslint-disable-next-line @typescript-eslint/no-unused-vars multiSign(transaction, options = {}) { return Promise.reject("The current wallet doesn't support multiSign."); } signTypedData(typedData) { let normalized; try { normalized = (0, typedData_js_1.normalizeAndValidateTypedData)(typedData); } catch (error) { return Promise.reject(error); } return this._signTypedData(normalized); } // eslint-disable-next-line @typescript-eslint/no-unused-vars _signTypedData(_typedData) { return Promise.reject("The current wallet doesn't support signTypedData."); } // eslint-disable-next-line @typescript-eslint/no-unused-vars switchChain(_chainId) { return Promise.reject("The current wallet doesn't support switch chain."); } } adapter.Adapter = Adapter; return adapter; } var utils$1 = {}; var hasRequiredUtils$1; function requireUtils$1 () { if (hasRequiredUtils$1) return utils$1; hasRequiredUtils$1 = 1; Object.defineProperty(utils$1, "__esModule", { value: true }); utils$1.isInBrowser = isInBrowser; utils$1.checkAdapterState = checkAdapterState; utils$1.isInMobileBrowser = isInMobileBrowser; /** * check simply if current environment is browser or not * @returns boolean */ function isInBrowser() { return typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined'; } /** * * @param {Function} check funcion to check if wallet is installed. return true if wallet is detected. * @returns */ function checkAdapterState(check) { if (!isInBrowser()) return; const disposers = []; function dispose() { for (const dispose of disposers) { dispose(); } } function checkAndDispose() { if (check()) { dispose(); } } const interval = setInterval(checkAndDispose, 500); disposers.push(() => clearInterval(interval)); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', checkAndDispose, { once: true }); disposers.push(() => document.removeEventListener('DOMContentLoaded', checkAndDispose)); } if (document.readyState !== 'complete') { window.addEventListener('load', checkAndDispose, { once: true }); disposers.push(() => window.removeEventListener('load', checkAndDispose)); } checkAndDispose(); // stop all task after 1min setTimeout(dispose, 60 * 1000); } /** * Simplily detect mobile device */ function isInMobileBrowser() { return (typeof navigator !== 'undefined' && navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i)); } return utils$1; } var addonAdapter = {}; var security = {}; var hasRequiredSecurity; function requireSecurity () { if (hasRequiredSecurity) return security; hasRequiredSecurity = 1; (function (exports$1) { var __awaiter = (security && security.__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()); }); }; Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.defaultSecurityOptions = void 0; exports$1.clearCache = clearCache; exports$1.fetchJsonWithCache = fetchJsonWithCache; exports$1.defaultSecurityOptions = { onRiskDetected: (result) => __awaiter(void 0, void 0, void 0, function* () { console.log(`[WalletAdapter] Risk detected:`, result); }), configUrls: [], enabled: false, timeout: 2000, retries: 0, cacheTTL: 10 * 60 * 1000, }; function isValidRisk(risk) { return (!!risk && typeof risk === 'object' && typeof risk.title === 'string' && risk.title.length > 0 && (risk.noticeType === 1 || risk.noticeType === 2 || risk.noticeType === 3)); } function sanitizeRisk(risk) { const clean = { title: risk.title, noticeType: risk.noticeType }; if (typeof risk.ext === 'string') clean.ext = risk.ext; if (typeof risk.ios === 'string') clean.ios = risk.ios; if (typeof risk.and === 'string') clean.and = risk.and; return clean; } /** * Defensively coerce an arbitrary remote payload into a well-formed RiskConfig. * * The config comes from a remote URL, so a bad release (or a tampered response) * must never break the connect flow. Anything malformed is dropped with a * warning rather than thrown: `wallets` must be a record whose values are * arrays, and each risk must have a non-empty string `title` and a `noticeType` * of 1/2/3. Invalid entries are discarded so downstream merging/consumption * only ever sees clean `Risk[]`. */ function normalizeRiskConfig(data) { const source = data && typeof data === 'object' ? data : {}; const wallets = {}; if (source.wallets && typeof source.wallets === 'object') { for (const [walletName, rawRisks] of Object.entries(source.wallets)) { if (!Array.isArray(rawRisks)) { console.warn(`[WalletAdapter] Ignoring malformed risks for "${walletName}": expected an array, got ${typeof rawRisks}.`); continue; } const validRisks = []; for (const risk of rawRisks) { if (isValidRisk(risk)) { validRisks.push(sanitizeRisk(risk)); } else { console.warn(`[WalletAdapter] Dropping malformed risk entry for "${walletName}":`, risk); } } if (validRisks.length > 0) { wallets[walletName] = validRisks; } } } return { v: typeof source.v === 'string' ? source.v : '', ts: typeof source.ts === 'number' ? source.ts : 0, wallets, }; } const _jsonCache = {}; function clearCache() { Object.keys(_jsonCache).forEach((key) => { Reflect.deleteProperty(_jsonCache, key); }); } function fetchJsonWithCache(options) { return __awaiter(this, void 0, void 0, function* () { const { configUrls = exports$1.defaultSecurityOptions.configUrls, timeout = exports$1.defaultSecurityOptions.timeout, retries = exports$1.defaultSecurityOptions.retries, onConfigFallback, cacheTTL = exports$1.defaultSecurityOptions.cacheTTL, } = options; const now = Date.now(); function fetchOneUrl(url) { return __awaiter(this, void 0, void 0, function* () { const cache = _jsonCache[url]; if (cache && now - cache.timestamp < cacheTTL) { return cache.data; } function fetchWithTimeout() { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeout); fetch(url, { signal: controller.signal }) .then((resp) => { clearTimeout(timer); if (!resp.ok) reject(new Error('Fetch failed with code: ' + resp.status)); else resp.json().then((data) => resolve(normalizeRiskConfig(data)), reject); }) .catch((err) => { clearTimeout(timer); reject(err); }); }); }); } for (let i = 0; i <= retries; i++) { try { const data = yield fetchWithTimeout(); _jsonCache[url] = { data, timestamp: Date.now() }; return data; } catch (e) { console.warn(`[WalletAdapter] Fetch attempt ${i + 1} for ${url} failed:`, e); // continue to next retry } } // All retries failed — let the outer caller decide (onConfigFallback or safe empty config) return null; }); } const results = yield Promise.all(configUrls.map(fetchOneUrl)); const configs = results.filter((r) => r !== null); if (configs.length > 0) { return configs.reduce((merged, config) => { var _a; if (config.ts > merged.ts) { merged.v = config.v; merged.ts = config.ts; } // Pass every risk from every source through to the DApp without // deduplication. Conflict resolution (highest severity wins, source // weighting, etc.) is the DApp's responsibility — the adapter just // delivers the union. for (const [wallet, risks] of Object.entries(config.wallets)) { merged.wallets[wallet] = [...((_a = merged.wallets[wallet]) !== null && _a !== void 0 ? _a : []), ...risks]; } return merged; }, { v: '', ts: 0, wallets: {} }); } // All URLs failed with no cache — call custom fallback or default to safe (allow connection) if (onConfigFallback) { return normalizeRiskConfig(yield onConfigFallback()); } return { v: '', ts: 0, wallets: {} }; }); } } (security)); return security; } var hasRequiredAddonAdapter; function requireAddonAdapter () { if (hasRequiredAddonAdapter) return addonAdapter; hasRequiredAddonAdapter = 1; var __awaiter = (addonAdapter && addonAdapter.__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()); }); }; Object.defineProperty(addonAdapter, "__esModule", { value: true }); addonAdapter.AddonAdapter = void 0; const adapter_js_1 = requireAdapter$1(); const errors_js_1 = requireErrors(); const security_js_1 = requireSecurity(); const types_js_1 = requireTypes$1(); const utils_js_1 = requireUtils$1(); /** * Class to provide security check for wallets. */ class AddonAdapter extends adapter_js_1.Adapter { constructor(params) { super(); this.commonConfig = { checkTimeout: 2 * 1000, openAppWithDeeplink: true, openUrlWhenWalletNotFound: true, securityOptions: security_js_1.defaultSecurityOptions, }; this._securityCheckCache = null; this.commonConfig = Object.assign(Object.assign({}, this.commonConfig), params); if (typeof this.commonConfig.checkTimeout !== 'number') { throw new Error(`[WalletAdapter] config.checkTimeout should be a number`); } AddonAdapter._validateSecurityOptions(this.commonConfig.securityOptions); } static _validateSecurityOptions(securityOptions) { const { enabled, configUrls } = securityOptions; if (enabled && (!configUrls || configUrls.length === 0)) { throw new Error(`[WalletAdapter] config.securityOptions.configUrls is required when securityOptions.enabled is true`); } } /** * Update the security options at runtime. The given options are merged into * the existing config, validated, and the cached security check result is * cleared so the next connect runs a fresh check with the new configuration. */ updateSecurityOptions(securityOptions) { const merged = Object.assign(Object.assign({}, this.commonConfig.securityOptions), securityOptions); AddonAdapter._validateSecurityOptions(merged); this.commonConfig.securityOptions = merged; this._securityCheckCache = null; } /** * Run the pre-connect pipeline (wallet discovery, deeplink/url fallback, * security check). * * @returns `true` when the caller should continue with the actual connect * flow, `false` when the adapter is already connected/connecting and the * caller should bail out. Throws `WalletNotFoundError` when the wallet * cannot be found. */ _beforeConnect() { return __awaiter(this, void 0, void 0, function* () { if (this.connected || this.connecting) return false; yield this._checkWallet(); if (this.readyState === types_js_1.WalletReadyState.NotFound) { if ((0, utils_js_1.isInBrowser)() && !this._openAppByDeepLinkIfNeed() && this.commonConfig.openUrlWhenWalletNotFound !== false) { window.open(this.url, '_blank'); } throw new errors_js_1.WalletNotFoundError(); } yield this.checkSecurity(); return true; }); } /** * Fetch remote config and do risk check. * In-flight calls share the same promise (so `onRiskDetected` fires at most * once even on a slow network). After the promise settles, the result is * cached for SECURITY_CHECK_CACHE_TTL; the next call after that window * runs a fresh check. */ checkSecurity() { return __awaiter(this, void 0, void 0, function* () { if (!this.commonConfig.securityOptions.enabled) return; const cache = this._securityCheckCache; if (cache && (cache.settledAt === null || Date.now() - cache.settledAt < AddonAdapter.SECURITY_CHECK_CACHE_TTL)) { return cache.promise; } const promise = (() => __awaiter(this, void 0, void 0, function* () { const result = yield (0, security_js_1.fetchJsonWithCache)(this.commonConfig.securityOptions); const risks = result.wallets[this.name]; if (risks && risks.length > 0) { const callback = this.commonConfig.securityOptions.onRiskDetected || security_js_1.defaultSecurityOptions.onRiskDetected; yield callback({ risks }); } }))(); const entry = { promise, settledAt: null }; this._securityCheckCache = entry; // The `.finally` chain returns a new promise that mirrors `promise`'s rejection. // Attach a noop `.catch` to avoid an unhandled rejection on that chain — the // original `promise` is still surfaced to callers via the return below. promise .finally(() => { if (this._securityCheckCache === entry) { entry.settledAt = Date.now(); } }) .catch(() => { }); return promise; }); } } addonAdapter.AddonAdapter = AddonAdapter; AddonAdapter.SECURITY_CHECK_CACHE_TTL = 5 * 1000; return addonAdapter; } var hasRequiredCjs$1; function requireCjs$1 () { if (hasRequiredCjs$1) return cjs; hasRequiredCjs$1 = 1; (function (exports$1) { var __createBinding = (cjs && cjs.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (cjs && cjs.__exportStar) || function(m, exports$1) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports$1, p)) __createBinding(exports$1, m, p); }; Object.defineProperty(exports$1, "__esModule", { value: true }); __exportStar(requireAdapter$1(), exports$1); __exportStar(requireErrors(), exports$1); __exportStar(requireTypes$1(), exports$1); __exportStar(requireTypedData(), exports$1); __exportStar(requireUtils$1(), exports$1); __exportStar(requireAddonAdapter(), exports$1); __exportStar(requireSecurity(), exports$1); } (cjs)); return cjs; } var utils = {}; var hasRequiredUtils; function requireUtils () { if (hasRequiredUtils) return utils; hasRequiredUtils = 1; var __awaiter = (utils && utils.__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()); }); }; Object.defineProperty(utils, "__esModule", { value: true }); utils.supportTron = supportTron; utils.supportTronLink = supportTronLink; utils.isInTronLinkApp = isInTronLinkApp; utils.openTronLink = openTronLink; utils.waitTronwebReady = waitTronwebReady; const tronwallet_abstract_adapter_1 = /*@__PURE__*/ requireCjs$1(); function supportTron() { return (0, tronwallet_abstract_adapter_1.isInBrowser)() && !!(window.tron && window.tron.isTronLink); } function supportTronLink() { return (0, tronwallet_abstract_adapter_1.isInBrowser)() && !!(supportTron() || window.tronLink || window.tronWeb); } /** * Detect if in TronLinkApp * Tron DApp running in the DApp Explorer injects iTron objects automatically to offer customized App service. * See [here](https://docs.tronlink.org/tronlink-app/dapp-support/dapp-explorer) */ function isInTronLinkApp() { return (0, tronwallet_abstract_adapter_1.isInBrowser)() && typeof window.iTron !== 'undefined'; } function openTronLink({ dappIcon, dappName } = { dappIcon: '', dappName: '' }) { if (!supportTronLink() && (0, tronwallet_abstract_adapter_1.isInMobileBrowser)() && !isInTronLinkApp()) { let defaultDappName = '', defaultDappIcon = ''; try { defaultDappName = document.title; const link = document.querySelector('link[rel*="icon"]'); if (link) { defaultDappIcon = new URL(link.getAttribute('href') || '', location.href).toString(); } } catch (_a) { // console.error(e); } const { origin, pathname, search, hash } = window.location; const url = origin + pathname + search + (hash.includes('?') ? hash : `${hash}?_=1`); const params = { action: 'open', actionId: Date.now() + '', callbackUrl: 'http://someurl.com', // no need callback dappIcon: dappIcon || defaultDappIcon, dappName: dappName || defaultDappName, url, protocol: 'TronLink', version: '1.0', chainId: '0x2b6653dc', }; window.location.href = `tronlinkoutside://pull.activity?param=${encodeURIComponent(JSON.stringify(params))}`; return true; } return false; } function waitTronwebReady(tronObj) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { const interval = setInterval(() => { if (tronObj.tronWeb) { clearInterval(interval); clearTimeout(timeout); resolve(); } }, 50); const timeout = setTimeout(() => { clearInterval(interval); reject('`window.tron.tronweb` is not ready.'); }, 2000); }); }); } return utils; } var hasRequiredAdapter; function requireAdapter () { if (hasRequiredAdapter) return adapter$1; hasRequiredAdapter = 1; (function (exports$1) { var __awaiter = (adapter$1 && adapter$1.__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()); }); }; Object.defineProperty(exports$1, "__esModule", { value: true }); exports$1.TronLinkAdapter = exports$1.TronLinkAdapterName = exports$1.chainIdNetworkMap = void 0; exports$1.getNetworkInfoByTronWeb = getNetworkInfoByTronWeb; const tronwallet_abstract_adapter_1 = /*@__PURE__*/ requireCjs$1(); const utils_js_1 = requireUtils(); exports$1.chainIdNetworkMap = { '0x2b6653dc': tronwallet_abstract_adapter_1.NetworkType.Mainnet, '0x94a9059e': tronwallet_abstract_adapter_1.NetworkType.Shasta, '0xcd8690dc': tronwallet_abstract_adapter_1.NetworkType.Nile, }; function getNetworkInfoByTronWeb(tronWeb) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; const { blockID = '' } = yield tronWeb.trx.getBlockByNumber(0); const chainId = `0x${blockID.slice(-8)}`; return { networkType: exports$1.chainIdNetworkMap[chainId] || tronwallet_abstract_adapter_1.NetworkType.Unknown, chainId, fullNode: ((_a = tronWeb.fullNode) === null || _a === void 0 ? void 0 : _a.host) || '', solidityNode: ((_b = tronWeb.solidityNode) === null || _b === void 0 ? void 0 : _b.host) || '', eventServer: ((_c = tronWeb.eventServer) === null || _c === void 0 ? void 0 : _c.host) || '', }; }); } exports$1.TronLinkAdapterName = 'TronLink'; class TronLinkAdapter extends tronwallet_abstract_adapter_1.AddonAdapter { // record if first connect event has emitted or not constructor(config = {}) { super(config); this.name = exports$1.TronLinkAdapterName; this.url = 'https://www.tronlink.org/'; this.icon = 'data:image/png;base64,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