๐Ÿ“ฑ react native

Overview

The react native sdk is a customizable package built in typescript that provides authenticated access to the SharpSports Context and Refresh methods. It is intended to be used as the integration path for React-Native mobile applications.

๐Ÿšง

Be sure to enable the Native SDK toggle under Settings->Account in the SharpSports dashboard to enable SDK Required books in the Linking UI.

Getting Started

Access

Request access by emailing [email protected].

Installation

Once your github account has been added as an outside collaborator to this sharpsports-mobile package please generate a Personal Access Token (PAT) to use when installing the package into your project. This should be a classic token with permission scope read:packages.

For details on how to create a classic PAT see: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token

  1. Authenticate to the github NPM registry in one of two ways

i) Add //npm.pkg.github.com/:_authToken=TOKEN (with your PAT) to an ~/.npmrc file.

ii) Use npm login

$ npm login --scope=@sharpsports --registry=https://npm.pkg.github.com

> Username: USERNAME
> Password: TOKEN
> Email: PUBLIC-EMAIL-ADDRESS
  1. Create a new file .npmrc in the same directory as your package.json with the following
@sharpsports:registry=https://npm.pkg.github.com

This file must be pushed to github with your project.

  1. Add "@sharpsports/sharpsports-mobile": VERSION to your package.json
  2. Run npm install

See https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry for more details

  1. Install additional React-Native dependencies directly in your application - these cannot be installed as sub-depedencies to the sharpsports-mobile package as it causes issues in the iOS buid. To see the compatible versions of these dependencies view the devDependencies in package.json of the sharpsports-mobile package.
npm install @react-native-community/netinfo
npm install @react-native-cookies/cookies
npm install @pusher/pusher-websocket-react-native
  1. Notes for Expo Users:
  • Please ensure you are using Expo version >46.0
  • Once sharpsports-mobile and necessary react-native dependencies are installed in your app, you will not be able to run your application locally using the expo managed workflow. Instead use the eas-cli or the following method on iOS:
    • iOS: npx expo prebuild && cd ios && pod install and then open the resulting workspace in XCode

Note: iOS deployment target must be >=13.0

Generate a Mobile Authentication Token

In order to initialize the SharpSports object in your application you need to generate a mobileAuthToken in your backend and retrieve it client-side.

First create an API endpoint in your backend to retrieve the mobileAuthToken from the SharpSports /v1/mobile/auth endpoint. Your API endpoint should:

  1. Require that the bettor is authenticated in your application
  2. Pass the internalId of the authenticated bettor as data to the /v1/mobile/auth endpoint
  3. Return the value of {"token":<mobileAuthToken>} you recieve from the /v1/mobile/auth endpoint

Example usage of /v1/mobile/auth is shown below in node:

const privateKey = 'my-private-api-key'
const internalId = 'internal-id-of-authenticated-bettor'

const HEADERS = {
  "Authorization" : `Token ${privateKey}`,
  "Content-Type": "application/json"
}

const DATA = {
  "internalId": internalId
}

const OPTS = {
  method: 'POST',
  headers: HEADERS,
  body: JSON.stringify(DATA)
};

let response = await fetch('https://api.sharpsports.io/v1/mobile/auth',OPTS)
let data = await response.json() //data takes the form {"token": <mobileAuthToken>}

Your application should fetch the mobileAuthToken once a bettor has logged in to your app and you can use it to initialize the SharpSports object.

The example-app in this repository is instructive, but shows the call that is to be made server-side within the app itself.

Initialize the SharpSports Object

Import the SharpSports package into your app and initialize.

import SharpSports from '@sharpsports/sharpsports-mobile';

const  internalId = 'internal-id-of-authenticated-bettor';
const  publicKey = 'my-public-api-key';
const  mobileAuthToken = 'mobile-auth-token';
const  sharpsports = new SharpSports(internalId,publicKey,mobileAuthToken);

Create a Linking Session in a WebView

The sharpsports.Context method corresponds to the API call POST https://api.sharpsports.io/v1/context. It returns a Promise that when resolved contains a context ID - {"cid": <cid>}.

Use this cid to render a webview that navigates to https://ui.sharpsports.io/link/<cid> (or a specific book/region if you prefer - see https://docs.sharpsports.io/#create-your-own-button-for-each-book). Make sure to generate a new cid each time the webview is opened; don't create a cid on app load and use for multiple sessions.

The WebView that you create should do the following:

  1. Use a state variable as the source uri. This state variable should be initialized using the response from the Context method and should be updated in onNavigationStateChange
  2. Inject JS returned by sharpsports.getInjectedJavascript() on every new page load
  3. Call sharpsports.onNavigationStateChange as part of the WebView onNavigationStateChange handler
  4. Call sharpsports.onMessage as part of the Webview onMessage handler
  5. Have third partry cookies enabled
  6. When the process of linking an account is complete, the Sharpsports UI will naviage to https://ui.sharpsports.io/done. You can hook on to this URL to exit the webview.

This can be achieved by following this example:

import React,{ useState } from 'react';
import SharpSports from '@sharpsports/sharpsports-mobile'

const internalId = 'your-internal-id'
const SSpublicKey = 'your-SharpSports-public-key'
const mobileAuthToken = 'mobile-auth-token'
const sharpsports = new SharpSports(internalId,SSpublicKey,mobileAuthToken)
const [webviewUrl, setWebviewUrl] = useState(null)
const [cid, setCid] = useState(null)

...

onClick = async() => {
  const response = await sharpsports.Context()
  const data = await response.json()
  setCid(data.cid)
  setWebviewUrl(`https://ui.sharpsports.io/link/${data.cid}`)
}

_onMessage = (data) => {
  //Any other onMessage handling that you have in your app
  sharpsports.onMessage(data,cid)
}
  
_onNavigationStateChange = (data) => {
  setWebviewUrl(data.url) //This is required to make sure JS is injected on every new page
  //Any other navigation handling that you have in your app
  //Case for exiting webview on /done url
  sharpsports.onNavigationStateChange(data)
}

...

    <WebView 
      source={{ uri: webviewUrl }} //this is required to block webview from linking out to external apps
      injectedJavaScript={sharpsports.getInjectedJavascript()}
      onNavigationStateChange={_onNavigationStateChange}
      onMessage={_onMessage}
      thirdPartyCookiesEnabled={true}
  />

Context Method

The sharpsports.Context() method allows you to generate a session for SharpSports UI components

Arguments

All of the arguments for the Context method are optional.

Setting Light/Dark Mode

You can set the SharpSports UI background color by using the uiMode parameter

dark: dark mode background

light: light mode background

system: use device's default setting

sharpsports.Context({uiMode: <light|dark|system>})

Generate a Context for Best Price Widget

If you need to generate a context for the SharpSports Best Price Widget you use the bestPrice parameter. Then navigate to the url https://ui.sharpsports.io/best-price/<cid>.

sharpsports.Context({bestPrice: true})

Refreshing Accounts

The sharpsports.Refresh() method allows you to make refresh requests to the SharpSports API.

๐Ÿšง

Version 3.2.0 contains a required alert message that appears when the Refresh method is called for particular books.

Arguments

By default the Refresh method will run a refresh on all accounts associated with the internalId that you provided when initializing the SharpSports object. Optionally you can pass a bettorId to refresh all accounts associated with that ID or a bettorAccountId to refresh just a specific account.

You can also optionally pass reverify: true as an argument to attach the reverify query parameter to the refresh request.

bettorId?: string;
bettorAccountId?: string;
reverify?: boolean;

Usage

Refresh by InternalID

sharpsports.Refresh()

corresponds to the API call

POST https://api.sharpsports.io/v1/bettors/<internalID>/refresh

Refresh by BettorID

sharpsports.Refresh({bettorId: <BTTR_ID>})

corresponds to the API call

POST https://api.sharpsports.io/v1/bettors/<BTTR_ID>/refresh

Refresh by BettorAccountID

sharpsports.Refresh({bettorAccountId: <BACT_ID>})

corresponds to the API call

POST https://api.sharpsports.io/v1/bettorAccounts/<BACT_ID>/refresh

Reverify

sharpsports.Refresh({bettorAccountId: <BACT_ID>, reverify: true})

corresponds to the API call

POST https://api.sharpsports.io/v1/bettorAccounts/<BACT_ID>/refresh?reverify=true