Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/common/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ export * from './tan-query/useFavoriteTrack'
export * from './tan-query/useUnfavoriteTrack'
export * from './tan-query/useToggleFavoriteTrack'
export * from './tan-query/useDeleteTrack'
export * from './tan-query/useUpdateTrack'
export * from './tan-query/types'
export * from './tan-query/useFollowers'
3 changes: 2 additions & 1 deletion packages/common/src/api/tan-query/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,6 @@ export const QUERY_KEYS = {
trendingIds: 'trendingIds',
trendingPlaylists: 'trendingPlaylists',
trendingUnderground: 'trendingUnderground',
trackPageLineup: 'trackPageLineup'
trackPageLineup: 'trackPageLineup',
userbank: 'userbank'
} as const
51 changes: 51 additions & 0 deletions packages/common/src/api/tan-query/useGetOrCreateUserBank.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { PublicKey } from '@solana/web3.js'
import { useQuery } from '@tanstack/react-query'

import { useAudiusQueryContext } from '~/audius-query'

import { QUERY_KEYS } from './queryKeys'
import { QueryOptions } from './types'
// Define the allowed mint types based on the SDK
type MintType = 'USDC' | 'wAUDIO'

export type GetOrCreateUserBankParams = {
wallet: string
mint?: MintType
}

const getUserBankQueryKey = (wallet: string) => [QUERY_KEYS.userbank, wallet]

/**
* Hook to get or create a user bank for a wallet
* This is a migration of the getOrCreateUserBank saga function to a TanStack Query mutation
*/
export const useGetOrCreateUserBank = (
wallet: string,
mint: MintType = 'USDC',
options?: QueryOptions
) => {
const { audiusSdk } = useAudiusQueryContext()

return useQuery({
queryKey: getUserBankQueryKey(wallet),
queryFn: async (): Promise<PublicKey> => {
try {
const sdk = await audiusSdk()

// Call the SDK's method to get or create a user bank
const result =
await sdk.services.claimableTokensClient.getOrCreateUserBank({
ethWallet: wallet,
mint
})

return result.userBank
} catch (error) {
console.error('Error getting or creating user bank', error)
throw error
}
Comment on lines +43 to +46
Copy link
Contributor

Choose a reason for hiding this comment

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

sentry instead of console?
I've also been wondering - should we add a try/catch (or some wrapper) to all our hooks to report to sentry?

},
...options,
enabled: options?.enabled !== false && !!wallet
})
}
81 changes: 81 additions & 0 deletions packages/common/src/api/tan-query/useUpdateStems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { useMutation } from '@tanstack/react-query'
import { useDispatch, useStore } from 'react-redux'

import { ID } from '~/models/Identifiers'
import { StemUpload, StemUploadWithFile } from '~/models/Stems'
import { Stem } from '~/models/Track'
import { deleteTrack } from '~/store/cache/tracks/actions'
import { CommonState } from '~/store/commonStore'
import { stemsUploadActions } from '~/store/stems-upload'
import { getCurrentUploads } from '~/store/stems-upload/selectors'
import { uuid } from '~/utils/uid'

const { startStemUploads } = stemsUploadActions

export type UpdateStemsArgs = {
trackId: ID
existingStems: Stem[] | undefined
updatedStems: Array<StemUpload | StemUploadWithFile> | undefined
}

/**
* Hook for updating stems on a track, handling both additions and removals
*/
export const useUpdateStems = () => {
const dispatch = useDispatch()
const store = useStore()

return useMutation({
mutationFn: async ({
trackId,
existingStems,
updatedStems
}: UpdateStemsArgs) => {
const inProgressStemUploads = getCurrentUploads(
Copy link
Contributor

@DejayJD DejayJD Mar 13, 2025

Choose a reason for hiding this comment

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

is this synchronous? Is not a useSelector type of hook?

edit: oh duh I see you're passing in state as of the call time

store.getState() as CommonState,
trackId
)

// Find stems that need to be added (new stems)
const addedStems = updatedStems?.filter((stem) => {
return !existingStems?.find((existingStem) => {
return existingStem.track_id === stem.metadata.track_id
})
})

// Filter to only stems that have files to upload
const addedStemsWithFiles = addedStems?.filter(
(stem) => 'file' in stem
) as StemUploadWithFile[]
Comment on lines +47 to +49
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: this could be done in the filter above


// Start uploads for new stems with files
if (addedStemsWithFiles.length > 0) {
dispatch(
startStemUploads({
parentId: trackId,
uploads: addedStemsWithFiles,
batchUID: uuid()
})
)
}

// Find stems that need to be removed
const removedStems = existingStems
?.filter((existingStem) => {
return !updatedStems?.find(
(stem) => stem.metadata.track_id === existingStem.track_id
)
})
.filter((existingStem) => {
return !inProgressStemUploads.find(
(upload) => upload.metadata.track_id === existingStem.track_id
)
})

// Delete removed stems
for (const stem of removedStems ?? []) {
dispatch(deleteTrack(stem.track_id))
}
}
})
}
Loading