TVM Connect
Create a connection to Nekoton-based wallets and dApps
Usage
Installation
To apply this component, install it with npm using following command:
npm install @broxus/tvm-connect
or using yarn:
yarn add @broxus/tvm-connect
Requirements
In general it works great with our UIkit package.
If you use this package you don't need to worry about the details.
Minimum requirements
If you are only going to use stores, you should install a few required packages
npm i everscale-inpage-provider mobx
or using yarn:
yarn add everscale-inpage-provider mobx
Full requirements
If you would like to use stores and included react components, you need to install a few more packages
npm i everscale-inpage-providermobx mobx-react-lite react-intl
or using yarn:
yarn add everscale-inpage-provider mobx-react-lite react-intl
TvmWalletService
The Wallet Service is a key part of this module. It accepts a number of settings and
parameters when created and has a convenient interface for working with a connected wallet.
It works with wallets whose providers and standalone RPC connections are
based on everscale-inpage-provider
and everscale-standalone-client
.
import { TvmChains } from '@broxus/js-core'
import { EverWallet, SparXWallet, TvmWalletProviderConfig, TvmWalletService, VenomWallet } from '@broxus/tvm-connect'
const sparxWallet: TvmWalletProviderConfig = {
connector: new SparXWallet(),
id: 'SparXWallet',
info: {
description: 'Your universal tool for TVM',
icon: '/assets/icons/SparXWallet.svg',
links: {
android: 'https://play.google.com/store/apps/details?id=com.broxus.sparx.app',
homepage: 'https://sparxwallet.com/',
ios: 'https://apps.apple.com/us/app/sparx-tvm-wallet/id6670219321',
},
name: 'SparX Wallet',
},
}
const everWallet: TvmWalletProviderConfig = {
connector: new EverWallet({ autoInit: false }),
id: 'EverWallet',
info: {
description: 'Premier wallet for the Everscale',
icon: '/assets/icons/EverWallet.svg',
links: {
android: 'https://play.google.com/store/apps/details?id=com.broxus.crystal.app',
chromeExtension: 'https://chrome.google.com/webstore/detail/ever-wallet/cgeeodpfagjceefieflmdfphplkenlfk',
firefoxExtension: 'https://addons.mozilla.org/en-GB/firefox/addon/ever-wallet/',
homepage: 'https://everwallet.net/',
ios: 'https://apps.apple.com/us/app/ever-wallet-everscale/id1581310780',
},
name: 'Ever Wallet',
},
}
const venomWallet: TvmWalletProviderConfig = {
connector: new VenomWallet(),
id: 'VenomWallet',
info: {
description: 'Safe, reliable, and 100% yours',
icon: '/assets/icons/VenomWallet.svg',
links: {
android: 'https://play.google.com/store/apps/details?id=com.venom.wallet',
chromeExtension: 'https://chrome.google.com/webstore/detail/venom-wallet/ojggmchlghnjlapmfbnjholfjkiidbch',
homepage: 'https://venomwallet.com/',
ios: 'https://apps.apple.com/app/venom-blockchain-wallet/id1622970889',
},
name: 'Venom Wallet',
},
}
const walletService = new TvmWalletService({
autoInit: false,
defaultNetworkId: TvmChains.EverscaleMainnet,
networks: [
{
chainId: TvmChains.EverscaleMainnet.toString(),
currency: {
decimals: 9,
icon: '/assets/icons/EVER.svg',
name: 'Native currency',
symbol: 'EVER',
wrappedCurrencyAddress: new AddressLiteral(
'0:a49cd4e158a9a15555e624759e2e4e766d22600b7800d891e46f9291f044a93d'),
},
explorer: {
accountsSubPath: 'accounts',
baseUrl: 'https://everscan.io',
title: 'EVER Scan',
transactionsSubPath: 'transactions',
},
id: `tvm-${TvmChains.EverscaleMainnet.toString()}`,
name: 'Everscale',
rpcUrl: 'https://jrpc.everwallet.net',
shortName: 'Everscale',
type: 'tvm',
},
],
providerId: 'EverWallet',
providers: [sparxWallet, everWallet, venomWallet],
})
await everWallet.connector.init()
const provider = await walletService.init()
await walletService.connect()
This is library/framework agnostic component. So, you can use it anywhere.
Using with React
First at all, you should wrap entire your app with TvmWalletServiceProvider
to share TvmWalletService
through all your app components.
import { TvmConnector, TvmWalletServiceProvider } from '@broxus/tvm-connect'
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { IntlProvider } from 'react-intl'
function App(): JSX.Element {
return (
<IntlProvider>
<TvmWalletServiceProvider>
...
<TvmConnector />
...
</TvmWalletServiceProvider>
</IntlProvider>
)
}
ReactDOM.render(<App />, document.body)
Custom service
You may use TvmWalletService
to create your own service with provider and connection.
import { TvmWalletService } from '@broxus/tvm-connect'
let service: TvmWalletService
export function useTvmConnect(): TvmWalletService {
if (service === undefined) {
service = new TvmWalletService({
defaultNetworkId: number,
networks: TvmNetworkConfig[],
providerId: string,
providers: TvmWalletProviderConfig[],
})
}
return service
}
function App(): JSX.Element {
const wallet = useTvmConnect()
return (
<IntlProvider>
<TvmWalletServiceProvider wallet={wallet}>
...
<TvmConnector />
...
</TvmWalletServiceProvider>
</IntlProvider>
)
}
Network configuration
Below you can see a models of the network configuration, native currency and explorer config.
interface NativeCurrency<T = any> {
balance?: string
decimals: number
icon?: string
name?: string
symbol: string
wrappedCurrencyAddress?: T
}
interface TvmNetworkConfig {
badge?: string
chainId: string
currency: NativeCurrency<Address>
disabled?: boolean
explorer: NetworkExplorerConfig
icon?: string
id: string
name: string
rpcUrl: string
shortName: string
tokensListUri?: string
tokenType?: string
type: 'tvm'
}
interface NetworkExplorerConfig {
accountsSubPath?: string | null
baseUrl: string
title: string
tokensSubPath?: string | null
transactionsSubPath?: string | null
}
Provider configuration
To use more providers (wallets) and their connections, you can configure these providers with
the providers
option that can be passed when instantiating the TvmWalletService
.
interface TvmWalletProviderConfig {
connector: NekotonConnector
info: {
description?: string
icon?: string
links?: TvmProviderPlatformLinks & { homepage?: string, universalLink?: string }
name: string
}
id: string
isRecent?: boolean
minVersion?: string
}
export type TvmProviderAvailablePlatforms = 'ios' | 'android' | 'chromeExtension' | 'firefoxExtension'
export type TvmProviderPlatformLinks = Partial<Record<TvmProviderAvailablePlatforms, string>>
Helpful utils
You can use isEverWalletBrowser
or isVenomWalletBrowser
to check environment.
isSparXWalletBrowser
- checks if your dApp is opened in mobile SparX Wallet WebView
isEverWalletBrowser
- checks if your dApp is opened in mobile Ever Wallet WebView
isVenomWalletBrowser
- checks if your dApp is opened in mobile Venom Wallet WebView
This will help you determine which connectors to use for mobile applications and for all other cases
import { TvmChains } from '@broxus/js-core'
import { TvmWalletService, useRecentConnectionMeta } from '@broxus/tvm-connect'
import { AddressLiteral } from 'everscale-inpage-provider'
const providers: TvmWalletProviderConfig[] = []
const networks: TvmNetworkConfig[] = [
{
chainId: TvmChains.EverscaleMainnet.toString(),
currency: {
decimals: 9,
icon: '/assets/icons/EVER.svg',
name: 'EVER',
symbol: 'EVER',
wrappedCurrencyAddress: new AddressLiteral('0:a49cd4e158a9a15555e624759e2e4e766d22600b7800d891e46f9291f044a93d'),
},
explorer: {
accountsSubPath: 'accounts',
baseUrl: 'https://everscan.io',
title: 'EVER Scan',
transactionsSubPath: 'transactions',
},
icon: '/assets/icons/EVER.svg',
id: `tvm-${TvmChains.EverscaleMainnet}`,
name: 'Everscale',
rpcUrl: 'https://jrpc.everwallet.net',
shortName: 'Everscale',
type: 'tvm',
},
{
chainId: TvmChains.VenomMainnet.toString(),
currency: {
decimals: 9,
icon: '/assets/icons/VENOM.svg',
name: 'VENOM',
symbol: 'VENOM',
wrappedCurrencyAddress: new AddressLiteral('0:77d36848bb159fa485628bc38dc37eadb74befa514395e09910f601b841f749e'),
},
explorer: {
accountsSubPath: 'accounts',
baseUrl: 'https://venomscan.com',
title: 'VenomScan',
transactionsSubPath: 'transactions',
},
icon: '/assets/icons/VENOM.svg',
id: `tvm-${TvmChains.VenomMainnet}`,
name: 'Venom Mainnet',
rpcUrl: 'https://jrpc.venom.foundation',
shortName: 'Venom',
type: 'tvm',
},
]
try {
const ua = getUserAgent()
const isSparXWallet = isSparXWalletBrowser(ua)
const isEverWallet = isEverWalletBrowser(ua)
const isVenomWallet = isVenomWalletBrowser(ua)
if (isSparXWallet) {
providers.push(sparxWallet)
defaultProviderId = sparxWallet.id
predefinedNetworkId = TvmChains.EverscaleMainnet
}
else if (isEverWallet) {
providers.push(everWallet)
defaultProviderId = everWallet.id
predefinedNetworkId = TvmChains.EverscaleMainnet
}
else if (isVenomWallet) {
providers.push(venomWallet)
defaultProviderId = venomWallet.id
predefinedNetworkId = TvmChains.VenomMainnet
}
else {
providers.push({
...sparxWallet,
minVersion: '0.4.0',
}, {
...everWallet,
minVersion: '0.4.0',
}, {
...venomWallet,
minVersion: '0.3.173',
})
}
}
catch (e) {}
let service: TvmWalletService
export function useTvmWallet(): TvmWalletService {
const [recentMeta] = useRecentConnectionMeta()
if (service === undefined) {
const networkId = recentMeta?.chainId ? Number(recentMeta.chainId) : TvmChains.EverscaleMainnet
service = new TvmWalletService({
defaultNetworkId: predefinedNetworkId ?? networkId,
networks,
providerId: recentMeta?.disconnected ? defaultProviderId : recentMeta?.providerId ?? defaultProviderId,
providers,
})
}
return service
}
Styling
If you are using our UIkit package it will it automatically adapts to your interface colors.
Otherwise, you can import standalone CSS
import '@broxus/tvm-connect/uikit.min.css'
import '@broxus/tvm-connect/style.min.css'
Below you can find all supported CSS variables and their defaults
--tvm-connect-dropdown-trigger-horizontal-padding: var(--global-small-gutter, 8px);
--tvm-connect-dropdown-trigger-vertical-padding: 0;
--tvm-connect-dropdown-background: var(--dropdown-background, #fff);
--tvm-connect-dropdown-border-radius: var(--dropdown-border-radius, 5px);
--tvm-connect-dropdown-box-shadow: 0 8px 32px 0 rgb(63 74 111 / 12%), 0 1px 4px 0 rgb(63 74 111 / 8%);
--tvm-connect-dropdown-color: var(--dropdown-color, #333);
--tvm-connect-dropdown-link-color: var(--dropdown-color, #0af);
--tvm-connect-provider-button-border-width: 2px;
--tvm-connect-provider-button-border-style: solid;
--tvm-connect-provider-button-border: transparent;
--tvm-connect-provider-button-hover-border: var(--global-primary-border, transparent);
--tvm-connect-modal-content-background: var(--modal-content-background, #fff);
--tvm-connect-modal-content-border-radius: 12px;
--tvm-connect-modal-content-box-shadow: 0 8px 32px 0 rgb(63 74 111 / 12%), 0 1px 4px 0 rgb(63 74 111 / 8%);
--tvm-connect-modal-content-color: var(--base-body-color, #383838);
--tvm-connect-modal-content-padding-horizontal: 18px;
--tvm-connect-modal-content-padding-vertical: var(--tvm-connect-modal-content-padding-horizontal);
--tvm-connect-modal-header-padding-horizontal: 0;
--tvm-connect-modal-header-padding-vertical: var(--tvm-connect-modal-content-padding-vertical);
--tvm-connect-modal-title-color: var(--base-heading-color, #383838);
--tvm-connect-modal-title-font-size: var(--modal-title-font-size, 18px);
--tvm-connect-modal-title-font-weight: 500;
--tvm-connect-modal-title-line-height: var(--modal-title-line-height, 22px);
--tvm-connect-modal-body-padding-horizontal: 0;
--tvm-connect-modal-body-padding-vertical: var(--tvm-connect-modal-content-padding-vertical);
--tvm-connect-modal-footer-padding-horizontal: 0;
--tvm-connect-modal-footer-padding-vertical: var(--tvm-connect-modal-content-padding-vertical);
--tvm-connect-drawer-content-background: var(--drawer-content-background, #fff);
--tvm-connect-drawer-content-border-radius: 16px;
--tvm-connect-drawer-content-box-shadow: 0 8px 32px 0 rgb(63 74 111 / 12%), 0 1px 4px 0 rgb(63 74 111 / 8%);
--tvm-connect-drawer-content-color: var(--base-body-color, #383838);
--tvm-connect-drawer-content-padding-horizontal: 24px;
--tvm-connect-drawer-content-padding-vertical: var(--tvm-connect-drawer-content-padding-horizontal);
--tvm-connect-drawer-header-padding-horizontal: 0;
--tvm-connect-drawer-header-padding-vertical: var(--tvm-connect-drawer-content-padding-vertical);
--tvm-connect-drawer-title-color: var(--base-heading-color, #383838);
--tvm-connect-drawer-title-font-size: var(--drawer-title-font-size, 24px);
--tvm-connect-drawer-title-font-weight: 500;
--tvm-connect-drawer-title-line-height: var(--drawer-title-line-height, 28px);
--tvm-connect-drawer-body-padding-horizontal: 0;
--tvm-connect-drawer-body-padding-vertical: var(--tvm-connect-drawer-content-padding-vertical);
--tvm-connect-drawer-footer-padding-horizontal: 0;
--tvm-connect-drawer-footer-padding-vertical: var(--tvm-connect-drawer-content-padding-vertical);
--tvm-connect-connection-request-button-border-width: 2px;
--tvm-connect-connection-request-button-border-style: solid;
--tvm-connect-connection-request-button-border: transparent;
--tvm-connect-connection-request-button-hover-border: var(--global-border, transparent);