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

feat(pera): add auto-connect for Pera Discover browser #323

Merged
merged 5 commits into from
Dec 7, 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
73 changes: 73 additions & 0 deletions packages/use-wallet/src/__tests__/wallets/pera.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,79 @@ describe('PeraWallet', () => {
expect(store.state.wallets[WalletId.PERA]).toBeUndefined()
expect(wallet.isConnected).toBe(false)
})

describe('auto-connect in Pera browser', () => {
let mockUserAgent: string

beforeEach(() => {
mockUserAgent = ''
vi.clearAllMocks()

vi.stubGlobal('window', {
navigator: {
get userAgent() {
return mockUserAgent
}
}
})
})

afterEach(() => {
vi.unstubAllGlobals()
})

it('should attempt auto-connect in Pera browser when no session exists and no active wallet', async () => {
mockUserAgent = 'pera/1.0.0'
mockPeraWallet.connect.mockResolvedValueOnce([account1.address])

await wallet.resumeSession()

expect(mockPeraWallet.connect).toHaveBeenCalled()
expect(store.state.wallets[WalletId.PERA]).toBeDefined()
expect(mockLogger.info).toHaveBeenCalledWith('Auto-connect successful')
})

it('should not attempt auto-connect if another wallet is active', async () => {
mockUserAgent = 'pera/1.0.0'

// Set up another active wallet
store.setState((state) => ({
...state,
activeWallet: WalletId.DEFLY,
wallets: {
[WalletId.DEFLY]: {
accounts: [account2],
activeAccount: account2
}
}
}))

await wallet.resumeSession()

expect(mockPeraWallet.connect).not.toHaveBeenCalled()
expect(mockLogger.info).toHaveBeenCalledWith('No session to resume')
})

it('should not attempt auto-connect in other browsers', async () => {
mockUserAgent = 'chrome/1.0.0'

await wallet.resumeSession()

expect(mockPeraWallet.connect).not.toHaveBeenCalled()
expect(mockLogger.info).toHaveBeenCalledWith('No session to resume')
})

it('should handle auto-connect failure gracefully', async () => {
mockUserAgent = 'pera/1.0.0'
mockPeraWallet.connect.mockRejectedValueOnce(new Error('Connect failed'))

await wallet.resumeSession()

expect(mockPeraWallet.connect).toHaveBeenCalled()
expect(mockLogger.warn).toHaveBeenCalledWith('Auto-connect failed:', 'Connect failed')
expect(store.state.wallets[WalletId.PERA]).toBeUndefined()
})
})
})

describe('setActive', () => {
Expand Down
73 changes: 73 additions & 0 deletions packages/use-wallet/src/__tests__/wallets/pera2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,79 @@ describe('PeraWallet', () => {
expect(store.state.wallets[WalletId.PERA2]).toBeUndefined()
expect(wallet.isConnected).toBe(false)
})

describe('auto-connect in Pera browser', () => {
let mockUserAgent: string

beforeEach(() => {
mockUserAgent = ''
vi.clearAllMocks()

vi.stubGlobal('window', {
navigator: {
get userAgent() {
return mockUserAgent
}
}
})
})

afterEach(() => {
vi.unstubAllGlobals()
})

it('should attempt auto-connect in Pera browser when no session exists and no active wallet', async () => {
mockUserAgent = 'pera/1.0.0'
mockPeraWallet.connect.mockResolvedValueOnce([account1.address])

await wallet.resumeSession()

expect(mockPeraWallet.connect).toHaveBeenCalled()
expect(store.state.wallets[WalletId.PERA2]).toBeDefined()
expect(mockLogger.info).toHaveBeenCalledWith('Auto-connect successful')
})

it('should not attempt auto-connect if another wallet is active', async () => {
mockUserAgent = 'pera/1.0.0'

// Set up another active wallet
store.setState((state) => ({
...state,
activeWallet: WalletId.DEFLY,
wallets: {
[WalletId.DEFLY]: {
accounts: [account2],
activeAccount: account2
}
}
}))

await wallet.resumeSession()

expect(mockPeraWallet.connect).not.toHaveBeenCalled()
expect(mockLogger.info).toHaveBeenCalledWith('No session to resume')
})

it('should not attempt auto-connect in other browsers', async () => {
mockUserAgent = 'chrome/1.0.0'

await wallet.resumeSession()

expect(mockPeraWallet.connect).not.toHaveBeenCalled()
expect(mockLogger.info).toHaveBeenCalledWith('No session to resume')
})

it('should handle auto-connect failure gracefully', async () => {
mockUserAgent = 'pera/1.0.0'
mockPeraWallet.connect.mockRejectedValueOnce(new Error('Connect failed'))

await wallet.resumeSession()

expect(mockPeraWallet.connect).toHaveBeenCalled()
expect(mockLogger.warn).toHaveBeenCalledWith('Auto-connect failed:', 'Connect failed')
expect(store.state.wallets[WalletId.PERA2]).toBeUndefined()
})
})
})

describe('signing transactions', () => {
Expand Down
15 changes: 15 additions & 0 deletions packages/use-wallet/src/wallets/pera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,21 @@ export class PeraWallet extends BaseWallet {
const state = this.store.state
const walletState = state.wallets[this.id]

// Check for Pera Discover browser and auto-connect if no other wallet is active
if (typeof window !== 'undefined' && window.navigator) {
const isPeraDiscover = window.navigator.userAgent.includes('pera')
if (isPeraDiscover && !walletState && !state.activeWallet) {
this.logger.info('Pera Discover browser detected, attempting auto-connect...')
try {
await this.connect()
this.logger.info('Auto-connect successful')
return
} catch (error: any) {
this.logger.warn('Auto-connect failed:', error.message)
}
}
}

// No session to resume
if (!walletState) {
this.logger.info('No session to resume')
Expand Down
15 changes: 15 additions & 0 deletions packages/use-wallet/src/wallets/pera2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,21 @@ export class PeraWallet extends BaseWallet {
const state = this.store.state
const walletState = state.wallets[this.id]

// Check for Pera Discover browser and auto-connect if no other wallet is active
if (typeof window !== 'undefined' && window.navigator) {
const isPeraDiscover = window.navigator.userAgent.includes('pera')
if (isPeraDiscover && !walletState && !state.activeWallet) {
this.logger.info('Pera Discover browser detected, attempting auto-connect...')
try {
await this.connect()
this.logger.info('Auto-connect successful')
return
} catch (error: any) {
this.logger.warn('Auto-connect failed:', error.message)
}
}
}

// No session to resume
if (!walletState) {
this.logger.info('No session to resume')
Expand Down
Loading