diff --git a/packages/common/src/services/audius-backend/AudiusBackend.ts b/packages/common/src/services/audius-backend/AudiusBackend.ts index adeb9476e44..8b4ddcfcec3 100644 --- a/packages/common/src/services/audius-backend/AudiusBackend.ts +++ b/packages/common/src/services/audius-backend/AudiusBackend.ts @@ -21,13 +21,7 @@ import { userMetadataToSdk } from '~/adapters/user' import { Env } from '~/services/env' import dayjs from '~/utils/dayjs' -import { - ID, - InstagramUser, - TikTokUser, - ComputedUserProperties, - WriteableUserMetadata -} from '../../models' +import { ID, ComputedUserProperties, WriteableUserMetadata } from '../../models' import { AnalyticsEvent } from '../../models/Analytics' import { ReportToSentryArgs } from '../../models/ErrorReporting' import * as schemas from '../../schemas' @@ -120,7 +114,6 @@ type AudiusBackendParams = { ) => Promise | null | boolean getHostUrl: () => Nullable identityServiceUrl: Maybe - generalAdmissionUrl: Maybe isElectron: Maybe localStorage?: LocalStorage nativeMobile: Maybe @@ -141,7 +134,6 @@ type AudiusBackendParams = { export const audiusBackend = ({ identityServiceUrl, - generalAdmissionUrl, nativeMobile, reportError, env @@ -216,28 +208,12 @@ export const audiusBackend = ({ } } - async function instagramHandle(handle: string) { - try { - const res = await fetch( - `${generalAdmissionUrl}/social/instagram/${handle}` - ) - const json: InstagramUser = await res.json() - return json - } catch (error) { - console.error(error) - return null - } + async function instagramHandle(_: string) { + return null } - async function tiktokHandle(handle: string) { - try { - const res = await fetch(`${generalAdmissionUrl}/social/tiktok/${handle}`) - const json: TikTokUser = await res.json() - return json - } catch (error) { - console.error(error) - return null - } + async function tiktokHandle(_: string) { + return null } async function clearNotificationBadges({ sdk }: { sdk: AudiusSdk }) { diff --git a/packages/common/src/services/env.ts b/packages/common/src/services/env.ts index 8a2091017f5..d7d9f805ba1 100644 --- a/packages/common/src/services/env.ts +++ b/packages/common/src/services/env.ts @@ -38,7 +38,6 @@ export type Env = { FINGERPRINT_PUBLIC_API_KEY: Nullable GA_HOSTNAME: string GA_MEASUREMENT_ID: string - GENERAL_ADMISSION: string HCAPTCHA_BASE_URL: string HCAPTCHA_SITE_KEY: string IDENTITY_SERVICE: string diff --git a/packages/common/src/services/oauth/formatSocialProfile.ts b/packages/common/src/services/oauth/formatSocialProfile.ts index eef22ff726c..8d21aa247d0 100644 --- a/packages/common/src/services/oauth/formatSocialProfile.ts +++ b/packages/common/src/services/oauth/formatSocialProfile.ts @@ -1,8 +1,4 @@ -import { - InstagramProfile, - TikTokProfile, - TwitterProfile -} from '~/store/account/types' +import { TikTokProfile, TwitterProfile } from '~/store/account/types' export const MAX_HANDLE_LENGTH = 30 export const MAX_DISPLAY_NAME_LENGTH = 32 @@ -68,69 +64,6 @@ export const formatTwitterProfile = async ( } } -export const formatInstagramProfile = async ( - instagramProfile: InstagramProfile, - generalAdmission: string, - resizeImage: ( - image: File, - maxWidth?: number, - square?: boolean, - key?: string - ) => Promise -) => { - let profileImage - if (instagramProfile.profile_pic_url_hd) { - try { - const profileUrl = `${generalAdmission}/proxy/simple?url=${encodeURIComponent( - instagramProfile.profile_pic_url_hd - )}` - const imageBlob = await fetch(profileUrl).then((r) => r.blob()) - const artworkFile = new File([imageBlob], 'Artwork', { - type: 'image/jpeg' - }) - const file = await resizeImage(artworkFile) - const url = URL.createObjectURL(file) - profileImage = { url, file } - } catch (e) { - console.error('Failed to fetch profile_pic_url_hd', e) - } - } - // Truncate to MAX_HANDLE_LENGTH characters because we don't support longer handles. - // If the user is verifed, they won't be able to claim the status if - // the handle doesn't match, so just pass through. - let requiresUserReview = false - let handleTooLong = false - if (instagramProfile.username.length > MAX_HANDLE_LENGTH) { - requiresUserReview = true - handleTooLong = true - if (!instagramProfile.is_verified) { - instagramProfile.username = instagramProfile.username.slice( - 0, - MAX_HANDLE_LENGTH - ) - } - } - if ( - !instagramProfile.full_name || - instagramProfile.full_name.length > MAX_DISPLAY_NAME_LENGTH - ) { - requiresUserReview = true - if (instagramProfile.full_name) { - instagramProfile.full_name = instagramProfile.full_name.slice( - 0, - MAX_DISPLAY_NAME_LENGTH - ) - } - } - - return { - profile: instagramProfile, - profileImage, - requiresUserReview, - handleTooLong - } -} - export const formatTikTokProfile = async ( tikTokProfile: TikTokProfile, resizeImage: ( diff --git a/packages/embed/README.md b/packages/embed/README.md index 301c64155a4..2398cec3f88 100644 --- a/packages/embed/README.md +++ b/packages/embed/README.md @@ -5,16 +5,9 @@ Like you've seen on [twitter](https://twitter.com/audius/status/1293624808459010 ## Running ``` -# Run against a local [General Admission](https://github.com/AudiusProject/general-admission) server -npm run start:dev - -# Run against staging Audius services -npm run start:stage - # Run against production Audius services npm run start:prod - ## Deploying Deployed via CI diff --git a/packages/embed/workers-site/index.js b/packages/embed/workers-site/index.js index f053324d4e7..a40152e748e 100644 --- a/packages/embed/workers-site/index.js +++ b/packages/embed/workers-site/index.js @@ -20,16 +20,6 @@ addEventListener('fetch', (event) => { }) async function handleEvent(event) { - const url = new URL(event.request.url) - const { pathname, search, hash } = url - - if (pathname.startsWith('/embed/api')) { - const destinationURL = GA + pathname + search + hash - const newRequest = new Request(destinationURL, event.request) - - return await fetch(newRequest) - } - const options = {} // Always map requests to `/` since this is an SPA options.mapRequestToAsset = (request) => { diff --git a/packages/embed/wrangler.toml b/packages/embed/wrangler.toml index 7951fbd1ede..ae8b8bf0e1a 100644 --- a/packages/embed/wrangler.toml +++ b/packages/embed/wrangler.toml @@ -10,9 +10,7 @@ entry-point = "workers-site" [env.test] name = "test" route = "test.audius.co/*" -vars = { GA = "https://general-admission.audius.co" } [env.production] name = "embed" -route = "embed.audius.co/*" -vars = { GA = "https://general-admission.audius.co" } \ No newline at end of file +route = "embed.audius.co/*" \ No newline at end of file diff --git a/packages/identity-service/src/config.js b/packages/identity-service/src/config.js index ea8d86ed5eb..1a709031f12 100644 --- a/packages/identity-service/src/config.js +++ b/packages/identity-service/src/config.js @@ -731,12 +731,6 @@ const config = convict({ default: '', env: 'aaoAddress' }, - generalAdmissionAddress: { - doc: 'General admission server address', - format: String, - default: '', - env: 'generalAdmissionAddress' - }, sentryDSN: { doc: 'Sentry DSN key', format: String, diff --git a/packages/identity-service/src/routes/instagram.js b/packages/identity-service/src/routes/instagram.js deleted file mode 100644 index 1c4ce0ace87..00000000000 --- a/packages/identity-service/src/routes/instagram.js +++ /dev/null @@ -1,214 +0,0 @@ -const request = require('request') -const retry = require('async-retry') -const config = require('../config.js') -const models = require('../models') -const txRelay = require('../relay/txRelay') -const { waitForUser } = require('../utils/waitForUser') - -const { - handleResponse, - successResponse, - errorResponseBadRequest, - errorResponseServerError -} = require('../apiHelpers') - -const generalAdmissionAddress = config.get('generalAdmissionAddress') - -/** - * This file contains the instagram endpoints for oauth - * For official documentation on the instagram oauth flow check out their site - * https://www.instagram.com/developer/authentication/ - */ -module.exports = function (app) { - /** - * The first leg of the Instagram Oauth. Given an oauth code, it first - * validates that the user owns the claimed account. Then it sends a - * request to go pull the instagram graph API full user data. - */ - app.post( - '/instagram', - handleResponse(async (req, res, next) => { - const { code } = req.body - - const reqObj = { - method: 'post', - url: 'https://api.instagram.com/oauth/access_token', - form: { - client_id: config.get('instagramAPIKey'), - client_secret: config.get('instagramAPISecret'), - grant_type: 'authorization_code', - redirect_uri: config.get('instagramRedirectUrl'), - code - } - } - - try { - const res = await doRequest(reqObj) - const authAccessToken = JSON.parse(res) - const { access_token: accessToken } = authAccessToken - - const instagramAPIUser = await doRequest({ - method: 'get', - url: 'https://graph.instagram.com/me', - qs: { - fields: 'id,username,account_type', - access_token: accessToken - } - }) - const igUser = JSON.parse(instagramAPIUser) - if (igUser.error) { - return errorResponseBadRequest(new Error(igUser.error.message)) - } - const existingInstagramUser = await models.InstagramUser.findOne({ - where: { - uuid: igUser.username, - blockchainUserId: { - [models.Sequelize.Op.not]: null - } - } - }) - if (existingInstagramUser) { - return errorResponseBadRequest( - `Another Audius profile has already been authenticated with Instagram user @${igUser.username}!` - ) - } - // Fetch the instagram full profile - const igProfileReqObj = { - method: 'get', - url: `${generalAdmissionAddress}/social/instagram/${igUser.username}` - } - - try { - const instagramProfileRes = await retry( - async () => doRequest(igProfileReqObj), - { retries: 3 } - ) - const instagramProfile = JSON.parse(instagramProfileRes) - - // Store the access token, user id, and current profile for user in db - await models.InstagramUser.upsert({ - uuid: igUser.username, - profile: instagramProfile, - verified: instagramProfile.is_verified, - accessToken - }) - - return successResponse(instagramProfile) - } catch (err) { - return errorResponseBadRequest(err) - } - } catch (err) { - return errorResponseBadRequest(err) - } - }) - ) - - /** - * After the user finishes onboarding in the client app and has a blockchain userId, we need to associate - * the blockchainUserId with the instagram profile - */ - app.post( - '/instagram/associate', - handleResponse(async (req, res, next) => { - const { uuid, userId, handle, blockNumber } = req.body - req.connection.setTimeout(60 * 1000) - const audiusLibsInstance = req.app.get('audiusLibs') - try { - const instagramObj = await models.InstagramUser.findOne({ - where: { uuid } - }) - const user = await waitForUser({ - userId, - handle, - blockNumber, - audiusLibsInstance, - logger: req.logger - }) - - const isUnassociated = instagramObj && !instagramObj.blockchainUserId - const handlesMatch = - instagramObj && - instagramObj.profile.username.toLowerCase() === - user.handle.toLowerCase() - // only set blockchainUserId if not already set - if (isUnassociated && handlesMatch) { - instagramObj.blockchainUserId = userId - - // Update the user's social verification status along with the social app handle that verification came from. - // If the user is not verified, send the transaction to ensure that their linked social handle is updated. - const [encodedABI, contractAddress] = - await audiusLibsInstance.User.updateSocialVerification( - userId, - config.get('userVerifierPrivateKey'), - { - is_verified: instagramObj.verified, - instagram_handle: instagramObj.profile.username - } - ) - const senderAddress = config.get('userVerifierPublicKey') - try { - const txProps = { - contractRegistryKey: 'EntityManager', - contractAddress, - encodedABI, - senderAddress, - gasLimit: null - } - await txRelay.sendTransaction( - req, - false, - txProps, - 'instagramVerified' - ) - } catch (e) { - return errorResponseBadRequest(e) - } - - const socialHandle = await models.SocialHandles.findOne({ - where: { handle } - }) - if (socialHandle) { - socialHandle.instagramHandle = instagramObj.profile.username - await socialHandle.save() - } else if (instagramObj.profile && instagramObj.profile.username) { - await models.SocialHandles.create({ - handle, - instagramHandle: instagramObj.profile.username - }) - } - - // the final step is to save userId to db and respond to request - try { - await instagramObj.save() - return successResponse() - } catch (e) { - return errorResponseBadRequest(e) - } - } else { - req.logger.error( - 'Instagram profile does not exist or userId has already been set', - instagramObj - ) - return errorResponseBadRequest( - 'Instagram profile does not exist or userId has already been set' - ) - } - } catch (err) { - return errorResponseBadRequest(err instanceof Error ? err.message : err) - } - }) - ) -} - -/** - * Since request is a callback based API, we need to wrap it in a promise to make it async/await compliant - * @param {Object} reqObj construct request object compatible with `request` module - */ -function doRequest(reqObj) { - return new Promise(function (resolve, reject) { - request(reqObj, function (err, r, body) { - if (err) reject(err) - else resolve(body) - }) - }) -} diff --git a/packages/mobile/src/services/audius-backend-instance.ts b/packages/mobile/src/services/audius-backend-instance.ts index 531340443af..be6ff20a82c 100644 --- a/packages/mobile/src/services/audius-backend-instance.ts +++ b/packages/mobile/src/services/audius-backend-instance.ts @@ -24,7 +24,6 @@ export const audiusBackendInstance = audiusBackend({ return `${env.PUBLIC_PROTOCOL}//${env.PUBLIC_HOSTNAME}` }, identityServiceUrl: env.IDENTITY_SERVICE, - generalAdmissionUrl: env.GENERAL_ADMISSION, isElectron: false, localStorage: AsyncStorage, nativeMobile: true, diff --git a/packages/mobile/src/services/env/env.dev.ts b/packages/mobile/src/services/env/env.dev.ts index e0862eadff2..a772dd59468 100644 --- a/packages/mobile/src/services/env/env.dev.ts +++ b/packages/mobile/src/services/env/env.dev.ts @@ -39,7 +39,6 @@ export const env: Env = { FINGERPRINT_PUBLIC_API_KEY: null, GA_HOSTNAME: 'audius.co', GA_MEASUREMENT_ID: 'G-XXXXX', - GENERAL_ADMISSION: 'http://audius-general-admission-1', HCAPTCHA_BASE_URL: 'https://audius.co', HCAPTCHA_SITE_KEY: '2abe61f1-af6e-4707-be19-a9a4146a9bea', IDENTITY_SERVICE: 'http://audius-identity-service-1', diff --git a/packages/mobile/src/services/env/env.prod.ts b/packages/mobile/src/services/env/env.prod.ts index a4802f9e848..82e227d2f53 100644 --- a/packages/mobile/src/services/env/env.prod.ts +++ b/packages/mobile/src/services/env/env.prod.ts @@ -40,7 +40,6 @@ export const env: Env = { FINGERPRINT_PUBLIC_API_KEY: 'MNtDQ4NCsNSP7YOkOiQT', GA_HOSTNAME: 'audius.co', GA_MEASUREMENT_ID: 'UA-120325397-2', - GENERAL_ADMISSION: 'https://general-admission.audius.co', HCAPTCHA_BASE_URL: 'https://audius.co', HCAPTCHA_SITE_KEY: 'b250803e-dcba-428c-bc87-8acf559aacb9', IDENTITY_SERVICE: 'https://identityservice.audius.co', diff --git a/packages/web/scripts/updateIpfsBuild.js b/packages/web/scripts/updateIpfsBuild.js deleted file mode 100644 index fe7c46ab873..00000000000 --- a/packages/web/scripts/updateIpfsBuild.js +++ /dev/null @@ -1,139 +0,0 @@ -const fs = require('fs') -const fetch = require('node-fetch') -const AbortController = require('abort-controller') -const pinataSDK = require('@pinata/sdk') - -const pinata = pinataSDK( - process.env.PINATA_KEY_NAME, - process.env.PINATA_KEY_SECRET -) - -const args = process.argv -console.log(process.argv) -if (args.length < 3) { - console.error('Need to provide environment ') - process.exit(1) -} else if (args.length > 3) { - console.warn('Extra arg provided') -} - -const env = args[2] -if (env !== 'dev' && env !== 'prod') { - console.error('Environment must be ') - process.exit(1) -} - -const config = { - dev: { - gaEndpoint: 'http://localhost:9001' - }, - prod: { - gaEndpoint: 'https://general-admission.audius.co' - } -} - -const endpoint = config[env].gaEndpoint - -const CONTENT_NODE_PEER_TIMEOUT = 1000 /* ms */ * 30 /* sec */ - -const updateContentNodePeers = async () => { - const contentNodesRes = await fetch(`${endpoint}/ipfs/content_nodes`) - const contentNodes = await contentNodesRes.json() - const ipfsRes = await fetch(`${endpoint}/ipfs/ipfs`) - const ipfsId = await ipfsRes.json() - const addr = ipfsId.addresses[0] - const connections = {} - for (const cn of contentNodes) { - const controller = new AbortController() - const timeout = setTimeout( - () => controller.abort(), - CONTENT_NODE_PEER_TIMEOUT - ) - try { - // make a req to each CN /ipfs_peer_info with url query caller_ipfs_id - const response = await fetch( - `${cn.endpoint}/ipfs_peer_info?caller_ipfs_id=${encodeURIComponent( - addr - )}`, - { signal: controller.signal } - ) - const responseJson = await response.json() - if (responseJson.data && responseJson.data.id) { - connections[cn.endpoint] = true - } else { - connections[cn.endpoint] = false - } - } catch (error) { - connections[cn.endpoint] = false - } finally { - clearTimeout(timeout) - } - } - if (Object.values(connections).every((isConnected) => !isConnected)) { - console.error('unable to update peer with a single ipfs content node') - process.exit(1) - } - console.log('Added ipfs peers') - console.log(JSON.stringify(connections, null, ' ')) - return addr -} - -const updateGABuild = async () => { - const res = await fetch(`${endpoint}/ipfs/update_build?site=audius`) - const response = await res.json() - if (!response.success) { - console.error('unable to update GA build') - process.exit(1) - } - console.log('Updated build folder in GA') -} - -const pinGABuild = async () => { - const res = await fetch(`${endpoint}/ipfs/pin_build?site=audius`) - if (!res.ok) { - console.error('unable to pin GA build') - process.exit(1) - } - const response = await res.json() - const cid = response.cid - console.log(`IPFS Pin Added CID: ${cid}`) - return cid -} - -const pinPinata = async (cid, addr) => { - const options = { - pinataMetadata: { - name: `Audius build ${env} ${cid} - ${new Date().toISOString()}` - }, - pinataOptions: { - hostNodes: [addr] - } - } - return new Promise((resolve, reject) => { - pinata - .pinByHash(cid, options) - .then((result) => { - console.log(`CID ${cid} pinned to pinata`) - resolve(result) - }) - .catch((err) => { - reject(err) - }) - }) -} - -const run = async () => { - try { - const addr = await updateContentNodePeers() - await updateGABuild() - const cid = await pinGABuild() - await pinPinata(cid, addr) - fs.writeFileSync(`./build_cid.txt`, cid) - process.exit() - } catch (err) { - console.log(err) - process.exit(1) - } -} - -run() diff --git a/packages/web/scripts/workers-site/index.js b/packages/web/scripts/workers-site/index.js index 838370b4609..29fc3366e61 100644 --- a/packages/web/scripts/workers-site/index.js +++ b/packages/web/scripts/workers-site/index.js @@ -44,16 +44,7 @@ function matchRoute(input) { return null } -function checkIsBot(val) { - if (!val) { - return false - } - const botTest = - /discordbot|facebookexternalhit|gigabot|ia_archiver|meta-externalfetcher|linkbot|linkedinbot|reaper|slackbot|snap url preview service|telegrambot|twitterbot|whatsapp|whatsup|yeti|yodaobot|zend|zoominfobot|embedly|iframely/i - return botTest.test(val) -} - -function checkIsCrawler(val) { +function isCrawler(val) { if (!val) { return false } @@ -339,17 +330,6 @@ async function handleEvent(request, env, ctx) { return response } - const isBot = checkIsBot(userAgent) - - if (isBot) { - const destinationURL = env.GA + pathname + search + hash - const newRequest = new Request(destinationURL, request) - newRequest.headers.set('host', env.GA) - newRequest.headers.set('x-access-token', env.GA_ACCESS_TOKEN) - - return await fetch(newRequest) - } - const isEmbed = pathname.startsWith('/embed') if (isEmbed) { const destinationURL = env.EMBED + pathname + search + hash @@ -369,7 +349,7 @@ async function handleEvent(request, env, ctx) { } // For now, only SSR for crawlers - if (SSR && checkIsCrawler(userAgent)) { + if (SSR && isCrawler(userAgent)) { const ssrResponse = await env.SSR.fetch(request.clone()) return ssrResponse } else { diff --git a/packages/web/src/services/audius-backend/audius-backend-instance.ts b/packages/web/src/services/audius-backend/audius-backend-instance.ts index 59b4756948a..dcca5421c48 100644 --- a/packages/web/src/services/audius-backend/audius-backend-instance.ts +++ b/packages/web/src/services/audius-backend/audius-backend-instance.ts @@ -22,7 +22,6 @@ export const audiusBackendInstance = audiusBackend({ getFeatureEnabled, getHostUrl: () => window.location.origin, identityServiceUrl: env.IDENTITY_SERVICE, - generalAdmissionUrl: env.GENERAL_ADMISSION, isElectron: isElectron(), nativeMobile: false, recaptchaSiteKey: env.RECAPTCHA_SITE_KEY, diff --git a/packages/web/src/services/env/env.dev.ts b/packages/web/src/services/env/env.dev.ts index 145152bb141..b888c29f3b6 100644 --- a/packages/web/src/services/env/env.dev.ts +++ b/packages/web/src/services/env/env.dev.ts @@ -38,7 +38,6 @@ export const env: Env = { FINGERPRINT_PUBLIC_API_KEY: null, GA_HOSTNAME: 'audius.co', GA_MEASUREMENT_ID: 'G-XXXXX', - GENERAL_ADMISSION: 'http://audius-general-admission-1', HCAPTCHA_BASE_URL: 'https://audius.co', HCAPTCHA_SITE_KEY: '2abe61f1-af6e-4707-be19-a9a4146a9bea', IDENTITY_SERVICE: 'http://audius-identity-service-1', diff --git a/packages/web/src/services/env/env.prod.ts b/packages/web/src/services/env/env.prod.ts index 5117efbaf87..b64199a9aa0 100644 --- a/packages/web/src/services/env/env.prod.ts +++ b/packages/web/src/services/env/env.prod.ts @@ -40,7 +40,6 @@ export const env: Env = { FINGERPRINT_PUBLIC_API_KEY: 'MNtDQ4NCsNSP7YOkOiQT', GA_HOSTNAME: 'audius.co', GA_MEASUREMENT_ID: 'G-V6N1ZTVGS5', - GENERAL_ADMISSION: 'https://general-admission.audius.co', HCAPTCHA_BASE_URL: 'https://audius.co', HCAPTCHA_SITE_KEY: 'b250803e-dcba-428c-bc87-8acf559aacb9', IDENTITY_SERVICE: 'https://identityservice.audius.co', diff --git a/packages/web/wrangler.toml b/packages/web/wrangler.toml index 12404987742..2e3438c5d64 100644 --- a/packages/web/wrangler.toml +++ b/packages/web/wrangler.toml @@ -11,14 +11,14 @@ name = "audius-release-candidate" services = [ { binding = "SSR", service = "audius-web-ssr-release-candidate" } ] -vars = { ENVIRONMENT = "production", GA = "https://general-admission.audius.co", EMBED = "https://embed.audius.workers.dev", API_URL = "https://api.audius.co", DISCOVERY_NODES = "https://api.audius.co" } +vars = { ENVIRONMENT = "production", EMBED = "https://embed.audius.workers.dev", API_URL = "https://api.audius.co", DISCOVERY_NODES = "https://api.audius.co" } [env.production] name = "audius" services = [ { binding = "SSR", service = "audius-web-ssr" } ] -vars = { ENVIRONMENT = "production", GA = "https://general-admission.audius.co", EMBED = "https://embed.audius.workers.dev", API_URL = "https://api.audius.co", DISCOVERY_NODES = "https://api.audius.co" } +vars = { ENVIRONMENT = "production", EMBED = "https://embed.audius.workers.dev", API_URL = "https://api.audius.co", DISCOVERY_NODES = "https://api.audius.co" } # Test environment, replace `test` with subdomain # Invoke with npx wrangler dev --env test @@ -27,4 +27,4 @@ name = "test" services = [ { binding = "SSR", service = "audius-web-ssr-test" } ] -vars = { ENVIRONMENT = "production", GA = "https://general-admission.audius.co", EMBED = "https://embed.audius.workers.dev", API_URL = "https://api.audius.co", DISCOVERY_NODES = "https://api.audius.co" } \ No newline at end of file +vars = { ENVIRONMENT = "production", EMBED = "https://embed.audius.workers.dev", API_URL = "https://api.audius.co", DISCOVERY_NODES = "https://api.audius.co" } \ No newline at end of file