Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: correct return of chain when connecting to bitcoin #3450

Merged
merged 2 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .changeset/tender-moles-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
'@reown/appkit-adapter-ethers': patch
'@reown/appkit-adapter-ethers5': patch
'@reown/appkit-adapter-solana': patch
'@reown/appkit-adapter-wagmi': patch
'@reown/appkit': patch
'@reown/appkit-utils': patch
'@reown/appkit-cdn': patch
'@reown/appkit-cli': patch
'@reown/appkit-common': patch
'@reown/appkit-core': patch
'@reown/appkit-experimental': patch
'@reown/appkit-polyfills': patch
'@reown/appkit-scaffold-ui': patch
'@reown/appkit-siwe': patch
'@reown/appkit-siwx': patch
'@reown/appkit-ui': patch
'@reown/appkit-wallet': patch
'@reown/appkit-wallet-button': patch
---

Fix the chainId response when connecting to bitcoin with multichain adapters
8 changes: 7 additions & 1 deletion packages/adapters/bitcoin/src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,17 @@ export class BitcoinAdapter extends AdapterBlueprint<BitcoinConnector> {
this.connector = connector
this.bindEvents(this.connector)

const chain = connector.chains.find(c => c.id === params.chainId) || connector.chains[0]

if (!chain) {
throw new Error('The connector does not support any of the requested chains')
}

return {
id: connector.id,
type: connector.type,
address,
chainId: this.networks[0]?.id || '',
chainId: chain.id,
provider: connector.provider
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class SatsConnectConnector extends ProviderEventEmitter implements Bitcoi
}

public get chains() {
return this.requestedChains
return this.requestedChains.filter(chain => chain.chainNamespace === 'bip122')
}

async request<T>(args: RequestArguments) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { BitcoinFeatures } from '../utils/wallet-standard/WalletFeatures.js
import type { Provider, RequestArguments } from '@reown/appkit-core'
import { ProviderEventEmitter } from '../utils/ProviderEventEmitter.js'
import { MethodNotSupportedError } from '../errors/MethodNotSupportedError.js'
import { bitcoin, bitcoinTestnet } from '@reown/appkit/networks'

export class WalletStandardConnector extends ProviderEventEmitter implements BitcoinConnector {
public readonly chain = 'bip122'
Expand Down Expand Up @@ -39,7 +40,18 @@ export class WalletStandardConnector extends ProviderEventEmitter implements Bit

public get chains() {
return this.wallet.chains
.map(chainId => this.requestedChains.find(chain => chain.caipNetworkId === chainId))
.map(chainId =>
this.requestedChains.find(chain => {
switch (chainId) {
case 'bitcoin:mainnet':
return chain.caipNetworkId === bitcoin.caipNetworkId
case 'bitcoin:testnet':
return chain.caipNetworkId === bitcoinTestnet.caipNetworkId
default:
return chain.caipNetworkId === chainId
Comment on lines +46 to +51
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wallet standard has a different set of ids?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, they use these aliases and not exactly caip-2

}
})
)
.filter(Boolean) as CaipNetwork[]
}

Expand Down
30 changes: 30 additions & 0 deletions packages/adapters/bitcoin/tests/BitcoinAdapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { BitcoinAdapter } from '../src'
import type { BitcoinApi } from '../src/utils/BitcoinApi'
import { bitcoin, mainnet } from '@reown/appkit/networks'
import { mockUTXO } from './mocks/mockUTXO'
import { SatsConnectConnector } from '../src/connectors/SatsConnectConnector'
import { mockSatsConnectProvider } from './mocks/mockSatsConnect'

function mockBitcoinApi(): { [K in keyof BitcoinApi.Interface]: Mock<BitcoinApi.Interface[K]> } {
return {
Expand All @@ -19,6 +21,34 @@ describe('BitcoinAdapter', () => {
adapter = new BitcoinAdapter({ api })
})

describe('connect', () => {
it('should return the chainId of the available chain from connector', async () => {
const connector = new SatsConnectConnector({
provider: mockSatsConnectProvider().provider,
requestedChains: [bitcoin],
getActiveNetwork: () => bitcoin
})
vi.spyOn(connector, 'connect').mockResolvedValueOnce('mock_address')

adapter.connectors.push(connector)

const result = await adapter.connect({
id: connector.id,
chainId: 'bitcoin:any_chain_id',
provider: connector.provider,
type: 'mock_type'
})

expect(result).toEqual({
id: connector.id,
type: connector.type,
address: 'mock_address',
chainId: bitcoin.id,
provider: connector.provider
})
})
})

describe('getBalance', () => {
it('should return the balance', async () => {
api.getUTXOs.mockResolvedValueOnce([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { SatsConnectConnector } from '../../src/connectors/SatsConnectConnector'
import { mockSatsConnectProvider } from '../mocks/mockSatsConnect'
import type { CaipNetwork } from '@reown/appkit-common'
import { MessageSigningProtocols } from 'sats-connect'
import { bitcoin } from '@reown/appkit/networks'
import { bitcoin, bitcoinTestnet, mainnet } from '@reown/appkit/networks'

describe('SatsConnectConnector', () => {
let connector: SatsConnectConnector
Expand All @@ -12,7 +12,12 @@ describe('SatsConnectConnector', () => {
let getActiveNetwork: Mock<() => CaipNetwork | undefined>

beforeEach(() => {
requestedChains = []
// requested chains may contain not bip122 chains
requestedChains = [
{ ...mainnet, caipNetworkId: 'eip155:1', chainNamespace: 'eip155' },
bitcoin,
bitcoinTestnet
]
mocks = mockSatsConnectProvider()
getActiveNetwork = vi.fn(() => bitcoin)
connector = new SatsConnectConnector({
Expand All @@ -39,7 +44,7 @@ describe('SatsConnectConnector', () => {
expect(connector.id).toBe(mocks.provider.name)
expect(connector.name).toBe(mocks.provider.name)
expect(connector.imageUrl).toBe(mocks.provider.icon)
expect(connector.chains).toEqual(requestedChains)
expect(connector.chains).toEqual([bitcoin, bitcoinTestnet])
})

it('should disconnect correctly', async () => {
Expand Down Expand Up @@ -309,7 +314,7 @@ describe('SatsConnectConnector', () => {

await callback?.({ type: 'networkChange' })

expect(emitSpy).toHaveBeenCalledWith('chainChanged', requestedChains)
expect(emitSpy).toHaveBeenCalledWith('chainChanged', [bitcoin, bitcoinTestnet])
})
})
})
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { CaipNetwork } from '@reown/appkit-common'
import { bitcoin, bitcoinTestnet } from '@reown/appkit/networks'
import { bitcoin, bitcoinTestnet, mainnet } from '@reown/appkit/networks'
import { WalletStandardConnector } from '../../src/connectors/WalletStandardConnector'
import { mockWalletStandardProvider } from '../mocks/mockWalletStandard'
import { MethodNotSupportedError } from '../../src/errors/MethodNotSupportedError'
Expand All @@ -20,7 +20,12 @@ describe('WalletStandardConnector', () => {
let requestedChains: CaipNetwork[]

beforeEach(() => {
requestedChains = [bitcoin, bitcoinTestnet]
// requested chains may contain not bip122 chains
requestedChains = [
{ ...mainnet, caipNetworkId: 'eip155:1', chainNamespace: 'eip155' },
bitcoin,
bitcoinTestnet
]
wallet = mockWalletStandardProvider()
connector = new WalletStandardConnector({
wallet,
Expand All @@ -40,10 +45,6 @@ describe('WalletStandardConnector', () => {
expect(connector.imageUrl).toBe(wallet.icon)
})

it('should map correctly only chains that are requested and the wallet supports', async () => {
expect(connector.chains).toEqual([bitcoin])
})

it('should throw if feature is not available', async () => {
wallet = mockWalletStandardProvider({
features: {}
Expand All @@ -55,6 +56,18 @@ describe('WalletStandardConnector', () => {
await expect(connector.connect()).rejects.toThrow(MethodNotSupportedError)
})

describe('chains', () => {
it('should map correctly only chains that are requested and the wallet supports', async () => {
expect(connector.chains).toEqual([bitcoin])
})

it('should map network id aliases', async () => {
vi.spyOn(wallet, 'chains', 'get').mockReturnValueOnce(['bitcoin:mainnet', 'bitcoin:testnet'])

expect(connector.chains).toEqual([bitcoin, bitcoinTestnet])
})
})

describe('watchWallets', () => {
it('should get wallets using the callback', async () => {
const callbackMock = vi.fn((...args) => {
Expand Down
Loading