···16# Enable debug logs for specific logger instances
17EXPO_PUBLIC_LOG_DEBUG=session
1800019# Chat service DID
20EXPO_PUBLIC_CHAT_PROXY_DID=
21
···16# Enable debug logs for specific logger instances
17EXPO_PUBLIC_LOG_DEBUG=session
1819+# Bluesky appview DID
20+EXPO_PUBLIC_BLUESKY_PROXY_DID=
21+22# Chat service DID
23EXPO_PUBLIC_CHAT_PROXY_DID=
24
+6
src/env/common.ts
···63export const LOG_DEBUG: string = process.env.EXPO_PUBLIC_LOG_DEBUG || ''
6465/**
00000066 * The DID of the chat service to proxy to
67 */
68export const CHAT_PROXY_DID: Did =
···63export const LOG_DEBUG: string = process.env.EXPO_PUBLIC_LOG_DEBUG || ''
6465/**
66+ * The DID of the Bluesky appview to proxy to
67+ */
68+export const BLUESKY_PROXY_DID: Did =
69+ process.env.EXPO_PUBLIC_BLUESKY_PROXY_DID || 'did:web:api.bsky.app'
70+71+/**
72 * The DID of the chat service to proxy to
73 */
74export const CHAT_PROXY_DID: Did =
···1import React, {useState} from 'react'
2import {ActivityIndicator, Keyboard, View} from 'react-native'
3-import {ComAtprotoServerDescribeServer} from '@atproto/api'
4-import {BskyAgent} from '@atproto/api'
5import {msg, Trans} from '@lingui/macro'
6import {useLingui} from '@lingui/react'
7import * as EmailValidator from 'email-validator'
···9import {isNetworkError} from '#/lib/strings/errors'
10import {cleanError} from '#/lib/strings/errors'
11import {logger} from '#/logger'
012import {atoms as a, useTheme} from '#/alf'
13import {Button, ButtonText} from '#/components/Button'
14import {FormError} from '#/components/forms/FormError'
···55 setIsProcessing(true)
5657 try {
58- const agent = new BskyAgent({service: serviceUrl})
59 await agent.com.atproto.server.requestPasswordReset({email})
60 onEmailSent()
61 } catch (e: any) {
···1import React, {useState} from 'react'
2import {ActivityIndicator, Keyboard, View} from 'react-native'
3+import {type ComAtprotoServerDescribeServer} from '@atproto/api'
04import {msg, Trans} from '@lingui/macro'
5import {useLingui} from '@lingui/react'
6import * as EmailValidator from 'email-validator'
···8import {isNetworkError} from '#/lib/strings/errors'
9import {cleanError} from '#/lib/strings/errors'
10import {logger} from '#/logger'
11+import {Agent} from '#/state/session/agent'
12import {atoms as a, useTheme} from '#/alf'
13import {Button, ButtonText} from '#/components/Button'
14import {FormError} from '#/components/forms/FormError'
···55 setIsProcessing(true)
5657 try {
58+ const agent = new Agent(null, {service: serviceUrl})
59 await agent.com.atproto.server.requestPasswordReset({email})
60 onEmailSent()
61 } catch (e: any) {
+2-2
src/screens/Login/SetNewPasswordForm.tsx
···1import {useState} from 'react'
2import {ActivityIndicator, View} from 'react-native'
3-import {BskyAgent} from '@atproto/api'
4import {msg, Trans} from '@lingui/macro'
5import {useLingui} from '@lingui/react'
6···9import {cleanError} from '#/lib/strings/errors'
10import {checkAndFormatResetCode} from '#/lib/strings/password'
11import {logger} from '#/logger'
012import {atoms as a, useTheme} from '#/alf'
13import {Button, ButtonText} from '#/components/Button'
14import {FormError} from '#/components/forms/FormError'
···63 setIsProcessing(true)
6465 try {
66- const agent = new BskyAgent({service: serviceUrl})
67 await agent.com.atproto.server.resetPassword({
68 token: formattedCode,
69 password,
···1import {useState} from 'react'
2import {ActivityIndicator, View} from 'react-native'
03import {msg, Trans} from '@lingui/macro'
4import {useLingui} from '@lingui/react'
5···8import {cleanError} from '#/lib/strings/errors'
9import {checkAndFormatResetCode} from '#/lib/strings/password'
10import {logger} from '#/logger'
11+import {Agent} from '#/state/session/agent'
12import {atoms as a, useTheme} from '#/alf'
13import {Button, ButtonText} from '#/components/Button'
14import {FormError} from '#/components/forms/FormError'
···63 setIsProcessing(true)
6465 try {
66+ const agent = new Agent(null, {service: serviceUrl})
67 await agent.com.atproto.server.resetPassword({
68 token: formattedCode,
69 password,
+1-1
src/state/messages/convo/agent.ts
···10import {nanoid} from 'nanoid/non-secure'
1112import {networkRetry} from '#/lib/async/retry'
013import {isNetworkError} from '#/lib/strings/errors'
14import {Logger} from '#/logger'
15import {isNative} from '#/platform/detection'
···33} from '#/state/messages/convo/types'
34import {type MessagesEventBus} from '#/state/messages/events/agent'
35import {type MessagesEventBusError} from '#/state/messages/events/types'
36-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
3738const logger = Logger.create(Logger.Context.ConversationAgent)
39
···10import {nanoid} from 'nanoid/non-secure'
1112import {networkRetry} from '#/lib/async/retry'
13+import {DM_SERVICE_HEADERS} from '#/lib/constants'
14import {isNetworkError} from '#/lib/strings/errors'
15import {Logger} from '#/logger'
16import {isNative} from '#/platform/detection'
···34} from '#/state/messages/convo/types'
35import {type MessagesEventBus} from '#/state/messages/events/agent'
36import {type MessagesEventBusError} from '#/state/messages/events/types'
03738const logger = Logger.create(Logger.Context.ConversationAgent)
39
+1-1
src/state/messages/events/agent.ts
···3import {nanoid} from 'nanoid/non-secure'
45import {networkRetry} from '#/lib/async/retry'
06import {isNetworkError} from '#/lib/strings/errors'
7import {Logger} from '#/logger'
8import {
···17 type MessagesEventBusParams,
18 MessagesEventBusStatus,
19} from '#/state/messages/events/types'
20-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
2122const logger = Logger.create(Logger.Context.DMsAgent)
23
···3import {nanoid} from 'nanoid/non-secure'
45import {networkRetry} from '#/lib/async/retry'
6+import {DM_SERVICE_HEADERS} from '#/lib/constants'
7import {isNetworkError} from '#/lib/strings/errors'
8import {Logger} from '#/logger'
9import {
···18 type MessagesEventBusParams,
19 MessagesEventBusStatus,
20} from '#/state/messages/events/types'
02122const logger = Logger.create(Logger.Context.DMsAgent)
23
+4-3
src/state/queries/handle-availability.ts
···1-import {Agent, ComAtprotoTempCheckHandleAvailability} from '@atproto/api'
2import {useQuery} from '@tanstack/react-query'
34import {
···10import {logger} from '#/logger'
11import {useDebouncedValue} from '#/components/live/utils'
12import * as bsky from '#/types/bsky'
01314export const RQKEY_handleAvailability = (
15 handle: string,
···74 },
75) {
76 if (serviceDid === BSKY_SERVICE_DID) {
77- const agent = new Agent({service: BSKY_SERVICE})
78 // entryway has a special API for handle availability
79 const {data} = await agent.com.atproto.temp.checkHandleAvailability({
80 handle,
···109 }
110 } else {
111 // 3rd party PDSes won't have this API so just try and resolve the handle
112- const agent = new Agent({service: PUBLIC_BSKY_SERVICE})
113 try {
114 const res = await agent.resolveHandle({
115 handle,
···1+import {ComAtprotoTempCheckHandleAvailability} from '@atproto/api'
2import {useQuery} from '@tanstack/react-query'
34import {
···10import {logger} from '#/logger'
11import {useDebouncedValue} from '#/components/live/utils'
12import * as bsky from '#/types/bsky'
13+import {Agent} from '../session/agent'
1415export const RQKEY_handleAvailability = (
16 handle: string,
···75 },
76) {
77 if (serviceDid === BSKY_SERVICE_DID) {
78+ const agent = new Agent(null, {service: BSKY_SERVICE})
79 // entryway has a special API for handle availability
80 const {data} = await agent.com.atproto.temp.checkHandleAvailability({
81 handle,
···110 }
111 } else {
112 // 3rd party PDSes won't have this API so just try and resolve the handle
113+ const agent = new Agent(null, {service: PUBLIC_BSKY_SERVICE})
114 try {
115 const res = await agent.resolveHandle({
116 handle,
+5-2
src/state/queries/messages/accept-conversation.ts
···1-import {ChatBskyConvoAcceptConvo, ChatBskyConvoListConvos} from '@atproto/api'
0002import {useMutation, useQueryClient} from '@tanstack/react-query'
304import {logger} from '#/logger'
5import {useAgent} from '#/state/session'
6-import {DM_SERVICE_HEADERS} from './const'
7import {
8 RQKEY as CONVO_LIST_KEY,
9 RQKEY_ROOT as CONVO_LIST_ROOT_KEY,
···1+import {
2+ type ChatBskyConvoAcceptConvo,
3+ type ChatBskyConvoListConvos,
4+} from '@atproto/api'
5import {useMutation, useQueryClient} from '@tanstack/react-query'
67+import {DM_SERVICE_HEADERS} from '#/lib/constants'
8import {logger} from '#/logger'
9import {useAgent} from '#/state/session'
010import {
11 RQKEY as CONVO_LIST_KEY,
12 RQKEY_ROOT as CONVO_LIST_ROOT_KEY,
···1-import {ChatBskyConvoDefs} from '@atproto/api'
2import {
3- QueryClient,
4 useMutation,
5 useQuery,
6 useQueryClient,
7} from '@tanstack/react-query'
809import {STALE} from '#/state/queries'
10-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
11import {useOnMarkAsRead} from '#/state/queries/messages/list-conversations'
12import {useAgent} from '#/state/session'
13import {
14- ConvoListQueryData,
15 getConvoFromQueryData,
16 RQKEY_ROOT as LIST_CONVOS_KEY,
17} from './list-conversations'
···1+import {type ChatBskyConvoDefs} from '@atproto/api'
2import {
3+ type QueryClient,
4 useMutation,
5 useQuery,
6 useQueryClient,
7} from '@tanstack/react-query'
89+import {DM_SERVICE_HEADERS} from '#/lib/constants'
10import {STALE} from '#/state/queries'
011import {useOnMarkAsRead} from '#/state/queries/messages/list-conversations'
12import {useAgent} from '#/state/session'
13import {
14+ type ConvoListQueryData,
15 getConvoFromQueryData,
16 RQKEY_ROOT as LIST_CONVOS_KEY,
17} from './list-conversations'
···1import {useQuery} from '@tanstack/react-query'
23-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
4import {useAgent} from '#/state/session'
5import {STALE} from '..'
6
···1import {useQuery} from '@tanstack/react-query'
23+import {DM_SERVICE_HEADERS} from '#/lib/constants'
4import {useAgent} from '#/state/session'
5import {STALE} from '..'
6
···1-import {ChatBskyConvoGetConvoForMembers} from '@atproto/api'
2import {useMutation, useQueryClient} from '@tanstack/react-query'
304import {logger} from '#/logger'
5-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
6import {useAgent} from '#/state/session'
7import {precacheConvoQuery} from './conversation'
8
···1+import {type ChatBskyConvoGetConvoForMembers} from '@atproto/api'
2import {useMutation, useQueryClient} from '@tanstack/react-query'
34+import {DM_SERVICE_HEADERS} from '#/lib/constants'
5import {logger} from '#/logger'
06import {useAgent} from '#/state/session'
7import {precacheConvoQuery} from './conversation'
8
+5-2
src/state/queries/messages/leave-conversation.ts
···1import {useMemo} from 'react'
2-import {ChatBskyConvoLeaveConvo, ChatBskyConvoListConvos} from '@atproto/api'
0003import {
4 useMutation,
5 useMutationState,
6 useQueryClient,
7} from '@tanstack/react-query'
809import {logger} from '#/logger'
10-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
11import {useAgent} from '#/state/session'
12import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations'
13
···1import {useMemo} from 'react'
2+import {
3+ type ChatBskyConvoLeaveConvo,
4+ type ChatBskyConvoListConvos,
5+} from '@atproto/api'
6import {
7 useMutation,
8 useMutationState,
9 useQueryClient,
10} from '@tanstack/react-query'
1112+import {DM_SERVICE_HEADERS} from '#/lib/constants'
13import {logger} from '#/logger'
014import {useAgent} from '#/state/session'
15import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations'
16
+1-1
src/state/queries/messages/list-conversations.tsx
···13} from '@tanstack/react-query'
14import throttle from 'lodash.throttle'
15016import {useCurrentConvoId} from '#/state/messages/current-convo-id'
17import {useMessagesEventBus} from '#/state/messages/events'
18import {useModerationOpts} from '#/state/preferences/moderation-opts'
19-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
20import {useAgent, useSession} from '#/state/session'
21import {useLeftConvos} from './leave-conversation'
22
···13} from '@tanstack/react-query'
14import throttle from 'lodash.throttle'
1516+import {DM_SERVICE_HEADERS} from '#/lib/constants'
17import {useCurrentConvoId} from '#/state/messages/current-convo-id'
18import {useMessagesEventBus} from '#/state/messages/events'
19import {useModerationOpts} from '#/state/preferences/moderation-opts'
020import {useAgent, useSession} from '#/state/session'
21import {useLeftConvos} from './leave-conversation'
22
+9-5
src/state/queries/messages/mute-conversation.ts
···1import {
2- ChatBskyConvoDefs,
3- ChatBskyConvoListConvos,
4- ChatBskyConvoMuteConvo,
5} from '@atproto/api'
6-import {InfiniteData, useMutation, useQueryClient} from '@tanstack/react-query'
000078-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
9import {useAgent} from '#/state/session'
10import {RQKEY as CONVO_KEY} from './conversation'
11import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations'
···1import {
2+ type ChatBskyConvoDefs,
3+ type ChatBskyConvoListConvos,
4+ type ChatBskyConvoMuteConvo,
5} from '@atproto/api'
6+import {
7+ type InfiniteData,
8+ useMutation,
9+ useQueryClient,
10+} from '@tanstack/react-query'
1112+import {DM_SERVICE_HEADERS} from '#/lib/constants'
13import {useAgent} from '#/state/session'
14import {RQKEY as CONVO_KEY} from './conversation'
15import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations'
+2-2
src/state/queries/messages/update-all-read.ts
···1-import {ChatBskyConvoListConvos} from '@atproto/api'
2import {useMutation, useQueryClient} from '@tanstack/react-query'
304import {logger} from '#/logger'
5-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
6import {useAgent} from '#/state/session'
7import {RQKEY as CONVO_LIST_KEY} from './list-conversations'
8
···1+import {type ChatBskyConvoListConvos} from '@atproto/api'
2import {useMutation, useQueryClient} from '@tanstack/react-query'
34+import {DM_SERVICE_HEADERS} from '#/lib/constants'
5import {logger} from '#/logger'
06import {useAgent} from '#/state/session'
7import {RQKEY as CONVO_LIST_KEY} from './list-conversations'
8
···1-import {AtpSessionData, AtpSessionEvent, BskyAgent} from '@atproto/api'
0000000002import {TID} from '@atproto/common-web'
034import {networkRetry} from '#/lib/async/retry'
5import {
06 BSKY_SERVICE,
7 DISCOVER_SAVED_FEED,
8 IS_PROD_SERVICE,
···19 configureModerationForAccount,
20 configureModerationForGuest,
21} from './moderation'
22-import {SessionAccount} from './types'
23import {isSessionExpired, isSignupQueued} from './util'
240025export function createPublicAgent() {
26 configureModerationForGuest() // Side effect but only relevant for tests
27- return new BskyAppAgent({service: PUBLIC_BSKY_SERVICE})
00028}
2930export async function createAgentAndResume(
···61 }
62 }
630064 return agent.prepare(gates, moderation, onSessionChange)
65}
66···93 const account = agentToSessionAccountOrThrow(agent)
94 const gates = tryFetchGates(account.did, 'prefer-fresh-gates')
95 const moderation = configureModerationForAccount(agent, account)
00096 return agent.prepare(gates, moderation, onSessionChange)
97}
98···180 logger.error(e, {message: `session: failed snoozeEmailConfirmationPrompt`})
181 }
18200183 return agent.prepare(gates, moderation, onSessionChange)
184}
185···234 }
235}
236000000000000237// Not exported. Use factories above to create it.
000238let realFetch = globalThis.fetch
239class BskyAppAgent extends BskyAgent {
240 persistSessionHandler: ((event: AtpSessionEvent) => void) | undefined =
···1+import {
2+ Agent as BaseAgent,
3+ type AtprotoServiceType,
4+ type AtpSessionData,
5+ type AtpSessionEvent,
6+ BskyAgent,
7+ type Did,
8+} from '@atproto/api'
9+import {type FetchHandler} from '@atproto/api/dist/agent'
10+import {type SessionManager} from '@atproto/api/dist/session-manager'
11import {TID} from '@atproto/common-web'
12+import {type FetchHandlerOptions} from '@atproto/xrpc'
1314import {networkRetry} from '#/lib/async/retry'
15import {
16+ BLUESKY_PROXY_HEADER,
17 BSKY_SERVICE,
18 DISCOVER_SAVED_FEED,
19 IS_PROD_SERVICE,
···30 configureModerationForAccount,
31 configureModerationForGuest,
32} from './moderation'
33+import {type SessionAccount} from './types'
34import {isSessionExpired, isSignupQueued} from './util'
3536+export type ProxyHeaderValue = `${Did}#${AtprotoServiceType}`
37+38export function createPublicAgent() {
39 configureModerationForGuest() // Side effect but only relevant for tests
40+41+ const agent = new BskyAppAgent({service: PUBLIC_BSKY_SERVICE})
42+ agent.configureProxy(BLUESKY_PROXY_HEADER)
43+ return agent
44}
4546export async function createAgentAndResume(
···77 }
78 }
7980+ agent.configureProxy(BLUESKY_PROXY_HEADER)
81+82 return agent.prepare(gates, moderation, onSessionChange)
83}
84···111 const account = agentToSessionAccountOrThrow(agent)
112 const gates = tryFetchGates(account.did, 'prefer-fresh-gates')
113 const moderation = configureModerationForAccount(agent, account)
114+115+ agent.configureProxy(BLUESKY_PROXY_HEADER)
116+117 return agent.prepare(gates, moderation, onSessionChange)
118}
119···201 logger.error(e, {message: `session: failed snoozeEmailConfirmationPrompt`})
202 }
203204+ agent.configureProxy(BLUESKY_PROXY_HEADER)
205+206 return agent.prepare(gates, moderation, onSessionChange)
207}
208···257 }
258}
259260+export class Agent extends BaseAgent {
261+ constructor(
262+ proxyHeader: ProxyHeaderValue | null,
263+ options: SessionManager | FetchHandler | FetchHandlerOptions,
264+ ) {
265+ super(options)
266+ if (proxyHeader) {
267+ this.configureProxy(proxyHeader)
268+ }
269+ }
270+}
271+272// Not exported. Use factories above to create it.
273+// WARN: In the factories above, we _manually set a proxy header_ for the agent after we do whatever it is we are supposed to do.
274+// Ideally, we wouldn't be doing this. However, since there is so much logic that requires making calls to the PDS right now, it
275+// feels safer to just let those run as-is and set the header afterward.
276let realFetch = globalThis.fetch
277class BskyAppAgent extends BskyAgent {
278 persistSessionHandler: ((event: AtpSessionEvent) => void) | undefined =
+1-1
src/view/com/modals/DeleteAccount.tsx
···10import {msg, Trans} from '@lingui/macro'
11import {useLingui} from '@lingui/react'
12013import {usePalette} from '#/lib/hooks/usePalette'
14import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
15import {cleanError} from '#/lib/strings/errors'
···17import {useTheme} from '#/lib/ThemeContext'
18import {isAndroid, isWeb} from '#/platform/detection'
19import {useModalControls} from '#/state/modals'
20-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
21import {useAgent, useSession, useSessionApi} from '#/state/session'
22import {atoms as a, useTheme as useNewTheme} from '#/alf'
23import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
···10import {msg, Trans} from '@lingui/macro'
11import {useLingui} from '@lingui/react'
1213+import {DM_SERVICE_HEADERS} from '#/lib/constants'
14import {usePalette} from '#/lib/hooks/usePalette'
15import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
16import {cleanError} from '#/lib/strings/errors'
···18import {useTheme} from '#/lib/ThemeContext'
19import {isAndroid, isWeb} from '#/platform/detection'
20import {useModalControls} from '#/state/modals'
021import {useAgent, useSession, useSessionApi} from '#/state/session'
22import {atoms as a, useTheme as useNewTheme} from '#/alf'
23import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
···31import {useQueryClient} from '@tanstack/react-query'
3233import {MAX_POST_LINES} from '#/lib/constants'
034import {useAnimatedValue} from '#/lib/hooks/useAnimatedValue'
35import {usePalette} from '#/lib/hooks/usePalette'
36import {makeProfileLink} from '#/lib/routes/links'
···41import {niceDate} from '#/lib/strings/time'
42import {s} from '#/lib/styles'
43import {logger} from '#/logger'
44-import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
45import {type FeedNotification} from '#/state/queries/notifications/feed'
46import {unstableCacheProfileView} from '#/state/queries/unstable-profile-cache'
47import {useAgent} from '#/state/session'
···31import {useQueryClient} from '@tanstack/react-query'
3233import {MAX_POST_LINES} from '#/lib/constants'
34+import {DM_SERVICE_HEADERS} from '#/lib/constants'
35import {useAnimatedValue} from '#/lib/hooks/useAnimatedValue'
36import {usePalette} from '#/lib/hooks/usePalette'
37import {makeProfileLink} from '#/lib/routes/links'
···42import {niceDate} from '#/lib/strings/time'
43import {s} from '#/lib/styles'
44import {logger} from '#/logger'
045import {type FeedNotification} from '#/state/queries/notifications/feed'
46import {unstableCacheProfileView} from '#/state/queries/unstable-profile-cache'
47import {useAgent} from '#/state/session'