Rafflebay: Building a lottery-based commerce-system for iOS. 
Published: 2020-05-20 06:38:42

As a graduating senior in the #Classof2020, I want to share one of my proudest projects over the course of my undergrad at UCLA. 

UCLA's computer science capstone course required teams of five to design, develop, and pitch technical projects with complete creative freedom. My team and I developed an iOS mobile application called *Rafflebay* which had the high-level goal to "gamify" online peer-to-peer shopping. 

![Rafflebay Splashscreen](https://dev-to-uploads.s3.amazonaws.com/i/cuiv0p0bmp7pz0wqj4qu.png)

People love shopping, discounts, and probability-based games (such as the lottery, sports betting, etc.). So, we combined these ideas to create an e-commerce system that encouraged users to purchase "raffle tickets" for a chance of winning that item at a large discount. These tickets were sold at a fraction of the item's price, where the price of each ticket divided by the item's expected value was equivalent to the percentage chance of winning that item. 

`For example, if Joe wanted to sell a pair of headphones for $100, he could sell ten $10 raffle tickets on our platform. Then users purchase tickets for $10 each until all the tickets are sold. At that point, a single winner is randomly drawn, and that user wins the item at a discounted price. Additionally, Joe is happy to receive the entire $100 that he wanted to get for his pair of headphones.`

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/kfm8qfsl99znxsvarf0t.png)

*Rafflebay Features:* 
 - Secure Login & Authentication: Our application implements a fully-secure authentication solution that utilizes a session-based approach via authentication tokens. All user information is securely stored in our AWS EC2 instance and all passwords are stored in hashed and salted form.


 - Reverse Chronological Item Feed: Rafflebay implements a reverse-chronological feed of available items to bid on. This ensures that every user is able to see the most recent items listed and have the best chance of winning items as soon as the tickets are available to buy. Other implementations would be to display closest-to-expiry (ie. chronological order), however, we decided against this due to the fact that many new items would get hidden and not encourage the high-transaction rates we wanted within our app. 

 - Item Ticket Purchasing & Bidding: A user is able to bid on every item listed on our application, minus their own items. Upon clicking on an item in the feed, a detailed description appears on the item which includes information about the expiration date of the raffle, ticket price, number of tickets remaining, item name, item description, and a photo of the item. Additionally, on this page, the user is able to purchase any number of tickets they desire, up to the amount remaining. Upon purchasing these tickets, the user is redirected to a confirmation page once the transaction is verified and the tickets have been added to the user’s account.

 - Email Notifications (via SendGrid): In order to ensure our users know immediately when they have won an item, we implemented email notifications via SendGrid. When item raffles randomly draw a winner, an email is sent out to the user notifying them of the item they won and the tracking information for that item. 

 - Tracking Information & Shipping Labels (via EasyPost): To keep our e-commerce site as simple as possible for our users, we wanted users to know the transit status of their won items. By utilizing EasyPost, our application generates shipping labels for sellers to attach to their packages. We then give the winner the tracking information of that label within the email notification. This additionally allows us to maintain separation of concern between buyers and sellers, removing the need for any communication or unnecessary confusion on shipping status.

 - Payment Processing (via Stripe): In order to manage funds, we utilized Stripe’s API to fund individual accounts. We do not expose any Complete Payment endpoints to the application or the user, instead of requiring Stripe to tell us directly when the payment is completed. We check the signature of Stripe’s request using our secret key, and mark the payment object as completed, ensuring no duplicate account crediting is made. Accounts must have the required balance prior to purchasing tickets for items.

 - Truly Random Winner Selection: A technical feature we implemented was a truly random winner selection. When a user purchases a ticket, the mobile device gathers entropy from the CPU clock via Swift’s Security framework. Using that information, we generate a 32bit that is sent along with the bid request to the server. Each bid performs this unique calculation on every device that purchases a ticket and our server aggregates all these numbers to truly select a random winner.

Throughout the development of Rafflebay, we utilized Agile Scrum to keep our development efforts on track with sprints lasting one week. We split ourselves between frontend and backend development with one individual also being the project manager & scrum master. We also aimed to utilize best practices through specific design patterns (such as observer, mediator, and proxy patterns) and kept a strict git workflow with code reviews and CI tests. At the end of the quarter, we pitched a production-grade deployed application with a live demonstration. All five of us were extremely proud of the final product we created in just 10 weeks. (We even received the most votes of all the capstone projects in the entire class!) 

_We uploaded a video of our application here! Check it out and see a working demo of what we made: https://www.youtube.com/watch?v=LUPsoCJiJBA&feature=emb_title_

Our technical stack included the following: 

- Frontend: 
  - iOS Swift
  - SwiftUI
  - CocoaPods (Alamofire, SwiftyJSON)

- Backend: 
  - NodeJS
  - Docker
  - PostgreSQL
  - Firebase (Static Image Store)
  - AWS EC2 Instance (Backend Deployment) 

- APIs: 
  - Stripe (Payment Management)
  - SendGrid (Email Notifications)
  - EasyPost (Shipping Label Creation & Tracking)