Skip to content

Commit

Permalink
Merge pull request #216 from radixdlt/develop
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
xstelea authored Nov 30, 2023
2 parents 4227000 + ea383c8 commit 82687a1
Show file tree
Hide file tree
Showing 13 changed files with 18,288 additions and 9,047 deletions.
27,105 changes: 18,163 additions & 8,942 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
"@ledgerhq/hw-transport-webhid": "^6.27.19",
"@mui/material": "^5.14.0",
"@radixdlt/babylon-gateway-api-sdk": "^1.0.1",
"@radixdlt/radix-connect-webrtc": "^1.0.1",
"@radixdlt/radix-connect-schemas": "^1.2.0",
"@radixdlt/radix-connect-webrtc": "^1.0.3",
"@stitches/react": "^1.2.8",
"@types/blake2b": "^2.1.0",
"bech32": "^2.0.0",
Expand Down
51 changes: 45 additions & 6 deletions src/chrome/content-script/content-script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ import { errAsync, okAsync, ResultAsync } from 'neverthrow'
import { logger } from 'utils/logger'
import { MessageLifeCycleEvent } from 'chrome/dapp/_types'
import { getConnectionPassword } from 'chrome/helpers/get-connection-password'
import {
WalletInteractionWithOrigin,
ExtensionInteraction,
} from '@radixdlt/radix-connect-schemas'
import { sendMessage } from 'chrome/helpers/send-message'

const chromeDAppClient = ChromeDAppClient()
const appLogger = logger.getSubLogger({ name: 'content-script' })

const chromeDAppClient = ChromeDAppClient(appLogger)

const sendMessageToDapp = (
message: Record<string, any>,
Expand Down Expand Up @@ -39,16 +46,48 @@ const messageHandler = MessageClient(
ContentScriptMessageHandler({
sendMessageToDapp,
sendMessageEventToDapp,
logger: logger.getSubLogger({ name: 'content-script' }),
logger,
}),
'contentScript',
{ logger },
{ logger: appLogger },
)

chromeDAppClient.messageListener((message) => {
messageHandler.onMessage(createMessage.incomingDappMessage('dApp', message))
})
const handleWalletInteraction = async (
walletInteraction: WalletInteractionWithOrigin,
) => {
sendMessage(createMessage.dAppRequest('contentScript', walletInteraction))
}

const handleExtensionInteraction = async (
extensionInteraction: ExtensionInteraction,
) => {
switch (extensionInteraction.discriminator) {
case 'openPopup':
await sendMessage(createMessage.openParingPopup())
break

case 'extensionStatus':
await getConnectionPassword().map((connectionPassword) => {
sendMessageToDapp(createMessage.extensionStatus(!!connectionPassword))
})
break

default:
logger.error({
reason: 'InvalidExtensionRequest',
interaction: extensionInteraction,
})
break
}
}

// incoming messages from dApps
chromeDAppClient.messageListener(
handleWalletInteraction,
handleExtensionInteraction,
)

// incoming messages from extension
chrome.runtime.onMessage.addListener((message: Message) => {
messageHandler.onMessage(message)
})
Expand Down
57 changes: 1 addition & 56 deletions src/chrome/content-script/message-handler.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import { addMetadata } from 'chrome/helpers/add-metadata'
import { errAsync, okAsync, ResultAsync } from 'neverthrow'
import { createMessage } from '../messages/create-message'
import {
ConfirmationMessageError,
Message,
messageDiscriminator,
MessageHandler,
MessageHandlerOutput,
SendMessageWithConfirmation,
} from '../messages/_types'
import { AppLogger } from 'utils/logger'
import { MessageLifeCycleEvent } from 'chrome/dapp/_types'
import { getConnectionPassword } from 'chrome/helpers/get-connection-password'
import { sendMessage } from 'chrome/messages/send-message'

export type ContentScriptMessageHandlerOptions = {
logger?: AppLogger
Expand All @@ -33,10 +28,7 @@ export const ContentScriptMessageHandler =
sendMessageToDapp,
logger,
}: ContentScriptMessageHandlerOptions): MessageHandler =>
(
message: Message,
sendMessageWithConfirmation: SendMessageWithConfirmation,
): MessageHandlerOutput => {
(message: Message): MessageHandlerOutput => {
switch (message?.discriminator) {
case messageDiscriminator.sendMessageEventToDapp: {
return sendMessageEventToDapp(message.data, message.messageEvent).map(
Expand All @@ -59,53 +51,6 @@ export const ContentScriptMessageHandler =
: okAsync({ sendConfirmation: false })
}

case messageDiscriminator.incomingDappMessage: {
switch (message.data?.discriminator) {
case messageDiscriminator.extensionStatus:
return getConnectionPassword()
.andThen((connectionPassword) =>
sendMessageToDapp(
createMessage.extensionStatus(!!connectionPassword),
).map(() => ({ sendConfirmation: false })),
)
.mapErr((error) => {
return {
reason: 'unableToGetConnectionPassword',
}
})
case messageDiscriminator.openParingPopup:
return sendMessage(createMessage.openParingPopup())
.map(() => ({
sendConfirmation: false,
}))
.mapErr(() => ({ reason: 'unableToOpenParingPopup' }))
default:
return sendMessageEventToDapp(
{
interactionId: message.data.interactionId,
metadata: { origin: window.location.origin },
},
'receivedByExtension',
)
.andThen(() =>
ResultAsync.combine([
sendMessageWithConfirmation(
createMessage.dAppRequest(
'contentScript',
addMetadata(message.data),
),
),
sendMessageWithConfirmation(
createMessage.detectWalletLink('contentScript'),
),
]),
)
.map(() => ({
sendConfirmation: false,
}))
}
}

default:
return errAsync({
reason: 'unhandledMessageDiscriminator',
Expand Down
48 changes: 45 additions & 3 deletions src/chrome/dapp/dapp-client.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { MessageLifeCycleEvent, dAppEvent } from 'chrome/dapp/_types'
import { ok } from 'neverthrow'
import {
WalletInteractionWithOrigin,
WalletInteraction,
ExtensionInteraction,
} from '@radixdlt/radix-connect-schemas'
import { AppLogger } from 'utils/logger'
import { addOriginToWalletInteraction } from 'chrome/helpers/add-origin-to-wallet-interaction'

export type ChromeDAppClient = ReturnType<typeof ChromeDAppClient>
export const ChromeDAppClient = () => {
export const ChromeDAppClient = (logger: AppLogger) => {
const sendMessage = (message: Record<string, any>) => {
window.dispatchEvent(
new CustomEvent(dAppEvent.receive, {
Expand All @@ -22,11 +29,46 @@ export const ChromeDAppClient = () => {
})

const messageListener = (
callbackFn: (message: Record<string, any>) => void,
onDappRequest: (message: WalletInteractionWithOrigin) => void,
onExtensionRequest: (message: ExtensionInteraction) => void,
) => {
window.addEventListener(dAppEvent.send, (event) => {
const { detail: message } = event as CustomEvent<any>
callbackFn(message)

if (message.interactionId)
sendMessageEvent(message.interactionId, 'receivedByExtension')

const dAppInteractionResult = WalletInteraction.safeParse(message)

if (dAppInteractionResult.success)
return onDappRequest(
addOriginToWalletInteraction(dAppInteractionResult.data),
)

const extensionInteractionResult = ExtensionInteraction.safeParse(message)

if (extensionInteractionResult.success)
return onExtensionRequest(extensionInteractionResult.data)

// openPopup is a special case, as it is missing interactionId in older walletSDK versions
const isOpenPopupRequest =
(message as ExtensionInteraction).discriminator === 'openPopup' &&
!message.interactionId

if (isOpenPopupRequest)
return onExtensionRequest({
...message,
interactionId: crypto.randomUUID(),
} as ExtensionInteraction)

if (message.interactionId)
sendMessage({
interactionId: message.interactionId,
discriminator: 'failure',
error: 'InvalidDappRequest',
})

logger.error({ reason: 'InvalidDappRequest', message })
})
}

Expand Down
9 changes: 0 additions & 9 deletions src/chrome/helpers/add-metadata.ts

This file was deleted.

14 changes: 14 additions & 0 deletions src/chrome/helpers/add-origin-to-wallet-interaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {
WalletInteraction,
WalletInteractionWithOrigin,
} from '@radixdlt/radix-connect-schemas'

export const addOriginToWalletInteraction = (
message: WalletInteraction,
): WalletInteractionWithOrigin => ({
...message,
metadata: {
...(message.metadata || {}),
origin: window.location.origin,
},
})
3 changes: 2 additions & 1 deletion src/chrome/messages/_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { LedgerRequest, LedgerResponse } from 'ledger/schemas'
import { ResultAsync } from 'neverthrow'
import { ILogObjMeta } from 'tslog/dist/types/interfaces'
import { ILogObj } from 'tslog'
import { WalletInteractionWithOrigin } from '@radixdlt/radix-connect-schemas'

export const messageDiscriminator = {
getConnectionPassword: 'getConnectionPassword',
Expand Down Expand Up @@ -151,7 +152,7 @@ export type Messages = {
>
[messageDiscriminator.dAppRequest]: MessageBuilder<
MessageDiscriminator['dAppRequest'],
{ data: Record<string, any> }
{ data: WalletInteractionWithOrigin }
>
[messageDiscriminator.walletMessage]: MessageBuilder<
MessageDiscriminator['walletMessage'],
Expand Down
6 changes: 5 additions & 1 deletion src/chrome/messages/create-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from './_types'
import { MessageLifeCycleEvent } from 'chrome/dapp/_types'
import { ILogObj, ILogObjMeta } from 'tslog/dist/types/interfaces'
import { WalletInteractionWithOrigin } from '@radixdlt/radix-connect-schemas'

export const createMessage = {
openParingPopup: () => ({
Expand Down Expand Up @@ -73,7 +74,10 @@ export const createMessage = {
discriminator: 'detectWalletLink',
messageId: crypto.randomUUID(),
}),
dAppRequest: (source: MessageSource, data: any): Messages['dAppRequest'] => ({
dAppRequest: (
source: MessageSource,
data: WalletInteractionWithOrigin,
): Messages['dAppRequest'] => ({
source,
discriminator: 'dAppRequest',
messageId: crypto.randomUUID(),
Expand Down
22 changes: 0 additions & 22 deletions src/chrome/messages/message-client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,28 +113,6 @@ const createTestHelper = ({
}

describe('message client', () => {
it('should send dApp request to wallet', async () => {
const testHelper = createTestHelper({})
testHelper.mockIncomingDappMessage({ interactionId: '123' })

await Promise.all([
firstValueFrom(
testHelper.subjects.messageSubject.pipe(
filter(
({ message }) =>
message.discriminator === 'confirmation' &&
message.source === 'offScreen',
),
),
),
firstValueFrom(
testHelper.subjects.messageSubject.pipe(
filter(({ message }) => message.discriminator === 'detectWalletLink'),
),
),
])
})

// offScreenPage does not have have access to the chrome tabs API
// so it has to proxy the message through background message handler
it('should send wallet response to dApp', async () => {
Expand Down
12 changes: 7 additions & 5 deletions src/chrome/offscreen/message-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ import {
import { LedgerResponse, isLedgerRequest } from 'ledger/schemas'
import { sendMessage } from 'chrome/helpers/send-message'
import { radixConnectConfig } from 'config'
import { WalletInteractionWithOrigin } from '@radixdlt/radix-connect-schemas'

export type OffscreenMessageHandler = ReturnType<typeof OffscreenMessageHandler>
export const OffscreenMessageHandler = (input: {
logsClient: LogsClient
connectorClient: ConnectorClient
dAppRequestQueue: Queue<any>
dAppRequestQueue: Queue<WalletInteractionWithOrigin>
ledgerToWalletQueue: Queue<LedgerResponse>
incomingWalletMessageQueue: Queue<any>
messageRouter: MessagesRouter
Expand Down Expand Up @@ -81,12 +82,13 @@ export const OffscreenMessageHandler = (input: {
}

case messageDiscriminator.dAppRequest: {
const { interactionId, metadata } = message.data
const walletInteraction: WalletInteractionWithOrigin = message.data
const { interactionId, metadata } = walletInteraction

return messageRouter
.add(tabId!, interactionId, metadata)
.asyncAndThen(() => {
if (!interactionId) return okAsync(null)
if (message.data?.items?.discriminator === 'cancelRequest')
if (walletInteraction.items.discriminator === 'cancelRequest')
return dAppRequestQueue
.cancel(interactionId)
.andThen(() =>
Expand All @@ -100,7 +102,7 @@ export const OffscreenMessageHandler = (input: {
),
)

return dAppRequestQueue.add(message.data, interactionId)
return dAppRequestQueue.add(walletInteraction, interactionId)
})
.map(() => ({ sendConfirmation: true }))
}
Expand Down
3 changes: 2 additions & 1 deletion src/chrome/offscreen/offscreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Message } from 'chrome/messages/_types'
import { filter, switchMap, timer, withLatestFrom } from 'rxjs'
import { ConnectorExtensionOptions } from 'options'
import { LogsClient } from './logs-client'
import { WalletInteractionWithOrigin } from '@radixdlt/radix-connect-schemas'

const logsClient = LogsClient()

Expand All @@ -31,7 +32,7 @@ const connectorClient = ConnectorClient({

connectorClient.connect()

const dAppRequestQueue = Queue<any>({
const dAppRequestQueue = Queue<WalletInteractionWithOrigin>({
key: 'dAppRequestQueue',
logger,
paused: true,
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ConnectionConfig } from '@radixdlt/radix-connect-webrtc'
const { version } = packageJson

const developmentConfig: Required<ConnectionConfig> = {
iceTransportPolicy: 'all',
signalingServerBaseUrl:
'wss://signaling-server-dev.rdx-works-main.extratools.works',
turnServers: [
Expand All @@ -23,6 +24,7 @@ const developmentConfig: Required<ConnectionConfig> = {

export const radixConnectConfig: Record<string, Required<ConnectionConfig>> = {
production: {
iceTransportPolicy: 'all',
signalingServerBaseUrl: 'wss://signaling-server.radixdlt.com',
turnServers: [
{
Expand Down

0 comments on commit 82687a1

Please sign in to comment.