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: custom bc pairing #827

Closed
wants to merge 2 commits into from
Closed
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
3 changes: 3 additions & 0 deletions packages/beacon-core/src/utils/multi-tab-channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ type BCMessageType =
| 'RESPONSE'
| 'DISCONNECT'
| BeaconMessageType
| 'INIT_REQ'
| 'INIT_RES'
| 'NEW_PEER'

type BCMessage = {
type: BCMessageType
Expand Down
117 changes: 111 additions & 6 deletions packages/beacon-dapp/src/dapp-client/DAppClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ export class DAppClient extends Client {

private isGetActiveAccountHandled: boolean = false

private _wcPairingRequest: ExposedPromise | undefined

private _initPromiseResolver: Function | undefined

private readonly openRequestsOtherTabs = new Set<string>()
/**
* A map of requests that are currently "open", meaning we have sent them to a wallet and are still awaiting a response.
Expand Down Expand Up @@ -452,6 +456,39 @@ export class DAppClient extends Client {
)

this.initUserID().catch((err) => logger.error(err.message))

this.multiTabChannel.isLeader()
.then(async (isLeader) => {
if (!isLeader) {
return
}

const wcOptions = {
projectId: this.wcProjectId,
relayUrl: this.wcRelayUrl,
metadata: {
name: this.name,
description: this.description ?? '',
url: this.appUrl ?? '',
icons: this.iconUrl ? [this.iconUrl] : []
}
}

this.walletConnectTransport = new DappWalletConnectTransport(
this.name,
await this.keyPair,
this.storage,
{
network: this.network.type,
opts: wcOptions
},
() => this.multiTabChannel.isLeader()
)

this.initEvents()

await this.addListener(this.walletConnectTransport)
})
}

private async onElectedLeaderhandler() {
Expand Down Expand Up @@ -491,11 +528,59 @@ export class DAppClient extends Client {
case 'DISCONNECT':
this._transport.isResolved() && this.disconnect()
break
case 'INIT_REQ':
this.initReqHandler(message.sender)
break
case 'INIT_RES':
this.initResHandler(message.data)
break
case 'NEW_PEER':
this.newPeerHandler(message.data)
break
default:
logger.error('onBCMessageHandler', 'message type not recognized', message)
}
}

private async newPeerHandler(peer: any) {
this.hideUI(['alert'])
this.setTransport(this.walletConnectTransport)
this.walletConnectTransport?.connect()
this.setActivePeer(peer)
this._initPromiseResolver && this._initPromiseResolver(TransportType.WALLETCONNECT)
}

private async initResHandler(request: any) {
if (!this._wcPairingRequest) {
return
}

this._wcPairingRequest.resolve(request)
this._wcPairingRequest = undefined
}

private async initReqHandler(sender: string) {
if (!await this.multiTabChannel.isLeader()) {
return
}

this.walletConnectTransport?.listenForNewPeer((peer) => {
this.hideUI(['toast'])
this.newPeerHandler(peer)
this.multiTabChannel.postMessage({
type: 'NEW_PEER',
data: peer,
recipient: sender
})
})

this.multiTabChannel.postMessage({
type: 'INIT_RES',
data: await this.walletConnectTransport?.getPairingRequestInfo(),
recipient: sender
})
}

private async prepareRequest({ data }: any, isV3 = false) {
if (!(await this.multiTabChannel.isLeader())) {
return
Expand Down Expand Up @@ -544,7 +629,7 @@ export class DAppClient extends Client {
public async initInternalTransports(): Promise<void> {
const keyPair = await this.keyPair

if (this.postMessageTransport || this.p2pTransport || this.walletConnectTransport) {
if (this.postMessageTransport || this.p2pTransport || (this.walletConnectTransport && this.walletConnectTransport.connectionStatus === TransportStatus.CONNECTED)) {
return
}

Expand Down Expand Up @@ -573,6 +658,11 @@ export class DAppClient extends Client {
}
}

// the leader tab has already initialized the transport
if (await this.multiTabChannel.isLeader()) {
return
}

this.walletConnectTransport = new DappWalletConnectTransport(
this.name,
keyPair,
Expand Down Expand Up @@ -778,7 +868,19 @@ export class DAppClient extends Client {
return p2pTransport.getPairingRequestInfo()
},
postmessagePeerInfo: () => postMessageTransport.getPairingRequestInfo(),
walletConnectPeerInfo: () => walletConnectTransport.getPairingRequestInfo(),
walletConnectPeerInfo: async () => {
if (await this.multiTabChannel.isLeader()) {
return await walletConnectTransport.getPairingRequestInfo()
}
// the current tab is not the leader
// send a request to the leader tab and wait for
// _wcPairingRequest to resolve
this._wcPairingRequest = new ExposedPromise()
this.multiTabChannel.postMessage({
type: 'INIT_REQ'
})
return await this._wcPairingRequest.promise
},
networkType: this.network.type,
abortedHandler: async () => {
logger.log('init', 'ABORTED')
Expand All @@ -805,6 +907,7 @@ export class DAppClient extends Client {
.catch((emitError) => console.warn(emitError))
}
}
this._initPromiseResolver = resolve
})

return this._initPromise
Expand Down Expand Up @@ -834,7 +937,7 @@ export class DAppClient extends Client {
this.postMessageTransport?.disconnect(),
this.walletConnectTransport?.disconnect()
])
this.postMessageTransport = this.p2pTransport = this.walletConnectTransport = undefined
this.postMessageTransport = this.p2pTransport = undefined
await this.setActivePeer(undefined)
await this.setTransport(undefined)
this._initPromise = undefined
Expand Down Expand Up @@ -874,7 +977,7 @@ export class DAppClient extends Client {
if (!this.debounceSetActiveAccount && transport instanceof WalletConnectTransport) {
this.debounceSetActiveAccount = true
this._initPromise = undefined
this.postMessageTransport = this.p2pTransport = this.walletConnectTransport = undefined
this.postMessageTransport = this.p2pTransport = undefined
if (await this.multiTabChannel.isLeader()) {
await transport.disconnect()
this.openRequestsOtherTabs.clear()
Expand Down Expand Up @@ -2010,7 +2113,6 @@ export class DAppClient extends Client {
this._initPromise = undefined
this.postMessageTransport = undefined
this.p2pTransport = undefined
this.walletConnectTransport = undefined
await this.setTransport()
await this.setActivePeer()
}
Expand Down Expand Up @@ -2295,6 +2397,10 @@ export class DAppClient extends Client {
throw await this.sendInternalError('BeaconID not defined')
}

if ((await this.transport).type === TransportType.WALLETCONNECT && !(await this.multiTabChannel.isLeader())) {
return await this.makeRequestBC(requestInput)
}

const request: Optional<T, IgnoredRequestInputProperties> &
Pick<U, IgnoredRequestInputProperties> = {
id: messageId,
Expand Down Expand Up @@ -2570,7 +2676,6 @@ export class DAppClient extends Client {
}
this.postMessageTransport = undefined
this.p2pTransport = undefined
this.walletConnectTransport = undefined
this.sendMetrics('performance-metrics/save', await this.buildPayload('disconnect', 'success'))
}

Expand Down
Loading