Make sure you have the newest Sequence.js, at least "0xsequence": "^0.41.2", in your package.json.
Put wallet.ts, connector.ts, and logo.ts in a folder called sequence
.
Created
September 28, 2022 16:36
-
-
Save arilotter/025a32193448fc3c42843061267ee85a to your computer and use it in GitHub Desktop.
Sequence Rainbowkit Connector
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
ConnectButton, | |
connectorsForWallets, | |
RainbowKitProvider, | |
wallet, | |
} from '@rainbow-me/rainbowkit'; | |
import { WagmiConfig } from 'wagmi'; | |
import { chain, configureChains, createClient } from 'wagmi'; | |
import { alchemyProvider } from 'wagmi/providers/alchemy'; | |
import "@rainbow-me/rainbowkit/styles.css"; | |
import { sequenceWallet } from './sequence/wallet'; | |
const defaultProvider = alchemyProvider({ | |
apiKey: process.env.ALCHEMY_APIKEY, | |
}); | |
export const { chains, provider, webSocketProvider } = configureChains( | |
[chain.polygonMumbai], | |
[defaultProvider], | |
); | |
const connectors = connectorsForWallets([ | |
{ | |
groupName: 'Recommended', | |
wallets: [ | |
sequenceWallet({ chains }), | |
wallet.metaMask({ chains }), | |
wallet.rainbow({ chains }), | |
wallet.walletConnect({ chains }), | |
], | |
}, | |
]); | |
const wagmiClient = createClient({ | |
autoConnect: true, | |
connectors: () => [...connectors()], | |
provider, | |
webSocketProvider, | |
}); | |
export default () => { | |
return ( | |
<WagmiConfig client={wagmiClient}> | |
<RainbowKitProvider chains={chains}> | |
<ConnectButton /> | |
</RainbowKitProvider> | |
</WagmiConfig> | |
); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// build by Ari Lotter | |
import { sequence } from '0xsequence' | |
import { mainnetNetworks, testnetNetworks } from '@0xsequence/network' | |
import type { ConnectOptions, ProviderConfig, Web3Provider } from '@0xsequence/provider' | |
import { Wallet } from '@0xsequence/provider' | |
import { Chain } from '@rainbow-me/rainbowkit' | |
import { Connector, ConnectorData, ConnectorNotFoundError, UserRejectedRequestError } from 'wagmi' | |
interface Options { | |
provider?: Partial<ProviderConfig> | |
connect?: ConnectOptions | |
shimDisconnect?: boolean | |
} | |
let initialized = false | |
export class SequenceConnector extends Connector<Web3Provider, Options | undefined> { | |
id = 'sequence' | |
name = 'Sequence' | |
// chains = chainConfigList | |
ready = true | |
provider: Web3Provider | null = null | |
wallet: Wallet | |
connected = false | |
constructor({ chains, options }: { chains?: Chain[]; options?: Options }) { | |
super({ chains, options }) | |
if (!initialized) { | |
initialized = true | |
sequence.initWallet(chains?.[0]?.id ?? 'polygon') | |
this.wallet = sequence.getWallet() | |
} | |
} | |
async connect(): Promise<Required<ConnectorData<Web3Provider>>> { | |
if (!this.wallet.isConnected()) { | |
this.emit('message', { type: 'connecting' }) | |
const e = await this.wallet.connect(this.options?.connect) | |
if (e.error) { | |
throw new UserRejectedRequestError(e.error) | |
} | |
if (!e.connected) { | |
throw new UserRejectedRequestError('Wallet connection rejected') | |
} | |
} | |
console.log('connect') | |
const chainId = await this.getChainId() | |
const provider = await this.getProvider() | |
const account = await this.getAccount() | |
// provider.on("accountsChanged", this.onAccountsChanged); | |
this.wallet.on('chainChanged', this.onChainChanged) | |
provider.on('disconnect', this.onDisconnect) | |
this.connected = true | |
return { | |
account, | |
chain: { | |
id: chainId, | |
unsupported: this.isChainUnsupported(chainId) | |
}, | |
provider | |
} | |
} | |
async disconnect() { | |
this.wallet.disconnect() | |
} | |
getAccount() { | |
return this.wallet.getAddress() | |
} | |
getChainId() { | |
// in mobile, when connecting with sequence Rainbowkit first tried to get ChainID for some reason, but in sequence you can't get ChainID before being connected, so forcing here to connect if you want to get ChainID | |
if (!this.wallet.isConnected()) { | |
return this.connect().then(() => this.wallet.getChainId()) | |
} | |
return this.wallet.getChainId() | |
} | |
async getProvider() { | |
if (!this.provider) { | |
const provider = this.wallet.getProvider() | |
if (!provider) { | |
throw new ConnectorNotFoundError('Failed to get Sequence Wallet provider.') | |
} | |
this.provider = provider | |
} | |
return this.provider | |
} | |
async getSigner() { | |
return this.wallet.getSigner() | |
} | |
async isAuthorized() { | |
try { | |
const account = await this.getAccount() | |
return !!account | |
} catch { | |
return false | |
} | |
} | |
async switchChain(chainId: number): Promise<Chain> { | |
await this.provider?.send('wallet_switchEthereumChain', [{ chainId: chainId }]) | |
return { id: chainId } as Chain | |
} | |
// eslint-disable-next-line @typescript-eslint/no-unused-vars | |
protected onAccountsChanged = (accounts: string[]) => {} | |
// eslint-disable-next-line @typescript-eslint/no-unused-vars | |
protected onChainChanged = (chain: number | string) => { | |
this.provider?.emit('chainChanged', chain) | |
const id = normalizeChainId(chain) | |
const unsupported = this.isChainUnsupported(id) | |
this.emit('change', { chain: { id, unsupported } }) | |
} | |
protected onDisconnect = () => { | |
this.emit('disconnect') | |
} | |
isChainUnsupported(chainId: number): boolean { | |
return !(mainnetNetworks.some(c => c.chainId === chainId) || testnetNetworks.some(c => c.chainId === chainId)) | |
} | |
} | |
function normalizeChainId(chainId: string | number | bigint) { | |
if (typeof chainId === 'string') return Number.parseInt(chainId, chainId.trim().substring(0, 2) === '0x' ? 16 : 10) | |
if (typeof chainId === 'bigint') return Number(chainId) | |
return chainId | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const sequenceLogo = | |
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCAzOTYgMzE4IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzVfMTMxKSI+DQo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDFfNV8xMzEpIj4NCjxwYXRoIGQ9Ik0wIDY3LjUwNDlMMCAyNTAuMTY1QzAgMjg3LjQ0NyAzMC4xNDAyIDMxNy42NyA2Ny4zMiAzMTcuNjdIMzI4LjY4QzM2NS44NiAzMTcuNjcgMzk2IDI4Ny40NDcgMzk2IDI1MC4xNjVWNjcuNTA0OUMzOTYgMzAuMjIzIDM2NS44NiAwIDMyOC42OCAwSDY3LjMyQzMwLjE0MDIgMCAwIDMwLjIyMyAwIDY3LjUwNDlaIiBmaWxsPSIjMTExMTExIi8+DQo8cGF0aCBkPSJNMCA2Ny41MDQ5TDAgMjUwLjE2NUMwIDI4Ny40NDcgMzAuMTQwMiAzMTcuNjcgNjcuMzIgMzE3LjY3SDMyOC42OEMzNjUuODYgMzE3LjY3IDM5NiAyODcuNDQ3IDM5NiAyNTAuMTY1VjY3LjUwNDlDMzk2IDMwLjIyMyAzNjUuODYgMCAzMjguNjggMEg2Ny4zMkMzMC4xNDAyIDAgMCAzMC4yMjMgMCA2Ny41MDQ5WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzVfMTMxKSIvPg0KPHBhdGggZD0iTTk4Ljk5OTkgNzkuNDE3NkM5OC45OTk5IDY4LjQ1MjMgOTAuMTM1MSA1OS41NjMyIDc5LjE5OTkgNTkuNTYzMkM2OC4yNjQ3IDU5LjU2MzIgNTkuMzk5OSA2OC40NTIzIDU5LjM5OTkgNzkuNDE3NkM1OS4zOTk5IDkwLjM4MjggNjguMjY0NyA5OS4yNzIgNzkuMTk5OSA5OS4yNzJDOTAuMTM1MSA5OS4yNzIgOTguOTk5OSA5MC4zODI4IDk4Ljk5OTkgNzkuNDE3NloiIGZpbGw9InVybCgjcGFpbnQxX2xpbmVhcl81XzEzMSkiLz4NCjxwYXRoIGQ9Ik05OC45OTk5IDc5LjQxNzZDOTguOTk5OSA2OC40NTIzIDkwLjEzNTEgNTkuNTYzMiA3OS4xOTk5IDU5LjU2MzJDNjguMjY0NyA1OS41NjMyIDU5LjM5OTkgNjguNDUyMyA1OS4zOTk5IDc5LjQxNzZDNTkuMzk5OSA5MC4zODI4IDY4LjI2NDcgOTkuMjcyIDc5LjE5OTkgOTkuMjcyQzkwLjEzNTEgOTkuMjcyIDk4Ljk5OTkgOTAuMzgyOCA5OC45OTk5IDc5LjQxNzZaIiBmaWxsPSJ1cmwoI3BhaW50Ml9saW5lYXJfNV8xMzEpIi8+DQo8cGF0aCBkPSJNOTguOTk5OSA3OS40MTc2Qzk4Ljk5OTkgNjguNDUyMyA5MC4xMzUxIDU5LjU2MzIgNzkuMTk5OSA1OS41NjMyQzY4LjI2NDcgNTkuNTYzMiA1OS4zOTk5IDY4LjQ1MjMgNTkuMzk5OSA3OS40MTc2QzU5LjM5OTkgOTAuMzgyOCA2OC4yNjQ3IDk5LjI3MiA3OS4xOTk5IDk5LjI3MkM5MC4xMzUxIDk5LjI3MiA5OC45OTk5IDkwLjM4MjggOTguOTk5OSA3OS40MTc2WiIgZmlsbD0idXJsKCNwYWludDNfbGluZWFyXzVfMTMxKSIvPg0KPHBhdGggZD0iTTk4Ljk5OTkgMjM4LjEyNkM5OC45OTk5IDIyNy4xNjEgOTAuMTM1MSAyMTguMjcyIDc5LjE5OTkgMjE4LjI3MkM2OC4yNjQ3IDIxOC4yNzIgNTkuMzk5OSAyMjcuMTYxIDU5LjM5OTkgMjM4LjEyNkM1OS4zOTk5IDI0OS4wOTIgNjguMjY0NyAyNTcuOTgxIDc5LjE5OTkgMjU3Ljk4MUM5MC4xMzUxIDI1Ny45ODEgOTguOTk5OSAyNDkuMDkyIDk4Ljk5OTkgMjM4LjEyNloiIGZpbGw9InVybCgjcGFpbnQ0X2xpbmVhcl81XzEzMSkiLz4NCjxwYXRoIGQ9Ik0zMzYuNiAxNTguODM1QzMzNi42IDE0Ny44NyAzMjcuNzM1IDEzOC45ODEgMzE2LjggMTM4Ljk4MUMzMDUuODY1IDEzOC45ODEgMjk3IDE0Ny44NyAyOTcgMTU4LjgzNUMyOTcgMTY5LjggMzA1Ljg2NSAxNzguNjkgMzE2LjggMTc4LjY5QzMyNy43MzUgMTc4LjY5IDMzNi42IDE2OS44IDMzNi42IDE1OC44MzVaIiBmaWxsPSJ1cmwoI3BhaW50NV9saW5lYXJfNV8xMzEpIi8+DQo8cGF0aCBkPSJNMzM2LjYgMTU4LjgzNUMzMzYuNiAxNDcuODcgMzI3LjczNSAxMzguOTgxIDMxNi44IDEzOC45ODFDMzA1Ljg2NSAxMzguOTgxIDI5NyAxNDcuODcgMjk3IDE1OC44MzVDMjk3IDE2OS44IDMwNS44NjUgMTc4LjY5IDMxNi44IDE3OC42OUMzMjcuNzM1IDE3OC42OSAzMzYuNiAxNjkuOCAzMzYuNiAxNTguODM1WiIgZmlsbD0idXJsKCNwYWludDZfbGluZWFyXzVfMTMxKSIvPg0KPHBhdGggZD0iTTMxNi44IDU5LjU2MzJIMTU4LjRDMTQ3LjQ2NSA1OS41NjMyIDEzOC42IDY4LjQ1MjMgMTM4LjYgNzkuNDE3NkMxMzguNiA5MC4zODI4IDE0Ny40NjUgOTkuMjcyIDE1OC40IDk5LjI3MkgzMTYuOEMzMjcuNzM1IDk5LjI3MiAzMzYuNiA5MC4zODI4IDMzNi42IDc5LjQxNzZDMzM2LjYgNjguNDUyMyAzMjcuNzM1IDU5LjU2MzIgMzE2LjggNTkuNTYzMloiIGZpbGw9InVybCgjcGFpbnQ3X2xpbmVhcl81XzEzMSkiLz4NCjxwYXRoIGQ9Ik0zMTYuOCAyMTguMjcySDE1OC40QzE0Ny40NjUgMjE4LjI3MiAxMzguNiAyMjcuMTYxIDEzOC42IDIzOC4xMjZDMTM4LjYgMjQ5LjA5MiAxNDcuNDY1IDI1Ny45ODEgMTU4LjQgMjU3Ljk4MUgzMTYuOEMzMjcuNzM1IDI1Ny45ODEgMzM2LjYgMjQ5LjA5MiAzMzYuNiAyMzguMTI2QzMzNi42IDIyNy4xNjEgMzI3LjczNSAyMTguMjcyIDMxNi44IDIxOC4yNzJaIiBmaWxsPSJ1cmwoI3BhaW50OF9saW5lYXJfNV8xMzEpIi8+DQo8cGF0aCBkPSJNMjM3LjYgMTM4Ljk4MUg3OS4yQzY4LjI2NDggMTM4Ljk4MSA1OS40IDE0Ny44NyA1OS40IDE1OC44MzVDNTkuNCAxNjkuOCA2OC4yNjQ4IDE3OC42OSA3OS4yIDE3OC42OUgyMzcuNkMyNDguNTM1IDE3OC42OSAyNTcuNCAxNjkuOCAyNTcuNCAxNTguODM1QzI1Ny40IDE0Ny44NyAyNDguNTM1IDEzOC45ODEgMjM3LjYgMTM4Ljk4MVoiIGZpbGw9InVybCgjcGFpbnQ5X2xpbmVhcl81XzEzMSkiLz4NCjwvZz4NCjwvZz4NCjxkZWZzPg0KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDBfbGluZWFyXzVfMTMxIiB4MT0iMTk4IiB5MT0iNC4wNTg1NGUtMDUiIHgyPSIxOTgiIHkyPSIzMTgiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4NCjxzdG9wIHN0b3AtY29sb3I9IiMxRDI3M0QiLz4NCjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzBEMEYxMyIvPg0KPC9saW5lYXJHcmFkaWVudD4NCjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQxX2xpbmVhcl81XzEzMSIgeDE9IjY1LjUiIHkxPSI5OSIgeDI9IjkyLjUiIHkyPSI2MyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPg0KPHN0b3Agc3RvcC1jb2xvcj0iIzQ0NjJGRSIvPg0KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjN0Q2OUZBIi8+DQo8L2xpbmVhckdyYWRpZW50Pg0KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDJfbGluZWFyXzVfMTMxIiB4MT0iNjIuODc5OSIgeTE9Ijk5LjI5MTIiIHgyPSI5Ni4xMzc3IiB5Mj0iOTcuNTkxMSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPg0KPHN0b3Agc3RvcC1jb2xvcj0iIzM3NTdGRCIvPg0KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNjk4MEZBIi8+DQo8L2xpbmVhckdyYWRpZW50Pg0KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDNfbGluZWFyXzVfMTMxIiB4MT0iNjIuODc5OSIgeTE9Ijk5LjI5MTIiIHgyPSI5Ni4xMzc3IiB5Mj0iOTcuNTkxMSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPg0KPHN0b3Agc3RvcC1jb2xvcj0iIzI0NDdGRiIvPg0KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNjk4MEZBIi8+DQo8L2xpbmVhckdyYWRpZW50Pg0KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDRfbGluZWFyXzVfMTMxIiB4MT0iNjUiIHkxPSIyNTEuNSIgeDI9IjkxLjUiIHkyPSIyMjMuNSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPg0KPHN0b3Agc3RvcC1jb2xvcj0iI0JDM0VFNiIvPg0KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjRDk3MkYxIi8+DQo8L2xpbmVhckdyYWRpZW50Pg0KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDVfbGluZWFyXzVfMTMxIiB4MT0iMzA1IiB5MT0iMTcyIiB4Mj0iMzI5LjUiIHkyPSIxNDYiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4NCjxzdG9wIHN0b3AtY29sb3I9IiMyOUJERkYiLz4NCjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzk2RTdGQiIvPg0KPC9saW5lYXJHcmFkaWVudD4NCjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQ2X2xpbmVhcl81XzEzMSIgeDE9IjMwMC4xOCIgeTE9IjE3OC40MTgiIHgyPSIzMzQuNTY3IiB5Mj0iMTc2Ljc3MiIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPg0KPHN0b3Agc3RvcC1jb2xvcj0iIzIzQkJGRiIvPg0KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjODVFN0ZGIi8+DQo8L2xpbmVhckdyYWRpZW50Pg0KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDdfbGluZWFyXzVfMTMxIiB4MT0iMTU0LjUiIHkxPSI5OSIgeDI9IjMxNy41IiB5Mj0iNjAiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4NCjxzdG9wIHN0b3AtY29sb3I9IiMyM0JCRkYiLz4NCjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzg1RTdGRiIvPg0KPC9saW5lYXJHcmFkaWVudD4NCjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQ4X2xpbmVhcl81XzEzMSIgeDE9IjE1NiIgeTE9IjI1OCIgeDI9IjMxMi41IiB5Mj0iMjE4IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+DQo8c3RvcCBzdG9wLWNvbG9yPSIjMjQ0N0ZGIi8+DQo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM2OTgwRkEiLz4NCjwvbGluZWFyR3JhZGllbnQ+DQo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50OV9saW5lYXJfNV8xMzEiIHgxPSI4Ni4wMDAxIiB5MT0iMTc5IiB4Mj0iMjM1LjUiIHkyPSIxMzkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4NCjxzdG9wIHN0b3AtY29sb3I9IiM2NjM0RkYiLz4NCjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzlDNkRGRiIvPg0KPC9saW5lYXJHcmFkaWVudD4NCjxjbGlwUGF0aCBpZD0iY2xpcDBfNV8xMzEiPg0KPHJlY3Qgd2lkdGg9IjM5NiIgaGVpZ2h0PSIzMTcuNjciIGZpbGw9IndoaXRlIi8+DQo8L2NsaXBQYXRoPg0KPGNsaXBQYXRoIGlkPSJjbGlwMV81XzEzMSI+DQo8cmVjdCB3aWR0aD0iMzk2IiBoZWlnaHQ9IjMxNy42NyIgZmlsbD0id2hpdGUiLz4NCjwvY2xpcFBhdGg+DQo8L2RlZnM+DQo8L3N2Zz4=' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Chain, Wallet } from '@rainbow-me/rainbowkit' | |
import { SequenceConnector } from './connector' | |
import { sequenceLogo } from './logo' | |
export interface MyWalletOptions { | |
chains: Chain[] | |
shimDisconnect?: boolean | undefined | |
} | |
export const sequenceWallet = ({ chains, shimDisconnect }: MyWalletOptions): Wallet => ({ | |
id: 'sequence', | |
name: 'Sequence', | |
iconUrl: sequenceLogo, | |
iconBackground: '#fff', | |
downloadUrls: { | |
// browserExtension: 'https://chrome.google.com/webstore/detail/sequence-wallet/ocmccklecaalljlflmclidjeclpcpdim' | |
// android: | |
// ios: | |
browserExtension: 'https://sequence.app' // default to the web app for now | |
}, | |
createConnector: () => { | |
const connector = new SequenceConnector({ | |
chains, | |
options: { | |
shimDisconnect, | |
connect: { | |
app: 'DappName', | |
authorize: false | |
} | |
} | |
}) | |
return { | |
connector, | |
mobile: { | |
getUri: async () => { | |
try { | |
await connector.connect() | |
return window.location.href | |
} catch (e) { | |
console.error('Failed to connect', e) | |
} | |
return '' | |
} | |
}, | |
desktop: { | |
getUri: async () => { | |
try { | |
await connector.connect() | |
} catch (e) { | |
console.error('Failed to connect', e) | |
} | |
return '' | |
} | |
} | |
} | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment