From 2033ffb1217016529e9d3ae045f491a88b84dd6f Mon Sep 17 00:00:00 2001 From: Kristoffer Date: Tue, 6 Aug 2024 10:10:00 +0200 Subject: [PATCH 1/2] feat(service) Add fitbit service for getting the number of steps --- package.json | 2 +- src/services/fitbitService.js | 40 +++++++++++++++++++++++++++ src/services/newIntegrationService.js | 11 ++++++-- src/services/reclaimService.js | 4 +++ src/utils/constants.js | 2 ++ 5 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 src/services/fitbitService.js diff --git a/package.json b/package.json index ac9ddd6..34b103b 100644 --- a/package.json +++ b/package.json @@ -32,4 +32,4 @@ "eslint-plugin-prettier": "^5.1.3", "prettier": "^3.2.5" } -} +} \ No newline at end of file diff --git a/src/services/fitbitService.js b/src/services/fitbitService.js new file mode 100644 index 0000000..1cccdc0 --- /dev/null +++ b/src/services/fitbitService.js @@ -0,0 +1,40 @@ +const axios = require('axios') +const { ReclaimServiceResponse } = require('../utils/reclaimServiceResponse') + +exports.processFitbitStepsData = async (proof, providerName) => { + const fitbitUserId = JSON.parse(proof[0].claimData.context) + .extractedParameters.userId + const lastUpdateTimeStamp = proof[0].claimData.timestampS + const accessToken = JSON.parse(proof[0].claimData.context).extractedParameters + .accessToken + const stepCount = await getUserSteps(fitbitUserId, accessToken) + + return new ReclaimServiceResponse( + providerName, + lastUpdateTimeStamp, + fitbitUserId, + stepCount, + proof[0] + ) +} + +/// Get the total steps for a user on the current day +const getUserSteps = async (userId, accessToken) => { + const today = new Date().toISOString().split('T')[0] + const url = `https://api.fitbit.com/1/user/${userId}/activities/steps/date/today/1d.json` + + try { + const response = await axios.get(url, { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }) + + const stepData = response.data['activities-steps'][0] + console.log(`Total steps for ${userId} on ${today}: ${stepData.value}`) + return parseInt(stepData.value, 10) + } catch (error) { + console.error('Error fetching Fitbit step data:', error.message) + throw error + } +} diff --git a/src/services/newIntegrationService.js b/src/services/newIntegrationService.js index 23f1e0f..a4b0bce 100644 --- a/src/services/newIntegrationService.js +++ b/src/services/newIntegrationService.js @@ -3,7 +3,8 @@ const { ReclaimServiceResponse } = require('../utils/reclaimServiceResponse') exports.processNewIntegrationData = async (proof, providerName) => { // TODO: Extract relevant data from the proof // Replace 'newParameter' with the actual parameter you need to extract - const newData = JSON.parse(proof[0].claimData.context).extractedParameters.newParameter + const newData = JSON.parse(proof[0].claimData.context).extractedParameters + .newParameter // TODO: Process the extracted data // Adjust the extraction logic based on the actual format of the data @@ -18,5 +19,11 @@ exports.processNewIntegrationData = async (proof, providerName) => { // TODO: Create a ReclaimServiceResponse object with the processed data // Adjust the parameters and processing logic based on the actual data structure - return new ReclaimServiceResponse(providerName, lastUpdateTimeStamp, username, parseInt(newValue, 10), proof[0]) + return new ReclaimServiceResponse( + providerName, + lastUpdateTimeStamp, + username, + parseInt(newValue, 10), + proof[0] + ) } diff --git a/src/services/reclaimService.js b/src/services/reclaimService.js index b33006f..0d0b7d1 100644 --- a/src/services/reclaimService.js +++ b/src/services/reclaimService.js @@ -3,6 +3,7 @@ const { Reclaim } = require('@reclaimprotocol/js-sdk') const { RECLAIM_PROVIDER_ID, RECLAIM_APP_ID } = require('../utils/constants') const { processTwitterData } = require('./twitterService') const { processGitHubData } = require('./githubService') +const { processFitbitStepsData } = require('./fitbitService') exports.signWithProviderID = async (userId, providerId) => { const providerName = RECLAIM_PROVIDER_ID[providerId] @@ -49,6 +50,9 @@ const handleReclaimSession = async (userId, reclaimClient, providerName) => { case 'GITHUB_ACCOUNT_VERIFICATION': processedData = await processGitHubData(proof, providerName) break + case 'FITBIT_STEPS_SERVICE': + processedData = await processFitbitStepsData(proof, providerName) + break default: throw new Error(`No handler for provider: ${providerName}`) } diff --git a/src/utils/constants.js b/src/utils/constants.js index 1c58669..74a4371 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -1,9 +1,11 @@ exports.RECLAIM_PROVIDER_ID = { twitter: 'TWITTER_ANALYTICS_VIEWS', github: 'GITHUB_ACCOUNT_VERIFICATION', + fitbit: 'FITBIT_ACCOUNT_VERIFICATION', } exports.RECLAIM_APP_ID = { TWITTER_ANALYTICS_VIEWS: 'your-twitter-app-id', GITHUB_ACCOUNT_VERIFICATION: 'your-github-app-id', + FITBIT_ACCOUNT_VERIFICATION: 'your-fitbit-app-id', } From 283afa0675091d44c2f8b596f05e6b447d8a6d15 Mon Sep 17 00:00:00 2001 From: Kristoffer Date: Tue, 6 Aug 2024 10:17:42 +0200 Subject: [PATCH 2/2] feat(CRIP): update fitbit crip proposal --- CRIP/CRIP-2.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 CRIP/CRIP-2.md diff --git a/CRIP/CRIP-2.md b/CRIP/CRIP-2.md new file mode 100644 index 0000000..637a3d6 --- /dev/null +++ b/CRIP/CRIP-2.md @@ -0,0 +1,67 @@ +| proposal | title | description | author | discussions-to | status | type | category | created | requires | +|----------|--------------------|-------------------------------|----------------------------|----------------|--------|-------------|----------|------------|----------| +| CRIP-002 | Fitbit Steps Integration | Integrate Fitbit step count data with Reclaim Protocol for Catoff | Your Name 0xksure@gmail.com| | Draft | Integration | CRIP | 2024-08-06 | | + +## Title + +Fitbit Steps Integration for Reclaim Protocol + +## Introduction + +This proposal aims to integrate Fitbit step count data with the Reclaim Protocol for use within the Catoff platform. By leveraging Fitbit's OAuth 2.0 authorization and step count API, we can create zero-knowledge proofs of users' walking activities, enabling innovative fitness-based challenges and wagers on the Catoff platform. + +## External APIs Needed + +- Fitbit OAuth 2.0 API +- Fitbit Activities API (specifically, the step count endpoint) + +## Use Cases + +1. Daily Step Challenge: Users can create or participate in challenges to reach a certain number of steps per day, with wagers based on achieving the goal. +2. Weekly Fitness Competition: Groups can compete for the highest total step count over a week, with automated payouts to the winners. + +## Data Provider + +- **Name**: Fitbit +- **Hash Value**: [To be provided by Reclaim Protocol] + +## Code Snippet + +```javascript +const axios = require('axios') +const { ReclaimServiceResponse } = require('../utils/reclaimServiceResponse') + +exports.processFitbitStepsData = async (proof, providerName) => { + const fitbitUserId = JSON.parse(proof[0].claimData.context).extractedParameters.userId + const lastUpdateTimeStamp = proof[0].claimData.timestampS + const stepCount = await getUserSteps(fitbitUserId, accessToken) + + return new ReclaimServiceResponse( + providerName, + lastUpdateTimeStamp, + fitbitUserId, + stepCount, + proof[0] + ) +} + +const getUserSteps = async (userId, accessToken) => { + const today = new Date().toISOString().split('T')[0] + const url = `https://api.fitbit.com/1/user/${userId}/activities/steps/date/today/1d.json` + + try { + const response = await axios.get(url, { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }) + + const stepData = response.data['activities-steps'][0] + console.log(`Total steps for ${userId} on ${today}: ${stepData.value}`) + return parseInt(stepData.value, 10) + } catch (error) { + console.error('Error fetching Fitbit step data:', error.message) + throw error + } +} +} \ No newline at end of file