Skip to content

Commit

Permalink
feat: Tip Claim frontend integration (#202)
Browse files Browse the repository at this point in the history
* Tip claim frontend integration

* Change fee calculation

* Use env for app

* Set estimation gas amount to 1 & tips icon

* Fix estimated fee

* Install wallet dialog

* Transaction hash text

* Fix estimation

* Disable STRK & JBY tokens

* Toast container padding

* Picker web style

* Change fee multiplication
  • Loading branch information
ugur-eren authored Jul 3, 2024
1 parent a05cec5 commit 384f168
Show file tree
Hide file tree
Showing 39 changed files with 619 additions and 246 deletions.
6 changes: 6 additions & 0 deletions JoyboyCommunity/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
EXPO_PUBLIC_NETWORK="SN_SEPOLIA" # SN_SEPOLIA, SN_MAIN
EXPO_PUBLIC_PROVIDER_URL="https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_7/your_api_key"

EXPO_PUBLIC_BACKEND_URL="http://localhost:3000/api"

EXPO_PUBLIC_WC_ID="your_wallet_connect_project_id"
2 changes: 2 additions & 0 deletions JoyboyCommunity/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@tanstack/react-query": "^5.40.0",
"@uniswap/sdk-core": "^5.3.1",
"@walletconnect/react-native-compat": "^2.13.3",
"axios": "^1.7.2",
"buffer": "^6.0.3",
"crypto-es": "^2.1.0",
"events": "^3.3.0",
Expand Down Expand Up @@ -71,6 +72,7 @@
"react-native-tab-view": "^3.5.2",
"react-native-web": "~0.19.6",
"starknet": "6.9.0",
"starknetkit": "^1.1.9",
"zustand": "^4.5.2"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions JoyboyCommunity/src/app/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ const HomeBottomTabNavigator: React.FC = () => {
/>

<HomeBottomTabsStack.Screen
name="Messages"
name="Tips"
component={Tips}
options={{
tabBarActiveTintColor: 'white',
tabBarInactiveTintColor: 'grey',
tabBarIcon: ({focused}) => (
<View style={{flex: 1, alignItems: 'center', gap: 4, justifyContent: 'center'}}>
<Icon
name="MessageIcon"
name="CoinIcon"
size={24}
color={focused ? 'bottomBarActive' : 'bottomBarInactive'}
/>
Expand Down
33 changes: 16 additions & 17 deletions JoyboyCommunity/src/app/StarknetProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {sepolia} from '@starknet-react/chains';
import {mainnet, sepolia} from '@starknet-react/chains';
import {
argent,
braavos,
infuraProvider,
StarknetConfig,
useInjectedConnectors,
voyager,
Expand All @@ -12,43 +11,43 @@ import {
useArgentMobileConnector,
} from '@starknet-wc/react';
import {Platform} from 'react-native';
import {constants} from 'starknet';

import {NETWORK_NAME, WALLET_CONNECT_ID} from '../constants/env';
import {RpcProviderProvider} from '../context/RpcProvider';
import {WalletQRModal} from '../modules/WalletQRModal';
import {providers} from '../services/provider';

export const StarknetReactProvider: React.FC<React.PropsWithChildren> = ({children}) => {
const {connectors} = useInjectedConnectors({
// Show these connectors if the user has no connector installed.
const chain = {
SN_MAIN: mainnet,
SN_SEPOLIA: sepolia,
}[NETWORK_NAME];

const provider = providers(chain);

const {connectors: injected} = useInjectedConnectors({
recommended: [argent(), braavos()],
// Hide recommended connectors if the user has any connector installed.
includeRecommended: 'onlyIfNoConnectors',
// Randomize the order of the connectors.
order: 'random',
includeRecommended: 'always',
});

const argentMobileConnector = useArgentMobileConnector();

const providers = infuraProvider({apiKey: '98f462b6b2644cadae88bdb695e467bf'});
const provider = providers(sepolia);

return (
<RpcProviderProvider provider={provider}>
<StarknetConfig
chains={[sepolia]}
chains={[chain]}
provider={providers}
connectors={[
argentMobileConnector({
chain: constants.NetworkName.SN_SEPOLIA,
// TODO: Move this to ENV
wcProjectId: 'a9b4b052eb741f95a54c90ac5bdb343e',
chain: NETWORK_NAME,
wcProjectId: WALLET_CONNECT_ID,
dappName: 'Joyboy',
description: 'Joyboy Starknet dApp',
url: 'https://joyboy.community',
provider,
}),

...(Platform.OS === 'web' ? connectors : []),
...(Platform.OS === 'web' ? injected : []),
]}
explorer={voyager}
>
Expand Down
36 changes: 18 additions & 18 deletions JoyboyCommunity/src/app/Wrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ const queryClient = new QueryClient({
const ModalProviders = ({children}: {children: React.ReactNode}) => {
return (
<ToastProvider>
<DialogProvider>
<WalletModalProvider>
<TransactionModalProvider>
<TipModalProvider>{children}</TipModalProvider>
</TransactionModalProvider>
</WalletModalProvider>
</DialogProvider>
<WalletModalProvider>
<TransactionModalProvider>
<TipModalProvider>{children}</TipModalProvider>
</TransactionModalProvider>
</WalletModalProvider>
</ToastProvider>
);
};
Expand All @@ -38,17 +36,19 @@ export const Wrapper: React.FC = () => {
<ThemeProvider>
<NostrProvider>
<QueryClientProvider client={queryClient}>
<StarknetProvider>
<SafeAreaProvider>
<PortalizeProvider>
<ModalProviders>
<RootScreenContainer>
<App />
</RootScreenContainer>
</ModalProviders>
</PortalizeProvider>
</SafeAreaProvider>
</StarknetProvider>
<SafeAreaProvider>
<PortalizeProvider>
<DialogProvider>
<StarknetProvider>
<ModalProviders>
<RootScreenContainer>
<App />
</RootScreenContainer>
</ModalProviders>
</StarknetProvider>
</DialogProvider>
</PortalizeProvider>
</SafeAreaProvider>
</QueryClientProvider>
</NostrProvider>
</ThemeProvider>
Expand Down
8 changes: 7 additions & 1 deletion JoyboyCommunity/src/components/Picker/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Picker as RNPicker, PickerProps as RNPickerProps} from '@react-native-picker/picker';
import {forwardRef} from 'react';
import {Platform} from 'react-native';

import {useStyles} from '../../hooks';
import {PickerContainer} from '../PickerContainer';
Expand All @@ -21,7 +22,12 @@ export const _Picker = forwardRef<RNPicker<string>, PickerProps>((props, ref) =>
containerStyle={styles.container}
textProps={{fontSize: 15, weight: 'semiBold', color: 'inputText'}}
>
<RNPicker ref={ref} selectedValue={selectedValue} {...restProps}>
<RNPicker
ref={ref}
selectedValue={selectedValue}
style={Platform.OS === 'web' && styles.web}
{...restProps}
>
{children}
</RNPicker>
</PickerContainer>
Expand Down
20 changes: 18 additions & 2 deletions JoyboyCommunity/src/components/Picker/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,27 @@ import {Spacing, ThemedStyleSheet} from '../../styles';

export default ThemedStyleSheet((theme) => ({
container: {
paddingVertical: Platform.OS === 'android' ? Spacing.none : Spacing.medium,
paddingHorizontal: Platform.OS === 'android' ? Spacing.medium : Spacing.large,
paddingVertical: Platform.select({
android: Spacing.none,
ios: Spacing.medium,
web: Spacing.none,
}),
paddingHorizontal: Platform.select({
android: Spacing.medium,
ios: Spacing.large,
web: Spacing.medium,
}),
borderWidth: 1,
borderColor: theme.colors.inputBorder,
backgroundColor: theme.colors.inputBackground,
borderRadius: 99,
},

web: {
backgroundColor: theme.colors.transparent,
borderWidth: 0,
borderRadius: 0,
paddingVertical: Spacing.medium,
paddingHorizontal: Spacing.xsmall,
},
}));
2 changes: 1 addition & 1 deletion JoyboyCommunity/src/constants/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import {constants} from 'starknet';
export const ESCROW_ADDRESSES = {
[constants.StarknetChainId.SN_MAIN]: '', // TODO: Add mainnet escrow address
[constants.StarknetChainId.SN_SEPOLIA]:
'0x017472b4ed23f5ef7faa41c8c2026ac4b251f8a48baa210e07fe811ed4d9cac1',
'0x078a022e6906c83e049a30f7464b939b831ecbe47029480d7e89684f20c8d263',
};
15 changes: 15 additions & 0 deletions JoyboyCommunity/src/constants/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {constants} from 'starknet';

export const NETWORK_NAME = process.env.EXPO_PUBLIC_NETWORK as constants.NetworkName;
export const PROVIDER_URL = process.env.EXPO_PUBLIC_PROVIDER_URL;

export const BACKEND_URL = process.env.EXPO_PUBLIC_BACKEND_URL;

export const WALLET_CONNECT_ID = process.env.EXPO_PUBLIC_WC_ID;

if (!Object.keys(constants.NetworkName).includes(NETWORK_NAME)) {
throw new Error(`Invalid network name: ${NETWORK_NAME}`);
}
if (!PROVIDER_URL) throw new Error('Missing PROVIDER_URL env variable');
if (!BACKEND_URL) throw new Error('Missing BACKEND_URL env variable');
if (!WALLET_CONNECT_ID) throw new Error('Missing WALLET_CONNECT_ID env variable');
1 change: 1 addition & 0 deletions JoyboyCommunity/src/constants/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export enum Entrypoint {
// Escrow
DEPOSIT = 'deposit',
CLAIM = 'claim',
GET_DEPOSIT = 'get_deposit',
}

export enum EventKey {
Expand Down
12 changes: 6 additions & 6 deletions JoyboyCommunity/src/constants/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export type MultiChainTokens = Record<TokenSymbol, MultiChainToken>;

export enum TokenSymbol {
ETH = 'ETH',
STRK = 'STRK',
JBY = 'JBY',
/* STRK = 'STRK',
JBY = 'JBY', */
}

export const ETH: MultiChainToken = {
Expand All @@ -34,7 +34,7 @@ export const ETH: MultiChainToken = {
},
};

export const STRK: MultiChainToken = {
/* export const STRK: MultiChainToken = {
[constants.StarknetChainId.SN_MAIN]: {
name: 'Stark',
symbol: TokenSymbol.STRK,
Expand Down Expand Up @@ -70,12 +70,12 @@ export const JBY: MultiChainToken = {
'0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
),
},
};
}; */

export const TOKENS: MultiChainTokens = {
[TokenSymbol.ETH]: ETH,
[TokenSymbol.STRK]: STRK,
[TokenSymbol.JBY]: JBY,
/* [TokenSymbol.STRK]: STRK,
[TokenSymbol.JBY]: JBY, */
};

export const TOKEN_ADDRESSES: Record<
Expand Down
3 changes: 3 additions & 0 deletions JoyboyCommunity/src/constants/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ export const ARGENT_APP_STORE_URL_FALLBACK =
export const ARGENT_GOOGLE_PLAY_URL = 'market://details?id=im.argent.contractwalletclient';
export const ARGENT_GOOGLE_PLAY_URL_FALLBACK =
'https://play.google.com/store/apps/details?id=im.argent.contractwalletclient';

export const ARGENT_X_INSTALL_URL = 'https://www.argent.xyz/argent-x/';
export const BRAAVOS_INSTALL_URL = 'https://braavos.app/download-braavos-wallet/';
9 changes: 6 additions & 3 deletions JoyboyCommunity/src/context/Toast/ToastContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {randomUUID} from 'expo-crypto';
import {createContext, useCallback, useMemo, useState} from 'react';
import {View} from 'react-native';
import {SafeAreaView} from 'react-native-safe-area-context';

import {ToastProps} from '../../components/Toast';
Expand Down Expand Up @@ -43,9 +44,11 @@ export const ToastProvider: React.FC<{children: React.ReactNode}> = ({children})

{toasts.length > 0 && (
<SafeAreaView style={styles.container}>
{toasts.map((toast) => (
<AnimatedToast key={toast.key} toast={toast} />
))}
<View style={styles.content}>
{toasts.map((toast) => (
<AnimatedToast key={toast.key} toast={toast} />
))}
</View>
</SafeAreaView>
)}
</ToastContext.Provider>
Expand Down
3 changes: 3 additions & 0 deletions JoyboyCommunity/src/context/Toast/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export default StyleSheet.create({
left: 0,
right: 0,
zIndex: 100,
},
content: {
paddingTop: Spacing.pagePadding,
paddingHorizontal: Spacing.pagePadding,
gap: Spacing.xsmall,
},
Expand Down
2 changes: 2 additions & 0 deletions JoyboyCommunity/src/hooks/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export {useClaim} from './useClaim';
export {useEstimateClaim} from './useEstimateClaim';
49 changes: 49 additions & 0 deletions JoyboyCommunity/src/hooks/api/useApiMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {
QueryClient,
useMutation,
UseMutationOptions,
UseMutationResult,
} from '@tanstack/react-query';
import {AxiosError} from 'axios';
import {useEffect} from 'react';

import {useToast} from '../modals';

export const useApiMutation = <
TFnData = unknown,
TData = TFnData,
TVariables = void,
TContext = unknown,
>(
options: UseMutationOptions<TFnData, AxiosError, TVariables, TContext>,
showErrorToast = true,
queryClient: QueryClient | undefined = undefined,
): UseMutationResult<TData, AxiosError, TVariables, TContext> => {
const mutation = useMutation(options, queryClient);

const {showToast} = useToast();

useEffect(() => {
if (showErrorToast && mutation.error) {
const {response} = mutation.error;
if (!response || typeof response.data !== 'object' || !('code' in response.data)) {
showToast({
type: 'error',
title: 'Request failed with no response, please try again later.',
});
return;
}

showToast({
type: 'error',
title: `Request failed with error code: ${response.data.code}`,
});
}

return () => {
//
};
}, [showErrorToast, mutation.error, showToast]);

return mutation as any;
};
13 changes: 13 additions & 0 deletions JoyboyCommunity/src/hooks/api/useClaim.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {NostrEvent} from '@nostr-dev-kit/ndk';

import {ApiInstance} from '../../services/api';
import {useApiMutation} from './useApiMutation';

export const useClaim = () => {
return useApiMutation({
mutationKey: ['claim'],
mutationFn: (event: NostrEvent) => {
return ApiInstance.post('/deposit/claim', {event});
},
});
};
13 changes: 13 additions & 0 deletions JoyboyCommunity/src/hooks/api/useEstimateClaim.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {NostrEvent} from '@nostr-dev-kit/ndk';

import {ApiInstance} from '../../services/api';
import {useApiMutation} from './useApiMutation';

export const useEstimateClaim = () => {
return useApiMutation({
mutationKey: ['estimateClaim'],
mutationFn: (event: NostrEvent) => {
return ApiInstance.post('/deposit/estimate-claim', {event});
},
});
};
Loading

0 comments on commit 384f168

Please sign in to comment.