Skip to content

Commit

Permalink
Merge branch 'main' into new-feed-improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
mantikoros committed Dec 14, 2024
2 parents d4aa3bb + e5f797f commit 5cacf76
Show file tree
Hide file tree
Showing 178 changed files with 19,233 additions and 177 deletions.
43 changes: 36 additions & 7 deletions backend/api/src/get-leaderboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ export const getLeaderboard: APIHandler<'leaderboard'> = async ({

if (kind === 'referral') {
const data = await pg.any(
`select id, total_referrals, total_referred_profit, total_referred_cash_profit
from user_referrals_profit limit $1`,
`select ur.id, ur.total_referrals, ur.total_referred_profit, ur.total_referred_cash_profit
from user_referrals_profit ur
join users u on ur.id = u.id
where coalesce((u.data->>'isBannedFromPosting')::boolean, false) is not true
limit $1`,
[limitValue]
)

Expand All @@ -41,13 +44,17 @@ export const getLeaderboard: APIHandler<'leaderboard'> = async ({
if ((kind == 'profit' || kind == 'loss') && !groupId) {
const query = renderSql(
from('user_portfolio_history_latest uph'),
join('users u on u.id = uph.user_id'),
select('uph.user_id as user_id'),
token === 'MANA'
? select('uph.profit as score') // excludes unranked
: select(
'uph.cash_balance + uph.cash_investment_value - uph.total_cash_deposits as score'
),
where('user_id not in ($1:list)', [HIDE_FROM_LEADERBOARD_USER_IDS]),
where(
`coalesce((u.data->>'isBannedFromPosting')::boolean, false) is not true`
),
orderBy(kind === 'loss' ? 'score asc' : 'score desc nulls last'),
limit(limitValue)
)
Expand All @@ -56,17 +63,39 @@ export const getLeaderboard: APIHandler<'leaderboard'> = async ({
score: r.score,
}))
}
if (kind === 'creator') {
const query = renderSql(
from('contracts c'),
join('users u on u.id = c.creator_id'),
select(
`c.creator_id as user_id, sum((c.data->'uniqueBettorCount')::bigint) as score`
),
groupBy('c.creator_id'),
where(`coalesce((c.data->'isRanked')::boolean, true) = true`), // unranked included in portfolio
where(
`coalesce((u.data->>'isBannedFromPosting')::boolean, false) is not true`
),
where('c.token = ${token}', { token }),
where('c.outcome_type != ${outcomeType}', { outcomeType: 'POLL' }),
where('c.outcome_type != ${outcomeType}', { outcomeType: 'BOUNTY' }),
orderBy('score desc nulls last'),
limit(limitValue)
)
return await pg.map(query, [], (r) => ({
userId: r.user_id,
score: r.score,
}))
}

const query = renderSql(
from('contracts c'),
join('user_contract_metrics ucm on ucm.contract_id = c.id'),
join('users u on u.id = ucm.user_id'),
where('ucm.answer_id is null'),
where(`coalesce((c.data->'isRanked')::boolean, true) = true`),

kind === 'creator' && [
select('c.creator_id as user_id, count(*) as score'),
groupBy('c.creator_id'),
],
where(
`coalesce((u.data->>'isBannedFromPosting')::boolean, false) is not true`
),

(kind === 'profit' || kind === 'loss') && [
select(`user_id, sum(profit) as score`),
Expand Down
32 changes: 17 additions & 15 deletions backend/api/src/get-site-activity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ import { convertContractComment } from 'common/supabase/comments'
export const getSiteActivity: APIHandler<'get-site-activity'> = async (
props
) => {
const {
limit,
blockedUserIds = [],
blockedGroupSlugs = [],
blockedContractIds = [],
} = props
const pg = createSupabaseDirectClient()
const { limit, offset = 0, blockedGroupSlugs = [], blockedContractIds = [] } = props
log('getSiteActivity called', { limit })

const blockedUserIds = [
'FDWTsTHFytZz96xmcKzf7S5asYL2', // yunabot (does a lot of manual trades)
...(props.blockedUserIds ?? []),
]
const pg = createSupabaseDirectClient()

const [recentBets, limitOrders, recentComments, newContracts] =
await Promise.all([
pg.manyOrNone(
Expand All @@ -32,10 +32,11 @@ export const getSiteActivity: APIHandler<'get-site-activity'> = async (
) THEN 5
ELSE 500
END
and is_api is not true
and user_id != all($1)
and contract_id != all($2)
order by created_time desc limit $3`,
[blockedUserIds, blockedContractIds, limit]
order by created_time desc limit $3 offset $4`,
[blockedUserIds, blockedContractIds, limit, offset]
),
pg.manyOrNone(
`select * from contract_bets
Expand All @@ -48,20 +49,21 @@ export const getSiteActivity: APIHandler<'get-site-activity'> = async (
) then 50
else 5000
end
and is_api is not true
and (data->>'isFilled')::boolean = false
and (data->>'isCancelled')::boolean = false
and user_id != all($1)
and contract_id != all($2)
order by created_time desc limit $3`,
[blockedUserIds, blockedContractIds, limit]
order by created_time desc limit $3 offset $4`,
[blockedUserIds, blockedContractIds, limit, offset]
),
pg.manyOrNone(
`select * from contract_comments
where (likes - coalesce(dislikes, 0)) >= 2
and user_id != all($1)
and contract_id != all($2)
order by created_time desc limit $3`,
[blockedUserIds, blockedContractIds, limit]
order by created_time desc limit $3 offset $4`,
[blockedUserIds, blockedContractIds, limit, offset]
),
pg.manyOrNone(
`select * from contracts
Expand All @@ -75,8 +77,8 @@ export const getSiteActivity: APIHandler<'get-site-activity'> = async (
where gc.contract_id = contracts.id
and g.slug = any($3)
)
order by created_time desc limit $4`,
[blockedUserIds, blockedContractIds, blockedGroupSlugs, limit]
order by created_time desc limit $4 offset $5`,
[blockedUserIds, blockedContractIds, blockedGroupSlugs, limit, offset]
),
])

Expand Down
14 changes: 2 additions & 12 deletions backend/api/src/resolve-market.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,12 @@ export const resolveMarketMain: APIHandler<
if (outcomeType === 'STONK') {
throw new APIError(403, 'STONK contracts cannot be resolved')
}
if (
props.outcome === 'CANCEL' &&
outcomeType === 'MULTIPLE_CHOICE' &&
contract.mechanism === 'cpmm-multi-1' &&
!contract.shouldAnswersSumToOne
) {
throw new APIError(
403,
'Independent multiple choice markets cannot currently be resolved n/a'
)
}

const caller = await getUser(auth.uid)
if (!caller) throw new APIError(400, 'Caller not found')
if (caller.isBannedFromPosting || caller.userDeleted)
throw new APIError(403, 'Deleted or banned user cannot resolve markets')
if (creatorId !== auth.uid) await throwErrorIfNotMod(auth.uid)
if (creatorId !== auth.uid) throwErrorIfNotMod(auth.uid)

if (
isProd() &&
Expand Down
1 change: 1 addition & 0 deletions common/src/api/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2000,6 +2000,7 @@ export const API = (_apiTypeCheck = {
props: z
.object({
limit: z.coerce.number().default(10),
offset: z.coerce.number().default(0),
blockedUserIds: z.array(z.string()).optional(),
blockedGroupSlugs: z.array(z.string()).optional(),
blockedContractIds: z.array(z.string()).optional(),
Expand Down
5 changes: 4 additions & 1 deletion common/src/payouts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ export const getIndependentMultiFixedPayouts = (
)
default:
case 'CANCEL':
return getFixedCancelPayouts(contractMetrics, filteredLiquidities)
return getFixedCancelPayouts(
contractMetrics.filter((metric) => metric.answerId === answer.id),
filteredLiquidities
)
}
}
4 changes: 4 additions & 0 deletions mani/.expo-shared/assets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
}
31 changes: 31 additions & 0 deletions mani/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
node_modules/
.expo/
dist/
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
credentials.json
credentials/
*.apk
*.aab
*.ipa
project.pbxproj
ios/Manifold/GoogleService-Info.plist
ios/Manifold.xcodeproj/project.pbxproj
/google-services.json
# macOS
.DS_Store
# simulator build
*.tar.gz
.env.local

# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
# The following patterns were generated by expo-cli

expo-env.d.ts
# @end expo-cli
128 changes: 128 additions & 0 deletions mani/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
We're using Expo to help with android and ios builds. You can find more information about Expo here: https://docs.expo.dev/introduction/expo/

## Installing

- The `native/` directory is not part of the yarn workspace, so you have to run `yarn` in the `native/` directory to install dependencies.
- You will need to install the Expo CLI globally: `npm install -g expo-cli`
- You need to set the `SENTRY_AUTH_TOKEN` via `eas:secret` [link](https://docs.expo.dev/build-reference/variables/#using-secrets-in-environment-variables)
- You need to make sure the Manifold Markets, Inc. team is set as the signer for app builds in Xcode - open up ios directory in Xcode and set the signing account.
- You need to register your device for development builds with Expo and install a provisioning profile, see the [Running a build](https://docs.expo.dev/development/build/) section with `eas device:create`

## Configuration

- `app.json` and `app.config.js` are the configuration files that determine basic functioning of the app. If you change them you'll have to clean your `android` and `ios` folders via `yarn clean`

## Developing

1. Connect your phone to your computer
2. **iOS**:
- `yarn build:ios:client:prod` or `yarn build:ios:client:dev` to build a dev client and drag it onto your iPhone to install it.
- `yarn start` or `yarn start:dev` and scan the QR code with camera
- Keep a dev client build in the native directory so you can just drag and drop them onto your phone to install them
3. **Android**:
- `yarn android:dev` or `yarn android:prod` builds and installs the dev client on your device automatically
- Scan the QR code with the app (it opens automatically after installing)
4. **Locally hosted manifold**:
- Set the `NEXT_PUBLIC_API_URL` in dev.sh to your local ip address
- Run `dev.sh prod` or `dev.sh dev` to start the local server
- Change the `baseUri` in `App.tsx` to your local ip address
- Follow one of the Android or iOS steps to start the app on your device

- **Note:** when switching between dev and prod you'll have to run `yarn clear` & Ctrl+C to clear the env variable.
- Want to see console logs? (Only works on android):
- Set the `NEXT_PUBLIC_API_URL` in dev.sh to your local ip address
- Change the `baseUri` in `App.tsx` to your local ip address
- `$ yarn android:prod` to start the app on your device
- On your computer, navigate to `chrome://inspect/#devices` in chrome and click inspect on the app
- Want to see app logs of a production build? (Only works on android):
- `$ adb logcat --pid=$(adb shell pidof -s com.markets.manifold)`

## Building

- You'll need to get Android signing credentials from Ian (located [here](https://drive.google.com/drive/folders/155gaiY97oY0IkQvHGKHqKbXEeO4LaVCe?usp=sharing)) to properly sign android builds for the google play store. You'll probably need to be added to the Apple Business developer team when we get that to build ios apps.
- After changing anything in the `app.config.js` or `app.json` you'll want to run `npx expo prebuild` to clear the android and ios folders
- Before every build we clean and reset the git tree so you'll want to make sure any changes are committed. The dialog will ask you to confirm this.
- After every build your git tree may be dirty with build artifacts. I tried removing these and ended up down in a git-sponsored nightmare, so I wouldn't advise trying to edit these files out of the git history unless you really know what you're doing.
- The following commands build the binaries locally by default. If you remove the `--local` flag it will build in the EAS/Expo cloud, (this tends to be much slower, though).
- Before every submission to the app store you'll want to bump the following fields in `app.json`:
- `expo.version`
- `expo.ios.buildNumber`
- `expo.android.versionCode`

**For Internal Testing**
`yarn build:android:preview`

- Builds an Android APK for previewing on a device
- `adb install build_name_here.apk` after it's built to install

`yarn build:ios:prod`

- Builds an iOS IPA that you can upload to TestFlight

`yarn build:ios:preview`

- Builds an iOS IPA for previewing on a device
- Drag and drop onto your plugged in iPhone Finder window to install

**External**
`yarn build:android:prod`

- Builds an Android App Bundle for Google Play distribution
- Upload to Google Play Console

`yarn build:ios:prod`

- Builds an iOS IPA for App Store distribution
- I think we use Transporter once we have our Apple Business Developer account set up

### OTA updates

`eas update --branch default` to publish an over-the-air update to production

### Adding Environment Variables

- Set the variable in `package.json` (used for local development aka `yarn ios:prod`)
- Add the key-value pair to the `extra.eas` object in `app.config.js` with value `process.env.YOUR_ENV_VARIABLE`
- Set the build variable in `eas.json` for the profile you want (used for eas builds aka `yarn build:ios:prod`)
- Reference it in js: `Constants.expoConfig?.extra?.eas.YOUR_ENV_VARIABLE`
- Run `yarn clear` to clear the env variable between builds

# Icons

find icons [here](https://icons.expo.fyi/)

## Notes

- The dev and prod version of the app use the same application id (`com.markets.manifold`). This may not be not ideal but it works.
- Notifications on android dev I think won't work bc we have to use Firebase's server signing key to send push notifications and I just linked our application id (com.markets.manifold) to the prod server signing key. To fix I'd have to have a separate application id for dev, which I could do but you can just test on prod
- Try out sending push notifications [here](https://expo.dev/notifications) (using the `pushToken` from your `private-user` object)
- Google play release console [here](https://play.google.com/console/u/1/developers/4817631028794628961/app/4973740210331758857/releases/overview)

## Monitoring

- [Sentry](https://sentry.io/organizations/manifold-markets/projects/react-native/?issuesType=new&project=4504040585494528)

## Updating Expo

- Check out the [helper guide](https://docs.expo.dev/bare/upgrade/?fromSdk=50&toSdk=51)

### Problems with building android after deleting `android/`

- `However we cannot choose between the following variants of project :react-native-iap: - amazonDebugRuntimeElements - playDebugRuntimeElements`
- Add `missingDimensionStrategy 'store', 'play'` to `android/app/build.gradle` in the `defaultConfig` section
- `error: cannot find symbol import com.markets.BuildConfig;`
- Add `namespace "com.markets.manifold"` in place of `namespace "com.manifold"` to `app/build.gradle`
- Add `package com.markets.manifold;` in place of incorrect package at the top of `native/android/app/src/release/java/com/manifold/ReactNativeFlipper.java`

## Troubleshooting

- getting an errors on build/install? like `Error: spawn .../manifold/native/android/gradlew EACCES`
- Delete the `android` or `ios` folders or run `yarn clean` and try again.
- environment variables not working? like `process.env.API_URL` is undefined
- Try running `yarn clear` and ctrl+c to clear the env variable and try again
- When in doubt: `yarn clean`
- Fastlane build failing? Could be a malformed import
- Pod install erroring out?
- I had to reinstall cocoapods via [these instructions](https://github.com/expo/expo/issues/20707#issuecomment-1377790160)
- Sentry problems? `sentry.properties` file not found or malformed?
- `eas build` couldn't find the sentry.properties file in the `android` directory generated from `eas.json`, so I set its path in eas.json to the root. If it's malformed, check the diff from the ones in the `ios` and `android` directories which are autogenerated from `eas.json`.
16 changes: 16 additions & 0 deletions mani/Supporting/Expo.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EXUpdatesCheckOnLaunch</key>
<string>ALWAYS</string>
<key>EXUpdatesEnabled</key>
<true/>
<key>EXUpdatesLaunchWaitMs</key>
<integer>0</integer>
<key>EXUpdatesSDKVersion</key>
<string>46.0.0</string>
<key>EXUpdatesURL</key>
<string>https://exp.host/@my-expo-username/my-app</string>
</dict>
</plist>
16 changes: 16 additions & 0 deletions mani/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# OSX
#
.DS_Store

# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
.cxx/

# Bundle artifacts
*.jsbundle
Loading

0 comments on commit 5cacf76

Please sign in to comment.