import { SofiaProRegular } from '@web3-onboard/common' import connectWallet from './connect.js' import disconnectWallet from './disconnect.js' import setChain from './chain.js' import { state } from './store/index.js' import { reset$, wallets$ } from './streams.js' import initI18N from './i18n/index.js' import App from './views/Index.svelte' import type { InitOptions, Notify } from './types.js' import { APP_INITIAL_STATE, STORAGE_KEYS } from './constants.js' import { configuration, updateConfiguration } from './configuration.js' import updateBalances from './update-balances.js' import { chainIdToHex, getLocalStore } from './utils.js' import { preflightNotifications } from './preflight-notifications.js' import { validateInitOptions, validateNotify, validateNotifyOptions } from './validation.js' import { addChains, updateAccountCenter, updateNotify, customNotification, setLocale, setPrimaryWallet, setWalletModules, updateConnectModal, updateTheme } from './store/actions.js' import type { PatchedEIP1193Provider } from '@web3-onboard/transaction-preview' import { getBlocknativeSdk } from './services.js' const API = { connectWallet, disconnectWallet, setChain, state: { get: state.get, select: state.select, actions: { setWalletModules, setLocale, updateNotify, customNotification, preflightNotifications, updateBalances, updateAccountCenter, setPrimaryWallet, updateTheme } } } export type OnboardAPI = typeof API export type { InitOptions, ConnectOptions, DisconnectOptions, WalletState, ConnectedChain, AccountCenter, AppState, CustomNotification, Notification, Notify, UpdateNotification, PreflightNotificationsOptions, Theme } from './types.js' export type { EIP1193Provider } from '@web3-onboard/common' function init(options: InitOptions): OnboardAPI { if (typeof window === 'undefined') return API if (options) { const error = validateInitOptions(options) if (error) { throw error } } const { wallets, chains, appMetadata = null, i18n, accountCenter, apiKey, notify, gas, connect, containerElements, transactionPreview, theme } = options if (containerElements) updateConfiguration({ containerElements }) const { device, svelteInstance } = configuration if (svelteInstance) { // if already initialized, need to cleanup old instance console.warn('Re-initializing Onboard and resetting back to initial state') reset$.next() } initI18N(i18n) addChains(chainIdToHex(chains)) if (typeof connect !== undefined) { updateConnectModal(connect) } // update accountCenter if (typeof accountCenter !== 'undefined') { let accountCenterUpdate if (device.type === 'mobile') { accountCenterUpdate = { ...APP_INITIAL_STATE.accountCenter, ...(accountCenter.mobile ? accountCenter.mobile : {}) } } else if (accountCenter.desktop) { accountCenterUpdate = { ...APP_INITIAL_STATE.accountCenter, ...accountCenter.desktop } } updateAccountCenter(accountCenterUpdate) } // update notify if (typeof notify !== 'undefined') { if ('desktop' in notify || 'mobile' in notify) { const error = validateNotifyOptions(notify) if (error) { throw error } if ( (!notify.desktop || (notify.desktop && !notify.desktop.position)) && accountCenter && accountCenter.desktop && accountCenter.desktop.position ) { notify.desktop.position = accountCenter.desktop.position } if ( (!notify.mobile || (notify.mobile && !notify.mobile.position)) && accountCenter && accountCenter.mobile && accountCenter.mobile.position ) { notify.mobile.position = accountCenter.mobile.position } let notifyUpdate: Partial if (device.type === 'mobile' && notify.mobile) { notifyUpdate = { ...APP_INITIAL_STATE.notify, ...notify.mobile } } else if (notify.desktop) { notifyUpdate = { ...APP_INITIAL_STATE.notify, ...notify.desktop } } updateNotify(notifyUpdate) } else { const error = validateNotify(notify as Notify) if (error) { throw error } const notifyUpdate: Partial = { ...APP_INITIAL_STATE.notify, ...notify } updateNotify(notifyUpdate) } } else { const notifyUpdate: Partial = APP_INITIAL_STATE.notify updateNotify(notifyUpdate) } const app = svelteInstance || mountApp() updateConfiguration({ appMetadata, svelteInstance: app, apiKey, initialWalletInit: wallets, gas, transactionPreview }) if (apiKey && transactionPreview) { const getBnSDK = async () => { transactionPreview.init({ containerElement: '#w3o-transaction-preview-container', sdk: await getBlocknativeSdk(), apiKey }) wallets$.subscribe(wallets => { wallets.forEach(({ provider }) => { transactionPreview.patchProvider(provider as PatchedEIP1193Provider) }) }) } getBnSDK() } theme && updateTheme(theme) // handle auto connection of last wallet if (connect && connect.autoConnectLastWallet) { const lastConnectedWallet = getLocalStore( STORAGE_KEYS.LAST_CONNECTED_WALLET ) lastConnectedWallet && API.connectWallet({ autoSelect: { label: lastConnectedWallet, disableModals: true } }) } return API } function mountApp() { class Onboard extends HTMLElement { constructor() { super() } } if (!customElements.get('onboard-v2')) { customElements.define('onboard-v2', Onboard) } // Add Fonts to main page const styleEl = document.createElement('style') styleEl.innerHTML = ` ${SofiaProRegular} ` document.body.appendChild(styleEl) // add to DOM const onboard = document.createElement('onboard-v2') const target = onboard.attachShadow({ mode: 'open' }) onboard.style.all = 'initial' target.innerHTML = ` ` const connectModalContEl = configuration.containerElements.connectModal const containerElementQuery = connectModalContEl || state.get().accountCenter.containerElement || 'body' const containerElement = document.querySelector(containerElementQuery) if (!containerElement) { throw new Error( `Element with query ${containerElementQuery} does not exist.` ) } containerElement.appendChild(onboard) const app = new App({ target }) return app } export default init