Create skeleton of buyLeaderboardSlot cloud function.
This commit is contained in:
		
							parent
							
								
									17b9ccae83
								
							
						
					
					
						commit
						de562799f4
					
				
							
								
								
									
										84
									
								
								functions/src/buy-leaderboard-slot.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								functions/src/buy-leaderboard-slot.tsx
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,84 @@
 | 
			
		|||
import * as functions from 'firebase-functions'
 | 
			
		||||
import * as admin from 'firebase-admin'
 | 
			
		||||
 | 
			
		||||
import { User } from '../../common/user'
 | 
			
		||||
 | 
			
		||||
export const buyLeaderboardSlot = functions
 | 
			
		||||
  .runWith({ minInstances: 1 })
 | 
			
		||||
  .https.onCall(
 | 
			
		||||
    async (
 | 
			
		||||
      data: {
 | 
			
		||||
        slotId: string
 | 
			
		||||
        reassessValue: number
 | 
			
		||||
      },
 | 
			
		||||
      context
 | 
			
		||||
    ) => {
 | 
			
		||||
      const userId = context?.auth?.uid
 | 
			
		||||
      if (!userId) return { status: 'error', message: 'Not authorized' }
 | 
			
		||||
 | 
			
		||||
      // Run as transaction to prevent race conditions.
 | 
			
		||||
      return await firestore.runTransaction(async (transaction) => {
 | 
			
		||||
        const userDoc = firestore.doc(`users/${userId}`)
 | 
			
		||||
        const userSnap = await transaction.get(userDoc)
 | 
			
		||||
        if (!userSnap.exists)
 | 
			
		||||
          return { status: 'error', message: 'User not found' }
 | 
			
		||||
        const user = userSnap.data() as User
 | 
			
		||||
 | 
			
		||||
        const { slotId, reassessValue } = data
 | 
			
		||||
 | 
			
		||||
        // TODO: find most recent purchase of slotId.
 | 
			
		||||
        // Fake data below:
 | 
			
		||||
        const prevSlotPurchase = {
 | 
			
		||||
          id: slotId,
 | 
			
		||||
          reassessValue: 100,
 | 
			
		||||
          userId: '',
 | 
			
		||||
          timestamp: 0,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (prevSlotPurchase) {
 | 
			
		||||
          const prevSlotUserDoc = firestore.doc(
 | 
			
		||||
            `users/${prevSlotPurchase.userId}`
 | 
			
		||||
          )
 | 
			
		||||
          const prevSlotUserSnap = await transaction.get(prevSlotUserDoc)
 | 
			
		||||
          if (!prevSlotUserSnap.exists)
 | 
			
		||||
            return { status: 'error', message: 'Previous slot owner not found' }
 | 
			
		||||
          const prevSlotUser = prevSlotUserSnap.data() as User
 | 
			
		||||
 | 
			
		||||
          const timeSinceLastPurchase = Date.now() - prevSlotPurchase.timestamp
 | 
			
		||||
          const hoursSinceLastPurchase =
 | 
			
		||||
            timeSinceLastPurchase / (1000 * 60 * 60)
 | 
			
		||||
 | 
			
		||||
          const harbergerTax =
 | 
			
		||||
            prevSlotPurchase.reassessValue * 0.1 * hoursSinceLastPurchase
 | 
			
		||||
          const prevSlotUserBalance = prevSlotUser.balance - harbergerTax
 | 
			
		||||
          if (!isFinite(prevSlotUserBalance)) {
 | 
			
		||||
            throw new Error(
 | 
			
		||||
              'Invalid user balance for previous slot owner ' +
 | 
			
		||||
                prevSlotUser.username
 | 
			
		||||
            )
 | 
			
		||||
          }
 | 
			
		||||
          transaction.update(prevSlotUserDoc, { balance: prevSlotUserBalance })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: If no prevSlotPurchase, use a default purchase price?
 | 
			
		||||
        const newBalance = user.balance - prevSlotPurchase.reassessValue
 | 
			
		||||
        if (!isFinite(newBalance)) {
 | 
			
		||||
          throw new Error('Invalid user balance for ' + user.username)
 | 
			
		||||
        }
 | 
			
		||||
        transaction.update(userDoc, { balance: newBalance })
 | 
			
		||||
 | 
			
		||||
        const newSlotPurchase = {
 | 
			
		||||
          id: slotId,
 | 
			
		||||
          reassessValue,
 | 
			
		||||
          userId,
 | 
			
		||||
          timestamp: Date.now(),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: save doc newSlotPurchase in some collection.
 | 
			
		||||
 | 
			
		||||
        return { status: 'success', slotPurchase: newSlotPurchase }
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
const firestore = admin.firestore()
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user