diff --git a/.circleci/src/jobs/@integration-jobs.yml b/.circleci/src/jobs/@integration-jobs.yml index e36baff7e02..8b17d865ef1 100644 --- a/.circleci/src/jobs/@integration-jobs.yml +++ b/.circleci/src/jobs/@integration-jobs.yml @@ -65,14 +65,8 @@ integration-test: name: run playwright tests command: | cd packages/web - trap 'npx playwright stop' EXIT RUN_AGAINST_LOCAL_STACK=true npx playwright test when: always - - run: - name: shutdown playwright - command: | - pkill -f playwright || true - when: always - store_test_results: path: packages/web/report.xml when: always diff --git a/packages/commands/src/utils.ts b/packages/commands/src/utils.ts index cf6934f8221..771757c7fb3 100644 --- a/packages/commands/src/utils.ts +++ b/packages/commands/src/utils.ts @@ -7,14 +7,11 @@ import { encodeHashId, decodeHashId, ResponseError, - Logger, type LoggerService } from '@audius/sdk' import { Hedgehog, - WalletManager, - getPlatformCreateKey, type GetFn, type SetAuthFn, type SetUserFn @@ -44,7 +41,6 @@ export const parseUserId = async (arg: string) => { } let audiusSdk: AudiusSdk | undefined -let currentUserId: number | undefined let currentHandle: string | undefined let hedgehog: Hedgehog | undefined @@ -138,7 +134,6 @@ class ErrorLogger implements LoggerService { export const initializeAudiusSdk = async ({ handle }: { handle?: string } = {}) => { - let isDummyWallet = false const solanaRelay = new SolanaRelay( new Configuration({ basePath: '/solana', @@ -157,7 +152,7 @@ export const initializeAudiusSdk = async ({ }) ) - if (!audiusSdk || !currentUserId || (handle && currentHandle !== handle)) { + if (!audiusSdk || (handle && currentHandle !== handle)) { // If handle was provided, unset current entropy and replace with the entropy // for the given user before initializing UserAuth if (handle) { @@ -167,29 +162,6 @@ export const initializeAudiusSdk = async ({ throw new Error(`Failed to find entropy for handle ${handle}`) } localStorage.setItem('hedgehog-entropy-key', handleEntropy) - } else { - isDummyWallet = true - // If we aren't logged in, create dummy entropy so sdk/libs work correctly - const entropy = localStorage.getItem('hedgehog-entropy-key') - if (!entropy) { - const password = `audius-dummy-pkey-${Math.floor( - Math.random() * 1000000 - )}` - const result = await WalletManager.createWalletObj( - password, - null, - localStorage, - getPlatformCreateKey() - ) - if (result instanceof Error) { - throw result - } - console.log(result.walletObj.getPrivateKeyString()) - const entropy = localStorage.getItem('hedgehog-entropy-key') - if (!entropy) { - throw new Error('Failed to create entropy') - } - } } const audiusWalletClient = createHedgehogWalletClient(getHedgehog()) @@ -205,25 +177,6 @@ export const initializeAudiusSdk = async ({ }) currentHandle = handle - - if (!isDummyWallet) { - try { - const [address] = - await audiusSdk.services.audiusWalletClient.getAddresses() - // Try to get current user. May fail if we're using a dummy entropy - const { data } = await audiusSdk.full.users.getUserAccount({ - wallet: address - }) - if (data?.user) { - currentUserId = await parseUserId(data.user.id) - if (!currentUserId) { - console.warn('Failed to parse currentUserId') - } - } - } catch (e) { - console.warn('Failed to get currentUser', e) - } - } } return audiusSdk diff --git a/packages/common/src/store/account/sagas.ts b/packages/common/src/store/account/sagas.ts index d61c82c72fd..3781ad0b240 100644 --- a/packages/common/src/store/account/sagas.ts +++ b/packages/common/src/store/account/sagas.ts @@ -242,7 +242,14 @@ export function* fetchAccountAsync({ if (user.handle) { // guest account don't have handles - yield* call(recordIPIfNotRecent, user.handle) + try { + yield* call(recordIPIfNotRecent, user.handle) + } catch (e) { + yield* call(reportToSentry, { + name: 'FetchAccountAsync', + error: e as Error + }) + } } // Cache the account and put the signedIn action. We're done. diff --git a/packages/discovery-provider/plugins/pedalboard/apps/archiver/src/workers/createStemsArchive/createStemsArchive.ts b/packages/discovery-provider/plugins/pedalboard/apps/archiver/src/workers/createStemsArchive/createStemsArchive.ts index 28d7908db26..94f38597f1a 100644 --- a/packages/discovery-provider/plugins/pedalboard/apps/archiver/src/workers/createStemsArchive/createStemsArchive.ts +++ b/packages/discovery-provider/plugins/pedalboard/apps/archiver/src/workers/createStemsArchive/createStemsArchive.ts @@ -13,6 +13,7 @@ import { import path from 'path' import { WorkerServices } from '../services' import { createUtils } from './utils' +import fetch from 'node-fetch' type StemsArchiveWorkerListener = WorkerListener< StemsArchiveJobData, diff --git a/packages/identity-service/src/authMiddleware.js b/packages/identity-service/src/authMiddleware.js index e5cf53a29a5..97bd39a260d 100644 --- a/packages/identity-service/src/authMiddleware.js +++ b/packages/identity-service/src/authMiddleware.js @@ -10,38 +10,7 @@ const models = require('./models') const audiusLibsWrapper = require('./audiusLibsInstance') const { encodeHashId } = require('./notifications/utils') - -/** - * queryDiscprovForUserId - Queries the discovery provider for the user w/ the walletaddress - * @param {string} walletAddress - * @returns {object} User Metadata object - */ -const queryDiscprovForUserId = async (walletAddress, handle) => { - const { discoveryProvider } = audiusLibsWrapper.getAudiusLibs() - - const response = await axios({ - method: 'get', - url: `${discoveryProvider.discoveryProviderEndpoint}/users`, - params: { - wallet: walletAddress - } - }) - - if (!Array.isArray(response.data.data) || !(response.data.data.length >= 1)) { - throw new Error('Unable to retrieve user from discovery provder') - } - const usersList = response.data.data - if (usersList.length === 1) { - const [user] = response.data.data - return user - } else { - for (const respUser of usersList) { - if (respUser.handle === handle) { - return respUser - } - } - } -} +const { decodeHashId } = require('@audius/sdk') /** * Queries for whether the wallet address has privilege to act as actingUserId @@ -101,7 +70,6 @@ async function authMiddleware(req, res, next) { try { const encodedDataMessage = req.get('Encoded-Data-Message') const signature = req.get('Encoded-Data-Signature') - const handle = req.query.handle const actingUserId = Number.parseInt(req.query.user_id, 10) if (!encodedDataMessage) throw new Error('[Error]: Encoded data missing') @@ -146,12 +114,23 @@ async function authMiddleware(req, res, next) { // This overwrites any provisionally set handles (b/c blockchainUserId is never set with those), // ensuring that the user.handle always represents the latest state on chain if (!user.blockchainUserId || !user.handle) { - const discprovUser = await queryDiscprovForUserId(walletAddress, handle) - user = await user.update({ - blockchainUserId: discprovUser.user_id, - handle: discprovUser.handle, - isGuest: !discprovUser.handle - }) + try { + const res = await req.app.get('audiusSdk').full.users.getUserAccount({ + wallet: walletAddress, + encodedDataMessage, + encodedDataSignature: signature + }) + const discprovUser = res.data.user + const userId = decodeHashId(discprovUser.id) + const handle = discprovUser.handle + user = await user.update({ + blockchainUserId: userId, + handle, + isGuest: !handle + }) + } catch (e) { + req.logger.error(e, 'Failed to update blockchainUserId/handle') + } } req.user = user next() @@ -178,7 +157,6 @@ const parameterizedAuthMiddleware = ({ shouldRespondBadRequest }) => { try { const encodedDataMessage = req.get('Encoded-Data-Message') const signature = req.get('Encoded-Data-Signature') - const handle = req.query.handle if (!encodedDataMessage) throw new Error('[Error]: Encoded data missing') if (!signature) throw new Error('[Error]: Encoded data signature missing') @@ -187,7 +165,7 @@ const parameterizedAuthMiddleware = ({ shouldRespondBadRequest }) => { data: encodedDataMessage, sig: signature }) - const user = await models.User.findOne({ + let user = await models.User.findOne({ where: { walletAddress }, attributes: [ 'id', @@ -203,11 +181,23 @@ const parameterizedAuthMiddleware = ({ shouldRespondBadRequest }) => { ) if (!user.blockchainUserId || !user.handle) { - const discprovUser = await queryDiscprovForUserId(walletAddress, handle) - await user.update({ - blockchainUserId: discprovUser.user_id, - handle: discprovUser.handle - }) + try { + const res = await req.app.get('audiusSdk').full.users.getUserAccount({ + wallet: walletAddress, + encodedDataMessage, + encodedDataSignature: signature + }) + const discprovUser = res.data.user + const userId = decodeHashId(discprovUser.id) + const handle = discprovUser.handle + user = await user.update({ + blockchainUserId: userId, + handle, + isGuest: !handle + }) + } catch (e) { + req.logger.error(e, 'Failed to update blockchainUserId/handle') + } } req.user = user next() diff --git a/packages/identity-service/src/index.ts b/packages/identity-service/src/index.ts index 29b80bb133f..60066f5314d 100644 --- a/packages/identity-service/src/index.ts +++ b/packages/identity-service/src/index.ts @@ -2,6 +2,7 @@ import { ethereumRouter } from './typed-routes/ethereum/ethRpc' import { solanaRouter } from './typed-routes/solana/solanaRelay' +import { DiscoveryNodeSelector, sdk } from '@audius/sdk' // Import libs before anything else becaues it takes a very long time to load. // Once it's imported once, it'll be in the cache and subsequent imports will be ~instant. @@ -26,6 +27,27 @@ process.on('unhandledRejection', (reason, promise) => { const start = async () => { const port = config.get('port') const app = new App(port) + + const environment = process.env.environment as + | 'development' + | 'staging' + | 'production' + | undefined + logger.info('Starting SDK in environment:', environment) + + const audiusSdk = sdk({ + appName: 'identity-service', + environment: environment ?? 'development', + services: { + discoveryNodeSelector: new DiscoveryNodeSelector({ + allowlist: config.get('discoveryProviderWhitelist') + ? new Set(config.get('discoveryProviderWhitelist').split(',')) + : undefined + }) + } + }) + app.express.set('audiusSdk', audiusSdk) + // TODO: Move this into App once it's typed app.express.use('/solana', solanaRouter) app.express.use('/ethereum', ethereumRouter) diff --git a/packages/sdk/src/sdk/api/challenges/ChallengesApi.ts b/packages/sdk/src/sdk/api/challenges/ChallengesApi.ts index 1331d91b251..22310bf7b9f 100644 --- a/packages/sdk/src/sdk/api/challenges/ChallengesApi.ts +++ b/packages/sdk/src/sdk/api/challenges/ChallengesApi.ts @@ -338,15 +338,18 @@ export class ChallengesApi extends GeneratedChallengesApi { * or challenge ID + specifier. */ public async claimAllRewards(request: ClaimAllRewardsRequest) { - const args = await parseParams( - 'claimAllRewards', - ClaimAllRewardsSchema - )(request) + await parseParams('claimAllRewards', ClaimAllRewardsSchema)(request) const res = await this.request({ path: '/rewards/claim', method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: args + body: { + ...('userId' in request ? { userId: request.userId } : {}), + ...('challengeId' in request + ? { challengeId: request.challengeId } + : {}), + ...('specifier' in request ? { specifier: request.specifier } : {}) + } }) return (await res.json()) as ClaimAllResponseBody } diff --git a/packages/sdk/src/sdk/config/staging.ts b/packages/sdk/src/sdk/config/staging.ts index 1a04552b9aa..116e55103fb 100644 --- a/packages/sdk/src/sdk/config/staging.ts +++ b/packages/sdk/src/sdk/config/staging.ts @@ -31,14 +31,6 @@ export const stagingConfig: SdkServicesConfig = { } ], "storageNodes": [ - { - "endpoint": "https://creatornode10.staging.audius.co", - "delegateOwnerWallet": "0xf7C96916bd37Ad76D4EEDd6536B81c29706C8056" - }, - { - "endpoint": "https://creatornode8.staging.audius.co", - "delegateOwnerWallet": "0x8fcFA10Bd3808570987dbb5B1EF4AB74400FbfDA" - }, { "endpoint": "https://creatornode12.staging.audius.co", "delegateOwnerWallet": "0x6b52969934076318863243fb92E9C4b3A08267b5" diff --git a/packages/sdk/src/sdk/sdk.ts b/packages/sdk/src/sdk/sdk.ts index ecc50e23ef5..e88b2343417 100644 --- a/packages/sdk/src/sdk/sdk.ts +++ b/packages/sdk/src/sdk/sdk.ts @@ -433,13 +433,6 @@ const initializeApis = ({ middleware, basePath: `${basePath}/v1` }) - const apiClientConfigWithDiscoveryNodeSelector = new Configuration({ - fetchApi: fetch, - middleware: [ - ...middleware, - services.discoveryNodeSelector.createMiddleware() - ] - }) const tracks = new TracksApi( apiClientConfig, @@ -508,7 +501,7 @@ const initializeApis = ({ ) const challenges = new ChallengesApi( - apiClientConfigWithDiscoveryNodeSelector, + apiClientConfig, users, services.discoveryNodeSelector, services.rewardManagerClient, diff --git a/packages/web/e2e/auth.setup.ts b/packages/web/e2e/auth.setup.ts index ec5f4fdc243..0a0c8ab7322 100644 --- a/packages/web/e2e/auth.setup.ts +++ b/packages/web/e2e/auth.setup.ts @@ -9,7 +9,7 @@ setup('authenticate', async ({ page }) => { const user = getUser() const base64Entropy = btoa(user.entropy.trim()) await page.goto(`/feed?login=${base64Entropy}`) - await expect(page.getByRole('heading', { name: 'Your Feed' })).toBeVisible({ + await expect(page.getByText(user.name)).toBeVisible({ timeout: 15000 }) await page.evaluate(() => { diff --git a/packages/web/e2e/data.seed.ts b/packages/web/e2e/data.seed.ts index 2f2437e67a2..117e9d0d8fd 100644 --- a/packages/web/e2e/data.seed.ts +++ b/packages/web/e2e/data.seed.ts @@ -77,7 +77,7 @@ setup('seed data', async () => { (async () => { console.info('Uploading remix...') await audiusCmd( - `track upload --remix-of '{"tracks":[{"parentTrackId":"${trackId}"}]}' -o json > ${dataFilePath('remix.json')}` + `track upload --remix-of ${trackId} -o json > ${dataFilePath('remix.json')}` ) const remixId = JSON.parse( await readFile(dataFilePath('remix.json'), 'utf8') diff --git a/packages/web/src/app/web-player/WebPlayer.jsx b/packages/web/src/app/web-player/WebPlayer.jsx index cd092f57d64..466906472e1 100644 --- a/packages/web/src/app/web-player/WebPlayer.jsx +++ b/packages/web/src/app/web-player/WebPlayer.jsx @@ -369,6 +369,7 @@ class WebPlayer extends Component { : authenticatedRoutes if ( !this.props.hasAccount && + this.props.accountStatus !== Status.IDLE && this.props.accountStatus !== Status.LOADING && allowedRoutes.some((route) => { const match = matchPath(getPathname(this.props.location), {