Skip to content

Commit

Permalink
feat: allowing public DID connection reuse and implicit connections. (#…
Browse files Browse the repository at this point in the history
…1014)

Signed-off-by: Thiago Romano <[email protected]>
Signed-off-by: Thiago Romano <[email protected]>
  • Loading branch information
thiagoromanos authored Nov 1, 2023
1 parent 374b616 commit 4ceef79
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 8 deletions.
2 changes: 2 additions & 0 deletions packages/legacy/core/App/contexts/configuration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export interface ConfigurationContext {
autoRedirectConnectionToHome?: boolean
proofRequestTemplates?: (useDevTemplates: boolean) => Array<ProofRequestTemplate>
enableTours?: boolean
enableImplicitInvitations?: boolean
enableReuseConnections?: boolean
showPreface?: boolean
}

Expand Down
19 changes: 17 additions & 2 deletions packages/legacy/core/App/navigators/RootStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,17 @@ const RootStack: React.FC = () => {
const theme = useTheme()
const defaultStackOptions = createDefaultStackOptions(theme)
const OnboardingTheme = theme.OnboardingTheme
const { pages, terms, splash, useBiometry, developer, preface, showPreface } = useConfiguration()
const {
pages,
terms,
splash,
useBiometry,
developer,
preface,
showPreface,
enableImplicitInvitations,
enableReuseConnections,
} = useConfiguration()
useDeepLinks()

// remove connection on mobile verifier proofs if proof is rejected regardless of if it has been opened
Expand Down Expand Up @@ -96,7 +106,12 @@ const RootStack: React.FC = () => {

try {
// Try connection based
const receivedInvitation = await connectFromInvitation(deepLink, agent)
const receivedInvitation = await connectFromInvitation(
deepLink,
agent,
enableImplicitInvitations,
enableReuseConnections
)
navigation.navigate(Stacks.ConnectionStack as any, {
screen: Screens.Connection,
params: { connectionId: receivedInvitation?.connectionRecord?.id },
Expand Down
10 changes: 8 additions & 2 deletions packages/legacy/core/App/navigators/TabStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import HomeStack from './HomeStack'

const TabStack: React.FC = () => {
const { width, height } = useWindowDimensions()
const { useCustomNotifications } = useConfiguration()
const { useCustomNotifications, enableReuseConnections, enableImplicitInvitations } = useConfiguration()
const { total } = useCustomNotifications()
const { t } = useTranslation()
const Tab = createBottomTabNavigator<TabStackParams>()
Expand Down Expand Up @@ -160,7 +160,13 @@ const TabStack: React.FC = () => {
if (!assertConnectedNetwork()) {
return
}
navigation.navigate(Stacks.ConnectStack, { screen: Screens.Scan })
navigation.navigate(Stacks.ConnectStack, {
screen: Screens.Scan,
params: {
implicitInvitations: enableImplicitInvitations,
reuseConnections: enableReuseConnections,
},
})
},
})}
>
Expand Down
10 changes: 9 additions & 1 deletion packages/legacy/core/App/screens/Scan.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,18 @@ const Scan: React.FC<ScanProps> = ({ navigation, route }) => {
if (route?.params && route.params['defaultToConnect']) {
defaultToConnect = route.params['defaultToConnect']
}
let implicitInvitations = false
if (route?.params && route.params['implicitInvitations']) {
implicitInvitations = route.params['implicitInvitations']
}
let reuseConnections = false
if (route?.params && route.params['reuseConnections']) {
reuseConnections = route.params['reuseConnections']
}

const handleInvitation = async (value: string): Promise<void> => {
try {
const receivedInvitation = await connectFromInvitation(value, agent)
const receivedInvitation = await connectFromInvitation(value, agent, implicitInvitations, reuseConnections)
if (receivedInvitation?.connectionRecord?.id) {
// not connectionless
navigation.getParent()?.navigate(Stacks.ConnectionStack, {
Expand Down
28 changes: 25 additions & 3 deletions packages/legacy/core/App/utils/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
BasicMessageRecord,
ProofExchangeRecord,
ProofState,
parseDid,
} from '@aries-framework/core'
import { BasicMessageRole } from '@aries-framework/core/build/modules/basic-messages/BasicMessageRole'
import {
Expand Down Expand Up @@ -815,14 +816,36 @@ export const receiveMessageFromDeepLink = async (url: string, agent: Agent | und
* @param agent an Agent instance
* @returns a connection record from parsing and receiving the invitation
*/
export const connectFromInvitation = async (uri: string, agent: Agent | undefined) => {
export const connectFromInvitation = async (
uri: string,
agent: Agent | undefined,
implicitInvitations: boolean = false,
reuseConnection: boolean = false
) => {
const invitation = await agent?.oob.parseInvitation(uri)

if (!invitation) {
throw new Error('Could not parse invitation from URL')
}

const record = await agent?.oob.receiveInvitation(invitation)
let record
if (implicitInvitations) {
try {
if (invitation.getDidServices().length > 0) {
const did = parseDid(invitation.getDidServices()[0])
record = await agent?.oob.receiveImplicitInvitation({
did: did.did,
label: invitation.label,
handshakeProtocols: invitation.handshakeProtocols,
})
}
} catch (e) {
// don't throw an error, will try to connect again below
}
}
if (!record) {
record = await agent?.oob.receiveInvitation(invitation, { reuseConnection })
}

return record
}
Expand All @@ -839,7 +862,6 @@ export const createConnectionInvitation = async (agent: Agent | undefined, goalC
if (!record) {
throw new Error('Could not create new invitation')
}

const invitationUrl = record.outOfBandInvitation.toUrl({ domain })

return {
Expand Down

2 comments on commit 4ceef79

@fc-santos
Copy link
Contributor

Choose a reason for hiding this comment

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

Hello @thiagoromanos, could you please explain how could I test the enableReuseConnection so a contact is not added in the contacts screen every time (scan QR Code - /out-of-band/create-invitation) if the contact already exists in the mobile wallet? A video would be appreciated!

@thiagoromanos
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right now it's not possible to do that using bifold as it is, because de DidResolver for react-native is not working properly, so I used a AFJ NodeJS proxy (like this one https://github.com/2060-io/aries-javascript-indy-vdr-proxy) to make the requests.
The test is quite simple. You create an invitation setting "use_public_did": true and in your wallet set enableReuseConnections: true on your configuration context. Doing that, next time you receive another invitation from the same agent using public_did, you will reuse the connection you already have. Note that you cannot use the same invite multiple times, to do that, use enableImplicitInvitations option on the configuration context. You will be able to use the same invitation multiple times, but each time a connection will be created.

Please sign in to comment.