Skip to content
Merged
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
34 changes: 11 additions & 23 deletions packages/common/src/adapters/accessConditionsFromSDK.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { AccessGate } from '@audius/sdk'
import {
instanceOfExtendedPurchaseGate,
instanceOfFollowGate,
instanceOfPurchaseGate,
instanceOfTokenGate
} from '@audius/sdk'

Expand All @@ -13,35 +13,23 @@ export const accessConditionsFromSDK = (
): AccessConditions | null => {
if (instanceOfFollowGate(input)) {
return { follow_user_id: input.followUserId }
} else if (instanceOfExtendedPurchaseGate(input)) {
const purchase = input.usdcPurchase
const splits = Array.isArray(purchase.splits)
? purchase.splits.map((s) => ({
user_id: s.userId,
percentage: s.percentage,
payout_wallet: s.payoutWallet,
amount: s.amount,
...(s.ethWallet != null && { eth_wallet: s.ethWallet })
}))
: []
const albumTrackPrice = (purchase as { albumTrackPrice?: number })
.albumTrackPrice
return {
usdc_purchase: {
price: purchase.price,
...(albumTrackPrice != null && { albumTrackPrice }),
splits
}
}
} else if (instanceOfTokenGate(input)) {
return {
token_gate: {
token_mint: input.tokenGate.tokenMint,
token_amount: input.tokenGate.tokenAmount
}
}
} else if ('nftCollection' in input && input.nftCollection != null) {
return null
} else if (instanceOfPurchaseGate(input)) {
return {
usdc_purchase: {
price: input.usdcPurchase.price,
splits: input.usdcPurchase.splits.map((s) => ({
user_id: s.userId,
percentage: s.percentage
}))
}
}
} else {
throw new Error(`Unsupported access gate type: ${JSON.stringify(input)}`)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/adapters/accessConditionsToSDK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const usdcPurchaseConditionsToSDK = (
ethWallet?: string
}
) => ({
userId: s.user_id ?? s.userId,
userId: s.user_id,
percentage: s.percentage,
payoutWallet: s.payout_wallet ?? s.payoutWallet ?? '',
amount: s.amount,
Expand Down
19 changes: 6 additions & 13 deletions packages/common/src/api/tan-query/upload/usePublishCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ type PublishCollectionContext = Pick<
'audiusSdk' | 'analytics' | 'dispatch' | 'reportToSentry'
> & {
userId: number
wallet: string
}

type PublishCollectionParams = {
Expand All @@ -52,15 +51,11 @@ type PublishCollectionParams = {
const getPublishCollectionOptions = (context: PublishCollectionContext) =>
mutationOptions({
mutationFn: async (params: PublishCollectionParams) => {
const { audiusSdk, userId, wallet } = context
const { audiusSdk, userId } = context
const sdk = await audiusSdk()
if (!userId || !wallet) {
if (!userId) {
throw new Error('User ID and wallet are required to publish collection')
}
const userBank = await sdk.services.claimableTokensClient.deriveUserBank({
ethWallet: wallet,
mint: 'USDC'
})

// If the collection is a premium album, this will populate the premium metadata (price/splits/etc)
let albumTrackPrice: number | undefined
Expand All @@ -73,15 +68,15 @@ const getPublishCollectionOptions = (context: PublishCollectionContext) =>
params.collectionMetadata.stream_conditions?.usdc_purchase
.albumTrackPrice ?? undefined
params.collectionMetadata.stream_conditions = getUSDCMetadata(
userBank.toString(),
userId,
params.collectionMetadata.stream_conditions
)
}

// Combine collection metadata into each track's metadata
for (const track of params.tracks) {
track.metadata = combineMetadata(
userBank.toString(),
userId,
track.metadata,
params.collectionMetadata,
albumTrackPrice
Expand Down Expand Up @@ -145,14 +140,12 @@ export const usePublishCollection = (
const { data: account = null } = useCurrentAccount()
const { data: accountUser } = useCurrentAccountUser()
const userId = account?.userId ?? undefined
const wallet = account?.walletAddresses.currentUser ?? undefined

return useMutation({
...options,
...getPublishCollectionOptions({
audiusSdk,
userId: userId!,
wallet: wallet!,
dispatch,
analytics,
reportToSentry
Expand Down Expand Up @@ -214,7 +207,7 @@ export const usePublishCollection = (
* taking the metadata from the playlist when the track is missing it.
*/
function combineMetadata(
userBank: string,
userId: number,
trackMetadata: TrackMetadataForUpload,
collectionMetadata: CollectionValues,
albumTrackPrice?: number
Expand Down Expand Up @@ -269,7 +262,7 @@ function combineMetadata(
usdc_purchase: { price: albumTrackPrice, splits: [] }
}
// Add splits to stream & download conditions
addPremiumMetadata(userBank, metadata)
addPremiumMetadata(userId, metadata)
}
return metadata
}
36 changes: 10 additions & 26 deletions packages/common/src/api/tan-query/upload/usePublishTracks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { USDC } from '@audius/fixed-decimal'
import { HashId, Id, type UploadResponse } from '@audius/sdk'
import { useMutation, useQueryClient } from '@tanstack/react-query'

Expand Down Expand Up @@ -29,7 +28,6 @@ type PublishTracksContext = Pick<
'audiusSdk' | 'analytics' | 'dispatch' | 'reportToSentry'
> & {
userId: number
wallet: string
kind?: 'tracks' | 'album' | 'playlist'
}

Expand All @@ -47,29 +45,22 @@ export const publishTracks = async (
) => {
const {
userId,
wallet,
kind,
audiusSdk,
dispatch,
reportToSentry,
analytics: { make, track }
} = context

if (!context.userId || !context.wallet) {
if (!context.userId) {
throw new Error('User ID and wallet are required to publish tracks')
}

const sdk = await audiusSdk()
const userBank = await sdk.services.claimableTokensClient.deriveUserBank({
ethWallet: wallet,
mint: 'USDC'
})

return await Promise.all(
params.map(async (param) => {
const snakeMetadata = addPremiumMetadata(
userBank.toString(),
param.metadata
)
const snakeMetadata = addPremiumMetadata(userId, param.metadata)

const trackId = await sdk.tracks.generateTrackId()
const camelMetadata = trackMetadataForUploadToSdk({
Expand Down Expand Up @@ -191,15 +182,13 @@ export const usePublishTracks = (
const { data: account } = useCurrentAccount()
const { data: accountUser } = useCurrentAccountUser()
const userId = account?.userId ?? undefined
const wallet = account?.walletAddresses.currentUser ?? undefined
const kind = options?.kind ?? 'tracks'

return useMutation({
...options,
...getPublishTracksOptions({
...queryContext,
userId: userId!,
wallet: wallet!,
kind
}),
onSuccess: async (data) => {
Expand Down Expand Up @@ -235,11 +224,10 @@ export const usePublishTracks = (
* returns updated conditions with price in WEI and splits in the new array format.
*/
export function getUSDCMetadata(
userBank: string,
userId: number,
stream_conditions: USDCPurchaseConditions
): USDCPurchaseConditions {
const priceCents = stream_conditions.usdc_purchase.price
const priceWei = Number(USDC(priceCents / 100).value.toString())
return {
usdc_purchase: {
price: priceCents,
Expand All @@ -248,9 +236,8 @@ export function getUSDCMetadata(
}),
splits: [
{
payout_wallet: userBank?.toString() ?? '',
percentage: 100,
amount: priceWei
user_id: userId,
percentage: 100
}
]
}
Expand All @@ -262,24 +249,21 @@ export function getUSDCMetadata(
* Converts prices to WEI and adds splits for USDC purchasable content.
*/
export function addPremiumMetadata<T extends TrackMetadataForUpload>(
userBank: string,
userId: number,
track: T
) {
// download_conditions could be set separately from stream_conditions, so we check for them first
if (isContentUSDCPurchaseGated(track.download_conditions)) {
track.download_conditions = getUSDCMetadata(
userBank,
userId,
track.download_conditions
)
}

if (isContentUSDCPurchaseGated(track.stream_conditions)) {
track.stream_conditions = getUSDCMetadata(userBank, track.stream_conditions)
track.stream_conditions = getUSDCMetadata(userId, track.stream_conditions)
// If stream_conditions are set, download_conditions should always match
track.download_conditions = getUSDCMetadata(
userBank,
track.stream_conditions
)
track.download_conditions = getUSDCMetadata(userId, track.stream_conditions)
}

return track
Expand Down
6 changes: 3 additions & 3 deletions packages/common/src/models/Track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ export type NftGatedConditions = {

/** Single split in USDC purchase conditions (matches API extended_payment_split). */
export type PaymentSplit = {
user_id?: number
user_id: number
percentage: number
payout_wallet: string
amount: number
payout_wallet?: string
amount?: number
eth_wallet?: string
}

Expand Down
6 changes: 3 additions & 3 deletions packages/common/src/schemas/upload/uploadFormSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ const TokenGatedConditionsSchema = z

/** Same as API extended_payment_split (snake-cased) */
const PaymentSplitSchema = z.object({
user_id: z.optional(z.number()),
user_id: z.number(),
percentage: z.number().min(0).max(100),
payout_wallet: z.string(),
amount: z.number().nonnegative(),
payout_wallet: z.string().optional(),
amount: z.number().nonnegative().optional(),
eth_wallet: z.optional(z.string())
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ models/NftGate.ts
models/Notification.ts
models/Notifications.ts
models/NotificationsResponse.ts
models/PaymentSplit.ts
models/PinCommentRequestBody.ts
models/Playlist.ts
models/PlaylistAddedTimestamp.ts
Expand Down
14 changes: 2 additions & 12 deletions packages/sdk/src/sdk/api/generated/default/models/AccessGate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ import {
FollowGateFromJSONTyped,
FollowGateToJSON,
} from './FollowGate';
import {
NftGate,
instanceOfNftGate,
NftGateFromJSON,
NftGateFromJSONTyped,
NftGateToJSON,
} from './NftGate';
import {
PurchaseGate,
instanceOfPurchaseGate,
Expand Down Expand Up @@ -54,7 +47,7 @@ import {
*
* @export
*/
export type AccessGate = FollowGate | NftGate | PurchaseGate | TipGate | TokenGate;
export type AccessGate = FollowGate | PurchaseGate | TipGate | TokenGate;

export function AccessGateFromJSON(json: any): AccessGate {
return AccessGateFromJSONTyped(json, false);
Expand All @@ -64,7 +57,7 @@ export function AccessGateFromJSONTyped(json: any, ignoreDiscriminator: boolean)
if ((json === undefined) || (json === null)) {
return json;
}
return { ...FollowGateFromJSONTyped(json, true), ...NftGateFromJSONTyped(json, true), ...PurchaseGateFromJSONTyped(json, true), ...TipGateFromJSONTyped(json, true), ...TokenGateFromJSONTyped(json, true) };
return { ...FollowGateFromJSONTyped(json, true), ...PurchaseGateFromJSONTyped(json, true), ...TipGateFromJSONTyped(json, true), ...TokenGateFromJSONTyped(json, true) };
}

export function AccessGateToJSON(value?: AccessGate | null): any {
Expand All @@ -78,9 +71,6 @@ export function AccessGateToJSON(value?: AccessGate | null): any {
if (instanceOfFollowGate(value)) {
return FollowGateToJSON(value as FollowGate);
}
if (instanceOfNftGate(value)) {
return NftGateToJSON(value as NftGate);
}
if (instanceOfPurchaseGate(value)) {
return PurchaseGateToJSON(value as PurchaseGate);
}
Expand Down
Loading
Loading