Skip to content

Commit

Permalink
Merge pull request #59 from Superlight-Labs/53-improve-onboarding-exp…
Browse files Browse the repository at this point in the history
…erience-2

53 improve onboarding experience 2
  • Loading branch information
lauhon authored Aug 2, 2023
2 parents 58344b6 + 3c3153f commit 711e3d4
Show file tree
Hide file tree
Showing 14 changed files with 67 additions and 41 deletions.
2 changes: 2 additions & 0 deletions apps/api/doctl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ services:
value:
- key: TATUM_MAIN_TOKEN
scope: RUN_AND_BUILD_TIME
type: SECRET
value:
- key: API_HOST
scope: RUN_AND_BUILD_TIME
value: 0.0.0.0
Expand Down
7 changes: 4 additions & 3 deletions apps/api/src/lib/routes/rest/rest-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const mapRouteError = (err: RouteError): HttpError => {
case 'Conflict': {
return {
statusCode: 409,
errorMsg: 'Conflict',
errorMsg: err.context,
};
}

Expand Down Expand Up @@ -83,7 +83,7 @@ enum ErrorTypes {

export type RouteError =
| { type: ErrorTypes.NotFound; context?: string }
| { type: ErrorTypes.Conflict; context?: string }
| { type: ErrorTypes.Conflict; context: string; error: unknown }
| { type: ErrorTypes.Other; error?: unknown; context?: string }
| { type: ErrorTypes.ThirdPartyError; error?: unknown; context?: string }
| { type: ErrorTypes.MissingHeader }
Expand All @@ -100,9 +100,10 @@ export const notFound = (context?: string): RouteError => ({
context,
});

export const conflict = (context?: string): RouteError => ({
export const conflict = (error: unknown, context: string): RouteError => ({
type: ErrorTypes.Conflict,
context,
error,
});

export const other = (context: string, error?: unknown): RouteError => ({
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const createServer = async (client: PrismaClient) => {
logger.info({ config }, 'Started up server with config');

// eslint-disable-next-line @typescript-eslint/no-var-requires
server.register(websocketPlugin);
server.register(websocketPlugin, { options: { perMessageDeflate: true } });
server.register(fastifyCookie, {
secret: config.cookieSecret,
});
Expand Down
17 changes: 9 additions & 8 deletions apps/api/src/service/data/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@ import { okAsync, ResultAsync } from 'neverthrow';
import { createUser, readUser } from 'src/repository/user.repository';
import { CreateUserRequest } from 'src/routes/user.routes';
import { CreateUserResponse, VerifyUserRequest } from '../../repository/user';
import { mapPrismaError } from '../prisma.service';

export const createNewUser = (
request: CreateUserRequest,
nonce: string
): ResultAsync<CreateUserResponse, RouteError> => {
return ResultAsync.fromPromise(createUser(request), e => other('Err while creating user', e)).map(
user => {
return {
nonce,
userId: user.id,
};
}
);
return ResultAsync.fromPromise(createUser(request), e =>
mapPrismaError('Err while creating user', e)
).map(user => {
return {
nonce,
userId: user.id,
};
});
};

export const verifyUser = (
Expand Down
17 changes: 17 additions & 0 deletions apps/api/src/service/prisma.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { RouteError, conflict, other } from '@lib/routes/rest/rest-error';
import { Prisma } from '@prisma/client';

export const mapPrismaError = (context: string, error: unknown): RouteError => {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
if (error.code === 'P2002') {
if (error.meta?.target && (error.meta.target as string).toLowerCase().includes('email')) {
return conflict(error, 'Email is already taken!');
}

return conflict(error, 'Request Conflicts with existing data!');
}
}

// Generic errors
return other(context, error);
};
35 changes: 15 additions & 20 deletions apps/mobile/ios/Superlight.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,8 @@
8909586346F1446FBC7F38F7 /* Manrope-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = CF90E6F5E18444DB80ACA389 /* Manrope-Bold.ttf */; };
9C1BE90F5B3BA00E499DC053 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 002007F0D7865D85912CB008 /* ExpoModulesProvider.swift */; };
BE0FED711FA04793A393A36C /* Manrope-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F08E3A02C91D4C128BD059C6 /* Manrope-Medium.ttf */; };
25EB0FAE214446E7A07AF781 /* lines-1.png in Resources */ = {isa = PBXBuildFile; fileRef = E6E0257A114043B4A54C83B7 /* lines-1.png */; };
8DFA3EA403164E198B9A1B9A /* lines-2.png in Resources */ = {isa = PBXBuildFile; fileRef = D8C740F384284231850614D3 /* lines-2.png */; };
4AF1EC8F562D4385BE4B620D /* lines-3.png in Resources */ = {isa = PBXBuildFile; fileRef = 9CD4FE5492754BC7A570431F /* lines-3.png */; };
D1132E7761E246F8B450E797 /* lines-4.png in Resources */ = {isa = PBXBuildFile; fileRef = B2A24E60FF2E4743AE1A34DF /* lines-4.png */; };
5E9550C5406A41F78245A2AB /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = D422B90EFC7945CCBFF2D46F /* logo.png */; };
CF6ED7F52A57128500BFB77F /* main.jsbundle in Resources */ = {isa = PBXBuildFile; fileRef = CF6ED7F42A57128500BFB77F /* main.jsbundle */; };
CF1E73642A66B9D5001B4F41 /* main.jsbundle in Resources */ = {isa = PBXBuildFile; fileRef = CF1E73632A66B9D5001B4F41 /* main.jsbundle */; };
CFD06DA52A7940B6001ACBF8 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = CFD06DA42A7940B6001ACBF8 /* assets */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -68,18 +64,19 @@
8E443CD86058416CC171C21D /* Pods-Superlight-SuperlightTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Superlight-SuperlightTests.debug.xcconfig"; path = "Target Support Files/Pods-Superlight-SuperlightTests/Pods-Superlight-SuperlightTests.debug.xcconfig"; sourceTree = "<group>"; };
9171F8B77B2EBF4AAD38B811 /* Pods-Superlight.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Superlight.release.xcconfig"; path = "Target Support Files/Pods-Superlight/Pods-Superlight.release.xcconfig"; sourceTree = "<group>"; };
98EE0A596452B594DB83D18E /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-Superlight-appTests/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
CF6ED7F42A57128500BFB77F /* main.jsbundle */ = {isa = PBXFileReference; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
9CD4FE5492754BC7A570431F /* lines-3.png */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "lines-3.png"; path = "../assets/images/lines-3.png"; sourceTree = "<group>"; };
B2A24E60FF2E4743AE1A34DF /* lines-4.png */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "lines-4.png"; path = "../assets/images/lines-4.png"; sourceTree = "<group>"; };
CF1E73632A66B9D5001B4F41 /* main.jsbundle */ = {isa = PBXFileReference; lastKnownFileType = text; name = main.jsbundle; path = ../main.jsbundle; sourceTree = "<group>"; };
CF90E6F5E18444DB80ACA389 /* Manrope-Bold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Manrope-Bold.ttf"; path = "../assets/fonts/Manrope-Bold.ttf"; sourceTree = "<group>"; };
CFD06DA42A7940B6001ACBF8 /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; path = assets; sourceTree = "<group>"; };
D422B90EFC7945CCBFF2D46F /* logo.png */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = logo.png; path = ../assets/images/logo.png; sourceTree = "<group>"; };
D8C740F384284231850614D3 /* lines-2.png */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "lines-2.png"; path = "../assets/images/lines-2.png"; sourceTree = "<group>"; };
E106C76C9437E735DA760AED /* Pods-Superlight-SuperlightTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Superlight-SuperlightTests.release.xcconfig"; path = "Target Support Files/Pods-Superlight-SuperlightTests/Pods-Superlight-SuperlightTests.release.xcconfig"; sourceTree = "<group>"; };
E6E0257A114043B4A54C83B7 /* lines-1.png */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "lines-1.png"; path = "../assets/images/lines-1.png"; sourceTree = "<group>"; };
E810E9BABA4AB7BA20CE55C8 /* libPods-Superlight-SuperlightTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Superlight-SuperlightTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
F08E3A02C91D4C128BD059C6 /* Manrope-Medium.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Manrope-Medium.ttf"; path = "../assets/fonts/Manrope-Medium.ttf"; sourceTree = "<group>"; };
FC51D5329F0795FDCFB7B890 /* libPods-Superlight.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Superlight.a"; sourceTree = BUILT_PRODUCTS_DIR; };
E6E0257A114043B4A54C83B7 /* lines-1.png */ = {isa = PBXFileReference; name = "lines-1.png"; path = "../assets/images/lines-1.png"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
D8C740F384284231850614D3 /* lines-2.png */ = {isa = PBXFileReference; name = "lines-2.png"; path = "../assets/images/lines-2.png"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
9CD4FE5492754BC7A570431F /* lines-3.png */ = {isa = PBXFileReference; name = "lines-3.png"; path = "../assets/images/lines-3.png"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
B2A24E60FF2E4743AE1A34DF /* lines-4.png */ = {isa = PBXFileReference; name = "lines-4.png"; path = "../assets/images/lines-4.png"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
D422B90EFC7945CCBFF2D46F /* logo.png */ = {isa = PBXFileReference; name = "logo.png"; path = "../assets/images/logo.png"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -170,6 +167,8 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
CFD06DA42A7940B6001ACBF8 /* assets */,
CF1E73632A66B9D5001B4F41 /* main.jsbundle */,
13B07FAE1A68108700A75B9A /* Superlight */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* SuperlightTests */,
Expand Down Expand Up @@ -331,19 +330,16 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CF1E73642A66B9D5001B4F41 /* main.jsbundle in Resources */,
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
8909586346F1446FBC7F38F7 /* Manrope-Bold.ttf in Resources */,
BE0FED711FA04793A393A36C /* Manrope-Medium.ttf in Resources */,
CFD06DA52A7940B6001ACBF8 /* assets in Resources */,
6592C7485FEF4BDA8EA4A865 /* Manrope-Regular.ttf in Resources */,
0264C8B579B240AE93F0DEF2 /* Inter-Bold.ttf in Resources */,
11BCB591E2B1445CB5A2EBD9 /* Inter-Medium.ttf in Resources */,
32154BA1B34945699A06CF8C /* Inter-Regular.ttf in Resources */,
25EB0FAE214446E7A07AF781 /* lines-1.png in Resources */,
8DFA3EA403164E198B9A1B9A /* lines-2.png in Resources */,
4AF1EC8F562D4385BE4B620D /* lines-3.png in Resources */,
D1132E7761E246F8B450E797 /* lines-4.png in Resources */,
5E9550C5406A41F78245A2AB /* logo.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -629,10 +625,9 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 10;
CURRENT_PROJECT_VERSION = 16;
DEVELOPMENT_TEAM = BXB7RBS9FX;
ENABLE_BITCODE = NO;

INFOPLIST_FILE = Superlight/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Superlight;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.finance";
Expand Down Expand Up @@ -665,7 +660,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 10;
CURRENT_PROJECT_VERSION = 16;
DEVELOPMENT_TEAM = BXB7RBS9FX;
INFOPLIST_FILE = Superlight/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Superlight;
Expand Down
Binary file added apps/mobile/ios/assets/assets/images/lines-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/mobile/ios/assets/assets/images/lines-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/mobile/ios/assets/assets/images/lines-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/mobile/ios/assets/assets/images/lines-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/mobile/ios/assets/assets/images/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion apps/mobile/src/hooks/useCreateAuth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CreateUserResponse } from '@superlight-labs/api/src/repository/user';
import { AppError, SignResult, appError } from '@superlight-labs/mpc-common';
import { AxiosError } from 'axios';
import { ResultAsync } from 'neverthrow';
import { AppUser } from 'state/auth.state';
import { SignUser, signWithDeviceKeyNoAuth } from 'utils/auth';
Expand All @@ -25,7 +26,15 @@ const createUser = (
email,
devicePublicKey,
}),
error => appError(error, 'Error while creating user')
error => {
let msg = 'Error while creating user';

if (error instanceof AxiosError) {
msg = error.response?.data?.error;
}

return appError(error, msg);
}
).map(axiosResponse => ({ ...axiosResponse.data, devicePublicKey }));

const createSignature = (user: SignUser & { nonce: string }): ResultAsync<SignResult, AppError> => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Title from 'components/shared/title/title.component';
import { useCreateAuth } from 'hooks/useCreateAuth';
import { useFailableAction } from 'hooks/useFailable';
import { useCallback, useState } from 'react';
import { Keyboard } from 'react-native';
import { RootStackParamList } from 'screens/main-navigation';
import { useAuthState } from 'state/auth.state';
import { constants } from 'utils/constants';
Expand All @@ -24,6 +25,7 @@ const OnboardingScreen = ({ navigation }: Props) => {
const { perform } = useFailableAction();

const getStarted = useCallback(async () => {
Keyboard.dismiss();
const newDevicePublicKey = await generateKeyPair(constants.deviceKeyName);

perform(createProfile(newDevicePublicKey, username, email)).onSuccess(user => {
Expand All @@ -35,7 +37,8 @@ const OnboardingScreen = ({ navigation }: Props) => {
if (username.length < 3 || email.length < 3) return true;
if (username.length > 36 || email.length > 100) return true;

if (!email.includes('@')) return true;
if (!email.includes('@') || email.endsWith('@') || email.endsWith('.') || !email.includes('.'))
return true;

return false;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ export const createWebsocket = Result.fromThrowable(
// TODO check if JWT makes sense here, this is a bit custom
try {
const ws = new WebSocket(
`${getProtocol(
process.env.NODE_ENV || 'development'
)}://${baseUrlWithoutProtocol}/mpc/ecdsa/${socketEndpoint}`,
`${getProtocol()}://${baseUrlWithoutProtocol}/mpc/ecdsa/${socketEndpoint}`,
undefined,
{
headers: {
Expand Down Expand Up @@ -101,10 +99,10 @@ export const logIncommingMessages = {
complete: () => logger.debug('Connection on Websocket closed'),
};

const getProtocol = (env: string) => {
if (env === 'production') {
return 'wss';
} else {
const getProtocol = () => {
if (__DEV__) {
return 'ws';
} else {
return 'wss';
}
};

0 comments on commit 711e3d4

Please sign in to comment.