Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .circleci/src/jobs/@integration-jobs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
49 changes: 1 addition & 48 deletions packages/commands/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@ import {
encodeHashId,
decodeHashId,
ResponseError,
Logger,
type LoggerService
} from '@audius/sdk'

import {
Hedgehog,
WalletManager,
getPlatformCreateKey,
type GetFn,
type SetAuthFn,
type SetUserFn
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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',
Expand All @@ -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) {
Expand All @@ -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())
Expand All @@ -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
Expand Down
9 changes: 8 additions & 1 deletion packages/common/src/store/account/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why might this fail?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

recordIP request requires that blockchainUserId exists in identity for that user, which requires that authMiddleware has sent a request to discovery to fill that in, which requires that the selected DN returns back that user. That's a fair number of contingent things that need to happen, and something as little as a network hiccup can interrupt. But it should be more resilient after this PR, given the retry logic baked in SDK! I added the try catch because this doesn't seem like something we want to break the login/account fetch flow regardless of how successful it is on average

} catch (e) {
yield* call(reportToSentry, {
name: 'FetchAccountAsync',
error: e as Error
})
}
}

// Cache the account and put the signedIn action. We're done.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
82 changes: 36 additions & 46 deletions packages/identity-service/src/authMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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()
Expand All @@ -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')
Expand All @@ -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',
Expand All @@ -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()
Expand Down
22 changes: 22 additions & 0 deletions packages/identity-service/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
Expand Down
13 changes: 8 additions & 5 deletions packages/sdk/src/sdk/api/challenges/ChallengesApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
8 changes: 0 additions & 8 deletions packages/sdk/src/sdk/config/staging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
9 changes: 1 addition & 8 deletions packages/sdk/src/sdk/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -508,7 +501,7 @@ const initializeApis = ({
)

const challenges = new ChallengesApi(
apiClientConfigWithDiscoveryNodeSelector,
apiClientConfig,
users,
services.discoveryNodeSelector,
services.rewardManagerClient,
Expand Down
2 changes: 1 addition & 1 deletion packages/web/e2e/auth.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand Down
2 changes: 1 addition & 1 deletion packages/web/e2e/data.seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
1 change: 1 addition & 0 deletions packages/web/src/app/web-player/WebPlayer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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), {
Expand Down