diff --git a/docs/src/routes/docs/[...4]wallets/[...37]bloom/+page.md b/docs/src/routes/docs/[...4]wallets/[...37]bloom/+page.md new file mode 100644 index 000000000..e66946d83 --- /dev/null +++ b/docs/src/routes/docs/[...4]wallets/[...37]bloom/+page.md @@ -0,0 +1,116 @@ +--- +title: Bloom +--- + +# {$frontmatter.title} + +Wallet module for connecting Bloom to web3-onboard. + +## Install + + + + +```sh copy +yarn add @web3-onboard/bloom +``` + + + + +```sh copy +npm install @web3-onboard/bloom +``` + + + + + +```typescript +type WalletConnectOptions = { + /** + * Project ID associated with [WalletConnect account](https://cloud.walletconnect.com) + */ + projectId: string + /** + * Defaults to `appMetadata.explore` that is supplied to the web3-onboard init + * Strongly recommended to provide atleast one URL as it is required by some wallets (i.e. MetaMask) + * To connect with walletconnect + */ + dappUrl?: string + /** + * List of Required Chain(s) ID for wallets to support in number format (integer or hex) + * Defaults to [1] - Ethereum + */ + requiredChains?: number[] | undefined + /** + * List of Optional Chain(s) ID for wallets to support in number format (integer or hex) + * Defaults to the chains provided within the web3-onboard init chain property + */ + optionalChains?: number[] | undefined + /** + * Additional required methods to be added to the default list of ['eth_sendTransaction', 'personal_sign'] + * Passed methods to be included along with the defaults methods - see https://docs.walletconnect.com/2.0/advanced/providers/ethereum#required-and-optional-methods + */ + additionalRequiredMethods?: string[] | undefined + /** + * Additional methods to be added to the default list of ['eth_sendTransaction', 'eth_signTransaction', 'personal_sign', 'eth_sign', 'eth_signTypedData', 'eth_signTypedData_v4'] + * Passed methods to be included along with the defaults methods - see https://docs.walletconnect.com/2.0/web/walletConnectModal/options + */ + additionalOptionalMethods?: string[] | undefined +) +``` + +## Usage + +```typescript +import Onboard from '@web3-onboard/core' +import bloomModule from '@web3-onboard/bloom' + +const wcInitOptions = { + /** + * Project ID associated with [WalletConnect account](https://cloud.walletconnect.com) + */ + projectId: 'abc123...', + /** + * Chains required to be supported by all wallets connecting to your DApp + */ + requiredChains: [1], + /** + * Chains required to be supported by all wallets connecting to your DApp + */ + optionalChains: [42161, 8453, 10, 137, 56], + /** + * Defaults to `appMetadata.explore` that is supplied to the web3-onboard init + * Strongly recommended to provide atleast one URL as it is required by some wallets (i.e. MetaMask) + * To connect with WalletConnect + */ + dappUrl: 'http://YourAwesomeDapp.com' +} + +// initialize the module with options +const bloom = bloomModule(wcInitOptions) + +// can also initialize with no options... + +const onboard = Onboard({ + // ... other Onboard options + wallets: [ + bloom + //... other wallets + ] +}) + +const connectedWallets = await onboard.connectWallet() + +// Assuming only wallet connect is connected, index 0 +// `instance` will give insight into the WalletConnect info +// such as namespaces, methods, chains, etc per wallet connected +const { instance } = connectedWallets[0] + +console.log(connectedWallets) +``` + +## Build Environments + +For build env configurations and setups please see the Build Env section [here](/docs/modules/core#build-environments) diff --git a/packages/bloom/README.md b/packages/bloom/README.md new file mode 100644 index 000000000..4f922a1f4 --- /dev/null +++ b/packages/bloom/README.md @@ -0,0 +1,94 @@ +# @web3-onboard/bloom + +## Wallet module for connecting Bloom to web3-onboard + +### Install + +`npm i @web3-onboard/core @web3-onboard/bloom` + +## Options + +```typescript +type WalletConnectOptions = { + /** + * Project ID associated with [WalletConnect account](https://cloud.walletconnect.com) + */ + projectId: string + /** + * Defaults to `appMetadata.explore` that is supplied to the web3-onboard init + * Strongly recommended to provide atleast one URL as it is required by some wallets (i.e. MetaMask) + * To connect with walletconnect + */ + dappUrl?: string + /** + * List of Required Chain(s) ID for wallets to support in number format (integer or hex) + * Defaults to [1] - Ethereum + */ + requiredChains?: number[] | undefined + /** + * List of Optional Chain(s) ID for wallets to support in number format (integer or hex) + * Defaults to the chains provided within the web3-onboard init chain property + */ + optionalChains?: number[] | undefined + /** + * Additional required methods to be added to the default list of ['eth_sendTransaction', 'personal_sign'] + * Passed methods to be included along with the defaults methods - see https://docs.walletconnect.com/2.0/advanced/providers/ethereum#required-and-optional-methods + */ + additionalRequiredMethods?: string[] | undefined + /** + * Additional methods to be added to the default list of ['eth_sendTransaction', 'eth_signTransaction', 'personal_sign', 'eth_sign', 'eth_signTypedData', 'eth_signTypedData_v4'] + * Passed methods to be included along with the defaults methods - see https://docs.walletconnect.com/2.0/web/walletConnectModal/options + */ + additionalOptionalMethods?: string[] | undefined +} +``` + +## Usage + +```typescript +import Onboard from '@web3-onboard/core' +import walletConnectModule from '@web3-onboard/walletconnect' + +const wcInitOptions = { + /** + * Project ID associated with [WalletConnect account](https://cloud.walletconnect.com) + */ + projectId: 'abc123...', + /** + * Chains required to be supported by all wallets connecting to your DApp + */ + requiredChains: [1], + /** + * Chains required to be supported by all wallets connecting to your DApp + */ + optionalChains: [42161, 8453, 10, 137, 56], + /** + * Defaults to `appMetadata.explore` that is supplied to the web3-onboard init + * Strongly recommended to provide atleast one URL as it is required by some wallets (i.e. MetaMask) + * To connect with WalletConnect + */ + dappUrl: 'http://YourAwesomeDapp.com' +} + +// initialize the module with options +const bloom = initBloom(wcInitOptions) + +// can also initialize with no options... + +const onboard = Onboard({ + // ... other Onboard options + wallets: [ + bloom + //... other wallets + ] +}) + +const connectedWallets = await onboard.connectWallet() + +// Assuming only wallet connect is connected, index 0 +// `instance` will give insight into the WalletConnect info +// such as namespaces, methods, chains, etc per wallet connected +const { instance } = connectedWallets[0] + +console.log(connectedWallets) +``` diff --git a/packages/bloom/package.json b/packages/bloom/package.json new file mode 100644 index 000000000..b7eab4f94 --- /dev/null +++ b/packages/bloom/package.json @@ -0,0 +1,73 @@ +{ + "name": "@web3-onboard/bloom", + "version": "2.0.0-alpha.1", + "description": "Unstoppable Domains module for connecting to Web3-Onboard. Web3-Onboard makes it simple to connect Ethereum hardware and software wallets to your dapp. Features standardised spec compliant web3 providers for all supported wallets, framework agnostic modern javascript UI with code splitting, CSS customization, multi-chain and multi-account support, reactive wallet state subscriptions and real-time transaction state change notifications.", + "keywords": [ + "Bloom", + "Iota", + "Shimmer", + "Ethereum", + "Web3", + "EVM", + "dapp", + "Multichain", + "Wallet", + "Transaction", + "Provider", + "Hardware Wallet", + "Notifications", + "React", + "Svelte", + "Vue", + "Next", + "Nuxt", + "MetaMask", + "Coinbase", + "WalletConnect", + "Ledger", + "Trezor", + "Connect Wallet", + "Ethereum Hooks", + "Blocknative", + "Mempool", + "pending", + "confirmed", + "Injected Wallet", + "Crypto", + "Crypto Wallet", + "Domain Name", + "Unstoppable Domains", + "Unstoppable" + ], + "repository": { + "type": "git", + "url": "https://github.com/blocknative/web3-onboard.git", + "directory": "packages/bloom" + }, + "homepage": "https://onboard.blocknative.com", + "bugs": "https://github.com/blocknative/web3-onboard/issues", + "module": "dist/index.js", + "browser": "dist/index.js", + "main": "dist/index.js", + "type": "module", + "typings": "dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "tsc", + "dev": "tsc -w", + "type-check": "tsc --noEmit" + }, + "license": "MIT", + "devDependencies": { + "typescript": "^5.4.5", + "@walletconnect/types": "^2.13.0" + }, + "dependencies": { + "@walletconnect/ethereum-provider": "^2.13.0", + "@web3-onboard/common": "^2.4.1", + "joi": "17.9.1", + "rxjs": "^7.5.2" + } +} diff --git a/packages/bloom/src/icon.ts b/packages/bloom/src/icon.ts new file mode 100644 index 000000000..d11ffd11f --- /dev/null +++ b/packages/bloom/src/icon.ts @@ -0,0 +1,81 @@ +export default ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +` diff --git a/packages/bloom/src/index.ts b/packages/bloom/src/index.ts new file mode 100644 index 000000000..1c89f4077 --- /dev/null +++ b/packages/bloom/src/index.ts @@ -0,0 +1,32 @@ +import { validateWCInitOptions } from './validation.js' +import type { WalletInit } from '@web3-onboard/common' +import walletConnect from './walletConnect.js' +import type { WalletConnectOptions } from './types.js' + +function initBloom(options: WalletConnectOptions): WalletInit { + if (!options) { + throw new Error( + `WalletConnect requires an initialization object to be passed - see the official docs for an example: https://onboard.blocknative.com/docs/wallets/walletconnect` + ) + } + + const error = validateWCInitOptions(options) + if (error) { + throw error + } + + const wallet = { + name: 'Bloom', + protocol: 'bloom', + downloadLink: 'https://bloomwallet.io/', + } + options.handleUri = (uri: string) => { + const deeplink = `${wallet.protocol}://wallet-connect/wc?uri=${encodeURIComponent(uri)}` + window.location.href = deeplink + return Promise.resolve() + } + + return walletConnect(wallet, options) +} + +export default initBloom diff --git a/packages/bloom/src/types.ts b/packages/bloom/src/types.ts new file mode 100644 index 000000000..3df47bea8 --- /dev/null +++ b/packages/bloom/src/types.ts @@ -0,0 +1,42 @@ +import { EthereumProviderOptions } from '@walletconnect/ethereum-provider/dist/types/EthereumProvider' + +export type WalletConnectOptions = { + /** + * Optional function to handle WalletConnect URI when it becomes available + */ + handleUri?: (uri: string) => Promise + /** + * Project ID associated with [WalletConnect account](https://cloud.walletconnect.com) + */ + projectId: string + /** + * Defaults to `appMetadata.explore` that is supplied to the web3-onboard init + * Strongly recommended to provide atleast one URL as it is required by some wallets (i.e. MetaMask) + * To connect with walletconnect + */ + dappUrl?: string + /** + * List of Required Chain(s) ID for wallets to support in number format (integer or hex) + * Defaults to [1] - Ethereum + */ + requiredChains?: number[] | undefined + /** + * List of Optional Chain(s) ID for wallets to support in number format (integer or hex) + * Defaults to the chains provided within the web3-onboard init chain property + */ + optionalChains?: number[] | undefined + /** + * `undefined` by default, see https://docs.walletconnect.com/2.0/web/walletConnectModal/options + */ + qrModalOptions?: EthereumProviderOptions['qrModalOptions'] + /** + * Additional required methods to be added to the default list of ['eth_sendTransaction', 'personal_sign'] + * Passed methods to be included along with the defaults methods - see https://docs.walletconnect.com/2.0/advanced/providers/ethereum#required-and-optional-methods + */ + additionalRequiredMethods?: string[] | undefined + /** + * Additional methods to be added to the default list of ['eth_sendTransaction', 'eth_signTransaction', 'personal_sign', 'eth_sign', 'eth_signTypedData', 'eth_signTypedData_v4'] + * Passed methods to be included along with the defaults methods - see https://docs.walletconnect.com/2.0/web/walletConnectModal/options + */ + additionalOptionalMethods?: string[] | undefined +} diff --git a/packages/bloom/src/utils.ts b/packages/bloom/src/utils.ts new file mode 100644 index 000000000..b7b5e6a7c --- /dev/null +++ b/packages/bloom/src/utils.ts @@ -0,0 +1,83 @@ +import type { CoreTypes } from '@walletconnect/types' + +export function getMetaData(appMetadata: any): CoreTypes.Metadata | undefined { + if (!appMetadata) return undefined + const wcMetaData: CoreTypes.Metadata = { + name: appMetadata.name, + description: appMetadata.description || '', + url: appMetadata.explore || appMetadata.gettingStartedGuide || '', + icons: [] + } + + if (appMetadata.icon !== undefined && appMetadata.icon.length) { + wcMetaData.icons = [appMetadata.icon] + } + if (appMetadata.logo !== undefined && appMetadata.logo.length) { + wcMetaData.icons = wcMetaData.icons.length + ? [...wcMetaData.icons, appMetadata.logo] + : [appMetadata.logo] + } + + return wcMetaData +} + +export function buildWCChains( + requiredChains: number[], + optionalChains: number[], + chains: { id: string }[] +): { + requiredChains: number[] + optionalChains: number[] +} { + // default to mainnet + const requiredChainsParsed: number[] = + Array.isArray(requiredChains) && + requiredChains.length && + requiredChains.every(num => !isNaN(num)) + ? // @ts-ignore + // Required as WC package does not support hex numbers + requiredChains.map(chainID => parseInt(chainID)) + : [] + + // Defaults to the chains provided within the web3-onboard init chain property + const optionalChainsParsed: number[] = + Array.isArray(optionalChains) && + optionalChains.length && + optionalChains.every(num => !isNaN(num)) + ? // @ts-ignore + // Required as WC package does not support hex numbers + optionalChains.map(chainID => parseInt(chainID)) + : chains.map(({ id }) => parseInt(id, 16)) + + return { + requiredChains: requiredChainsParsed, + optionalChains: optionalChainsParsed + } +} + +export function buildWCMethods( + additionalRequiredMethods: string[], + additionalOptionalMethods: string[], + requiredMethods: string[], + allMethods: string[] +): { + requiredMethods: string[] + optionalMethods: string[] +} { + const requiredMethodsSet = new Set( + additionalRequiredMethods && Array.isArray(additionalRequiredMethods) + ? [...additionalRequiredMethods, ...requiredMethods] + : requiredMethods + ) + const _requiredMethods = Array.from(requiredMethodsSet) + + const optionalMethods = + additionalOptionalMethods && Array.isArray(additionalOptionalMethods) + ? [...additionalOptionalMethods, ...allMethods] + : allMethods + + return { + requiredMethods: _requiredMethods, + optionalMethods + } +} diff --git a/packages/bloom/src/validation.ts b/packages/bloom/src/validation.ts new file mode 100644 index 000000000..33e5cf7ef --- /dev/null +++ b/packages/bloom/src/validation.ts @@ -0,0 +1,57 @@ +import Joi from 'joi' +import type { WalletConnectOptions } from './types.js' + +const wcOptions = Joi.object({ + handleUri: Joi.func().optional(), + version: Joi.number() + .optional() + .custom((value, helpers) => { + if (value === 1) { + console.warn( + 'Version 1 of WalletConnect has been fully deprecated. This version of @web3-onboard/walletconnect only supports version 2' + ) + } else if (value !== 2 && value !== undefined) { + return helpers.error('any.invalid', { + message: + 'Invalid version number. This version of @web3-onboard/walletconnect only supports version 2' + }) + } + return value // return the value unchanged if it's valid or not provided + }, 'Custom version validation'), + projectId: Joi.string().messages({ + 'any.required': `WalletConnect version 2 requires a projectId. Please visit https://cloud.walletconnect.com to get one.` + }), + dappUrl: Joi.string() + .optional() + .custom((value, helpers) => { + if (!value) { + return helpers.message({ + message: + 'It is strongly recommended to supply a dappUrl as it is required by some wallets (i.e. MetaMask) to allow connection.', + type: 'any.custom' + }) + } + return value // return the value unchanged if it's provided + }, 'Custom dappUrl validation'), + requiredChains: Joi.array().items(Joi.number()).optional(), + optionalChains: Joi.array().items(Joi.number()).optional(), + qrModalOptions: Joi.object().optional(), + additionalRequiredMethods: Joi.array().items(Joi.string()).optional(), + additionalOptionalMethods: Joi.array().items(Joi.string()).optional() +}) + +type ValidateReturn = Joi.ValidationResult | null + +const validate = ( + validator: Joi.AnySchema, + data: unknown +): ValidateReturn => { + const result = validator.validate(data) + return result.error ? result : null +} + +export const validateWCInitOptions = ( + data: WalletConnectOptions +): ValidateReturn => { + return validate(wcOptions, data) +} diff --git a/packages/bloom/src/walletConnect.ts b/packages/bloom/src/walletConnect.ts new file mode 100644 index 000000000..09db43167 --- /dev/null +++ b/packages/bloom/src/walletConnect.ts @@ -0,0 +1,343 @@ +import type { EthereumProviderOptions } from '@walletconnect/ethereum-provider/dist/types/EthereumProvider' +import type { JQueryStyleEventEmitter } from 'rxjs/internal/observable/fromEvent' +import type { WalletConnectOptions } from './types.js' +import type { + Chain, + ProviderAccounts, + WalletInit, + EIP1193Provider +} from '@web3-onboard/common' +import { createDownloadMessage } from '@web3-onboard/common' +import { buildWCChains, buildWCMethods, getMetaData } from './utils.js' + +// methods that require user interaction +const methods = [ + 'eth_sendTransaction', + 'eth_signTransaction', + 'personal_sign', + 'eth_sign', + 'eth_signTypedData', + 'eth_signTypedData_v4', + 'wallet_addEthereumChain', + 'wallet_switchEthereumChain' +] + +declare type ArrayOneOrMore = { + 0: T +} & Array + +function walletConnect( + wallet: { + name: string, + protocol: string, + downloadLink: string, + }, + options: WalletConnectOptions +): WalletInit { + if (!options.dappUrl) { + console.warn( + `It is strongly recommended to supply a dappUrl to the WalletConnect init object as it is required by some wallets (i.e. MetaMask) to allow connection.` + ) + } + const { qrModalOptions, handleUri } = options + + let instance: unknown + + return () => { + return { + label: wallet.name, + getIcon: async () => (await import('./icon.js')).default, + getInterface: async ({ chains, EventEmitter, appMetadata }) => { + + // Check if the wallet can be opened by a deeplink like protocol://XYZ + const isInstalled = checkIfProtocolIsSupported(wallet.protocol) + if (!isInstalled) { + throw new Error(createDownloadMessage(wallet.name, wallet.downloadLink)) + } + + const { ProviderRpcError, ProviderRpcErrorCode } = await import( + '@web3-onboard/common' + ) + + const { default: EthereumProvider, REQUIRED_METHODS } = await import( + '@walletconnect/ethereum-provider' + ) + + const { Subject, fromEvent } = await import('rxjs') + const { takeUntil, take } = await import('rxjs/operators') + + const { requiredChains, optionalChains } = buildWCChains( + options.requiredChains ?? [], + options.optionalChains ?? [], + chains + ) + const { requiredMethods, optionalMethods } = buildWCMethods( + options.additionalRequiredMethods ?? [], + options.additionalOptionalMethods ?? [], + REQUIRED_METHODS, + methods + ) + + const connector = await EthereumProvider.init({ + projectId: options.projectId, + chains: requiredChains, + methods: requiredMethods, + optionalChains: optionalChains as unknown as ArrayOneOrMore, + optionalMethods, + showQrModal: !options.handleUri, + qrModalOptions: qrModalOptions, + rpcMap: chains + .map(({ id, rpcUrl }) => ({ id, rpcUrl })) + .reduce((rpcMap: Record, { id, rpcUrl }) => { + rpcMap[parseInt(id, 16)] = rpcUrl || '' + return rpcMap + }, {}), + metadata: getMetaData(appMetadata) + } as EthereumProviderOptions) + + const emitter = new EventEmitter() + class EthProvider { + public request: EIP1193Provider['request'] + public connector: InstanceType + public chains: Chain[] + public disconnect: EIP1193Provider['disconnect'] + // @ts-ignore + public emit: typeof EventEmitter['emit'] + // @ts-ignore + public on: typeof EventEmitter['on'] + // @ts-ignore + public removeListener: typeof EventEmitter['removeListener'] + + private disconnected$: InstanceType + + constructor({ + connector, + chains + }: { + connector: InstanceType + chains: Chain[] + }) { + this.emit = emitter.emit.bind(emitter) + this.on = emitter.on.bind(emitter) + this.removeListener = emitter.removeListener.bind(emitter) + + this.connector = connector + this.chains = chains + this.disconnected$ = new Subject() + + // listen for accountsChanged + fromEvent(this.connector, 'accountsChanged', payload => payload) + .pipe(takeUntil(this.disconnected$)) + .subscribe({ + next: payload => { + const accounts = Array.isArray(payload) ? payload : [payload] + this.emit('accountsChanged', accounts) + }, + error: console.warn + }) + + // listen for chainChanged + fromEvent( + this.connector as JQueryStyleEventEmitter, + 'chainChanged', + (payload: number) => payload + ) + .pipe(takeUntil(this.disconnected$)) + .subscribe({ + next: chainId => { + const hexChainId = isHexString(chainId) + ? chainId + : `0x${chainId.toString(16)}` + this.emit('chainChanged', hexChainId) + }, + error: console.warn + }) + + // listen for disconnect event + fromEvent( + this.connector as JQueryStyleEventEmitter, + 'session_delete', + (payload: string) => payload + ) + .pipe(takeUntil(this.disconnected$)) + .subscribe({ + next: () => { + this.emit('accountsChanged', []) + this.disconnected$.next(true) + typeof localStorage !== 'undefined' && + localStorage.removeItem('walletconnect') + }, + error: console.warn + }) + + this.disconnect = () => { + if (this.connector.session) { + this.connector.disconnect() + instance = null + } + } + + if (options?.handleUri) { + // listen for uri event + fromEvent( + this.connector as JQueryStyleEventEmitter, + 'display_uri', + (payload: string) => payload + ) + .pipe(takeUntil(this.disconnected$)) + .subscribe(async uri => { + try { + handleUri && (await handleUri(uri)) + } catch (error) { + throw `An error occurred when handling the URI. Error: ${error}` + } + }) + } + + const checkForSession = () => { + const session = this.connector.session + instance = session + if (session) { + this.emit('accountsChanged', this.connector.accounts) + this.emit('chainChanged', this.connector.chainId) + } + } + checkForSession() + + this.request = async ({ method, params }) => { + if (method === 'eth_chainId') { + return isHexString(this.connector.chainId) + ? this.connector.chainId + : `0x${this.connector.chainId.toString(16)}` + } + + if (method === 'eth_requestAccounts') { + return new Promise( + async (resolve, reject) => { + // Subscribe to connection events + fromEvent( + this.connector as JQueryStyleEventEmitter< + any, + { chainId: number } + >, + 'connect', + (payload: { chainId: number | string }) => payload + ) + .pipe(take(1)) + .subscribe({ + next: ({ chainId }) => { + this.emit('accountsChanged', this.connector.accounts) + const hexChainId = isHexString(chainId) + ? chainId + : `0x${chainId.toString(16)}` + this.emit('chainChanged', hexChainId) + resolve(this.connector.accounts as ProviderAccounts) + }, + error: reject + }) + + // Check if connection is already established + if (!this.connector.session) { + // create new session + await this.connector.connect().catch(err => { + console.error('err creating new session: ', err) + reject( + new ProviderRpcError({ + code: 4001, + message: 'User rejected the request.' + }) + ) + }) + } else { + // update ethereum provider to load accounts & chainId + const accounts = this.connector.accounts + const chainId = this.connector.chainId + instance = this.connector.session + const hexChainId = `0x${chainId.toString(16)}` + this.emit('chainChanged', hexChainId) + return resolve(accounts as ProviderAccounts) + } + } + ) + } + + if (method === 'eth_selectAccounts') { + throw new ProviderRpcError({ + code: ProviderRpcErrorCode.UNSUPPORTED_METHOD, + message: `The Provider does not support the requested method: ${method}` + }) + } + + if (method == 'wallet_switchEthereumChain') { + if (!params) { + throw new ProviderRpcError({ + code: ProviderRpcErrorCode.INVALID_PARAMS, + message: `The Provider requires a chainId to be passed in as an argument` + }) + } + const chainIdObj = params[0] as { chainId?: number } + if ( + !chainIdObj.hasOwnProperty('chainId') || + typeof chainIdObj['chainId'] === 'undefined' + ) { + throw new ProviderRpcError({ + code: ProviderRpcErrorCode.INVALID_PARAMS, + message: `The Provider requires a chainId to be passed in as an argument` + }) + } + return this.connector.request({ + method: 'wallet_switchEthereumChain', + params: [ + { + chainId: chainIdObj.chainId + } + ] + }) + } + + return this.connector.request>({ + method, + params + }) + } + } + } + + return { + provider: new EthProvider({ chains, connector }), + instance + } + } + } + } +} + +const isHexString = (value: string | number) => { + if (typeof value !== 'string' || !value.match(/^0x[0-9A-Fa-f]*$/)) { + return false + } + + return true +} + +// This is a workaround to determine if a protocol is supported by the users device +// This doesn't work for Linux devices, as for that not error are thrown when the protocol is not supported +function checkIfProtocolIsSupported(protocol: string) { + let iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + document.body.appendChild(iframe); + + if (!iframe.contentWindow) { + return false; + } + try { + iframe.contentWindow.location.href = protocol + '://'; + return true; + } catch(e) { + return false; + } finally { + document.body.removeChild(iframe); + } +} + +export default walletConnect diff --git a/packages/bloom/tsconfig.json b/packages/bloom/tsconfig.json new file mode 100644 index 000000000..503e032ba --- /dev/null +++ b/packages/bloom/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*"], + + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "declarationDir": "dist", + "allowSyntheticDefaultImports": true, + "paths": { + "*": ["./src/*", "./node_modules/*"] + }, + "typeRoots": ["node_modules/@types"] + } +} diff --git a/packages/demo/package.json b/packages/demo/package.json index 4a5937aa5..b6a8861a8 100644 --- a/packages/demo/package.json +++ b/packages/demo/package.json @@ -31,6 +31,7 @@ "@web3-onboard/arcana-auth": "^2.1.0", "@web3-onboard/bitget": "2.1.1", "@web3-onboard/blocto": "^2.1.1", + "@web3-onboard/bloom": "2.0.0-alpha.1", "@web3-onboard/capsule": "2.2.0-alpha.1", "@web3-onboard/cede-store": "^2.3.1", "@web3-onboard/core": "2.22.2-alpha.2", diff --git a/packages/demo/src/App.svelte b/packages/demo/src/App.svelte index f1bcefbb2..39191c635 100644 --- a/packages/demo/src/App.svelte +++ b/packages/demo/src/App.svelte @@ -36,6 +36,7 @@ import arcanaAuthModule from '@web3-onboard/arcana-auth' import venlyModule from '@web3-onboard/venly' import bitgetModule from '@web3-onboard/bitget' + import bloomModule from '@web3-onboard/bloom' import particleAuthModule from '@web3-onboard/particle-network' import capsuleModule, { Environment, @@ -209,6 +210,10 @@ const cedeStore = cedeStoreModule() const blocto = bloctoModule() const tallyho = tallyHoModule() + const bloom = bloomModule({ + projectId: 'f6bd6e2911b56f5ac3bc8b2d0e2d7ad5', + dappUrl: 'https://www.onboard.blocknative.com' + }) const webauthnSigner = new WebauthnSigner({ rpId: 'localhost', @@ -293,6 +298,7 @@ okx, tallyho, bitget, + bloom, enkrypt, infinityWallet, mewWallet,