···11import {useMutation} from '@tanstack/react-query'
2233import {useAgent, useSession} from '#/state/session'
44+import {pdsAgent} from '#/state/session/agent'
4556export function useConfirmEmail({
67 onSuccess,
···1516 throw new Error('No email found for the current account')
1617 }
17181818- await agent.com.atproto.server.confirmEmail({
1919+ await pdsAgent(agent).com.atproto.server.confirmEmail({
1920 email: currentAccount.email.trim(),
2021 token: token.trim(),
2122 })
···88import {saveBytesToDisk} from '#/lib/media/manip'
99import {logger} from '#/logger'
1010import {useAgent} from '#/state/session'
1111+import {pdsAgent} from '#/state/session/agent'
1112import {atoms as a, useTheme, web} from '#/alf'
1213import {Button, ButtonIcon, ButtonText} from '#/components/Button'
1314import * as Dialog from '#/components/Dialog'
···3435 try {
3536 setLoading('repo')
3637 const did = agent.session.did
3737- const downloadRes = await agent.com.atproto.sync.getRepo({did})
3838+ const downloadRes = await pdsAgent(agent).com.atproto.sync.getRepo({did})
3839 const saveRes = await saveBytesToDisk(
3940 'repo.car',
4041 downloadRes.data,
+2-1
src/screens/SignupQueued.tsx
···8899import {logger} from '#/logger'
1010import {isSignupQueued, useAgent, useSessionApi} from '#/state/session'
1111+import {pdsAgent} from '#/state/session/agent'
1112import {useOnboardingDispatch} from '#/state/shell'
1213import {Logo} from '#/view/icons/Logo'
1314import {atoms as a, native, useBreakpoints, useTheme, web} from '#/alf'
···3839 const checkStatus = React.useCallback(async () => {
3940 setProcessing(true)
4041 try {
4141- const res = await agent.com.atproto.temp.checkSignupQueue()
4242+ const res = await pdsAgent(agent).com.atproto.temp.checkSignupQueue()
4243 if (res.data.activated) {
4344 // ready to go, exchange the access token for a usable one and kick off onboarding
4445 await agent.sessionManager.refreshSession()
+21
src/state/preferences/custom-appview-did.tsx
···11+import {isDid} from '@atproto/api'
22+33+import {device, useStorage} from '#/storage'
44+55+export function useCustomAppViewDid() {
66+ const [customAppViewDid = undefined, setCustomAppViewDid] = useStorage(
77+ device,
88+ ['customAppViewDid'],
99+ )
1010+1111+ return [customAppViewDid, setCustomAppViewDid] as const
1212+}
1313+1414+export function readCustomAppViewDidUri() {
1515+ const maybeDid = device.get(['customAppViewDid'])
1616+ if (!maybeDid || !isDid(maybeDid)) {
1717+ return undefined
1818+ }
1919+2020+ return `${maybeDid}#bsky_appview`
2121+}
···1717import {type ImageMeta} from '#/state/gallery'
1818import {STALE} from '#/state/queries'
1919import {useAgent, useSession} from '#/state/session'
2020+import {pdsAgent} from '#/state/session/agent'
2021import {invalidate as invalidateMyLists} from './my-lists'
2122import {RQKEY as PROFILE_LISTS_RQKEY} from './profile-lists'
2223···152153 record.avatar = undefined
153154 }
154155 const res = (
155155- await agent.com.atproto.repo.putRecord({
156156+ await pdsAgent(agent).com.atproto.repo.putRecord({
156157 repo: currentAccount.did,
157158 collection: 'app.bsky.graph.list',
158159 rkey,
···231232232233 // apply in chunks
233234 for (const writesChunk of chunk(writes, 10)) {
234234- await agent.com.atproto.repo.applyWrites({
235235+ await pdsAgent(agent).com.atproto.repo.applyWrites({
235236 repo: currentAccount.did,
236237 writes: writesChunk,
237238 })
+3-2
src/state/queries/messages/actor-declaration.ts
···3344import {logger} from '#/logger'
55import {useAgent, useSession} from '#/state/session'
66+import {pdsAgent} from '#/state/session/agent'
67import {RQKEY as PROFILE_RKEY} from '../profile'
7889export function useUpdateActorDeclaration({
···1920 return useMutation({
2021 mutationFn: async (allowIncoming: 'all' | 'none' | 'following') => {
2122 if (!currentAccount) throw new Error('Not signed in')
2222- const result = await agent.com.atproto.repo.putRecord({
2323+ const result = await pdsAgent(agent).com.atproto.repo.putRecord({
2324 repo: currentAccount.did,
2425 collection: 'chat.bsky.actor.declaration',
2526 rkey: 'self',
···6970 return useMutation({
7071 mutationFn: async () => {
7172 if (!currentAccount) throw new Error('Not signed in')
7272- const result = await agent.api.com.atproto.repo.deleteRecord({
7373+ const result = await pdsAgent(agent).com.atproto.repo.deleteRecord({
7374 repo: currentAccount.did,
7475 collection: 'chat.bsky.actor.declaration',
7576 rkey: 'self',
+2-1
src/state/queries/postgate/index.ts
···2121 POSTGATE_COLLECTION,
2222} from '#/state/queries/postgate/util'
2323import {useAgent} from '#/state/session'
2424+import {pdsAgent} from '#/state/session/agent'
2425import * as bsky from '#/types/bsky'
25262627export async function getPostgateRecord({
···9697 const postUrip = new AtUri(postUri)
97989899 await networkRetry(2, () =>
9999- agent.api.com.atproto.repo.putRecord({
100100+ pdsAgent(agent).com.atproto.repo.putRecord({
100101 repo: agent.session!.did,
101102 collection: POSTGATE_COLLECTION,
102103 rkey: postUrip.rkey,
+4-3
src/state/queries/preferences/index.ts
···2323 type ThreadViewPreferences,
2424 type UsePreferencesQueryResponse,
2525} from '#/state/queries/preferences/types'
2626-import {useAgent} from '#/state/session'
2626+import {useBlankPrefAuthedAgent as useAgent} from '#/state/session'
2727+import {pdsAgent} from '#/state/session/agent'
2728import {saveLabelers} from '#/state/session/agent-config'
2829import {useAgeAssurance} from '#/ageAssurance'
2930import {makeAgeRestrictedModerationPrefs} from '#/ageAssurance/util'
···4950 if (!agent.did) {
5051 return DEFAULT_LOGGED_OUT_PREFERENCES
5152 } else {
5252- const res = await agent.getPreferences()
5353+ const res = await pdsAgent(agent).getPreferences()
53545455 // save to local storage to ensure there are labels on initial requests
5556 saveLabelers(
···113114114115 return useMutation({
115116 mutationFn: async () => {
116116- await agent.app.bsky.actor.putPreferences({preferences: []})
117117+ await pdsAgent(agent).app.bsky.actor.putPreferences({preferences: []})
117118 // triggers a refetch
118119 await queryClient.invalidateQueries({
119120 queryKey: preferencesQueryKey,
+57-15
src/state/queries/resolve-identity.ts
···11+import {type Did, isDid} from '@atproto/api'
22+import {useQuery} from '@tanstack/react-query'
33+44+import {STALE} from '.'
15import {LRU} from './direct-fetch-record'
66+const RQKEY_ROOT = 'resolve-identity'
77+export const RQKEY = (did: string) => [RQKEY_ROOT, did]
2833-const serviceCache = new LRU<`did:${string}`, string>()
99+// this isn't trusted...
1010+export type DidDocument = {
1111+ '@context'?: string[]
1212+ id?: string
1313+ alsoKnownAs?: string[]
1414+ verificationMethod?: VerificationMethod[]
1515+ service?: Service[]
1616+}
41755-export async function resolvePdsServiceUrl(did: `did:${string}`) {
1818+export type VerificationMethod = {
1919+ id?: string
2020+ type?: string
2121+ controller?: string
2222+ publicKeyMultibase?: string
2323+}
2424+2525+export type Service = {
2626+ id?: string
2727+ type?: string
2828+ serviceEndpoint?: string
2929+}
3030+3131+const serviceCache = new LRU<Did, DidDocument>()
3232+3333+export async function resolveDidDocument(did: Did) {
634 return await serviceCache.getOrTryInsertWith(did, async () => {
735 const docUrl = did.startsWith('did:plc:')
836 ? `https://plc.directory/${did}`
937 : `https://${did.substring(8)}/.well-known/did.json`
10381111- // TODO: validate!
1212- const doc: {
1313- service: {
1414- serviceEndpoint: string
1515- type: string
1616- }[]
1717- } = await (await fetch(docUrl)).json()
1818- const service = doc.service.find(
1919- s => s.type === 'AtprotoPersonalDataServer',
2020- )?.serviceEndpoint
3939+ // TODO: we should probably validate this...
4040+ return await (await fetch(docUrl)).json()
4141+ })
4242+}
21432222- if (service === undefined)
2323- throw new Error(`could not find a service for ${did}`)
2424- return service
4444+export function findService(doc: DidDocument, id: string, type?: string) {
4545+ // probably not defensive enough, but we don't have atproto/did as a dep...
4646+ if (!Array.isArray(doc?.service)) return
4747+ return doc.service.find(
4848+ s => s?.serviceEndpoint && s?.id === id && (!type || s?.type === type),
4949+ )
5050+}
5151+5252+export async function resolvePdsServiceUrl(did: Did) {
5353+ const doc = await resolveDidDocument(did)
5454+ return findService(doc, '#atproto_pds', 'AtprotoPersonalDataServer')
5555+ ?.serviceEndpoint
5656+}
5757+5858+export function useDidDocument({did}: {did: string}) {
5959+ return useQuery<DidDocument | undefined>({
6060+ staleTime: STALE.HOURS.ONE,
6161+ queryKey: RQKEY(did || ''),
6262+ async queryFn() {
6363+ if (!isDid(did)) return undefined
6464+ return await resolveDidDocument(did)
6565+ },
6666+ enabled: isDid(did) && !(did.includes('#') || did.includes('?')),
2567 })
2668}
+4-3
src/state/queries/starter-packs.ts
···2727import {STALE} from '#/state/queries/index'
2828import {invalidateListMembersQuery} from '#/state/queries/list-members'
2929import {useAgent} from '#/state/session'
3030+import {pdsAgent} from '#/state/session/agent'
3031import * as bsky from '#/types/bsky'
31323233const RQKEY_ROOT = 'starter-pack'
···203204 if (removedItems.length !== 0) {
204205 const chunks = chunk(removedItems, 50)
205206 for (const chunk of chunks) {
206206- await agent.com.atproto.repo.applyWrites({
207207+ await pdsAgent(agent).com.atproto.repo.applyWrites({
207208 repo: agent.session!.did,
208209 writes: chunk.map(i => ({
209210 $type: 'com.atproto.repo.applyWrites#delete',
···220221 if (addedProfiles.length > 0) {
221222 const chunks = chunk(addedProfiles, 50)
222223 for (const chunk of chunks) {
223223- await agent.com.atproto.repo.applyWrites({
224224+ await pdsAgent(agent).com.atproto.repo.applyWrites({
224225 repo: agent.session!.did,
225226 writes: chunk.map(p => ({
226227 $type: 'com.atproto.repo.applyWrites#create',
···237238 }
238239239240 const rkey = parseStarterPackUri(currentStarterPack.uri)!.rkey
240240- await agent.com.atproto.repo.putRecord({
241241+ await pdsAgent(agent).com.atproto.repo.putRecord({
241242 repo: agent.session!.did,
242243 collection: 'app.bsky.graph.starterpack',
243244 rkey,
+2-1
src/state/queries/threadgate/index.ts
···1818} from '#/state/queries/threadgate/util'
1919import {useUpdatePostThreadThreadgateQueryCache} from '#/state/queries/usePostThread'
2020import {useAgent} from '#/state/session'
2121+import {pdsAgent} from '#/state/session/agent'
2122import {useThreadgateHiddenReplyUrisAPI} from '#/state/threadgate-hidden-replies'
2223import * as bsky from '#/types/bsky'
2324···162163 })
163164164165 await networkRetry(2, () =>
165165- agent.api.com.atproto.repo.putRecord({
166166+ pdsAgent(agent).com.atproto.repo.putRecord({
166167 repo: agent.session!.did,
167168 collection: 'app.bsky.feed.threadgate',
168169 rkey: postUrip.rkey,