Advertisement
orpheusmercury

ml wallet api

Jan 17th, 2018
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 113.06 KB | None | 0 0
  1.  
  2.  
  3. #import "MLWalletAPI.h"
  4. #import "MLWalletEvent.h"
  5.  
  6. #import "MLWalletAcquisitionSource.h"
  7. #import "MLWalletAcquisition.h"
  8.  
  9. #import "MLPayoutRecipient.h"
  10.  
  11. #import "MLHALClient.h"
  12. #import "MLApplication.h"
  13. #import "MLPurchase.h"
  14. #import "NSString+URLEncode.h"
  15. #import <PromiseKit/PromiseKit.h>
  16. #import "UIActionSheet+AnyPromise.h"
  17.  
  18. #import "Stripe.h"
  19. #import "MLSubledgerParser.h"
  20. #import "MLSubscriptionTier.h"
  21. #import "MLSubscriptionPlan.h"
  22.  
  23. #import "MLSubscription.h"
  24.  
  25. #import "MLNavigationStackController.h"
  26. #import "MLRootNavigationController.h"
  27.  
  28. #import "MLStripePaymentModel.h"
  29.  
  30. #import "MLGiftManager.h"
  31.  
  32. #import "PMKUIKit.h"
  33. #import "MLInAppPurchaseManager.h"
  34.  
  35. #import "NSString+MD5.h"
  36.  
  37. #import "NSData+MD5.h"
  38.  
  39. #import "MLPayoutRequest.h"
  40.  
  41. #import "NSDecimalNumber+Modulo.h"
  42.  
  43. #import "MLGift.h"
  44.  
  45. #import "UIAlertView+AnyPromise.h"
  46.  
  47. #import <AudioToolbox/AudioServices.h>
  48.  
  49. #import "MLSoundEffects.h"
  50.  
  51. #import "MLLeaderBoardEntry.h"
  52.  
  53. @interface MLWalletAPI()
  54.  
  55. @property (nonatomic, strong) NSMutableArray * subscriptionTiers;
  56. @property (nonatomic, strong) NSMutableDictionary * subscriptions;
  57.  
  58. @end
  59.  
  60. @implementation MLWalletAPI
  61.  
  62.  
  63. #pragma mark -
  64. #pragma mark API interface
  65.  
  66. +(void)setSubscriptionPlanForChannel:(MLChannel*)channel withTier:(MLSubscriptionTier*)tier{
  67.  
  68. //channels' subscriptionTiers should also be populated during fetch
  69. channel.subscriptionTier = tier;
  70.  
  71. [self getCurrentUserWalletsWithCompletion:^(NSError *error, NSArray *wallets) {
  72.  
  73. if(!error){
  74.  
  75. MLWallet * currentUserWallet = [wallets firstObject];
  76.  
  77. [self getSubscriptionPlanForChannel:channel withCompletion:^(NSError *error, MLSubscriptionPlan *subscriptionPlan) {
  78.  
  79. if(!error && subscriptionPlan){
  80.  
  81. MLLog(@"Subscription plan already exists - update tier?");
  82.  
  83. }
  84. else{
  85.  
  86.  
  87. MLSubscriptionPlan * p = [MLSubscriptionPlan planForChannel:channel withTier:tier];
  88.  
  89. [[self sharedInstance] performRequestWithPath:[NSString stringWithFormat:@"%@/subscription_plans", currentUserWallet.objectId] andMethod:@"POST" andJSONDictionary:p.jsonDictionary andCompletion:^(NSError *error, id jsonDict) {
  90.  
  91. if(!error){
  92. MLLog(@"setSubscriptionPlanForChannel %@: No error", channel.objectId);
  93. }
  94. else{
  95. MLLog(@"setSubscriptionPlanForChannel %@: Error! %@", channel.objectId, error);
  96. }
  97.  
  98. }];
  99.  
  100.  
  101.  
  102. }
  103.  
  104.  
  105. }];
  106.  
  107. }
  108. else{
  109. [MLHelper showTempAlertWithString:@"Could not fetch wallet for plan"];
  110. }
  111.  
  112. }];
  113.  
  114. }
  115.  
  116. +(AnyPromise*)promiseSubscriptionPlanForChannel:(MLChannel*)channel{
  117.  
  118. return [AnyPromise promiseWithResolverBlock:^(PMKResolver _Nonnull resolve) {
  119. [self getSubscriptionPlanForChannel:channel withCompletion:^(NSError *error, MLSubscriptionPlan *subscriptionPlan) {
  120. if(!error){
  121. resolve(subscriptionPlan);
  122. }
  123. else{
  124. resolve(error);
  125. }
  126. }];
  127. }];
  128.  
  129. }
  130.  
  131. +(void)getSubscriptionPlanForChannel:(MLChannel*)channel withCompletion:(MLSubscriptionPlanCompletionBlock)completion{
  132.  
  133. MLLog(@"MLWalletAPI get subscription plan for channel %@", channel.objectId);
  134. //get author's wallet
  135.  
  136. [self getWalletWithLabel:channel.author.username withCompletion:^(NSError *error, MLWallet *wallet) {
  137.  
  138. if(!error){
  139. MLLog(@"getSubscriptionPlanForChannel: success fetching wallet for user %@", channel.author.username);
  140.  
  141. //get subscription plans from wallet
  142. [self getSubscriptionPlansFromWallet:wallet withCompletion:^(NSError *error, NSArray *subscriptionPlans) {
  143. if(!error){
  144. MLLog(@"getSubscriptionPlanForChannel: success getting subscriptionPlans for wallet %@", wallet.objectId);
  145. //match channel id
  146.  
  147.  
  148. MLSubscriptionPlan * planForChannel = nil;
  149. for(MLSubscriptionPlan * sp in subscriptionPlans){
  150.  
  151. if([sp.channelUrl isEqualToString:channel.objectId]){
  152. MLLog(@"getSubscriptionPlanForChannel Found a matching channel in subscription plans %@", channel.objectId);
  153. planForChannel = sp;
  154. }
  155.  
  156. }
  157.  
  158. if(!planForChannel){
  159. MLLog(@"getSubscriptionPlanForChannel did not find matching subscription plan");
  160. }
  161.  
  162. completion(error, planForChannel);
  163.  
  164.  
  165. }
  166. else{
  167.  
  168. completion(error, nil);
  169.  
  170. MLLog(@"getSubscriptionPlanForChannel: Error getting subscriptionPlans for wallet %@ %@", wallet.objectId, error);
  171. }
  172. }];
  173.  
  174. }
  175. else{
  176.  
  177. completion(error, nil);
  178. MLLog(@"getSubscriptionPlanForChannel: Error fetching wallet for user %@ %@", channel.author.username, error);
  179. }
  180.  
  181. }];
  182.  
  183.  
  184.  
  185.  
  186. //return plan with correct id
  187.  
  188. }
  189.  
  190. +(void)getSubscriptionStatusForChannels:(NSArray *)channels withCompletion:(MLSubscriptionStatusCompletionBlock)completion{
  191.  
  192.  
  193. NSLog(@"Get subscription status for channels");
  194.  
  195. [self checkForCurrentUserPaymentMethodsAndCustomerId:^(NSError *error, MLWallet *wallet, BOOL hasPaymentMethod, BOOL hasStripeCustomerId) {
  196.  
  197. if(!error){
  198. [self getSubscriptionsFromWallet:wallet withCompletion:^(NSError *error, NSArray *subscriptions) {
  199. //this should be enough for us to tell if a user is subscribed
  200.  
  201. MLLog(@"getSubscriptionsFromWallet completion in getSubscriptionStatusForChannels error: %@", error);
  202. completion(error);
  203. }];
  204.  
  205. }
  206. else{
  207. completion(error);
  208. }
  209.  
  210. }];
  211.  
  212. }
  213.  
  214.  
  215.  
  216. + (void) populateSubscriptionTierForChannel: (MLChannel *) channel withCompletion: (MLSingleSubscriptionTierCompletionBlock) completion {
  217. [self getSubscriptionPlanForChannel:channel withCompletion:^(NSError *error, MLSubscriptionPlan *subscriptionPlan) {
  218.  
  219. if(!error){
  220.  
  221.  
  222. [self getSubscriptionTiersWithCompletion:^(NSError *error, NSArray *subscriptionTiers) {
  223.  
  224. if(!error){
  225.  
  226. MLSubscriptionTier * correctTier = nil;
  227.  
  228. for(MLSubscriptionTier * t in subscriptionTiers){
  229.  
  230. if([t.objectId.lastPathComponent intValue] == subscriptionPlan.subscriptionTierId){
  231.  
  232. correctTier = t;
  233. }
  234.  
  235. }
  236.  
  237. channel.subscriptionTier = correctTier;
  238.  
  239. completion(error, channel.subscriptionTier);
  240.  
  241.  
  242. }
  243. else{
  244. completion(error, nil);
  245.  
  246. }
  247.  
  248. }];
  249. //subscriptionPlan.subscriptionTierId
  250. //calculate subscription price
  251.  
  252.  
  253.  
  254.  
  255. }
  256. else{
  257. //error getting subscription plan for channel
  258. completion(error, nil);
  259. }
  260.  
  261.  
  262. }];
  263. }
  264.  
  265.  
  266. +(void)checkIfCurrentUserHasPurchasedChannel:(MLChannel*)channel withCompletion:(MLCurrentUserHasPurchasedChannelCompletionBlock)completion{
  267.  
  268.  
  269. if(channel.currentUserHasPurchased){
  270. completion(nil, YES);
  271. return;
  272. }
  273.  
  274. if([channel.author isCurrentUser]){
  275. completion(nil, YES);
  276. return;
  277. }
  278.  
  279. NSLog(@"MLWalletAPI checkIfCurrentHasPurchasedChannel - needs to query for payment plans / methods etc.%@", channel.objectId);
  280.  
  281. //if we don't have the subscription info on hand - this should only fire if a subscription is new and/or the first time?
  282.  
  283. [self getCurrentUserWalletsWithCompletion:^(NSError *error, NSArray *wallets) {
  284.  
  285. if(!error){
  286.  
  287. //current user wallet
  288. MLWallet * w = [wallets objectAtIndex:0];
  289.  
  290. [self getWalletEventsForWallet:w withCompletion:^(NSError *error, NSMutableArray *walletEvents) {
  291.  
  292.  
  293. NSLog(@"MLWalletAPI checkIfCurrentHasPurchasedChannel %@ after gettingWalletEvents %i", channel.objectId, [walletEvents count]);
  294.  
  295.  
  296. if(!error){
  297.  
  298. BOOL hasPurchased = NO;
  299.  
  300. //find paywall purchase event with object id
  301. for(MLWalletEvent * e in walletEvents){
  302.  
  303. NSLog(@"Checking wallet event %@ withType %i item.objectId %@", e.objectId, e.type, e.item.objectId);
  304.  
  305. if(e.type == MLWalletEventTypePaywallPurchase && [e.item.objectId isEqualToString:channel.objectId]){
  306.  
  307. NSLog(@"Found a matching WalletDeal for channel %@", e.item.objectId);
  308.  
  309. hasPurchased = YES;
  310. channel.currentUserHasPurchased = YES;
  311. }
  312. }
  313.  
  314. channel.currentUserHasPurchased = hasPurchased;
  315.  
  316. completion(error, hasPurchased);
  317.  
  318. }
  319. else{
  320.  
  321. NSLog(@"MLWalletAPI checkIfCurrentHasPurchasedChannel %@ error getting wallet events %@", channel.objectId, error);
  322.  
  323. completion(error, nil);
  324. }
  325.  
  326. }];
  327.  
  328. }
  329. else{
  330.  
  331. NSLog(@"MLWalletAPI checkIfCurrentHasPurchasedChannel %@ error getting wallet %@", channel.objectId, error);
  332.  
  333. //error finding wallet
  334. completion(error, nil);
  335. }
  336.  
  337.  
  338. }];
  339.  
  340.  
  341.  
  342. }
  343.  
  344.  
  345. +(void)checkIfCurrentUserSubscribesToChannel:(MLChannel*)channel withCompletion:(MLCurrentUserSubscribesToChannelCompletionBlock)completion{
  346.  
  347. completion(nil, NO, nil);
  348. return;
  349.  
  350. if([self currentUserSubscribesToChannel:channel]){
  351. completion(nil, YES, nil);
  352. return;
  353. }
  354.  
  355.  
  356. MLLog(@"MLWalletAPI checkIfCurrentUserSubscribesToChannel - needs to query for payment plans / methods etc.%@", channel.objectId);
  357.  
  358. //if we don't have the subscription info on hand - this should only fire if a subscription is new and/or the first time?
  359.  
  360. [self checkForCurrentUserPaymentMethodsAndCustomerId:^(NSError *error, MLWallet *wallet, BOOL hasPaymentMethod, BOOL hasStripeCustomerId) {
  361.  
  362. if(!error){
  363. [self getSubscriptionsFromWallet:wallet withCompletion:^(NSError *error, NSArray *subscriptions) {
  364.  
  365. MLLog(@"getSubscriptionsFromWallet completion in checkIfCurrentUserSubscribesToChannel error: %@", error);
  366.  
  367. if(!error){
  368.  
  369. BOOL subscribes = NO;
  370.  
  371. MLLog(@"No error getting subscriptions %i", [subscriptions count]);
  372.  
  373. if([self currentUserSubscribesToChannel:channel]){
  374. subscribes = YES;
  375. completion(error, subscribes, nil);
  376. }
  377. else{
  378.  
  379. MLLog(@"Doesnt subscribe to channel - get subscription tier to pass back to prompt user for signing up");
  380. [self getSubscriptionPlanForChannel:channel withCompletion:^(NSError *error, MLSubscriptionPlan *subscriptionPlan) {
  381.  
  382. if(!error){
  383.  
  384.  
  385. [self getSubscriptionTiersWithCompletion:^(NSError *error, NSArray *subscriptionTiers) {
  386.  
  387. if(!error){
  388.  
  389. MLSubscriptionTier * correctTier = nil;
  390.  
  391. for(MLSubscriptionTier * t in subscriptionTiers){
  392.  
  393. if([t.objectId.lastPathComponent intValue] == subscriptionPlan.subscriptionTierId){
  394.  
  395. correctTier = t;
  396. }
  397.  
  398. }
  399.  
  400. channel.subscriptionTier = correctTier;
  401.  
  402. completion(error, NO, correctTier);
  403.  
  404.  
  405. }
  406. else{
  407. completion(error, NO, NO);
  408.  
  409. }
  410.  
  411. }];
  412. //subscriptionPlan.subscriptionTierId
  413. //calculate subscription price
  414.  
  415.  
  416.  
  417.  
  418. }
  419. else{
  420. //error getting subscription plan for channel
  421. completion(error, NO, nil);
  422. }
  423.  
  424.  
  425. }];
  426. }
  427. }
  428. else{
  429.  
  430. completion(error, NO, nil);
  431. }
  432.  
  433. }];
  434. }
  435. else{
  436. completion(error, NO, nil);
  437. }
  438.  
  439. }];
  440.  
  441.  
  442. }
  443.  
  444. -(void)setupSubscriptions{
  445.  
  446. if(!self.subscriptions){
  447. self.subscriptions = [NSMutableDictionary new];
  448. }
  449.  
  450. }
  451.  
  452. -(void)setSubscription:(MLSubscription*)sub forChannelId:(NSString*)string{
  453.  
  454. [self setupSubscriptions];
  455.  
  456. if(![self.subscriptions objectForKey:string]){
  457. [self.subscriptions setObject:sub forKey:string];
  458. }
  459.  
  460. }
  461.  
  462. -(BOOL)hasSubscriptionForChannelWithId:(NSString*)string{
  463.  
  464. //NSLog(@"MLWalletAPI: hasSubscriptionForChannelWithId: %@", string);
  465. //NSLog(@"MLWalletAPI: subscribesToChannelWithId: %@", string);
  466.  
  467. if([self.subscriptions objectForKey:string]){
  468.  
  469. MLLog(@"Found %@ in dictionary", string);
  470. return YES;
  471. }
  472. else{
  473.  
  474. //MLLog(@"MLWalletAPI: did not find string: %@ in dictionary keys %@", string, [self.subscriptions allKeys]);
  475. return NO;
  476. }
  477.  
  478.  
  479. }
  480.  
  481. +(BOOL)currentUserSubscribesToChannel:(MLChannel *)channel{
  482.  
  483. //MLLog(@"current user subscribes to channel - synchronous approach");
  484.  
  485. if([channel.author.objectId isEqualToString:[[MLUser currentUser] objectId]]){
  486. return YES;
  487. }
  488. else{
  489. return [[self sharedInstance] hasSubscriptionForChannelWithId:channel.objectId];
  490. }
  491.  
  492. }
  493.  
  494. +(AnyPromise*)promiseChannelInfoForSubscription:(MLSubscription*)sub{
  495.  
  496. return [AnyPromise promiseWithResolverBlock:^(PMKResolver _Nonnull resolve) {
  497.  
  498. NSLog(@"Promise Channel Infor For Subscription");
  499. [self fetchChannelInfoForSubscription:sub withCompletion:^(NSError *error, id result) {
  500.  
  501. if(!error){
  502. resolve((MLSubscription *)result);
  503. }
  504. else{
  505. resolve(error);
  506. }
  507.  
  508. }];
  509.  
  510. }];
  511.  
  512. }
  513.  
  514. +(AnyPromise*)subscribedChannelsForUser:(MLUser*)user{
  515.  
  516. NSLog(@"promise subscribedChannelsForUser");
  517.  
  518. return [AnyPromise promiseWithResolverBlock:^(PMKResolver _Nonnull resolve) {
  519.  
  520. [self getSubscribedChannelsForUser:user withCompletion:^(NSError *error, NSArray *results) {
  521. resolve(error ?: results);
  522. }];
  523.  
  524. }];
  525.  
  526. }
  527.  
  528. +(void)getSubscribedChannelsForUser:(MLUser *)user withCompletion:(MLResultsErrorCompletionBlock)completion{
  529.  
  530. NSLog(@"getSubscribedChannelsForUser");
  531.  
  532. [self getWalletWithLabel:user.username withCompletion:^(NSError *error, MLWallet *wallet) {
  533.  
  534.  
  535. if(!error){
  536. [self getSubscriptionsFromWallet:wallet withCompletion:^(NSError *error, NSArray *subscriptions) {
  537.  
  538.  
  539.  
  540. NSMutableArray * followedChannels = [NSMutableArray new];
  541. for(MLSubscription * s in subscriptions){
  542.  
  543. MLChannel * c = (MLChannel*)[MLChannel instanceFromId:s.channelObjectId];
  544. if(c){
  545. [followedChannels addObject:c];
  546. }
  547. else{
  548. MLLog(@"Nil channel from object cache - was assuming this would return an empty one");
  549. }
  550. }
  551.  
  552.  
  553. NSLog(@"Calling populate channels in getSubscribedChannelsForUser");
  554. [MLHALClient populateChannels:followedChannels].then(^(NSArray*channels){
  555. completion(nil, channels);
  556. }).catch(^(NSError * error){
  557. completion(error, nil);
  558. });
  559.  
  560. }];
  561. }
  562. else{
  563. completion(error, nil);
  564. }
  565. }];
  566.  
  567.  
  568.  
  569. }
  570.  
  571. +(void)fetchChannelInfoForSubscription:(MLSubscription*)sub withCompletion:(MLSingleResultErrorCompletionBlock)completion{
  572.  
  573. if(!sub.subscriptionPlanObjectId){
  574. completion(nil, sub);
  575. }
  576.  
  577. MLLog(@"Populating subscription %@ by fetching subscriptionPlanId", sub.subscriptionPlanObjectId);
  578.  
  579. [[self sharedInstance] performRequestWithPath:sub.subscriptionPlanObjectId andMethod:@"GET" andCompletion:^(NSError *error, id jsonDict) {
  580.  
  581.  
  582. MLLog(@"got subscription plan for channel %@", jsonDict);
  583.  
  584. MLSubscriptionPlan * sp = [MLSubscriptionPlan instanceFromJSON:jsonDict withObjectId:sub.subscriptionPlanObjectId];
  585.  
  586. sub.subscriptionPlan = sp;
  587.  
  588. sub.channelObjectId = [jsonDict objectForKey:@"channelUrl"];
  589.  
  590. [[self sharedInstance] setSubscription:sub forChannelId:sub.channelObjectId];
  591.  
  592. completion(error, sub);
  593.  
  594. }];
  595.  
  596. }
  597.  
  598. +(void)getSubscriptionsFromWallet:(MLWallet*)wallet withCompletion:(MLSubscriptionsCompletionBlock)completion{
  599.  
  600. NSLog(@"getSubscriptionsFromWallet");
  601.  
  602. [[self sharedInstance] setupSubscriptions];
  603.  
  604. //POST /wallets/{walletId}/subscription_plans
  605. [[self sharedInstance] performRequestWithPath:[NSString stringWithFormat:@"%@/subscriptions", wallet.objectId] andMethod:@"GET" andCompletion:^(NSError *error, id jsonDict) {
  606.  
  607. __block NSMutableArray * subscriptionResults = [NSMutableArray new];
  608.  
  609. if(!error){
  610.  
  611. MLLog(@"getSubscriptionsWithCompletion results %@", jsonDict);
  612.  
  613.  
  614. for(NSDictionary * d in jsonDict){
  615.  
  616. MLSubscription * s = [MLSubscription instanceFromJSON:[NSMutableDictionary dictionaryWithDictionary:d] withObjectId:[NSString stringWithFormat:@"%@/subscriptions/%@",[wallet objectId], [d valueForKey:@"id"]]];
  617.  
  618. [subscriptionResults addObject:s];
  619.  
  620.  
  621. MLLog(@"MLWalletAPI: just added subscription to subscription results %@", s.objectId);
  622.  
  623.  
  624. }
  625. }
  626. else{
  627. MLLog(@"MLWalletAPI: getSubscriptionsWithCompletion error %@", error);
  628. }
  629.  
  630. NSMutableDictionary * subPromises = [NSMutableDictionary new];
  631.  
  632. for(MLSubscription * s in subscriptionResults){
  633. if(s.subscriptionPlanObjectId && s.objectId){
  634. [subPromises setObject:[MLWalletAPI promiseChannelInfoForSubscription:s] forKey:s.objectId];
  635. }
  636. else{
  637. MLLog(@"MLWalletAPI: getSubscriptionsFromWallet ignoring subscription with no subplanid");
  638.  
  639. }
  640. }
  641.  
  642. MLLog(@"MLWalletAPI: getSubscriptionsFromWallet got %i subpromises", [[subPromises allKeys] count]);
  643.  
  644.  
  645. PMKWhen(subPromises).then(^(NSDictionary*results){
  646.  
  647. MLLog(@"MLWalletAPI: getSubscriptionsFromWallet callback in PMKWhen %@", [results allKeys]);
  648.  
  649. NSMutableArray * outputResults = [NSMutableArray new];
  650.  
  651.  
  652. for(MLSubscription * s in subscriptionResults){
  653.  
  654. if(s.subscriptionPlanObjectId){
  655.  
  656. MLLog(@"object for key is of class %@", [[results objectForKey:s.objectId] class]);
  657.  
  658. MLSubscription * populatedSub = [results objectForKey:s.objectId];
  659.  
  660. MLLog(@"Adding subscription after promises %@ subPlanId %@ channelObjectId %@", s.objectId, s.subscriptionPlan.objectId, s.channelObjectId);
  661. if(populatedSub){
  662. [outputResults addObject:populatedSub];
  663. }
  664. else{
  665. MLLog(@"Nil subscription from populated subscriptions?");
  666. }
  667.  
  668. }
  669. else{
  670. MLLog(@"MLWalletAPI: ignoring subscription without subscriptionPlanObjectId after promises %@", s.objectId);
  671.  
  672.  
  673. }
  674.  
  675. }
  676.  
  677. MLLog(@"MLWalletAPI: completed loading subscriptions from wallet");
  678.  
  679. completion(error, outputResults);
  680.  
  681. });
  682.  
  683.  
  684. }];
  685.  
  686. }
  687.  
  688. +(void)checkForCurrentUserPaymentMethodsAndCustomerId:(MLWalletCheckForPaymentMethodsAndCustomerIdCompletionBlock)completion{
  689.  
  690. [self getCurrentUserWalletsWithCompletion:^(NSError *error, NSArray *wallets) {
  691.  
  692. if(!error){
  693.  
  694. __block MLWallet * currentUserWallet = [wallets firstObject];
  695.  
  696. MLLog(@"Got wallet %@ with stripeCustomerId %@", currentUserWallet.objectId, currentUserWallet.stripeCustomerId);
  697.  
  698.  
  699. __block BOOL hasCustomerID = YES;
  700. if(!currentUserWallet.stripeCustomerId || currentUserWallet.stripeCustomerId.length == 0){
  701. hasCustomerID = NO;
  702. }
  703.  
  704. [self getPaymentMethodsForWallet:currentUserWallet withCompletion:^(NSError *error, MLPaymentMethod *paymentMethod) {
  705.  
  706. BOOL hasPaymentMethod = paymentMethod ? YES : NO;
  707.  
  708. completion(error, currentUserWallet, hasPaymentMethod, hasCustomerID);
  709.  
  710. }];
  711.  
  712. }
  713. else{
  714. MLLog(@"subscribeToChannel: error getting current user wallet %@", error);
  715. completion(error, nil, NO, NO);
  716. }
  717.  
  718. }];
  719.  
  720. }
  721.  
  722. +(void)presentSubscriptionPromptForChannel:(MLChannel*)channel withCompletion:(MLBoolCompletionBlockWithError)completion{
  723.  
  724. [[self sharedInstance] presentSubscriptionPromptForChannel:channel withCompletion:completion];
  725.  
  726. }
  727.  
  728. -(void)presentSubscriptionPromptForChannel:(MLChannel*)channel withCompletion:(MLBoolCompletionBlockWithError)completion{
  729.  
  730. NSLog(@"presentSubscriptionPromptForChannelEntry pause");
  731.  
  732. MLLog(@"Does not subscribe so now we will make a subscription for a channel here %@", channel.objectId);
  733.  
  734. UIAlertView *alert = [UIAlertView new];
  735. int membershipPriceInCoins = channel.membershipPriceInBits;
  736. BOOL channelNameIsBlank = [MLHelper stringTrimmedOfWhiteSpace:channel.name].length < 1;
  737. NSString *title = channelNameIsBlank ? [NSString stringWithFormat:@"Unlock this post"] : [NSString stringWithFormat:@"Unlock '%@'", channel.name];
  738. title = [title stringByAppendingString:[NSString stringWithFormat:@" for %i %@?", membershipPriceInCoins, [MLHelper conditionallyPluralString:@"Coin" withCount:membershipPriceInCoins]]];
  739.  
  740. alert.title = title;
  741.  
  742.  
  743. [alert addButtonWithTitle:@"Not Now"];
  744. [alert addButtonWithTitle:@"Unlock"];
  745.  
  746.  
  747. [alert promise].then(^(NSNumber *dismissedButtonIndex){
  748. //…
  749. if(dismissedButtonIndex.intValue == 1){
  750.  
  751.  
  752. [MLWalletAPI purchaseChannel:channel withCompletion:^(NSError *error, BOOL success) {
  753. completion(YES, error);
  754.  
  755. }];
  756.  
  757.  
  758. }
  759. else{
  760.  
  761. completion(NO, nil);
  762. //[MLHelper showTempAlertWithString:@"Purchase cancelled."];
  763.  
  764. }
  765. });
  766.  
  767.  
  768. }
  769.  
  770.  
  771. +(void)subscribeToChannel:(MLChannel*)channel withCompletion:(MLSubscribeToChannelCompletionBlock)completion{
  772.  
  773. //registered customer_id and payment method in wallet before creating a subscription
  774.  
  775. NSLog(@"MLWalletAPI: subscribe to channel %@", channel.objectId);
  776.  
  777. [self checkForCurrentUserPaymentMethodsAndCustomerId:^(NSError *error, MLWallet *wallet, BOOL hasPaymentMethod, BOOL hasStripeCustomerId) {
  778.  
  779. if(!error){
  780.  
  781. if(!wallet || !hasPaymentMethod || !hasStripeCustomerId){
  782.  
  783. MLLog(@"subscribeToChannel: Something wrong with user payment setup %@ hasPaymentMethod:%@ hasStripeCustomerId:%@", wallet, hasPaymentMethod ? @"YES" : @"NO", hasStripeCustomerId ? @"YES" : @"NO");
  784. completion(error, NO);
  785.  
  786. }
  787.  
  788. MLWallet * currentUserWallet = wallet;
  789.  
  790. [self getSubscriptionPlanForChannel:channel withCompletion:^(NSError *error, MLSubscriptionPlan *subscriptionPlan) {
  791.  
  792. if(!error){
  793.  
  794. MLSubscription * s = [MLSubscription subscriptionForPlan:subscriptionPlan];
  795.  
  796. [[self sharedInstance] performRequestWithPath:[NSString stringWithFormat:@"%@/subscriptions", currentUserWallet.objectId] andMethod:@"POST" andJSONDictionary:s.jsonDictionary andCompletion:^(NSError *error, id jsonDict) {
  797.  
  798. if(!error){
  799.  
  800. [self getSubscriptionsFromWallet:wallet withCompletion:^(NSError *error, NSArray *subscriptionPlans) {
  801. completion(error, YES);
  802. MLLog(@"subscribeToChannel %@: No error", channel.objectId);
  803. }];
  804.  
  805.  
  806.  
  807. }
  808. else{
  809. completion(error, NO);
  810. MLLog(@"subscribeToChannel %@: Error! %@", channel.objectId, error);
  811. }
  812.  
  813. }];
  814.  
  815. }
  816. else{
  817. MLLog(@"subscribeToChannel %@: Error getting subsciption plan for channel %@", channel.objectId, error);
  818. completion(error, NO);
  819. }
  820.  
  821. }];
  822.  
  823. }
  824. else{
  825. MLLog(@"subscribeToChannel: error getting current user wallet %@", error);
  826. completion(error, NO);
  827. }
  828. }];
  829.  
  830.  
  831.  
  832. }
  833.  
  834. +(void)unsubscribeFromChannel:(MLChannel*)channel withCompletion:(MLErrorCompletionBlock)completion{
  835.  
  836. if(!channel.objectId){
  837. [MLHelper showTempAlertWithString:@"Channel doesnt have ID"];
  838. return;
  839. }
  840.  
  841.  
  842. [self getCurrentUserWalletsWithCompletion:^(NSError *error, NSArray *wallets) {
  843.  
  844. if(!error){
  845.  
  846. [self getSubscriptionsFromWallet:[wallets firstObject] withCompletion:^(NSError *error, NSArray *subscriptions) {
  847.  
  848. if(!error){
  849. MLSubscription * subForChannel;
  850.  
  851. for(MLSubscription * s in subscriptions){
  852.  
  853. NSLog(@"Compaing %@ to %@", s.channelObjectId, channel.objectId);
  854. if([s.channelObjectId isEqualToString:channel.objectId]){
  855. subForChannel = s;
  856. }
  857. }
  858.  
  859. if(subForChannel){
  860. [subForChannel deleteWithCompletion:^(NSError *error) {
  861. if(error){
  862. NSLog(@"Error deleting MLSubscription %@", error);
  863. }
  864. completion(error);
  865.  
  866. }];
  867. }
  868. }
  869. else{
  870. completion(error);
  871. }
  872.  
  873. }];
  874.  
  875. }
  876. else{
  877. [MLHelper showTempAlertWithString:@"Error getting your wallets - try again"];
  878. }
  879.  
  880.  
  881. }];
  882.  
  883.  
  884.  
  885. }
  886.  
  887.  
  888. +(void)getSubscriptionPlansFromWallet:(MLWallet*)wallet withCompletion:(MLSubscriptionPlansCompletionBlock)completion{
  889.  
  890. //POST /wallets/{walletId}/subscription_plans
  891. [[self sharedInstance] performRequestWithPath:[NSString stringWithFormat:@"%@/subscription_plans", wallet.objectId] andMethod:@"GET" andCompletion:^(NSError *error, id jsonDict) {
  892.  
  893. NSMutableArray * plans = [NSMutableArray new];
  894.  
  895. if(!error){
  896.  
  897. for(NSDictionary * d in jsonDict){
  898.  
  899. [plans addObject:[MLSubscriptionPlan instanceFromJSON:[NSMutableDictionary dictionaryWithDictionary:d] withObjectId:[NSString stringWithFormat:@"%@/subscription_plans/%@",[wallet objectId], [d valueForKey:@"id"]]]];
  900.  
  901. }
  902. MLLog(@"getSubscriptionPlansWithCompletion results %@", jsonDict);
  903. }
  904. else{
  905. MLLog(@"getSubscriptionPlansWithCompletion error %@", error);
  906. }
  907.  
  908. completion(error, plans);
  909.  
  910. }];
  911.  
  912. }
  913.  
  914. +(void)getSubscriptionTiersWithCompletion:(MLSubscriptionTiersCompletionBlock)completion{
  915.  
  916. NSLog(@"GET SUBSCRIPTION TIERS WITH COMPLETION");
  917.  
  918. [[self sharedInstance] performRequestWithPath:[NSString stringWithFormat:@"%@/subscription_tiers", kWalletServerAddress] andMethod:@"GET" andCompletion:^(NSError *error, id jsonDict) {
  919.  
  920. NSMutableArray * tiers = [NSMutableArray new];
  921.  
  922. if(!error){
  923.  
  924. for(NSDictionary * d in jsonDict){
  925.  
  926. [tiers addObject:[MLSubscriptionTier instanceFromJSON:[NSMutableDictionary dictionaryWithDictionary:d] withObjectId:[NSString stringWithFormat:@"%@/subscription_tiers/%@",kWalletServerAddress, [d valueForKey:@"id"]]]];
  927.  
  928. }
  929. MLLog(@"getSubscriptionTiersWithCompletion results %@", jsonDict);
  930. }
  931. else{
  932. MLLog(@"getSubscriptionTiersWithCompletion error %@", error);
  933. }
  934.  
  935. completion(error, tiers);
  936.  
  937. }];
  938.  
  939. }
  940.  
  941.  
  942. +(void)testWalletAPI{
  943.  
  944. [self getWalletsWithCompletion:^(NSError *error, NSArray *wallets) {
  945. MLLog(@"getWalletsWithCompletion: completion: error:%@ data:%@", error, wallets);
  946. }];
  947.  
  948. [self getWalletWithLabel:@"whittle" withCompletion:^(NSError *error, MLWallet *wallet) {
  949. if(!error){
  950. MLLog(@"getWalletsWithLabel:whitte completion: data:%@", wallet.objectId);
  951. }
  952. else{
  953. MLLog(@"getWalletsWithLabel:whitte completion: error:%@", error);
  954. }
  955. }];
  956.  
  957. MLWallet * testWallet;
  958. testWallet.label = @"testLabel";
  959.  
  960. MLWallet * knownWallet = [MLWallet new];
  961. knownWallet.objectId = [NSString stringWithFormat:@"%@/%@", kWalletServerAddress, @"wallets/1"];
  962.  
  963. [self getWallet:knownWallet withCompletion:^(NSError *error, MLWallet *wallet) {
  964. MLLog(@"getWallet:WithCompletion: completion: error:%@ data:%@", error, wallet);
  965.  
  966. [self getBalanceOfWallet:knownWallet withCompletion:^(NSError *error, NSDecimalNumber * balance) {
  967. MLLog(@"getBalanceOfWallet:WithCompletion: completion: error:%@ data:%@", error, balance);
  968.  
  969. [self postWalletEvent:nil toWallet:knownWallet withCompletion:^(NSError *error, MLWalletEvent *walletEvent) {
  970. MLLog(@"postEvent: completion: error:%@ data:%@", error, walletEvent);
  971.  
  972. }];
  973.  
  974. }];
  975.  
  976. }];
  977.  
  978.  
  979. MLWalletEvent * knownWalletEvent;
  980. knownWalletEvent.objectId = [NSString stringWithFormat:@"%@/%@", kWalletServerAddress, @"wallets/1/deals/1"];
  981. [self getWalletEvent:knownWalletEvent withCompletion:^(NSError *error, MLWalletEvent *walletEvent) {
  982. MLLog(@"getWalletEvent: completion: error:%@ data:%@", error, walletEvent);
  983. }];
  984.  
  985. MLUser * demoUser = [MLUser factoryInstance];
  986. demoUser.username = @"orpheus";
  987.  
  988.  
  989. }
  990.  
  991. #pragma mark -
  992. #pragma mark API interface
  993.  
  994. +(void)tipUser:(MLUser*)seller forPost:(MLPost *)post gift:(MLGift*)gift withCompletion:(MLSingleWalletEventCompletionBlock)completion{
  995.  
  996.  
  997. int amountInBits = [MLWalletAPI convertDollarsToBits:gift.amountInDollars];
  998.  
  999. NSLog(@"tipUser: Tip user a gift %@ %i",gift.name, amountInBits);
  1000.  
  1001.  
  1002. [self ensureBalanceMinimum:amountInBits before:^(NSError *error) {
  1003.  
  1004. NSLog(@"tipUser: Return in ensure balance minimum %i error:%@", amountInBits, error);
  1005.  
  1006. if(!error){
  1007.  
  1008. __block MLWalletEvent * mlwe = [MLWalletEvent tipForUser:seller forPost:post ofGift:gift];
  1009.  
  1010. NSMutableDictionary * walletPromises = [NSMutableDictionary new];
  1011.  
  1012. [walletPromises setObject:[self promiseWalletForUser:mlwe.seller] forKey:@"seller"];
  1013. [walletPromises setObject:[self promiseWalletForUser:mlwe.customer] forKey:@"customer"];
  1014.  
  1015. NSLog(@"tipUser: about to launch wallet promises");
  1016.  
  1017. PMKWhen(walletPromises).then(^(NSDictionary *promiseResults){
  1018.  
  1019.  
  1020. NSLog(@"tipUser: Is this where the crash is? %@", [[promiseResults objectForKey:@"seller"] class]);
  1021.  
  1022.  
  1023. MLWallet * sellerWallet = [[promiseResults objectForKey:@"seller"] firstObject];
  1024. MLWallet * customerWallet = [[promiseResults objectForKey:@"customer"] firstObject];
  1025.  
  1026. if(sellerWallet && customerWallet){
  1027.  
  1028. NSLog(@"tipUser: wallets are both there");
  1029.  
  1030. mlwe.debitedWallet = customerWallet;
  1031. mlwe.creditedWallet = sellerWallet;
  1032. //assuming they have object ids ?
  1033.  
  1034. //new money server
  1035. [self postWalletEvent:mlwe toWallet:mlwe.debitedWallet withCompletion:completion];
  1036.  
  1037. }
  1038. else if(!sellerWallet){
  1039. [MLHelper showTempAlertWithString:[NSString stringWithFormat:@"%@ is not set up to receive tips!", mlwe.seller.username]];
  1040. }
  1041.  
  1042. }).catch(^(NSError *error){
  1043.  
  1044. NSLog(@"tipUser: catch error");
  1045.  
  1046. [MLHelper showTempAlertWithString:[NSString stringWithFormat:@"%@ is not set up to receive tips! %@",mlwe.seller.username, error.localizedDescription]];
  1047.  
  1048. NSLog(@"Can't load wallets %@", error.localizedDescription);
  1049. });
  1050.  
  1051.  
  1052. }
  1053.  
  1054. }];
  1055.  
  1056. }
  1057.  
  1058. +(void)purchaseChannel:(MLChannel*)channel withCompletion:(MLSingleWalletEventCompletionBlock)completion{
  1059.  
  1060. MLLog(@"purchase Channel %@", channel.objectId);
  1061.  
  1062. [self ensureBalanceMinimum:channel.membershipPriceInBits before:^(NSError *error) {
  1063.  
  1064. if(!error){
  1065.  
  1066. __block MLWalletEvent * mlwe = [MLWalletEvent purchaseForChannel:channel];
  1067.  
  1068. NSMutableDictionary * walletPromises = [NSMutableDictionary new];
  1069.  
  1070. [walletPromises setObject:[self promiseWalletForUser:mlwe.seller] forKey:@"seller"];
  1071. [walletPromises setObject:[self promiseWalletForUser:mlwe.customer] forKey:@"customer"];
  1072.  
  1073. PMKWhen(walletPromises).then(^(NSDictionary *promiseResults){
  1074.  
  1075.  
  1076. MLLog(@"Is this where the crash is?");
  1077.  
  1078.  
  1079. MLWallet * sellerWallet = [[promiseResults objectForKey:@"seller"] firstObject];
  1080. MLWallet * customerWallet = [[promiseResults objectForKey:@"customer"] firstObject];
  1081.  
  1082. if(sellerWallet && customerWallet){
  1083.  
  1084. mlwe.debitedWallet = customerWallet;
  1085. mlwe.creditedWallet = sellerWallet;
  1086. //assuming they have object ids ?
  1087. [self postWalletEvent:mlwe toWallet:mlwe.debitedWallet withCompletion:completion];
  1088. [MLGiftManager showCelebrationForPaywallUnlock];
  1089. }
  1090. else if(!sellerWallet){
  1091. [MLHelper showTempAlertWithString:[NSString stringWithFormat:@"%@ is not set up to receive tips!", mlwe.seller.username]];
  1092. }
  1093.  
  1094. }).catch(^(NSError *error){
  1095.  
  1096. [MLHelper showTempAlertWithString:[NSString stringWithFormat:@"%@ is not set up to receive tips! %@",mlwe.seller.username, error.localizedDescription]];
  1097.  
  1098. MLLog(@"Can't load wallets %@", error.localizedDescription);
  1099. });
  1100.  
  1101.  
  1102. }
  1103.  
  1104. }];
  1105.  
  1106. }
  1107.  
  1108. +(void)refreshWalletAPIModel:(MLModel*)source withCompletion:(MLSingleResultErrorCompletionBlock)completion{
  1109.  
  1110. NSLog(@"MLWalletAPI 2.0: refreshWalletAPIModel: %@", source.objectId);
  1111.  
  1112. [[self sharedInstance] performRequestWithPath:source.objectId andMethod:@"GET" andCompletion:^(NSError *error, id jsonDict) {
  1113.  
  1114. if(!error){
  1115. [source populateWithJSON:jsonDict];
  1116. completion(nil, source);
  1117. }
  1118. else{
  1119. completion(error, source);
  1120. }
  1121.  
  1122. }];
  1123.  
  1124. }
  1125.  
  1126. +(void) getAcquisitionSourcesForWallet: (MLWallet *) wallet withCompletion: (MLMultipleWalletAcquisitionSourcesCompletionBlock) completion {
  1127.  
  1128.  
  1129. NSLog(@"MLWalletAPI 2.0: getAcquisitionSourcesForWallet: %@", wallet.objectId);
  1130.  
  1131. NSNumber *walletId = [NSNumber numberWithInteger:[[[wallet.objectId componentsSeparatedByString:@"/"] lastObject] integerValue]];
  1132.  
  1133. NSString * collectionPath = [NSString stringWithFormat:@"%@/acquisition_sources", wallet.objectId];
  1134.  
  1135. [[self sharedInstance] performRequestWithPath:collectionPath andMethod:@"GET" andCompletion:^(NSError *error, id jsonDict) {
  1136. if(jsonDict){
  1137.  
  1138. NSLog(@"MLWalletAPI 2.0: getAcquisitionSourcesForWallet: %@ json dict is %@", wallet.objectId, jsonDict);
  1139.  
  1140. NSArray *sources = [NSArray arrayWithArray:jsonDict];
  1141.  
  1142. NSMutableArray * sourceModels = [NSMutableArray new];
  1143.  
  1144. if (sources.count > 0) {
  1145. MLLog(@"found payment methods");
  1146.  
  1147. for(NSDictionary * d in sources){
  1148.  
  1149.  
  1150.  
  1151. MLWalletAcquisitionSource *as = [MLWalletAcquisitionSource instanceFromJSON:d withObjectId:[NSString stringWithFormat:@"%@/acquisition_sources/%@", kWalletServerAddress,[d valueForKey:@"id"]]];
  1152.  
  1153. NSLog(@"Populating AcquisitionSource with ID %@", as.objectId);
  1154.  
  1155. as.wallet = wallet;
  1156.  
  1157. NSLog(@"");
  1158.  
  1159. [sourceModels addObject:as];
  1160.  
  1161. }
  1162. }
  1163.  
  1164. completion(nil, sourceModels);
  1165.  
  1166. }
  1167. else{
  1168. //handle request error
  1169. completion(error, nil);
  1170. MLLog(@"Error getAcquisitionSourcesForWallet! %@", error.localizedDescription);
  1171. }
  1172.  
  1173. }];
  1174.  
  1175. }
  1176.  
  1177. +(void)makeInAppPurchaseAcquisitionSourceWithWallet:(MLWallet*)wallet andCompletion:(MLWalletAcquisitionSourceCompletionBlock)completion{
  1178.  
  1179.  
  1180. NSLog(@"MLWalletAPI 2.0: makeInAppPurchaseAcquisitionSourceWithWallet: %@", wallet.objectId);
  1181.  
  1182. MLWalletAcquisitionSource * as = [MLWalletAcquisitionSource new];
  1183. as.type = MLWalletAcquisitionSourceTypeInAppPurchase;
  1184. as.wallet = wallet;
  1185.  
  1186. [as saveWithCompletion:^(NSError *error, MLModel *model) {
  1187.  
  1188. if(!error){
  1189.  
  1190. NSLog(@"MLWalletAPI 2.0: makeInAppPurchaseAcquisitionSourceWithWallet: %@ no error", wallet.objectId);
  1191. NSLog(@"MLWalletAcquisitionSource: saveWithCompletion %@", model.objectId);
  1192.  
  1193. completion(nil, (MLWalletAcquisitionSource*)model);
  1194.  
  1195. }
  1196. else{
  1197.  
  1198. NSLog(@"MLWalletAPI 2.0: makeInAppPurchaseAcquisitionSourceWithWallet: %@ error %@ ", wallet.objectId, error);
  1199. completion(error, nil);
  1200.  
  1201. }
  1202.  
  1203. }];
  1204.  
  1205.  
  1206. }
  1207.  
  1208. +(void)getInAppPurchaseAcquisitionSourceForWallet:(MLWallet *)wallet withCompletion:(MLWalletAcquisitionSourceCompletionBlock)completion{
  1209.  
  1210.  
  1211. NSLog(@"MLWalletAPI 2.0: getInAppPurchaseAcquisitionSourceForWallet: %@", wallet.objectId);
  1212.  
  1213. [self getAcquisitionSourcesForWallet:wallet withCompletion:^(NSError *error, NSMutableArray *acquisitionSources) {
  1214.  
  1215. if(!error){
  1216.  
  1217. NSLog(@"MLWalletAPI 2.0: getInAppPurchaseAcquisitionSourceForWallet: %@ no error %i acquisition sources", wallet.objectId, [acquisitionSources count]);
  1218.  
  1219. MLWalletAcquisitionSource * inAppAcquisitionSource;
  1220.  
  1221. //check for inapppurchase acquisition source
  1222. for(MLWalletAcquisitionSource * as in acquisitionSources){
  1223. if(as.type == MLWalletAcquisitionSourceTypeInAppPurchase){
  1224. inAppAcquisitionSource = as;
  1225. }
  1226. }
  1227.  
  1228. if(inAppAcquisitionSource){
  1229.  
  1230. NSLog(@"MLWalletAPI 2.0: getInAppPurchaseAcquisitionSourceForWallet: %@ found inAppAcquisitionSource %@", wallet.objectId, inAppAcquisitionSource.objectId);
  1231. completion(nil, inAppAcquisitionSource);
  1232. }
  1233. else{
  1234.  
  1235. NSLog(@"MLWalletAPI 2.0: getInAppPurchaseAcquisitionSourceForWallet: %@ did not find in App acquisition source now will make inAppPurchaseAcquisitionSource", wallet.objectId);
  1236.  
  1237. //need to create acquisition source
  1238. [self makeInAppPurchaseAcquisitionSourceWithWallet:wallet andCompletion:completion];
  1239.  
  1240. }
  1241.  
  1242. }
  1243. else{
  1244.  
  1245. NSLog(@"MLWalletAPI 2.0: getInAppPurchaseAcquisitionSourceForWallet: %@ error getting acquisition sources %@", wallet.objectId, error);
  1246.  
  1247. completion(error, nil);
  1248. }
  1249.  
  1250.  
  1251. }];
  1252.  
  1253.  
  1254. }
  1255.  
  1256.  
  1257. +(void)purchaseCoinsAtTierLevel:(MLCoinPurchaseTier)tier withCompletion:(MLSingleWalletEventCompletionBlock)completion {
  1258. MLLog(@"purchaseCoinsAtTierLevel: %li", (long)tier);
  1259.  
  1260. NSLog(@"MLWalletAPI 2.0 purchaseCoinsAtTierLevel: %i withCompletion", (int)tier);
  1261.  
  1262. //then posting the event
  1263. //MLWalletEvent * mlwe = [MLWalletEvent bitsPurchaseOfAmount:amountInBits];
  1264.  
  1265. //get current user wallet
  1266.  
  1267. NSMutableDictionary * walletPromises = [NSMutableDictionary new];
  1268.  
  1269. [walletPromises setObject:[self promiseWalletForUser:[MLUser currentUser]] forKey:@"customer"];
  1270.  
  1271. PMKWhen(walletPromises).then(^(NSDictionary *promiseResults){
  1272.  
  1273. NSLog(@"MLWalletAPI 2.0 purchaseCoinsAtTierLevel: after getting wallets", (int)tier);
  1274.  
  1275.  
  1276. MLWallet * customerWallet = [[promiseResults objectForKey:@"customer"] firstObject];
  1277.  
  1278. //get/make acquisition source for wallet in app purchases
  1279.  
  1280. [self getInAppPurchaseAcquisitionSourceForWallet:customerWallet withCompletion:^(NSError *error, MLWalletAcquisitionSource *acquisitionSource) {
  1281.  
  1282. if(!error){
  1283.  
  1284. NSLog(@"MLWalletAPI 2.0 purchaseCoinsAtTierLevel: successfully got inAppPurchaseAcquistiionSource %@", acquisitionSource.objectId);
  1285.  
  1286.  
  1287. //perform actual in app purchase
  1288. [MLInAppPurchaseManager purchaseCoinsAtInAppPurchaseTier:tier withCompletion:^(NSError *error, NSData *receipt) {
  1289.  
  1290. if(!error){
  1291. [[NSNotificationCenter defaultCenter] postNotificationName:kPurchaseNotification object:nil userInfo:@{@"success":@YES}];
  1292. NSLog(@"MLWalletAPI 2.0 MLInAppPurchaseManager transactionCompleted with receipt %@", receipt);
  1293.  
  1294. //create acquistion
  1295. MLWalletAcquisition * a = [acquisitionSource acquisitionWithReceipt:receipt];
  1296.  
  1297. NSMutableURLRequest * mur = [[self sharedInstance] requestWithPath:[NSString stringWithFormat:@"%@/acquisitions", acquisitionSource.objectId] andMethod:@"POST" andBody:a.receipt];
  1298.  
  1299. [mur setValue:@"application/pkcs7-mime" forHTTPHeaderField:@"Content-Type"];
  1300. [mur setValue:@"base64" forHTTPHeaderField:@"Content-Encoding"];
  1301. [mur setValue:[a.receipt MD5] forHTTPHeaderField:@"Content-MD5"];
  1302.  
  1303.  
  1304. [[self sharedInstance] performRequest:mur forJSONDictionaryWithCompletion:^(NSError *error, id jsonDict) {
  1305.  
  1306. NSLog(@"Just performed save of MLWalletAcquisition %@", jsonDict);
  1307.  
  1308. if(!error){
  1309. completion(nil, nil);
  1310. NSLog(@"MLWalletAPI 2.0 successfully saved MLWalletAcquisition %@", jsonDict);
  1311. }
  1312. else{
  1313. completion(error, nil);
  1314. NSLog(@"MLWalletAPI 2.0 error saving MLWalletAcquisition %@", error);
  1315.  
  1316. }
  1317.  
  1318.  
  1319. }];
  1320.  
  1321. }
  1322. else{
  1323. [[NSNotificationCenter defaultCenter] postNotificationName:kPurchaseNotification object:nil userInfo:@{@"success":@NO}];
  1324. NSLog(@"MLWalletAPI 2.0 error purchasing coins %@", error);
  1325. completion(error, nil);
  1326. }
  1327.  
  1328. }];
  1329.  
  1330. }
  1331.  
  1332. }];
  1333.  
  1334. }).catch(^(NSError *error){
  1335.  
  1336. MLLog(@"Can't load wallets %@", error.localizedDescription);
  1337.  
  1338. completion(error, nil);
  1339. // any errors in any of the above promises land here
  1340. });
  1341.  
  1342. }
  1343.  
  1344. /*
  1345.  
  1346.  
  1347. */
  1348. +(void)purchaseBits:(NSInteger)amountInBits withCompletion:(MLSingleWalletEventCompletionBlock)completion {
  1349. MLLog(@"Purchase bits:: %li", (long)amountInBits);
  1350.  
  1351. //then posting the event
  1352. MLWalletEvent * mlwe = [MLWalletEvent bitsPurchaseOfAmount:amountInBits];
  1353.  
  1354. //get current user wallet
  1355.  
  1356. NSMutableDictionary * walletPromises = [NSMutableDictionary new];
  1357.  
  1358. [walletPromises setObject:[self promiseWalletForUser:mlwe.customer] forKey:@"customer"];
  1359.  
  1360. PMKWhen(walletPromises).then(^(NSDictionary *promiseResults){
  1361.  
  1362. MLWallet * customerWallet = [[promiseResults objectForKey:@"customer"] firstObject];
  1363.  
  1364. //get payment method
  1365. NSMutableDictionary * paymentMethodPromises = [NSMutableDictionary new];
  1366.  
  1367. [paymentMethodPromises setObject:[self promisePaymentMethodForWallet:customerWallet] forKey:@"paymentMethod"];
  1368.  
  1369. PMKWhen(paymentMethodPromises).then(^(NSDictionary *paymentPromiseResults){
  1370. MLLog(@"payment promise results %@", paymentMethodPromises);
  1371. MLPaymentMethod * paymentMethod = [[paymentPromiseResults objectForKey:@"paymentMethod"] firstObject];
  1372. //if (paymentMethod.methodId) {
  1373. MLLog(@"purchaseBits paymentMethodPromises");
  1374. mlwe.paymentMethod = paymentMethod;
  1375. [self postWalletEvent:mlwe toWallet:customerWallet withCompletion:completion];
  1376.  
  1377. //}
  1378. // else {
  1379. // MLLog(@"purchaseBits show CC screen");
  1380. // //show credit card screen
  1381. // completion(nil, nil);
  1382. // }
  1383.  
  1384.  
  1385. }).catch(^(NSError *error){
  1386. MLLog(@"Error with payment method promises");
  1387. completion(error, nil);
  1388. });
  1389.  
  1390.  
  1391. }).catch(^(NSError *error){
  1392.  
  1393. MLLog(@"Can't load wallets %@", error.localizedDescription);
  1394.  
  1395. completion(error, nil);
  1396. // any errors in any of the above promises land here
  1397. });
  1398.  
  1399. }
  1400. +(AnyPromise*)promisePaymentMethodForWallet:(MLWallet*)wallet{
  1401. MLLog(@"promise payment method for wallet %@", wallet);
  1402. return [AnyPromise promiseWithResolverBlock:^(PMKResolver _Nonnull resolve) {
  1403.  
  1404. [self getPaymentMethodsForWallet:wallet withCompletion:^(NSError *error, MLPaymentMethod *paymentMethod) {
  1405. MLLog(@"Promise payment method completion %@ %@", error.localizedDescription, wallet);
  1406.  
  1407. if (paymentMethod) {
  1408. resolve(error ?: @[paymentMethod]);
  1409. }
  1410. else {
  1411. if (error) {
  1412. resolve(error ?: nil);
  1413. }
  1414. else {
  1415. int errCode = MLWalletErrorNoPaymentMethod;
  1416. NSString *errorDomain = @"com.masslab.error";
  1417. NSError *underlyingError = [[NSError alloc] initWithDomain:errorDomain
  1418. code:errCode userInfo:nil];
  1419. // Create and return the custom domain error.
  1420. NSDictionary *errorDictionary = @{ NSLocalizedDescriptionKey : @"Payment method does not exist",
  1421. NSUnderlyingErrorKey : underlyingError };
  1422.  
  1423. NSError *anError = [[NSError alloc] initWithDomain:errorDomain
  1424. code:errCode userInfo:errorDictionary];
  1425.  
  1426. resolve(anError ?: nil);
  1427. }
  1428.  
  1429. }
  1430. }];
  1431.  
  1432. }];
  1433.  
  1434. }
  1435.  
  1436. +(AnyPromise*)promiseWalletForUser:(MLUser*)user{
  1437.  
  1438. return [AnyPromise promiseWithResolverBlock:^(PMKResolver _Nonnull resolve) {
  1439.  
  1440. NSLog(@"Promise wallet for user %@", user.username);
  1441. [self getWalletWithLabel:user.username withCompletion:^(NSError *error, MLWallet *wallet) {
  1442. NSLog(@"Promise wallet for user completion %@ %@", error.localizedDescription, wallet);
  1443. if (wallet) {
  1444. resolve(error ?: @[wallet]);
  1445. }
  1446. else {
  1447.  
  1448. if (error) {
  1449. resolve(error ?: nil);
  1450. }
  1451. else {
  1452. int errCode = MLWalletErrorNoWallet;
  1453. NSString *errorDomain = @"com.masslab.error";
  1454. NSError *underlyingError = [[NSError alloc] initWithDomain:errorDomain
  1455. code:errCode userInfo:nil];
  1456. // Create and return the custom domain error.
  1457. NSDictionary *errorDictionary = @{ NSLocalizedDescriptionKey : @"Wallet does not exist",
  1458. NSUnderlyingErrorKey : underlyingError };
  1459.  
  1460. NSError *anError = [[NSError alloc] initWithDomain:errorDomain
  1461. code:errCode userInfo:errorDictionary];
  1462.  
  1463. resolve(anError ?: nil);
  1464. }
  1465.  
  1466. }
  1467.  
  1468. }];
  1469.  
  1470. }];
  1471.  
  1472. }
  1473.  
  1474.  
  1475. +(void)getBalanceForCurrentUserWithCompletion:(MLWalletCurrentUserBalanceCompletionBlock)completion{
  1476.  
  1477. MLLog(@"MLWalletAPI :: Get balance with completion");
  1478.  
  1479. NSMutableDictionary * walletPromises = [NSMutableDictionary new];
  1480.  
  1481. [walletPromises setObject:[self promiseWalletForUser:[MLUser currentUser]] forKey:@"user"];
  1482.  
  1483. PMKWhen(walletPromises).then(^(NSDictionary *promiseResults){
  1484.  
  1485. MLLog(@"MLWalletAPI :: Get balance with completion inside promise");
  1486.  
  1487. MLWallet * sellerWallet = [[promiseResults objectForKey:@"user"] firstObject];
  1488.  
  1489. [self getBalanceOfWallet:sellerWallet withCompletion:^(NSError *error, NSDecimalNumber * balance) {
  1490.  
  1491. MLLog(@"MLWalletAPI :: Get balance with completion inside get balance of wallet");
  1492.  
  1493. completion(error,balance);
  1494. }];
  1495.  
  1496. }).catch(^(NSError *error){
  1497.  
  1498. completion(error, nil); //used to be nil
  1499. // any errors in any of the above promises land here
  1500. MLLog(@"Can't load wallets %@", error.localizedDescription);
  1501. });
  1502.  
  1503.  
  1504. }
  1505.  
  1506. +(void)getEarningsForCurrentUserWithCompletion:(MLWalletCurrentUserBalanceCompletionBlock)completion{
  1507.  
  1508. MLLog(@"MLWalletAPI :: Get balance with completion");
  1509.  
  1510. NSMutableDictionary * walletPromises = [NSMutableDictionary new];
  1511.  
  1512. [walletPromises setObject:[self promiseWalletForUser:[MLUser currentUser]] forKey:@"user"];
  1513.  
  1514. PMKWhen(walletPromises).then(^(NSDictionary *promiseResults){
  1515.  
  1516. MLLog(@"MLWalletAPI :: Get balance with completion inside promise");
  1517.  
  1518. MLWallet * sellerWallet = [[promiseResults objectForKey:@"user"] firstObject];
  1519.  
  1520. [self getEarningsOfWallet:sellerWallet withCompletion:^(NSError *error, NSDecimalNumber * balance) {
  1521.  
  1522. MLLog(@"MLWalletAPI :: Get balance with completion inside get balance of wallet");
  1523.  
  1524. completion(error,balance);
  1525. }];
  1526.  
  1527. }).catch(^(NSError *error){
  1528.  
  1529. completion(error, nil); //used to be nil
  1530. // any errors in any of the above promises land here
  1531. MLLog(@"Can't load wallets %@", error.localizedDescription);
  1532. });
  1533.  
  1534.  
  1535. }
  1536.  
  1537. /*
  1538. +(void)getTipsForPost:(MLPost*)post withCompletion:(MLWalletCurrentUserActivityCompletionBlock)completion{
  1539.  
  1540.  
  1541. [self getWalletActivityForCurrentUserWithCompletion:^(NSError *error, NSMutableArray *purchases) {
  1542.  
  1543. if(!error){
  1544.  
  1545. NSMutableArray * output = [NSMutableArray new];
  1546. for(MLPurchase * p in purchases){
  1547.  
  1548. NSLog(@"Purchase isTip:%@ byUser:%@ objectId:%@", p.isTip ? @"YES" : @"NO", p.seller.username, p.post.objectId);
  1549. if([p.post.objectId isEqualToString:post.objectId] && p.type == MLPurchaseGroupTypeTipsReceived){
  1550. [output addObject:p];
  1551. }
  1552.  
  1553. }
  1554.  
  1555. completion(error, output);
  1556.  
  1557. }
  1558. else{
  1559. NSLog(@"Get tips for post %@ error %@", post.objectId, error);
  1560. completion(error, nil);
  1561.  
  1562. }
  1563.  
  1564. }];
  1565.  
  1566. }
  1567. */
  1568.  
  1569. +(void)getTipsForPost:(MLPost*)post withCompletion:(MLWalletCurrentUserActivityCompletionBlock)completion{
  1570.  
  1571.  
  1572. NSLog(@"MLWalletAPI: getTipsForPost: %@", post.objectId);
  1573.  
  1574. [self getCurrentUserWalletsWithCompletion:^(NSError *error, NSArray *wallets) {
  1575. if(!error){
  1576.  
  1577. NSLog(@"MLWalletAPI: getTipsForPost: %@ got current user wallets", post.objectId);
  1578.  
  1579. MLWallet * wallet = [wallets firstObject];
  1580.  
  1581. [self getWalletEventsForWallet:wallet withCompletion:^(NSError *error, NSMutableArray *walletLines) {
  1582.  
  1583.  
  1584. NSLog(@"MLWalletAPI: getTipsForPost: %@ got wallet events %@ %lu", post.objectId, error, (unsigned long)[walletLines count]);
  1585.  
  1586. if(!error){
  1587.  
  1588. NSMutableArray * tips = [NSMutableArray new];
  1589.  
  1590. for(MLWalletEvent * e in walletLines){
  1591.  
  1592. if((e.type == MLWalletEventTypeTip || e.type == MLWalletEventTypeGift) && e.item.objectId == post.objectId){
  1593. NSLog(@"Found a tip that matches");
  1594. [tips addObject:e];
  1595.  
  1596. }
  1597.  
  1598. }
  1599.  
  1600. completion(nil, tips);
  1601.  
  1602. }
  1603. else{
  1604. NSLog(@"MLWalletAPI: getTipsForPost: error getting wallet events %@", error);
  1605. completion(error, nil);
  1606. }
  1607.  
  1608. }];
  1609.  
  1610. }
  1611. else{
  1612. NSLog(@"MLWalletAPI: getTipsForPost: error getting current user wallets %@", error);
  1613.  
  1614. completion(error, nil);
  1615.  
  1616. }
  1617. }];
  1618.  
  1619.  
  1620.  
  1621. }
  1622.  
  1623. +(void)getTopTipperForPost:(MLPost*)post withCompletion:(MLSingleResultErrorCompletionBlock)completion{
  1624.  
  1625.  
  1626. //1. Search for the _content reference_ matching the video URL.
  1627. ///example
  1628. //https://money-dev.portalserv.net/content_references?uri=https%3A%2F%2Fcontent-dev.portalserv.net%2Fvideos%2F314
  1629.  
  1630. NSURL * url = [NSURL URLWithString:@"content_references" relativeToURL:[NSURL URLWithString:kWalletServerAddress]];
  1631.  
  1632. NSURLComponents *components = [NSURLComponents componentsWithString:url.absoluteString];
  1633.  
  1634. NSURLQueryItem *uri = [NSURLQueryItem queryItemWithName:@"uri" value:post.objectId];
  1635.  
  1636. if(!components.queryItems){
  1637. components.queryItems = [NSArray new];
  1638. }
  1639.  
  1640. components.queryItems = [components.queryItems arrayByAddingObjectsFromArray:@[uri]];
  1641.  
  1642. NSLog(@"MLWalletAPI:: getTopTipperForPost: about to request content reference leaderboard id at %@", components.URL.absoluteString);
  1643.  
  1644. //this should return an id for the leaderboard
  1645. [self performRequestWithPath:components.URL.absoluteString andMethod:@"GET" andCompletion:^(NSError *error, id jsonDict) {
  1646.  
  1647. if(!error){
  1648.  
  1649. NSLog(@"MLWalletAPI:: getTopTipperForPost: content reference leaderboard id json %@", jsonDict);
  1650.  
  1651. NSString * identifier = [[jsonDict firstObject] objectForKey:@"id"];
  1652.  
  1653. if(!identifier){
  1654. NSLog(@"MLWalletAPI:: getTopTipperForPost: no identifier for leaderboard found");
  1655. completion(nil, nil);
  1656. return;
  1657. }
  1658.  
  1659. //2. Fetch the _gift leaderboards_ for that content reference.
  1660. //money/content_references/<ContentReferenceId>/gift_leaderboards
  1661.  
  1662. NSURL * leaderBoardURL = [NSURL URLWithString:[NSString stringWithFormat:@"content_references/%@/gift_leaderboards", identifier] relativeToURL:[NSURL URLWithString:kWalletServerAddress]];
  1663.  
  1664. [self performRequestWithPath:leaderBoardURL.absoluteString andMethod:@"GET" andCompletion:^(NSError *error, id jsonDict2) {
  1665.  
  1666. if(!error){
  1667.  
  1668. MLLeaderBoardEntry * lbe = nil;
  1669.  
  1670. NSLog(@"MLWalletAPI:: getTopTipperForPost: leaderBoard json %@", jsonDict2);
  1671. for(NSDictionary * actualDict in jsonDict2){
  1672.  
  1673. NSString * leaderBoardEntryId = [NSString stringWithFormat:@"%@/leaderboard_entries/%@", kWalletServerAddress, [actualDict objectForKey:@"id"]];
  1674.  
  1675. MLLeaderBoardEntry * leaderBoardEntry = [MLLeaderBoardEntry instanceFromJSON:[jsonDict2 firstObject] withObjectId:leaderBoardEntryId];
  1676.  
  1677. if(!lbe){
  1678. lbe = leaderBoardEntry;
  1679. }
  1680. else if([leaderBoardEntry amountInCoins] > [lbe amountInCoins]){
  1681. lbe = leaderBoardEntry;
  1682. }
  1683.  
  1684. }
  1685. if(lbe){
  1686. [MLHALClient syncModel:lbe.user withCompletion:^(NSError *error, id result) {
  1687.  
  1688. if(!error){
  1689. NSLog(@"MLWalletAPI:: getTopTipperForPost: username of top tipper is %@ with %i coins", lbe.user.username, [lbe amountInCoins]);
  1690.  
  1691. completion(nil, lbe);
  1692. }
  1693. else{
  1694. NSLog(@"MLWalletAPI:: getTopTipperForPost: error syncing user");
  1695. completion(error, nil);
  1696. }
  1697.  
  1698. }];
  1699. }
  1700. else{
  1701. NSLog(@"MLWalletAPI:: getTopTipperForPost: no leaderboard found in results %@", jsonDict2);
  1702. completion([NSError errorWithDomain:@"com.masslab.portal" code:404 userInfo:@{@"localizedDescription":@"No leaderboard found"}], nil);
  1703. }
  1704.  
  1705. }
  1706. else{
  1707.  
  1708. NSLog(@"MLWalletAPI:: getTopTipperForPost: error requesting content reference leaderboard body at %@ error: %@", leaderBoardURL.absoluteString, error);
  1709.  
  1710. completion(error, nil);
  1711. }
  1712.  
  1713. }];
  1714. }
  1715. else{
  1716.  
  1717. NSLog(@"MLWalletAPI:: getTopTipperForPost: error requesting content reference leaderboard id at %@ error: %@", components.URL.absoluteString, error);
  1718.  
  1719. completion(error, nil);
  1720. }
  1721.  
  1722. }];
  1723.  
  1724.  
  1725.  
  1726.  
  1727. }
  1728.  
  1729. +(void)getWalletActivityForCurrentUserWithCompletion:(MLWalletCurrentUserActivityCompletionBlock)completion{
  1730.  
  1731. MLLog(@"MLWalletAPI :: Get balance with completion");
  1732.  
  1733. NSMutableDictionary * walletPromises = [NSMutableDictionary new];
  1734.  
  1735. [walletPromises setObject:[self promiseWalletForUser:[MLUser currentUser]] forKey:@"user"];
  1736.  
  1737. PMKWhen(walletPromises).then(^(NSDictionary *promiseResults){
  1738.  
  1739. MLLog(@"MLWalletAPI :: Get balance with completion inside promise");
  1740.  
  1741. MLWallet * sellerWallet = [[promiseResults objectForKey:@"user"] firstObject];
  1742.  
  1743.  
  1744. [self getLinesOfWallet:sellerWallet withCompletion:^(NSError *error, NSMutableArray *walletLines) {
  1745. completion(error, walletLines);
  1746. }];
  1747.  
  1748.  
  1749. }).catch(^(NSError *error){
  1750.  
  1751. MLLog(@"Can't load wallets %@", error.localizedDescription);
  1752. completion(error, nil);
  1753. // any errors in any of the above promises land here
  1754. });
  1755.  
  1756.  
  1757.  
  1758. }
  1759.  
  1760. #pragma mark -
  1761. #pragma mark API interface - direct
  1762.  
  1763. //GET me/wallets
  1764. +(void)getCurrentUserWalletsWithCompletion:(MLWalletsCompletionBlock)completion{
  1765.  
  1766. NSLog(@"MLWalletAPI getCurrentUserWalletsWithCompletion before making request");
  1767.  
  1768. [[self sharedInstance] performRequestWithPath:@"/" andMethod:@"GET" andCompletion:^(NSError *error, id jsonResults) {
  1769.  
  1770. if(!error){
  1771.  
  1772. NSLog(@"getCurrentUserWalletsWithCompletion: %@", jsonResults);
  1773.  
  1774. NSMutableArray * outputArray = [NSMutableArray new];
  1775. for(NSDictionary * d in jsonResults){
  1776. NSLog(@"adding Wallet to outputAray %@", d);
  1777. [outputArray addObject:[MLWallet instanceFromJSON:d withObjectId:[NSString stringWithFormat:@"%@/wallets/%@",kWalletServerAddress, [d valueForKey:@"id"]]]];
  1778. }
  1779.  
  1780. completion(nil, outputArray);
  1781. }
  1782. else{
  1783. NSLog(@"Error getting current user's Wallets! %@", error.localizedDescription);
  1784. completion(error, nil);
  1785.  
  1786. }
  1787.  
  1788. }];
  1789.  
  1790. }
  1791.  
  1792.  
  1793. //GET /wallets
  1794. //List all wallets: currently for debugging only
  1795. +(void)getWalletsWithCompletion:(MLWalletsCompletionBlock)completion{
  1796.  
  1797. NSLog(@"Get wallets with completion for user %@", [[MLUser currentUser] objectId]);
  1798.  
  1799. [[self sharedInstance] performRequestWithPath:@"/wallets" andMethod:@"GET" andCompletion:^(NSError *error, id jsonResults) {
  1800.  
  1801. if(!error){
  1802.  
  1803. NSLog(@"getWalletsWithCompletion: %@", jsonResults);
  1804.  
  1805. NSMutableArray * outputArray = [NSMutableArray new];
  1806. for(NSDictionary * d in jsonResults){
  1807. [outputArray addObject:[MLWallet instanceFromJSON:d withObjectId:[NSString stringWithFormat:@"%@/wallets/%@",kWalletServerAddress, [d valueForKey:@"id"]]]];
  1808. NSLog(@"Just added wallet %@", [[outputArray lastObject] objectId]);
  1809. }
  1810.  
  1811. completion(nil, outputArray);
  1812. }
  1813. else{
  1814. MLLog(@"Error getting Wallets! %@", error.localizedDescription);
  1815. completion(error, nil);
  1816.  
  1817. }
  1818.  
  1819. }];
  1820.  
  1821. }
  1822.  
  1823. //GET /wallets?label={label}
  1824. //Search for wallets by label
  1825. +(void)getWalletWithLabel:(NSString*)label withCompletion:(MLSingleWalletCompletionBlock)completion{
  1826.  
  1827.  
  1828. [[self sharedInstance] performRequestWithPath:[NSString stringWithFormat:@"/wallets?label=%@",[label urlencode]] andMethod:@"GET" andCompletion:^(NSError *error, NSDictionary *jsonDict) {
  1829.  
  1830. if(!error && jsonDict){
  1831.  
  1832. MLLog(@"success: getWalletWithLabel: %@", jsonDict);
  1833. MLWallet * tw = [MLWallet instanceFromJSON:jsonDict withObjectId:[NSString stringWithFormat:@"%@/wallets/%@",kWalletServerAddress, [jsonDict valueForKey:@"id"]]];
  1834. completion(nil, tw);
  1835.  
  1836. }
  1837. else{
  1838. MLLog(@"Error getWalletWithLabel! %@", error.localizedDescription);
  1839. completion(error, nil);
  1840. }
  1841.  
  1842. }];
  1843. }
  1844.  
  1845. //POST /wallets
  1846. //Create a new wallet
  1847. +(void)postNewWalletWithCompletion:(MLWallet*)wallet withCompletion:(MLSingleWalletCompletionBlock)completion{
  1848.  
  1849. [[self sharedInstance] performRequestWithPath:@"wallets" andMethod:@"POST" andJSONDictionary:[wallet jsonDictionary] andCompletion:^(NSError *error, NSDictionary *jsonDict) {
  1850.  
  1851. if(!error){
  1852. MLLog(@"postNewWalletWithCompletion: %@", jsonDict);
  1853. completion(error, [MLWallet instanceFromJSON:jsonDict withObjectId:[NSString stringWithFormat:@"%@/wallets/%@",kWalletServerAddress, [jsonDict valueForKey:@"id"]]]);
  1854. }
  1855. else{
  1856. MLLog(@"Error postNewWalletWithCompletion! %@", error.localizedDescription);
  1857. completion(error, nil);
  1858. }
  1859.  
  1860. }];
  1861.  
  1862. }
  1863.  
  1864. //GET /wallets/{walletId}
  1865. //View a wallet
  1866. +(void)getWallet:(MLWallet*)wallet withCompletion:(MLSingleWalletCompletionBlock)completion{
  1867.  
  1868. [[self sharedInstance] performRequestWithPath:wallet.objectId andMethod:@"GET" andCompletion:^(NSError *error, NSDictionary *jsonDict) {
  1869.  
  1870. if(!error){
  1871.  
  1872. MLLog(@"getWallet (by id): %@", jsonDict);
  1873.  
  1874. completion(nil, [MLWallet instanceFromJSON:jsonDict withObjectId:[NSString stringWithFormat:@"%@/wallets/%@",kWalletServerAddress, [jsonDict valueForKey:@"id"]]]);
  1875.  
  1876. }
  1877. else{
  1878.  
  1879. MLLog(@"Error getWallet (by id) %@", error.localizedDescription);
  1880.  
  1881. completion(error, nil);
  1882.  
  1883. }
  1884.  
  1885. }];
  1886.  
  1887. }
  1888.  
  1889. //GET /wallets/{walletId}/balance
  1890. //Check the balance of a wallet
  1891. +(void)getBalanceOfWallet:(MLWallet*)wallet withCompletion:(MLWalletBalanceCompletionBlock)completion{
  1892.  
  1893. [[self sharedInstance] performRequestWithPath:[NSString stringWithFormat:@"%@/balance",wallet.objectId] andMethod:@"GET" andCompletion:^(NSError *error, NSDictionary *jsonDict) {
  1894.  
  1895. if(!error){
  1896. MLLog(@"getBalanceOfWallet: %@", jsonDict);
  1897.  
  1898. NSDecimal dbalance = [[[[jsonDict objectForKey:@"balance"] objectForKey:@"value"] objectForKey:@"amount"] decimalValue];
  1899.  
  1900. NSDecimalNumber * balance = [NSDecimalNumber decimalNumberWithDecimal:dbalance];
  1901.  
  1902. NSLog(@"Type of balance is %@", [[[jsonDict objectForKey:@"balance"] objectForKey:@"value"] objectForKey:@"type"]);
  1903.  
  1904. if([[[[jsonDict objectForKey:@"balance"] objectForKey:@"value"] objectForKey:@"type"] isEqualToString:@"debit"]){
  1905. balance = [balance decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"-1"]];
  1906. }
  1907.  
  1908. MLLog(@"getBalanceOfWallet: %@", [MLHelper formattedDecimalNumber:balance]);
  1909.  
  1910. /*
  1911. [self getEarningsOfWallet:wallet withCompletion:^(NSError *error, NSDecimalNumber *balanceInDollars) {
  1912. completion(error, [balance decimalNumberBySubtracting:balanceInDollars]);
  1913. }];
  1914. */
  1915. //now we are subtracting earnings from this wallet
  1916. completion(error, balance);
  1917. }
  1918. else{
  1919.  
  1920. completion(error, nil);
  1921. MLLog(@"Error getBalanceOfWallet: %@", error.localizedDescription);
  1922. }
  1923.  
  1924. }];
  1925. }
  1926.  
  1927. //GET /wallets/{walletId}/balance
  1928. //Check the balance of a wallet
  1929. +(void)getEarningsOfWallet:(MLWallet*)wallet withCompletion:(MLWalletBalanceCompletionBlock)completion{
  1930.  
  1931. [self getWalletEventsForWallet:wallet withCompletion:^(NSError *error, NSMutableArray *walletLines) {
  1932.  
  1933. NSDecimalNumber * earningsInDollars = [NSDecimalNumber decimalNumberWithString:@"0.0"];
  1934.  
  1935. if(!error){
  1936.  
  1937. NSLog(@"About to compile earnings from %i events for wallet %@", [walletLines count], wallet.objectId);
  1938.  
  1939. for(MLWalletEvent * event in walletLines){
  1940.  
  1941. NSLog(@"Event: debited wallet: %@ credited: %@ type:%i", event.debitedWallet.objectId, event.creditedWallet.objectId, event.type);
  1942.  
  1943. if([event.creditedWallet.objectId isEqualToString:wallet.objectId]){
  1944.  
  1945. NSLog(@"Found an event credited to current user");
  1946.  
  1947. if(event.type == MLWalletEventTypeTip || event.type == MLWalletEventTypeGift || event.type == MLWalletEventTypePaywallPurchase){
  1948.  
  1949. NSLog(@"Found an event: Adding %f", event.amountInDollars.floatValue);
  1950. earningsInDollars = [earningsInDollars decimalNumberByAdding:event.amountInDollars];
  1951.  
  1952. }
  1953.  
  1954. }
  1955.  
  1956. }
  1957.  
  1958. }
  1959.  
  1960. completion(error, earningsInDollars);
  1961.  
  1962. }];
  1963.  
  1964. }
  1965.  
  1966. //GET /wallets/{walletId}/balance
  1967. //Check the balance of a wallet
  1968. +(void)getTipTotalForWallet:(MLWallet*)wallet withCompletion:(MLWalletBalanceCompletionBlock)completion{
  1969.  
  1970. [self getWalletEventsForWallet:wallet withCompletion:^(NSError *error, NSMutableArray *walletLines) {
  1971.  
  1972. NSDecimalNumber * earningsInDollars = [NSDecimalNumber decimalNumberWithString:@"0.0"];
  1973.  
  1974. if(!error){
  1975.  
  1976. NSLog(@"About to compile earnings from %i events for wallet %@", [walletLines count], wallet.objectId);
  1977.  
  1978. for(MLWalletEvent * event in walletLines){
  1979.  
  1980. NSLog(@"Event: debited wallet: %@ credited: %@ type:%i", event.debitedWallet.objectId, event.creditedWallet.objectId, event.type);
  1981.  
  1982. if([event.creditedWallet.objectId isEqualToString:wallet.objectId]){
  1983.  
  1984. NSLog(@"Found an event credited to current user");
  1985.  
  1986. if(event.type == MLWalletEventTypeTip || event.type == MLWalletEventTypeGift){
  1987.  
  1988. NSLog(@"Found an event: Adding %f", event.amountInDollars.floatValue);
  1989. earningsInDollars = [earningsInDollars decimalNumberByAdding:event.amountInDollars];
  1990.  
  1991. }
  1992.  
  1993. }
  1994.  
  1995. }
  1996.  
  1997. }
  1998.  
  1999. completion(error, earningsInDollars);
  2000.  
  2001. }];
  2002.  
  2003. }
  2004.  
  2005. //GET /wallets/{walletId}/balance
  2006. //Check the balance of a wallet
  2007. +(void)getPaywallTotalForWallet:(MLWallet*)wallet withCompletion:(MLWalletBalanceCompletionBlock)completion{
  2008.  
  2009. [self getWalletEventsForWallet:wallet withCompletion:^(NSError *error, NSMutableArray *walletLines) {
  2010.  
  2011. NSDecimalNumber * earningsInDollars = [NSDecimalNumber decimalNumberWithString:@"0.0"];
  2012.  
  2013. if(!error){
  2014.  
  2015. NSLog(@"About to compile earnings from %i events for wallet %@", [walletLines count], wallet.objectId);
  2016.  
  2017. for(MLWalletEvent * event in walletLines){
  2018.  
  2019. NSLog(@"Event: debited wallet: %@ credited: %@ type:%i", event.debitedWallet.objectId, event.creditedWallet.objectId, event.type);
  2020.  
  2021. if([event.creditedWallet.objectId isEqualToString:wallet.objectId]){
  2022.  
  2023. NSLog(@"Found an event credited to current user");
  2024.  
  2025. if(event.type == MLWalletEventTypePaywallPurchase){
  2026.  
  2027. NSLog(@"Found an event: Adding %f", event.amountInDollars.floatValue);
  2028. earningsInDollars = [earningsInDollars decimalNumberByAdding:event.amountInDollars];
  2029.  
  2030. }
  2031.  
  2032. }
  2033.  
  2034. }
  2035.  
  2036. }
  2037.  
  2038. completion(error, earningsInDollars);
  2039.  
  2040. }];
  2041.  
  2042. }
  2043.  
  2044.  
  2045. +(void)getTipTotalForCurrentUserWithCompletion:(MLWalletCurrentUserBalanceCompletionBlock)completion{
  2046.  
  2047. MLLog(@"MLWalletAPI :: Get balance with completion");
  2048.  
  2049. NSMutableDictionary * walletPromises = [NSMutableDictionary new];
  2050.  
  2051. [walletPromises setObject:[self promiseWalletForUser:[MLUser currentUser]] forKey:@"user"];
  2052.  
  2053. PMKWhen(walletPromises).then(^(NSDictionary *promiseResults){
  2054.  
  2055. MLLog(@"MLWalletAPI :: Get balance with completion inside promise");
  2056.  
  2057. MLWallet * sellerWallet = [[promiseResults objectForKey:@"user"] firstObject];
  2058.  
  2059. [self getTipTotalForWallet:sellerWallet withCompletion:^(NSError *error, NSDecimalNumber * balance) {
  2060.  
  2061. MLLog(@"MLWalletAPI :: Get balance with completion inside get balance of wallet");
  2062.  
  2063. completion(error,balance);
  2064. }];
  2065.  
  2066. }).catch(^(NSError *error){
  2067.  
  2068. completion(error, nil); //used to be nil
  2069. // any errors in any of the above promises land here
  2070. MLLog(@"Can't load wallets %@", error.localizedDescription);
  2071. });
  2072.  
  2073.  
  2074. }
  2075.  
  2076. +(void)getPaywallTotalForCurrentUserWithCompletion:(MLWalletCurrentUserBalanceCompletionBlock)completion{
  2077.  
  2078. MLLog(@"MLWalletAPI :: Get balance with completion");
  2079.  
  2080. NSMutableDictionary * walletPromises = [NSMutableDictionary new];
  2081.  
  2082. [walletPromises setObject:[self promiseWalletForUser:[MLUser currentUser]] forKey:@"user"];
  2083.  
  2084. PMKWhen(walletPromises).then(^(NSDictionary *promiseResults){
  2085.  
  2086. MLLog(@"MLWalletAPI :: Get balance with completion inside promise");
  2087.  
  2088. MLWallet * sellerWallet = [[promiseResults objectForKey:@"user"] firstObject];
  2089.  
  2090. [self getPaywallTotalForWallet:sellerWallet withCompletion:^(NSError *error, NSDecimalNumber * balance) {
  2091.  
  2092. MLLog(@"MLWalletAPI :: Get balance with completion inside get balance of wallet");
  2093.  
  2094. completion(error,balance);
  2095. }];
  2096.  
  2097. }).catch(^(NSError *error){
  2098.  
  2099. completion(error, nil); //used to be nil
  2100. // any errors in any of the above promises land here
  2101. MLLog(@"Can't load wallets %@", error.localizedDescription);
  2102. });
  2103.  
  2104.  
  2105. }
  2106.  
  2107.  
  2108.  
  2109.  
  2110.  
  2111. //POST /wallets/{walletId}/deals
  2112. //Create a transaction crediting the wallet specified in the URL
  2113. +(void)postWalletEvent:(MLWalletEvent*)event toWallet:(MLWallet*)wallet withCompletion:(MLSingleWalletEventCompletionBlock)completion{
  2114. NSLog(@"postWalletEvent:");
  2115.  
  2116. //should use walletevent collection path here
  2117.  
  2118. //sort of a hack here:
  2119. NSString * pathToPost;
  2120.  
  2121. if(event.type == MLWalletEventTypeTip || event.type == MLWalletEventTypeGift || event.type == MLWalletEventTypePaywallPurchase){
  2122. pathToPost = [NSString stringWithFormat:@"%@/deals",wallet.objectId];
  2123. }
  2124. else if(event.type == MLWalletEventTypeExternal){
  2125. pathToPost = [NSString stringWithFormat:@"%@/deals",event.paymentMethod.objectId];
  2126. MLLog(@"postWalletEvent pathToPost: %@", pathToPost);
  2127. }
  2128.  
  2129.  
  2130. [[self sharedInstance] performRequestWithPath:pathToPost andMethod:@"POST" andJSONDictionary:[event jsonDictionary] andCompletion:^(NSError *error, NSDictionary *jsonDict) {
  2131. if(!error){
  2132.  
  2133. completion(error, event);
  2134. }
  2135. else{
  2136. completion(error, event);
  2137. MLLog(@"Error postNewEventWithCompletion! %@", error.localizedDescription);
  2138. }
  2139.  
  2140. }];
  2141. }
  2142.  
  2143. //GET /wallets/{walletId}/deals/{eventId}
  2144. //View an event: currently for debugging only
  2145. +(void)getWalletEvent:(MLWalletEvent*)event withCompletion:(MLSingleWalletEventCompletionBlock)completion{
  2146.  
  2147. [[self sharedInstance] performRequestWithPath:event.objectId andMethod:@"GET" andCompletion:^(NSError *error, NSDictionary *jsonDict) {
  2148.  
  2149. if(!error){
  2150. MLLog(@"getWalletEvent: %@", jsonDict);
  2151. }
  2152. else{
  2153. MLLog(@"Error getWalletEvent: (by id) %@", error.localizedDescription);
  2154. }
  2155.  
  2156. }];
  2157.  
  2158. }
  2159.  
  2160. //GET /wallets/{walletId}/lines
  2161. //Get a list of prior transactions for a wallet
  2162. +(void)getLinesOfWallet:(MLWallet*)wallet withCompletion:(MLWalletLinesCompletionBlock)completion{
  2163.  
  2164. [[self sharedInstance] performRequestWithPath:[NSString stringWithFormat:@"%@/lines",wallet.objectId] andMethod:@"GET" andCompletion:^(NSError *error, NSDictionary *jsonDict) {
  2165.  
  2166. if(!error){
  2167. MLLog(@"getLinesOfWallet jsonDict: %@", jsonDict);
  2168. }
  2169. else{
  2170. MLLog(@"Error getLinesOfWallet: %@", error.localizedDescription);
  2171. }
  2172.  
  2173. completion(error, [MLSubledgerParser purchasesFromSubledgerData:jsonDict]);
  2174.  
  2175. }];
  2176. }
  2177.  
  2178. //
  2179. +(void)getWalletEventsForWallet:(MLWallet*)wallet withCompletion:(MLWalletLinesCompletionBlock)completion{
  2180.  
  2181. [[self sharedInstance] performRequestWithPath:[NSString stringWithFormat:@"%@/deals",wallet.objectId] andMethod:@"GET" andCompletion:^(NSError *error, NSDictionary *jsonDict) {
  2182.  
  2183. if(!error){
  2184. MLLog(@"getEventsOfWallet jsonDict: %@", jsonDict);
  2185. //
  2186.  
  2187. NSArray *events = [NSArray arrayWithArray:jsonDict];//is it an array
  2188.  
  2189. NSMutableArray * results = [NSMutableArray new];
  2190.  
  2191. for(NSDictionary * dict in events){
  2192.  
  2193. static int id_int = 0;
  2194.  
  2195. if([dict objectForKey:@"id"]){
  2196. id_int = [[dict objectForKey:@"id"] intValue];
  2197. }
  2198. else{
  2199. id_int++;
  2200. }
  2201.  
  2202. MLWalletEvent * e = [MLWalletEvent instanceFromJSON:dict withObjectId:[NSString stringWithFormat:@"%@/deals/%i", kWalletServerAddress, id_int]];
  2203.  
  2204. [results addObject:e];
  2205.  
  2206. }
  2207.  
  2208. completion(error, results);
  2209.  
  2210. }
  2211. else{
  2212.  
  2213. completion(error, nil);
  2214. MLLog(@"Error getEventsOfWallet: %@", error.localizedDescription);
  2215. }
  2216.  
  2217. }];
  2218. }
  2219.  
  2220. #pragma mark Stripe
  2221. +(void)getStripePublishableKeyWithCompletion:(MLWalletStripePublishableKeyCompletionBlock)completion{
  2222. [[self sharedInstance] performRequestWithPath:@"/keys" andMethod:@"GET" andCompletion:^(NSError *error, NSDictionary *jsonDict) {
  2223.  
  2224. if(!error){
  2225. [Stripe setDefaultPublishableKey:[jsonDict objectForKey:@"stripePublishableKey"]];
  2226. MLLog(@"stripe key jsonDict: %@", jsonDict);
  2227. }
  2228. else{
  2229. MLLog(@"Error stipe key: %@", error.localizedDescription);
  2230. }
  2231.  
  2232. completion(error, [jsonDict objectForKey:@"key"]);
  2233.  
  2234. }];
  2235. }
  2236.  
  2237. +(void) createStripeTokenWithCard:(STPCardParams *) card withCompletion:(MLWalletStripeTokenCompletionBlock)completion {
  2238. [[STPAPIClient sharedClient] createTokenWithCard:card completion:^(STPToken *token, NSError *error) {
  2239. if (token) {
  2240.  
  2241. completion(nil, token);
  2242.  
  2243. } else {
  2244. completion(error, nil);
  2245. MLLog(@"error creating stripe token %@", error);
  2246. }
  2247. }];
  2248. }
  2249.  
  2250.  
  2251.  
  2252. +(void) getPaymentMethodsForWallet: (MLWallet *) wallet withCompletion: (MLWalletPaymentMethodsCompletionBlock) completion {
  2253. NSNumber *walletId = [NSNumber numberWithInteger:[[[wallet.objectId componentsSeparatedByString:@"/"] lastObject] integerValue]];
  2254.  
  2255. NSString * collectionPath = [NSString stringWithFormat:@"/wallets/%@/payment_methods", walletId];
  2256.  
  2257. [[self sharedInstance] performRequestWithPath:collectionPath andMethod:@"GET" andCompletion:^(NSError *error, id jsonDict) {
  2258. if(jsonDict){
  2259. MLLog(@"getPaymentMethodsForWallet: %@", jsonDict);
  2260. //for now each user only has one payment method
  2261. //NSString *methodId = [[jsonDict objectAtIndex:0] objectForKey:@"id"]; //first object in array returned is method id
  2262. NSArray *methods = [NSArray arrayWithArray:jsonDict];
  2263. if (methods.count > 0) {
  2264. MLLog(@"found payment methods");
  2265. MLPaymentMethod *paymentMethod = [MLPaymentMethod instanceFromJSON:jsonDict withObjectId:[NSString stringWithFormat:@"%@/%@/%@",kWalletServerAddress, collectionPath,[jsonDict valueForKey:@"id"]]];
  2266. completion(nil, paymentMethod);
  2267. }
  2268. // else {
  2269. // MLLog(@"found no payment methods");
  2270. // MLPaymentMethod *dummyMethod = [MLPaymentMethod new];
  2271. // completion(nil, dummyMethod);
  2272. // }
  2273. }
  2274. else{
  2275. //handle request error
  2276. completion(error, nil);
  2277. MLLog(@"Error getPaymentMethodsForWallet! %@", error.localizedDescription);
  2278. }
  2279.  
  2280. }];
  2281.  
  2282. }
  2283.  
  2284. +(void) postPaymentMethod:(MLPaymentMethod *)paymentMethod toWallet:(MLWallet *) wallet withCompletion:(MLWalletPostPaymentMethodCompletionBlock)completion {
  2285. NSNumber *walletId = [NSNumber numberWithInteger:[[[wallet.objectId componentsSeparatedByString:@"/"] lastObject] integerValue]];
  2286. NSDictionary * stripeDict = @{@"stripeCardToken": paymentMethod.tokenId};
  2287. [[self sharedInstance] performRequestWithPath:[NSString stringWithFormat:@"/wallets/%@/payment_methods", walletId] andMethod:@"POST" andJSONDictionary:stripeDict andCompletion:^(NSError *error, NSDictionary *jsonDict) {
  2288. if(!error){
  2289. completion(nil, YES);
  2290. MLLog(@"postPaymentMethod: %@", jsonDict);
  2291. }
  2292. else{
  2293. MLLog(@"Error postPaymentMethod! %@", error.localizedDescription);
  2294. completion(error, nil);
  2295. }
  2296.  
  2297. }];
  2298.  
  2299. }
  2300.  
  2301. /*
  2302.  
  2303. Ensurepaymentmethod will prompt the user to enter credit card info (and whatever else they need to do) before executing an action
  2304.  
  2305. This could also prompt the user to buy bits if needed
  2306.  
  2307. Something similar should be done with ensure balance - maybe ensureBalanceIsAtLeast:(int)amount - prompting user to buy bits and or enter credit card info
  2308.  
  2309. */
  2310.  
  2311. /*
  2312.  
  2313. 10/4/2016 - is there ever a case where we want to ensure payment info without buying bits? This whole thing should run through the buying bits flow
  2314.  
  2315.  
  2316. */
  2317.  
  2318. +(NSArray *) purchaseOptions {
  2319. NSArray *buttonTitles = @[@"100 Coins for $0.99", @"500 Coins for $4.99", @"1000 Coins for $9.99", @"2500 Coins for $24.99", @"10000 Coins for $99.99"];
  2320. return buttonTitles;
  2321. }
  2322.  
  2323.  
  2324. //here minimum bits will just be used to filter the bit options if the
  2325. +(void) promptUserToBuyBits:(int)minimumBits withCompletion:(MLErrorCompletionBlock)completion{
  2326.  
  2327. UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"Not Enough Coins"]
  2328. message:@"Use Coins to unlock this post. This price was added by the creator of this post." delegate:self cancelButtonTitle: @"Not now"
  2329. otherButtonTitles: @"Get Coins", nil];
  2330.  
  2331. [alert show];
  2332.  
  2333. NSLog(@"ml wallet api promptUserToBuyBits delegate: %@", alert.delegate);
  2334.  
  2335. }
  2336.  
  2337. +(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
  2338. if(buttonIndex == 0) {
  2339.  
  2340. //[[NSNotificationCenter defaultCenter] postNotificationName:@"RestrictAccessToPayContentNotification" object:nil userInfo:nil];
  2341. }
  2342. else if(buttonIndex == 1){
  2343. [self presentActionSheetWithPurchaseOptions];
  2344. }
  2345. }
  2346. +(void) presentActionSheetWithPurchaseOptions {
  2347.  
  2348. UIImage* coinImage = [UIImage imageNamed:@"coin_24dp_.png"];
  2349. UIImageView* coinImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, coinImage.size.width, coinImage.size.height)];
  2350. coinImageView.tag = 98765;
  2351. [coinImageView setImage:coinImage];
  2352.  
  2353. UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Get Coins"
  2354. message:[NSString stringWithFormat:@"Use Coins to reward people and keep Portal ad-free. \nCash out rewards you receive at portal.xyz."]
  2355. preferredStyle:UIAlertControllerStyleActionSheet];
  2356.  
  2357. NSArray *buttonTitles = [self purchaseOptions];
  2358.  
  2359. NSDictionary *attr = nil;
  2360.  
  2361. UIColor *textColor = [UIColor colorWithRed:3/255.0f green:3/255.0f blue:3/255.0f alpha:1];
  2362. attr = @{
  2363. NSFontAttributeName: [UIFont systemFontOfSize:17 weight:UIFontWeightMedium],
  2364. NSForegroundColorAttributeName: textColor
  2365. };
  2366.  
  2367. NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"\n\n\nGet Coins"] attributes:attr];
  2368. [alert setValue:title forKey:@"attributedTitle"];
  2369.  
  2370. NSDictionary *attr2 = nil;
  2371.  
  2372. attr2 = @{
  2373. NSFontAttributeName: [UIFont systemFontOfSize:13 weight:UIFontWeightRegular],
  2374. NSForegroundColorAttributeName: textColor
  2375. };
  2376.  
  2377. NSMutableAttributedString *msg = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"Use Coins to reward people and keep Portal ad-free. \nCash out rewards you receive at portal.xyz."] attributes:attr2];
  2378. [alert setValue:msg forKey:@"attributedMessage"];
  2379.  
  2380. //[alert setValue: ivMyImageView forKey:@"accessoryView"];
  2381.  
  2382. [alert.view addSubview:coinImageView];
  2383. coinImageView.frame = CGRectMake(0, 16, coinImageView.image.size.width, coinImageView.image.size.height);
  2384.  
  2385. coinImageView.center = CGPointMake([MLSkinHelper screenSizeSmallerDimension]/2 - 8, coinImageView.center.y); //for some reason this magic number works to keep the imageview centered in the alert
  2386. NSLog(@"coin center %@. view frame %@", NSStringFromCGPoint(coinImageView.center), NSStringFromCGRect(coinImageView.superview.frame));
  2387.  
  2388. MLCoinPurchaseTier purchaseTier = -1;
  2389. int purchaseIndex = 1;
  2390. for(NSString * s in buttonTitles){
  2391.  
  2392. switch (purchaseIndex) {
  2393. case 1:
  2394. purchaseTier = MLCoinPurchaseTier1;
  2395. break;
  2396. case 2:
  2397. purchaseTier = MLCoinPurchaseTier5;
  2398. break;
  2399. case 3:
  2400. purchaseTier = MLCoinPurchaseTier10;
  2401. break;
  2402. case 4:
  2403. purchaseTier = MLCoinPurchaseTier25;
  2404. break;
  2405. case 5:
  2406. purchaseTier = MLCoinPurchaseTier60;
  2407. break;
  2408. default:
  2409. break;
  2410. }
  2411.  
  2412. NSLog(@"presentActionSheetWithPurchaseOptions adding action with purchaseTier:%i and purchaseIndex:%i buttonTitle:%@", purchaseTier, purchaseIndex, s);
  2413. UIAlertAction* action = [UIAlertAction actionWithTitle:s style:UIAlertActionStyleDefault
  2414. handler:^(UIAlertAction * action) {
  2415. [self makePurchaseAtTier:purchaseTier];
  2416. }];
  2417. [alert addAction:action];
  2418. purchaseIndex++;
  2419. }
  2420.  
  2421. MLRootNavigationController *rootController = (MLRootNavigationController *)[[[[UIApplication sharedApplication] delegate] window] rootViewController];
  2422. [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
  2423. [rootController dismissViewControllerAnimated:YES completion:^{
  2424.  
  2425. }];
  2426. }]];
  2427.  
  2428. [rootController presentViewController:alert animated:YES completion:^{
  2429.  
  2430. }];
  2431.  
  2432.  
  2433. // UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
  2434. // handler:^(UIAlertAction * action) {}];
  2435. //
  2436. //
  2437. // [self presentViewController:alert animated:YES completion:nil];
  2438. //
  2439. // NSDictionary *attr = nil;
  2440. //
  2441. // UIColor *textColor = [UIColor colorWithRed:10/255.0f green:91/255.0f blue:255/255.0f alpha:1];
  2442. // attr = @{
  2443. // NSFontAttributeName: [UIFont systemFontOfSize:13 weight:UIFontWeightSemibold],
  2444. // NSForegroundColorAttributeName: textColor
  2445. // };
  2446. //
  2447. // NSMutableAttributedString *msg = [[NSMutableAttributedString alloc] initWithString:@"New Title" attributes:attr];
  2448. //
  2449. //
  2450. // NSArray *buttonTitles = [self purchaseOptions];
  2451. //
  2452. // UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:msg delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle: nil otherButtonTitles:nil];
  2453. //
  2454. // for(NSString * s in buttonTitles){
  2455. // [actionSheet addButtonWithTitle:s];
  2456. // }
  2457.  
  2458.  
  2459. // [actionSheet promiseInView:nil].then(^(NSNumber *seletedButtonIndex){
  2460. //
  2461. // int buttonIndex = [seletedButtonIndex intValue];
  2462. //
  2463. // NSString* btnTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
  2464. //
  2465. // MLLog(@"Clicked button at index %i", buttonIndex);
  2466. //
  2467. // MLCoinPurchaseTier purchaseTier = -1;
  2468. //
  2469. // switch (buttonIndex) {
  2470. // case 0:
  2471. // break;
  2472. //
  2473. // case 1:
  2474. // purchaseTier = MLCoinPurchaseTier1;
  2475. // break;
  2476. // case 2:
  2477. // purchaseTier = MLCoinPurchaseTier5;
  2478. // break;
  2479. // case 3:
  2480. // purchaseTier = MLCoinPurchaseTier10;
  2481. // break;
  2482. // case 4:
  2483. // purchaseTier = MLCoinPurchaseTier25;
  2484. // break;
  2485. // case 5:
  2486. // purchaseTier = MLCoinPurchaseTier60;
  2487. // break;
  2488. // default:
  2489. // break;
  2490. // }
  2491. //
  2492. // [self makePurchaseAtTier:purchaseTier];
  2493. //
  2494. // });
  2495.  
  2496. }
  2497. #pragma mark - Custom Credit Card Form
  2498. +(void) makePurchaseAtTier:(MLCoinPurchaseTier) tier {
  2499.  
  2500. NSLog(@"");
  2501.  
  2502. if(tier >= 0){
  2503.  
  2504. #ifdef PORTAL_PREVIEW
  2505.  
  2506. [MLHelper showTempAlertWithString:@"In App Purchases are disabled in Preview"];
  2507.  
  2508. return;
  2509.  
  2510. #endif
  2511.  
  2512. [MLWalletAPI purchaseCoinsAtTierLevel:tier withCompletion:^(NSError *error, MLWalletEvent *wallet) {
  2513. if(!error){
  2514. [MLHelper showTempAlertWithString:[NSString stringWithFormat:@"Successfully purchased coins at tier level %i", tier]];
  2515. [[NSNotificationCenter defaultCenter] postNotificationName:kTipNotification object:nil userInfo:@{@"success":@YES}];
  2516.  
  2517. [MLSoundEffects playSoundEffectOfType:MLSoundEffectTypePurchaseCoins];
  2518. //completion(error);
  2519. //[self redraw];
  2520. }
  2521. else {
  2522. [[NSNotificationCenter defaultCenter] postNotificationName:kTipNotification object:nil userInfo:@{@"success":@NO}];
  2523. [MLHelper showTempAlertWithString:@"Error purchasing Coins"];
  2524. //completion(error);
  2525.  
  2526. }
  2527. }];
  2528.  
  2529. }
  2530. else{
  2531. [[NSNotificationCenter defaultCenter] postNotificationName:kPurchaseNotification object:nil userInfo:@{@"success":@NO}];
  2532. NSError * error = [NSError errorWithDomain:@"com.masslab.portal" code:101 userInfo:@{@"localizedDescription":@"Didn't buy bits in wallet"}];
  2533. NSLog(@"error at purchaseCoinsAtTierLevel: %@", error);
  2534. //completion(error);
  2535. }
  2536.  
  2537. }
  2538.  
  2539. +(void)ensureBalanceMinimum:(int)bitsRequired before:(MLErrorCompletionBlock)completion{
  2540.  
  2541. [self getBalanceForCurrentUserWithCompletion:^(NSError *error, NSDecimalNumber *balanceInDollars) {
  2542.  
  2543.  
  2544. int balanceInBits = [MLWalletAPI convertDollarsToBits:balanceInDollars];
  2545.  
  2546. BOOL hasCash = balanceInBits >= bitsRequired; //check balance
  2547.  
  2548. if(hasCash){
  2549. completion(nil);
  2550. }
  2551. else{
  2552.  
  2553. [self promptUserToBuyBits:bitsRequired withCompletion:^(NSError *error) {
  2554. NSLog(@"ensure balance minimum prompt bits");
  2555. //[MLHelper showTempAlertWithString:[NSString stringWithFormat:@"You need to buy at least %i bits", bitsRequired - balanceInBits]];
  2556.  
  2557. //NSError * error = [NSError errorWithDomain:@"com.masslab.com" code:101 userInfo:@{@"localizedDecscription":@"Not enough bits in wallet"}];
  2558. completion(error);
  2559. }];
  2560.  
  2561.  
  2562. }
  2563.  
  2564. }];
  2565.  
  2566. }
  2567.  
  2568. +(void)changePaymentMethodWithCompletion:(MLErrorCompletionBlock)completion{
  2569.  
  2570. AppDelegate * del = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  2571. MLNavigationStackController * stackController = [del currentStackController];
  2572.  
  2573. MLLog(@"show stripe %@", [self class]);
  2574. MLStripePaymentModel *content = [MLStripePaymentModel new];
  2575. content.contentDescription.type = MLContentTypePayment;
  2576. [content.contentDescription.properties setValue:[NSNumber numberWithBool:YES] forKey:@"hidesPlayerView"];
  2577. [stackController presentControllerForModel:content withCompletion:^(NSError *error, MLNavigationCallbackState state) {
  2578.  
  2579. NSLog(@"MLWalletAPI Callback in pop of controller in ensurePaymentMethodBefore");
  2580.  
  2581. if(state == MLNavigationCallbackStateSubmitted){
  2582. completion(nil);
  2583. }
  2584. else{
  2585. completion(error);
  2586. }
  2587.  
  2588. }];
  2589. }
  2590.  
  2591. /*
  2592. +(void)ensurePaymentMethodBefore:(MLErrorCompletionBlock)completion{
  2593.  
  2594. [self checkForCurrentUserPaymentMethodsAndCustomerId:^(NSError *error, MLWallet *wallet, BOOL hasPaymentMethod, BOOL hasStripeCustomerId) {
  2595.  
  2596. if(!error && wallet && hasPaymentMethod && hasStripeCustomerId){
  2597. completion(nil);
  2598. }
  2599. else if (!hasPaymentMethod){
  2600.  
  2601. [self changePaymentMethodWithCompletion:completion];
  2602.  
  2603. }
  2604. else{
  2605. NSLog(@"SOMETHING ELSE IS WRONG WITH THE WALLET - has paymentMethod");
  2606. }
  2607.  
  2608.  
  2609. }];
  2610.  
  2611. //stackController presentControllerForModel:<#(MLModel *)#> withCompletion:<#^(NSError *error, MLNavigationCallbackState state)completion#>
  2612.  
  2613. }
  2614. */
  2615.  
  2616. #pragma mark -
  2617. #pragma mark Payouts
  2618.  
  2619. +(void) getPayoutRecipientsForWallet: (MLWallet *) wallet withCompletion: (MLMultiplePayoutRecipientsCompletionBlock) completion {
  2620.  
  2621.  
  2622. NSLog(@"MLWalletAPI 2.0: getAcquisitionSourcesForWallet: %@", wallet.objectId);
  2623.  
  2624. NSNumber *walletId = [NSNumber numberWithInteger:[[[wallet.objectId componentsSeparatedByString:@"/"] lastObject] integerValue]];
  2625.  
  2626. NSString * collectionPath = [NSString stringWithFormat:@"%@/payout_recipients", wallet.objectId];
  2627.  
  2628. [[self sharedInstance] performRequestWithPath:collectionPath andMethod:@"GET" andCompletion:^(NSError *error, id jsonDict) {
  2629. if(jsonDict){
  2630.  
  2631. NSLog(@"MLWalletAPI 2.0: getPayoutRecipientsForWallet: %@ json dict is %@", wallet.objectId, jsonDict);
  2632.  
  2633. NSArray *recipients = [NSArray arrayWithArray:jsonDict];
  2634.  
  2635. NSMutableArray * sourceModels = [NSMutableArray new];
  2636.  
  2637. if (recipients.count > 0) {
  2638. MLLog(@"found payment methods");
  2639.  
  2640. for(NSDictionary * d in recipients){
  2641.  
  2642.  
  2643.  
  2644. MLPayoutRecipient *pr = [MLPayoutRecipient instanceFromJSON:d withObjectId:[NSString stringWithFormat:@"%@/payout_recipients/%@", kWalletServerAddress,[d valueForKey:@"id"]]];
  2645.  
  2646. NSLog(@"Populating getPayoutRecipientsForWallet with ID %@", pr.objectId);
  2647.  
  2648. pr.wallet = wallet;
  2649.  
  2650.  
  2651. [sourceModels addObject:pr];
  2652.  
  2653. }
  2654. }
  2655.  
  2656. completion(nil, sourceModels);
  2657.  
  2658. }
  2659. else{
  2660. //handle request error
  2661. completion(error, nil);
  2662. MLLog(@"Error getPayoutRecipientsForWallet! %@", error.localizedDescription);
  2663. }
  2664.  
  2665. }];
  2666.  
  2667. }
  2668.  
  2669. +(void)makePayoutRecipientForWallet:(MLWallet*)wallet withAccountIdentifier:(NSString*)accountIdentifier andCompletion:(MLPayoutRecipientCompletionBlock)completion{
  2670.  
  2671.  
  2672. NSLog(@"MLWalletAPI 2.0: makePayoutRecipientForWallet: %@", wallet.objectId);
  2673.  
  2674. MLPayoutRecipient * pr = [MLPayoutRecipient new];
  2675. pr.clearinghouse = @"PayPal";
  2676. pr.wallet = wallet;
  2677. pr.accountIdentifier = accountIdentifier;
  2678.  
  2679. [pr saveWithCompletion:^(NSError *error, MLModel *model) {
  2680.  
  2681. if(!error){
  2682.  
  2683. NSLog(@"MLWalletAPI 2.0: makePayoutRecipientForWallet: %@ no error", wallet.objectId);
  2684. NSLog(@"MLPayoutRecipient: saveWithCompletion %@", model.objectId);
  2685.  
  2686. completion(nil, (MLWalletAcquisitionSource*)model);
  2687.  
  2688. }
  2689. else{
  2690.  
  2691. NSLog(@"MLWalletAPI 2.0: makePayoutRecipientForWallet: %@ error %@ ", wallet.objectId, error);
  2692. completion(error, nil);
  2693.  
  2694. }
  2695.  
  2696. }];
  2697.  
  2698.  
  2699. }
  2700.  
  2701. +(void)getPayoutRecipientForWallet:(MLWallet *)wallet withAccountIdentifier:(NSString*)accountIdentifier withCompletion:(MLPayoutRecipientCompletionBlock)completion{
  2702.  
  2703. NSLog(@"MLWalletAPI 2.0 PayoutRequest getPayoutRecipientForWallet");
  2704.  
  2705. [self getPayoutRecipientsForWallet:wallet withCompletion:^(NSError *error, NSMutableArray *payoutRecipients) {
  2706.  
  2707. if(!error){
  2708.  
  2709. NSLog(@"MLWalletAPI 2.0: getPayoutRecipientForWallet: %@ no error %i payout recipients", wallet.objectId, [payoutRecipients count]);
  2710.  
  2711. MLPayoutRecipient * recipientWithAccountIdentifier;
  2712.  
  2713. //check for inapppurchase acquisition source
  2714. for(MLPayoutRecipient * pr in payoutRecipients){
  2715. if([pr.accountIdentifier isEqualToString:accountIdentifier]){
  2716. recipientWithAccountIdentifier = pr;
  2717. }
  2718. }
  2719.  
  2720. if(recipientWithAccountIdentifier){
  2721.  
  2722. NSLog(@"MLWalletAPI 2.0: getPayoutRecipientForWallet: %@ withAccountIdentifier:%@ found %@", wallet.objectId, accountIdentifier, recipientWithAccountIdentifier.objectId);
  2723. completion(nil, recipientWithAccountIdentifier);
  2724. }
  2725. else{
  2726.  
  2727. NSLog(@"MLWalletAPI 2.0: getPayoutRecipientForWallet: %@ did not find payout recipient with accountIdentifier now will make a new one", wallet.objectId);
  2728.  
  2729. //need to create acquisition source
  2730. [self makePayoutRecipientForWallet:wallet withAccountIdentifier:accountIdentifier andCompletion:completion];
  2731.  
  2732. }
  2733.  
  2734. }
  2735. else{
  2736.  
  2737. NSLog(@"MLWalletAPI 2.0: getPayoutRecipientForWallet: %@ error getting Payout recipients %@", wallet.objectId, error);
  2738.  
  2739. completion(error, nil);
  2740. }
  2741.  
  2742.  
  2743. }];
  2744.  
  2745.  
  2746. }
  2747.  
  2748.  
  2749. +(void) requestPayoutOfAmount:(int)amountInCoins toPaypalAccount:(NSString*)paypalAccount{
  2750.  
  2751. NSLog(@"MLWalletAPI 2.0 PayoutRequest request payout of amount %i to paypalAccount %@", amountInCoins, paypalAccount);
  2752.  
  2753. [self getCurrentUserWalletsWithCompletion:^(NSError *error, NSArray *wallets) {
  2754.  
  2755. if(!error){
  2756.  
  2757. MLWallet * currentUserWallet = [wallets firstObject];
  2758.  
  2759. [self getPayoutRecipientForWallet:currentUserWallet withAccountIdentifier:paypalAccount withCompletion:^(NSError *error, MLPayoutRecipient *payoutRecipient) {
  2760.  
  2761. if(!error){
  2762. NSLog(@"MLWalletAPI 2.0 getPayoutRecipientForWallet: no error %@", payoutRecipient.objectId);
  2763.  
  2764.  
  2765. NSDecimalNumber * amountInDollars = [MLWalletAPI convertBitsToDollars:amountInCoins];
  2766.  
  2767. MLPayoutRequest * r = [payoutRecipient payoutRequestForAmountInDollars:amountInDollars];
  2768.  
  2769. [r saveWithCompletion:^(NSError *error, MLModel *model) {
  2770.  
  2771. if(!error){
  2772. NSLog(@"MLWalletAPI 2.0 PayoutRequest success! %@", model.objectId);
  2773. }
  2774. else{
  2775. NSLog(@"MLWalletAPI 2.0 PayoutRequest error! %@", error);
  2776. }
  2777.  
  2778. }];
  2779. }
  2780. else{
  2781.  
  2782. }
  2783.  
  2784. }];
  2785.  
  2786.  
  2787. }
  2788. else{
  2789. [MLHelper showTempAlertWithString:@"Could not fetch wallet ub request payout of amount"];
  2790. }
  2791.  
  2792. }];
  2793.  
  2794. }
  2795.  
  2796.  
  2797. #pragma mark -
  2798. #pragma mark Utility
  2799.  
  2800. +(void)performRequestWithPath:(NSString*)path andMethod:(NSString*)method andCompletion:(MLWalletJSONResultsCompletionBlock) completion{
  2801. [[self sharedInstance] performRequestWithPath:path andMethod:method andCompletion:completion];
  2802. }
  2803.  
  2804.  
  2805. -(void)performRequestWithPath:(NSString*)path andMethod:(NSString*)method andCompletion:(MLWalletJSONResultsCompletionBlock) completion{
  2806.  
  2807. [self performRequestWithPath:path andMethod:method andJSONDictionary:nil andCompletion:completion];
  2808.  
  2809. }
  2810.  
  2811. -(void)performRequestWithPath:(NSString*)path andMethod:(NSString*)method andJSONDictionary:(NSDictionary*)jsonDict andCompletion:(MLWalletJSONResultsCompletionBlock) completion{
  2812.  
  2813. NSLog(@"MLWalletAPI perform request with path %@ and method %@ and dictionary %@", path, method, jsonDict);
  2814.  
  2815. if(![path hasPrefix:@"http"]){
  2816. path = [kWalletServerAddress stringByAppendingPathComponent:path];
  2817. }
  2818.  
  2819. MLLog(@"About to request %@ with method %@ and dictionary %@", path, method, jsonDict);
  2820.  
  2821. NSMutableURLRequest * req = [self requestWithPath:path andMethod:method andBody:jsonDict ? [NSJSONSerialization dataWithJSONObject:jsonDict options:nil error:nil] : nil];
  2822. [req setValue:[MLApplication authorizationHeaderString] forHTTPHeaderField:@"Authorization"];
  2823. [self performRequest:req forJSONDictionaryWithCompletion:completion];
  2824. }
  2825.  
  2826.  
  2827. -(NSMutableURLRequest*)requestWithPath:(NSString*)path andMethod:(NSString*)method{
  2828. return [self requestWithPath:path andMethod:method andBody:nil];
  2829. }
  2830.  
  2831. -(NSMutableURLRequest*)requestWithPath:(NSString*)path andMethod:(NSString*)method andBody:(NSData*)body{
  2832.  
  2833. //constructing request
  2834.  
  2835. MLLog(@"MLWalletAPI: requestWithPath:%@ andMethod:%@",path, method);
  2836.  
  2837. NSURL * url = [NSURL URLWithString:path];
  2838. NSMutableURLRequest * mur = [[NSMutableURLRequest alloc] initWithURL:url];
  2839. [mur setHTTPMethod:method];
  2840. [mur setValue:@"application/hal+json, application/json;q=0.8" forHTTPHeaderField:@"Accept"];
  2841. if(body){
  2842. [mur setHTTPBody:body];
  2843. }
  2844. [mur setValue:[MLApplication authorizationHeaderString] forHTTPHeaderField:@"Authorization"];
  2845.  
  2846. return mur;
  2847.  
  2848. }
  2849.  
  2850. -(void)performRequest:(NSMutableURLRequest*)request
  2851. forJSONDictionaryWithCompletion:(MLWalletJSONResultsCompletionBlock) completion{
  2852.  
  2853.  
  2854. NSLog(@"MLWalletAPI: url %@", request.URL);
  2855. NSLog(@"MLWalletAPI: headers %@", request.allHTTPHeaderFields);
  2856. NSLog(@"MLWalletAPI: body %@", request.HTTPBody);
  2857.  
  2858. [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
  2859.  
  2860. if(connectionError){
  2861. NSLog(@"Connection error! %li %@ %@", connectionError.code, connectionError.localizedDescription, request.URL);
  2862. }
  2863.  
  2864. NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
  2865. NSLog(@"MLWalletAPI: response status code: %ld for %@", (long)[httpResponse statusCode], request.URL);
  2866.  
  2867. NSLog(@"MLWalletAPI: performRequest: %@ %i Got json back %lu %@", request.URL, httpResponse.statusCode, [data length], [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
  2868.  
  2869. if(httpResponse.statusCode >= 400 && httpResponse.statusCode < 500){
  2870.  
  2871. connectionError = [NSError errorWithDomain:@"com.masslab.portal" code:httpResponse.statusCode userInfo:@{@"localizedDescription" : [NSString stringWithFormat:@"Http error in MLWalletAPI perform request %@", request.URL]}];
  2872.  
  2873. completion(connectionError, nil);
  2874.  
  2875. return;
  2876.  
  2877. }
  2878.  
  2879. NSLog(@"response %@ %@", response, [self class]);
  2880.  
  2881. NSLog(@"data %@ %@", data, [self class]);
  2882.  
  2883. if(data.length < 3){
  2884. MLLog(@"response is empty!");
  2885. completion(nil, nil);
  2886. return;
  2887. }
  2888.  
  2889. NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data
  2890. options:kNilOptions
  2891. error:&connectionError];
  2892.  
  2893. NSLog(@"json %@ %@", json, [self class]);
  2894.  
  2895.  
  2896. completion(connectionError, json);
  2897.  
  2898. }];
  2899. }
  2900.  
  2901. +(int)convertCentsToBits:(int)cents{
  2902.  
  2903. NSDecimalNumber * amountInDollars = [self convertCentsToDollars:cents];
  2904.  
  2905. return [self convertDollarsToBits:amountInDollars];
  2906.  
  2907. }
  2908.  
  2909. //99c -> 25 Coins = 50c in the system 1 coin is actually 2c
  2910.  
  2911. +(int)convertBitsToCents:(int)bits{
  2912.  
  2913. NSDecimalNumber * amountInDollars = [self convertBitsToDollars:bits];
  2914.  
  2915. //100 for pennies per dollar, nothing to do with the bits to dollar conversion rate
  2916. return [[amountInDollars decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"100"]] intValue];
  2917.  
  2918. }
  2919.  
  2920. +(int)convertDollarsToBits:(NSDecimalNumber *)dollars{
  2921.  
  2922. return [[dollars decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"200"]] intValue];
  2923.  
  2924. //return [[dollars decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithString:@"50"]] intValue];
  2925.  
  2926. }
  2927. +(NSDecimalNumber*)convertBitsToDollars:(int)bits{
  2928.  
  2929. NSLog(@"convert %i bits to dollars", bits);
  2930.  
  2931. //we just want to divide by 50
  2932. NSDecimalNumber * amount = [NSDecimalNumber decimalNumberWithMantissa:bits exponent:0 isNegative:NO];
  2933.  
  2934. amount = [amount decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"200"]];
  2935. //old amount = [amount decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"50"]];
  2936.  
  2937. NSLog(@"Converting bits to dollars %@", amount);
  2938.  
  2939. return amount;
  2940.  
  2941. }
  2942. +(NSDecimalNumber*)convertCentsToDollars:(int)cents{
  2943.  
  2944. //100 for pennies per dollar, nothing to do with the bits to dollar conversion rate
  2945. return [[NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%i", cents]] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
  2946.  
  2947. }
  2948.  
  2949. +(NSDictionary*)amountDictionaryFromBits:(int)bits{
  2950.  
  2951. NSDecimalNumber * d = [self convertBitsToDollars:bits];
  2952.  
  2953. return [self amountDictionaryFromDollars:d];
  2954. }
  2955.  
  2956. +(NSDictionary*)amountDictionaryFromDollars:(NSDecimalNumber*)d{
  2957.  
  2958. MLUnpackedDecimalNumber updn = [d unpack];
  2959.  
  2960. return @{@"currencyCodeA":@"USD", @"mantissa":[NSNumber numberWithInt:updn.mantissa], @"exponent":[NSNumber numberWithInt:updn.exponent]};
  2961. }
  2962.  
  2963. +(NSDecimalNumber*)convertAmountDictionaryToDollars:(NSDictionary*)dictionary{
  2964.  
  2965. return [NSDecimalNumber decimalNumberWithMantissa:[[dictionary objectForKey:@"mantissa"] integerValue] exponent:[[dictionary objectForKey:@"exponent"] integerValue] isNegative:NO];
  2966.  
  2967. }
  2968.  
  2969.  
  2970. @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement