Skip to content

Commit

Permalink
chore(wallet-mobile): support yoroi links throught qr scan (#3678)
Browse files Browse the repository at this point in the history
  • Loading branch information
stackchain authored Oct 6, 2024
1 parent e9f300f commit da2a88f
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 20 deletions.
2 changes: 2 additions & 0 deletions apps/wallet-mobile/src/features/Scan/common/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export const codeContent = {
'web+cardano://claim/v1?code=42&faucet_url=https%3A%2F%2Ffaucet.com&memo=memo-text&message=message1&message=message2&message=message3&extra=extra',
legacyCip13Transfer:
'web+cardano:addr_test1qrgpjmyy8zk9nuza24a0f4e7mgp9gd6h3uayp0rqnjnkl54v4dlyj0kwfs0x4e38a7047lymzp37tx0y42glslcdtzhqzp57km?extra=extra&amount=1.23&memo=memo&message=message',
yoroiPaymentRequestWithLink:
'yoroi://yoroi-wallet.com/w1/transfer/request/ada-with-link?link=web%252Bcardano%253Aaddr1qxvn5nehgdjadqpztxqckh4yz37h0vc7rnl57x9jfaraxxe627hhjyls27xwmke4e4ewn27rv3qcntakvp7wd53dqahqxuhfua%253Famount%253D2',
},
},
} as const
8 changes: 8 additions & 0 deletions apps/wallet-mobile/src/features/Scan/common/parsers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,12 @@ describe('parseScanAction', () => {
params: expect.any(Object),
})
})

it('should correctly parse a Yoroi link', () => {
const result = parseScanAction(codeContent.links.success.yoroiPaymentRequestWithLink)
expect(result).toEqual({
action: 'launch-url',
url: codeContent.links.success.yoroiPaymentRequestWithLink,
})
})
})
55 changes: 36 additions & 19 deletions apps/wallet-mobile/src/features/Scan/common/parsers.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import {linksCardanoModuleMaker} from '@yoroi/links'
import {Links, Scan} from '@yoroi/types'
import {freeze} from 'immer'

export const parseScanAction = (codeContent: string): Scan.Action => {
const isLink = codeContent.includes(':')
const isPossibleLink = codeContent.includes(':')

// NOTE: if it is a string < 256 with valid characters, it'd be consider a Yoroi Receiver (wallet address | domain name)
if (!isLink) {
if (!isPossibleLink) {
if (codeContent.length > 255 || !nonProtocolRegex.test(codeContent)) throw new Scan.Errors.UnknownContent()
return {
return freeze({
action: 'send-only-receiver',
receiver: codeContent,
}
} as const)
}

if (isOpenableLink(codeContent)) {
return freeze({
action: 'launch-url',
url: codeContent,
} as const)
}

const cardanoLinks = linksCardanoModuleMaker()
Expand All @@ -20,24 +28,33 @@ export const parseScanAction = (codeContent: string): Scan.Action => {

if (parsedCardanoLink.config.authority === 'claim') {
const {faucet_url: url, code, ...params} = parsedCardanoLink.params
return {
action: 'claim',
url,
code,
params,
} as const
return freeze(
{
action: 'claim',
url,
code,
params,
} as const,
true,
)
}

const {address: receiver, amount, memo, message} = parsedCardanoLink.params
return {
action: 'send-single-pt',
receiver,
params: {
amount,
memo,
message,
},
} as const
return freeze(
{
action: 'send-single-pt',
receiver,
params: {
amount,
memo,
message,
},
} as const,
true,
)
}

const nonProtocolRegex = /^[a-zA-Z0-9_\-.$]+$/
const isOpenableLink = (content: string) => {
return content.startsWith('yoroi') || content.startsWith('https')
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {toBigInt} from '@yoroi/common'
import {useTransfer} from '@yoroi/transfer'
import {Scan} from '@yoroi/types'
import * as React from 'react'
import {Alert} from 'react-native'
import {Alert, Linking} from 'react-native'

import {useModal} from '../../../components/Modal/ModalContext'
import {useClaimErrorResolver} from '../../../features/Claim/common/useClaimErrorResolver'
Expand Down Expand Up @@ -46,6 +46,11 @@ export const useTriggerScanAction = ({insideFeature}: {insideFeature: Scan.Featu

const trigger = (scanAction: Scan.Action) => {
switch (scanAction.action) {
case 'launch-url': {
Linking.openURL(scanAction.url)
break
}

case 'send-single-pt': {
if (insideFeature !== 'send') resetTransferState()

Expand Down
2 changes: 2 additions & 0 deletions packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ import {ScanErrorUnknown, ScanErrorUnknownContent} from './scan/errors'
import {
ScanAction,
ScanActionClaim,
ScanActionLaunchUrl,
ScanActionSendOnlyReceiver,
ScanActionSendSinglePt,
ScanFeature,
Expand Down Expand Up @@ -657,6 +658,7 @@ export namespace Scan {
export type ActionClaim = ScanActionClaim
export type ActionSendOnlyReceiver = ScanActionSendOnlyReceiver
export type ActionSendSinglePt = ScanActionSendSinglePt
export type ActionScanLaunchUrl = ScanActionLaunchUrl
}

export namespace Claim {
Expand Down
6 changes: 6 additions & 0 deletions packages/types/src/scan/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,15 @@ export type ScanActionClaim = Readonly<{
params: Record<string, any> | undefined
}>

export type ScanActionLaunchUrl = Readonly<{
action: 'launch-url'
url: string
}>

export type ScanAction =
| ScanActionSendOnlyReceiver
| ScanActionSendSinglePt
| ScanActionClaim
| ScanActionLaunchUrl

export type ScanFeature = 'send' | 'scan'

0 comments on commit da2a88f

Please sign in to comment.