wallet-stack 1.0.0-alpha.122 → 1.0.0-alpha.123
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -7
- package/package.json +1 -2
- package/plugin/build/withAndroidUserAgent.js +2 -2
- package/plugin/build/withIosAppDelegateResetKeychain.js +2 -2
- package/plugin/build/withIosUserAgent.js +2 -2
- package/src/analytics/Events.tsx +0 -2
- package/src/analytics/Properties.tsx +0 -2
- package/src/analytics/docs.ts +2 -2
- package/src/config.ts +1 -1
- package/src/home/TabHome.tsx +0 -5
- package/src/home/actions.ts +0 -10
- package/src/home/reducers.ts +0 -7
- package/src/home/selectors.ts +0 -9
- package/src/images/Images.ts +0 -1
- package/src/images/WelcomeLogo.tsx +10 -9
- package/src/navigator/SettingsMenu.tsx +0 -9
- package/src/onboarding/welcome/Welcome.tsx +1 -10
- package/src/public/createApp.ts +1 -1
- package/src/public/navigate.ts +3 -3
- package/src/public/types.tsx +0 -5
- package/src/redux/migrations.test.ts +15 -0
- package/src/redux/migrations.ts +4 -0
- package/src/redux/store.test.ts +1 -2
- package/src/redux/store.ts +1 -1
- package/src/statsig/constants.ts +0 -5
- package/src/statsig/types.ts +0 -2
- package/src/viem/prepareTransactions.test.ts +1 -105
- package/src/viem/prepareTransactions.ts +1 -20
- package/src/viem/saga.test.ts +0 -13
- package/src/viem/saga.ts +0 -7
- package/tsconfig.base.json +1 -1
- package/src/divviProtocol/saga.test.ts +0 -51
- package/src/divviProtocol/saga.ts +0 -44
- package/src/home/DivviBottomSheet.test.tsx +0 -59
- package/src/home/DivviBottomSheet.tsx +0 -197
- package/src/images/DivviLogo.tsx +0 -22
- package/src/images/assets/pie.png +0 -0
- package/src/images/assets/pie@1.5x.png +0 -0
- package/src/images/assets/pie@2x.png +0 -0
- package/src/images/assets/pie@3x.png +0 -0
- package/src/images/assets/pie@4x.png +0 -0
package/README.md
CHANGED
|
@@ -22,7 +22,6 @@ Built on top of [Expo](https://expo.dev), the industry standard for React Native
|
|
|
22
22
|
- Optimism Mainnet
|
|
23
23
|
- Polygon PoS
|
|
24
24
|
- Base
|
|
25
|
-
- 🔌 **Protocol Integration**: Native support for the Divvi protocol
|
|
26
25
|
- 📱 **App Store Ready**: Streamlined deployment process using Expo EAS
|
|
27
26
|
|
|
28
27
|
## Quick Start
|
|
@@ -75,12 +74,6 @@ We welcome contributions! Please read our [Contributing Guidelines](CONTRIBUTING
|
|
|
75
74
|
|
|
76
75
|
Found a security issue? Please report it following our [Security Policy](SECURITY.md).
|
|
77
76
|
|
|
78
|
-
## Community
|
|
79
|
-
|
|
80
|
-
- 💬 Join our [Discord](https://discord.com/invite/EaxZDhMuDn)
|
|
81
|
-
- 🐦 Follow us on [X](https://x.com/letsdivvi)
|
|
82
|
-
- 📝 Read our [Blog](https://blog.divvi.xyz)
|
|
83
|
-
|
|
84
77
|
## License
|
|
85
78
|
|
|
86
79
|
This project is licensed under the [Apache License 2.0](LICENSE).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wallet-stack",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.123",
|
|
4
4
|
"author": "Valora Inc",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -122,7 +122,6 @@
|
|
|
122
122
|
"dependencies": {
|
|
123
123
|
"@badrap/result": "~0.2.13",
|
|
124
124
|
"@crowdin/ota-client": "^2.0.1",
|
|
125
|
-
"@divvi/referral-sdk": "^2.2.0",
|
|
126
125
|
"@fiatconnect/fiatconnect-sdk": "^0.5.74",
|
|
127
126
|
"@fiatconnect/fiatconnect-types": "^13.3.11",
|
|
128
127
|
"@gorhom/bottom-sheet": "^5.1.1",
|
|
@@ -68,7 +68,7 @@ function addUserAgentCode(src, appName) {
|
|
|
68
68
|
const withAndroidUserAgent = (config, { appName }) => {
|
|
69
69
|
return (0, config_plugins_1.withMainApplication)(config, (config) => {
|
|
70
70
|
if (!['kt'].includes(config.modResults.language)) {
|
|
71
|
-
throw new Error(`Cannot setup
|
|
71
|
+
throw new Error(`Cannot setup Wallet Stack because the project MainApplication is not a supported language: ${config.modResults.language}`);
|
|
72
72
|
}
|
|
73
73
|
try {
|
|
74
74
|
config.modResults.contents = addNeededImports(config.modResults.contents).contents;
|
|
@@ -76,7 +76,7 @@ const withAndroidUserAgent = (config, { appName }) => {
|
|
|
76
76
|
}
|
|
77
77
|
catch (error) {
|
|
78
78
|
if (error.code === 'ERR_NO_MATCH') {
|
|
79
|
-
throw new Error(`Cannot add
|
|
79
|
+
throw new Error(`Cannot add Wallet Stack to the project's MainApplication because it's malformed. Please report this with a copy of your project MainApplication.`);
|
|
80
80
|
}
|
|
81
81
|
throw error;
|
|
82
82
|
}
|
|
@@ -59,7 +59,7 @@ function addCallResetKeychain(src) {
|
|
|
59
59
|
const withIosAppDelegateResetKeychain = (config) => {
|
|
60
60
|
return (0, config_plugins_1.withAppDelegate)(config, (config) => {
|
|
61
61
|
if (config.modResults.language !== 'swift') {
|
|
62
|
-
throw new Error(`Cannot setup
|
|
62
|
+
throw new Error(`Cannot setup Wallet Stack because the project AppDelegate is not Swift: ${config.modResults.language}`);
|
|
63
63
|
}
|
|
64
64
|
try {
|
|
65
65
|
config.modResults.contents = addResetKeychainFunction(config.modResults.contents).contents;
|
|
@@ -67,7 +67,7 @@ const withIosAppDelegateResetKeychain = (config) => {
|
|
|
67
67
|
}
|
|
68
68
|
catch (error) {
|
|
69
69
|
if (error.code === 'ERR_NO_MATCH') {
|
|
70
|
-
throw new Error(`Cannot add
|
|
70
|
+
throw new Error(`Cannot add Wallet Stack to the project's AppDelegate because it's malformed. Please report this with a copy of your project AppDelegate.`);
|
|
71
71
|
}
|
|
72
72
|
throw error;
|
|
73
73
|
}
|
|
@@ -39,14 +39,14 @@ function addUserAgentCode(src, appName) {
|
|
|
39
39
|
const withIosUserAgent = (config, { appName }) => {
|
|
40
40
|
return (0, config_plugins_1.withAppDelegate)(config, (config) => {
|
|
41
41
|
if (config.modResults.language !== 'swift') {
|
|
42
|
-
throw new Error(`Cannot setup
|
|
42
|
+
throw new Error(`Cannot setup Wallet Stack because the project AppDelegate is not Swift: ${config.modResults.language}`);
|
|
43
43
|
}
|
|
44
44
|
try {
|
|
45
45
|
config.modResults.contents = addUserAgentCode(config.modResults.contents, appName ?? config.name).contents;
|
|
46
46
|
}
|
|
47
47
|
catch (error) {
|
|
48
48
|
if (error.code === 'ERR_NO_MATCH') {
|
|
49
|
-
throw new Error(`Cannot add
|
|
49
|
+
throw new Error(`Cannot add Wallet Stack to the project's AppDelegate because it's malformed. Please report this with a copy of your project AppDelegate.`);
|
|
50
50
|
}
|
|
51
51
|
throw error;
|
|
52
52
|
}
|
package/src/analytics/Events.tsx
CHANGED
|
@@ -47,8 +47,6 @@ export enum HomeEvents {
|
|
|
47
47
|
nft_celebration_animation_displayed = 'nft_celebration_animation_displayed',
|
|
48
48
|
nft_reward_accept = 'nft_reward_accept',
|
|
49
49
|
nft_reward_dismiss = 'nft_reward_dismiss',
|
|
50
|
-
divvi_bottom_sheet_displayed = 'divvi_bottom_sheet_displayed',
|
|
51
|
-
divvi_bottom_sheet_cta_pressed = 'divvi_bottom_sheet_cta_pressed',
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
export enum SettingsEvents {
|
|
@@ -197,8 +197,6 @@ interface HomeEventsProperties {
|
|
|
197
197
|
contractAddress: string
|
|
198
198
|
remainingDays: number
|
|
199
199
|
}
|
|
200
|
-
[HomeEvents.divvi_bottom_sheet_displayed]: undefined
|
|
201
|
-
[HomeEvents.divvi_bottom_sheet_cta_pressed]: undefined
|
|
202
200
|
}
|
|
203
201
|
|
|
204
202
|
interface SettingsEventsProperties {
|
package/src/analytics/docs.ts
CHANGED
|
@@ -84,8 +84,6 @@ export const eventDocs: Record<AnalyticsEventType, string> = {
|
|
|
84
84
|
[HomeEvents.nft_celebration_animation_displayed]: `When user has seen an NFT celebration confetti animation`,
|
|
85
85
|
[HomeEvents.nft_reward_accept]: `When user press "Use reward" button when presented with an NFT reward`,
|
|
86
86
|
[HomeEvents.nft_reward_dismiss]: `When user dismiss the bottom sheet when presented with an NFT reward`,
|
|
87
|
-
[HomeEvents.divvi_bottom_sheet_displayed]: `When the Divvi bottom sheet is displayed to the user`,
|
|
88
|
-
[HomeEvents.divvi_bottom_sheet_cta_pressed]: `When the user presses the CTA button in the Divvi bottom sheet.`,
|
|
89
87
|
[SettingsEvents.settings_profile_edit]: ``,
|
|
90
88
|
[SettingsEvents.profile_generate_name]: ``,
|
|
91
89
|
[SettingsEvents.profile_save]: ``,
|
|
@@ -672,4 +670,6 @@ export const eventDocs: Record<AnalyticsEventType, string> = {
|
|
|
672
670
|
// [JumpstartEvents.jumpstart_add_assets_action_press]: 'When user selects an add assets action from the available options',
|
|
673
671
|
// [JumpstartEvents.jumpstart_intro_seen]: `when jumpstart intro is seen by the user`,
|
|
674
672
|
// [OnboardingEvents.stale_keychain_items_cleared]: `Stale keychain items where found during onboarding and cleared`,
|
|
673
|
+
// [HomeEvents.divvi_bottom_sheet_displayed]: `When the Divvi bottom sheet is displayed to the user`,
|
|
674
|
+
// [HomeEvents.divvi_bottom_sheet_cta_pressed]: `When the user presses the CTA button in the Divvi bottom sheet.`,
|
|
675
675
|
}
|
package/src/config.ts
CHANGED
|
@@ -32,7 +32,7 @@ export const APP_NAME = appConfig.displayName
|
|
|
32
32
|
export const APP_REGISTRY_NAME = configOrThrow('APP_REGISTRY_NAME')
|
|
33
33
|
|
|
34
34
|
// DEV only related settings
|
|
35
|
-
export const isE2EEnv = stringToBoolean(process.env.
|
|
35
|
+
export const isE2EEnv = stringToBoolean(process.env.EXPO_PUBLIC_WALLET_STACK_E2E || 'false')
|
|
36
36
|
export const DEV_RESTORE_NAV_STATE_ON_RELOAD = stringToBoolean(
|
|
37
37
|
Config.DEV_RESTORE_NAV_STATE_ON_RELOAD || 'false'
|
|
38
38
|
)
|
package/src/home/TabHome.tsx
CHANGED
|
@@ -22,7 +22,6 @@ import NftCelebration from 'src/home/celebration/NftCelebration'
|
|
|
22
22
|
import NftReward from 'src/home/celebration/NftReward'
|
|
23
23
|
import {
|
|
24
24
|
balancesLoadingSelector,
|
|
25
|
-
showDivviBottomSheetSelector,
|
|
26
25
|
showNftCelebrationSelector,
|
|
27
26
|
showNftRewardSelector,
|
|
28
27
|
} from 'src/home/selectors'
|
|
@@ -38,7 +37,6 @@ import colors from 'src/styles/colors'
|
|
|
38
37
|
import TransactionFeed from 'src/transactions/feed/TransactionFeed'
|
|
39
38
|
import TransactionFeedV2 from 'src/transactions/feed/TransactionFeedV2'
|
|
40
39
|
import { hasGrantedContactsPermission } from 'src/utils/contacts'
|
|
41
|
-
import DivviBottomSheet from './DivviBottomSheet'
|
|
42
40
|
|
|
43
41
|
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList)
|
|
44
42
|
|
|
@@ -62,8 +60,6 @@ function TabHome(_props: Props) {
|
|
|
62
60
|
const showNftCelebration = canShowNftCelebration && isFocused && !showNotificationSpotlight
|
|
63
61
|
const canShowNftReward = useSelector(showNftRewardSelector)
|
|
64
62
|
const showNftReward = canShowNftReward && isFocused && !showNotificationSpotlight
|
|
65
|
-
const canShowDivviBottomSheet = useSelector(showDivviBottomSheetSelector)
|
|
66
|
-
const showDivviBottomSheet = canShowDivviBottomSheet && isFocused && !showNotificationSpotlight
|
|
67
63
|
const showZerionTransactionFeed = getFeatureGate(StatsigFeatureGates.SHOW_ZERION_TRANSACTION_FEED)
|
|
68
64
|
const hideActionsCarousel = getAppConfig().experimental?.activity?.hideActionsCarousel ?? false
|
|
69
65
|
|
|
@@ -166,7 +162,6 @@ function TabHome(_props: Props) {
|
|
|
166
162
|
)}
|
|
167
163
|
{showNftCelebration && <NftCelebration />}
|
|
168
164
|
{showNftReward && <NftReward />}
|
|
169
|
-
{showDivviBottomSheet && <DivviBottomSheet />}
|
|
170
165
|
</SafeAreaView>
|
|
171
166
|
)
|
|
172
167
|
}
|
package/src/home/actions.ts
CHANGED
|
@@ -11,7 +11,6 @@ export enum Actions {
|
|
|
11
11
|
NFT_CELEBRATION_DISPLAYED = 'HOME/NFT_CELEBRATION_DISPLAYED',
|
|
12
12
|
NFT_REWARD_READY_TO_DISPLAY = 'HOME/NFT_REWARD_READY_TO_DISPLAY',
|
|
13
13
|
NFT_REWARD_DISPLAYED = 'HOME/NFT_REWARD_DISPLAYED',
|
|
14
|
-
DIVVI_BOTTOM_SHEET_SEEN = 'HOME/DIVVI_BOTTOM_SHEET_SEEN',
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
export interface VisitHomeAction {
|
|
@@ -64,10 +63,6 @@ interface NftRewardDisplayedAction {
|
|
|
64
63
|
type: Actions.NFT_REWARD_DISPLAYED
|
|
65
64
|
}
|
|
66
65
|
|
|
67
|
-
interface DivviBottomSheetSeenAction {
|
|
68
|
-
type: Actions.DIVVI_BOTTOM_SHEET_SEEN
|
|
69
|
-
}
|
|
70
|
-
|
|
71
66
|
export type ActionTypes =
|
|
72
67
|
| SetLoadingAction
|
|
73
68
|
| UpdateNotificationsAction
|
|
@@ -77,7 +72,6 @@ export type ActionTypes =
|
|
|
77
72
|
| NftCelebrationDisplayedAction
|
|
78
73
|
| NftRewardReadyToDisplayAction
|
|
79
74
|
| NftRewardDisplayedAction
|
|
80
|
-
| DivviBottomSheetSeenAction
|
|
81
75
|
|
|
82
76
|
export const visitHome = (): VisitHomeAction => ({
|
|
83
77
|
type: Actions.VISIT_HOME,
|
|
@@ -148,7 +142,3 @@ export const nftRewardReadyToDisplay = ({
|
|
|
148
142
|
export const nftRewardDisplayed = (): NftRewardDisplayedAction => ({
|
|
149
143
|
type: Actions.NFT_REWARD_DISPLAYED,
|
|
150
144
|
})
|
|
151
|
-
|
|
152
|
-
export const divviBottomSheetSeen = (): DivviBottomSheetSeenAction => ({
|
|
153
|
-
type: Actions.DIVVI_BOTTOM_SHEET_SEEN,
|
|
154
|
-
})
|
package/src/home/reducers.ts
CHANGED
|
@@ -42,7 +42,6 @@ export interface State {
|
|
|
42
42
|
loading: boolean
|
|
43
43
|
notifications: IdToNotification
|
|
44
44
|
hasVisitedHome: boolean
|
|
45
|
-
hasSeenDivviBottomSheet: boolean
|
|
46
45
|
nftCelebration: {
|
|
47
46
|
networkId: NetworkId
|
|
48
47
|
contractAddress: string
|
|
@@ -57,7 +56,6 @@ export const initialState = {
|
|
|
57
56
|
loading: false,
|
|
58
57
|
notifications: {},
|
|
59
58
|
hasVisitedHome: false,
|
|
60
|
-
hasSeenDivviBottomSheet: false,
|
|
61
59
|
nftCelebration: null,
|
|
62
60
|
}
|
|
63
61
|
|
|
@@ -180,11 +178,6 @@ export const homeReducer = (
|
|
|
180
178
|
: NftCelebrationStatus.rewardDisplayed,
|
|
181
179
|
},
|
|
182
180
|
}
|
|
183
|
-
case Actions.DIVVI_BOTTOM_SHEET_SEEN:
|
|
184
|
-
return {
|
|
185
|
-
...state,
|
|
186
|
-
hasSeenDivviBottomSheet: true,
|
|
187
|
-
}
|
|
188
181
|
default:
|
|
189
182
|
return state
|
|
190
183
|
}
|
package/src/home/selectors.ts
CHANGED
|
@@ -71,12 +71,3 @@ export const showNftRewardSelector = (state: RootState) => {
|
|
|
71
71
|
state.home.nftCelebration.status === NftCelebrationStatus.reminderReadyToDisplay
|
|
72
72
|
)
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
export const showDivviBottomSheetSelector = (state: RootState) => {
|
|
76
|
-
const featureGateEnabled = getFeatureGate(StatsigFeatureGates.SHOW_DIVVI_SLICES_BOTTOM_SHEET)
|
|
77
|
-
if (!featureGateEnabled) {
|
|
78
|
-
return false
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return !state.home.hasSeenDivviBottomSheet
|
|
82
|
-
}
|
package/src/images/Images.ts
CHANGED
|
@@ -19,4 +19,3 @@ export const pointsCardBackground = require('src/images/assets/points-card-backg
|
|
|
19
19
|
export const pointsIllustration = require('src/images/assets/points-illustration.png')
|
|
20
20
|
export const walletSafe = require('src/images/assets/wallet-safe.png')
|
|
21
21
|
export const earnCardBackground = require('src/images/assets/earn-card-background.png')
|
|
22
|
-
export const divviPie = require('src/images/assets/pie.png')
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import
|
|
2
|
+
import { StyleSheet, Text } from 'react-native'
|
|
3
3
|
import { getAppConfig } from 'src/appConfig'
|
|
4
|
+
import { typeScale } from 'src/styles/fonts'
|
|
4
5
|
|
|
5
6
|
export default function WelcomeLogo() {
|
|
6
7
|
const CustomWelcomeLogo = getAppConfig().themes?.default?.assets?.welcomeLogo
|
|
@@ -8,12 +9,12 @@ export default function WelcomeLogo() {
|
|
|
8
9
|
return <CustomWelcomeLogo />
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
return
|
|
12
|
-
<Svg width={168} height={58} viewBox={`0 0 168 58`} fill="none">
|
|
13
|
-
<Path
|
|
14
|
-
fill="#000"
|
|
15
|
-
d="m30.447 1.167 8.835 3.723V57h-7.331l-1.805-3.685a11.426 11.426 0 0 1-2.143 1.993c-.777.526-1.617.965-2.52 1.316-.876.351-1.816.602-2.819.752-1.003.15-2.055.226-3.158.226-2.757 0-5.301-.502-7.633-1.504-2.33-1.003-4.348-2.382-6.053-4.136-1.68-1.78-3.008-3.86-3.985-6.241C.882 43.34.406 40.783.406 38.051c0-2.757.476-5.327 1.429-7.708.978-2.381 2.306-4.449 3.985-6.203 1.68-1.755 3.685-3.133 6.016-4.136 2.356-1.003 4.913-1.504 7.67-1.504 1.078 0 2.118.088 3.12.263 1.003.151 1.968.389 2.895.715.928.325 1.805.751 2.632 1.278a11.78 11.78 0 0 1 2.294 1.917V1.167Zm.075 36.846c0-1.754-.263-3.321-.79-4.7-.5-1.378-1.228-2.544-2.18-3.496-.928-.953-2.043-1.679-3.346-2.181-1.304-.501-2.758-.752-4.362-.752-1.579 0-3.033.289-4.361.865a9.572 9.572 0 0 0-3.346 2.331c-.928 1.003-1.655 2.181-2.18 3.534-.527 1.354-.79 2.82-.79 4.399 0 1.604.263 3.096.79 4.474.525 1.379 1.252 2.569 2.18 3.572.927.978 2.043 1.755 3.346 2.331 1.328.552 2.782.827 4.361.827 1.604 0 3.058-.238 4.362-.714 1.303-.501 2.418-1.228 3.346-2.181.952-.977 1.68-2.155 2.18-3.534.527-1.404.79-2.995.79-4.775Zm20.227-18.648h8.836V57h-8.836V19.365ZM49.773 5.98c0-.752.138-1.466.413-2.143a6.18 6.18 0 0 1 1.166-1.767A4.994 4.994 0 0 1 53.043.904a4.975 4.975 0 0 1 2.105-.451 5.23 5.23 0 0 1 2.143.451A5.305 5.305 0 0 1 59.06 2.07a5.29 5.29 0 0 1 1.165 1.767c.276.677.414 1.391.414 2.143 0 .752-.138 1.466-.414 2.143A5.29 5.29 0 0 1 59.06 9.89c-.502.501-1.09.89-1.767 1.166a5.639 5.639 0 0 1-2.144.413 5.36 5.36 0 0 1-2.105-.413 4.994 4.994 0 0 1-1.692-1.166 6.18 6.18 0 0 1-1.166-1.767 5.626 5.626 0 0 1-.413-2.143ZM83.159 57l-16.43-37.635h9.436l10.152 24.777 10.678-24.777h9.437L89.325 57h-6.166Zm41.056 0-16.43-37.635h9.437l10.152 24.777 10.677-24.777h9.437L130.381 57h-6.166Zm29.778-37.635h8.835V57h-8.835V19.365Zm-.978-13.385c0-.752.138-1.466.414-2.143.3-.677.689-1.266 1.165-1.767a4.99 4.99 0 0 1 1.692-1.166 4.978 4.978 0 0 1 2.106-.451c.752 0 1.466.151 2.143.451a5.32 5.32 0 0 1 1.767 1.166c.501.501.89 1.09 1.165 1.767a5.62 5.62 0 0 1 .414 2.143 5.62 5.62 0 0 1-.414 2.143 5.282 5.282 0 0 1-1.165 1.767 5.32 5.32 0 0 1-1.767 1.166 5.639 5.639 0 0 1-2.143.413 5.363 5.363 0 0 1-2.106-.413 4.99 4.99 0 0 1-1.692-1.166 6.168 6.168 0 0 1-1.165-1.767 5.62 5.62 0 0 1-.414-2.143Z"
|
|
16
|
-
/>
|
|
17
|
-
</Svg>
|
|
18
|
-
)
|
|
12
|
+
return <Text style={styles.header}>Wallet Stack</Text>
|
|
19
13
|
}
|
|
14
|
+
|
|
15
|
+
const styles = StyleSheet.create({
|
|
16
|
+
header: {
|
|
17
|
+
...typeScale.displaySmall,
|
|
18
|
+
textAlign: 'center',
|
|
19
|
+
},
|
|
20
|
+
})
|
|
@@ -35,7 +35,6 @@ import Lock from 'src/icons/Lock'
|
|
|
35
35
|
import Wallet from 'src/icons/navigator/Wallet'
|
|
36
36
|
import Preferences from 'src/icons/Preferences'
|
|
37
37
|
import Stack from 'src/icons/Stack'
|
|
38
|
-
import DivviLogo from 'src/images/DivviLogo'
|
|
39
38
|
import { headerWithCloseButton } from 'src/navigator/Headers'
|
|
40
39
|
import { navigate } from 'src/navigator/NavigationService'
|
|
41
40
|
import { Screens } from 'src/navigator/Screens'
|
|
@@ -277,9 +276,6 @@ export default function SettingsMenu({ route }: Props) {
|
|
|
277
276
|
</View>
|
|
278
277
|
</TouchableWithoutFeedback>
|
|
279
278
|
{getDevSettingsComp()}
|
|
280
|
-
<View style={styles.logo}>
|
|
281
|
-
<DivviLogo />
|
|
282
|
-
</View>
|
|
283
279
|
</ScrollView>
|
|
284
280
|
</SafeAreaView>
|
|
285
281
|
)
|
|
@@ -345,9 +341,4 @@ const styles = StyleSheet.create({
|
|
|
345
341
|
debugInfoText: {
|
|
346
342
|
...typeScale.bodySmall,
|
|
347
343
|
},
|
|
348
|
-
logo: {
|
|
349
|
-
marginTop: 'auto',
|
|
350
|
-
paddingVertical: Spacing.Thick24,
|
|
351
|
-
alignItems: 'center',
|
|
352
|
-
},
|
|
353
344
|
})
|
|
@@ -10,7 +10,6 @@ import { OnboardingEvents } from 'src/analytics/Events'
|
|
|
10
10
|
import { getAppConfig } from 'src/appConfig'
|
|
11
11
|
import BottomSheet, { BottomSheetModalRefType } from 'src/components/BottomSheet'
|
|
12
12
|
import Button, { BtnSizes, BtnTypes } from 'src/components/Button'
|
|
13
|
-
import DivviLogo from 'src/images/DivviLogo'
|
|
14
13
|
import WelcomeLogo from 'src/images/WelcomeLogo'
|
|
15
14
|
import { nuxNavigationOptions } from 'src/navigator/Headers'
|
|
16
15
|
import { navigate, navigateInitialTab } from 'src/navigator/NavigationService'
|
|
@@ -124,9 +123,6 @@ export default function Welcome() {
|
|
|
124
123
|
testID={'RestoreAccountButton'}
|
|
125
124
|
/>
|
|
126
125
|
</View>
|
|
127
|
-
<View style={styles.divviLogoContainer}>
|
|
128
|
-
<DivviLogo />
|
|
129
|
-
</View>
|
|
130
126
|
</ImageBackground>
|
|
131
127
|
<BottomSheet
|
|
132
128
|
forwardedRef={demoModeBottomSheetRef}
|
|
@@ -164,18 +160,13 @@ const styles = StyleSheet.create({
|
|
|
164
160
|
},
|
|
165
161
|
buttonView: {
|
|
166
162
|
paddingHorizontal: Spacing.Thick24,
|
|
163
|
+
paddingBottom: 76,
|
|
167
164
|
},
|
|
168
165
|
image: {
|
|
169
166
|
flex: 1,
|
|
170
167
|
justifyContent: 'center',
|
|
171
168
|
marginTop: Spacing.XLarge48,
|
|
172
169
|
},
|
|
173
|
-
divviLogoContainer: {
|
|
174
|
-
width: '100%',
|
|
175
|
-
marginTop: Spacing.Large32,
|
|
176
|
-
paddingBottom: Spacing.Regular16,
|
|
177
|
-
alignItems: 'center',
|
|
178
|
-
},
|
|
179
170
|
demoModeButton: {
|
|
180
171
|
marginTop: Spacing.Thick24,
|
|
181
172
|
},
|
package/src/public/createApp.ts
CHANGED
|
@@ -22,7 +22,7 @@ function getOnboardingFeatures(config: PublicAppConfig) {
|
|
|
22
22
|
}
|
|
23
23
|
// Special case for e2e to test phone number verification
|
|
24
24
|
// As we're not yet sure how we wanna expose this feature in the runtime
|
|
25
|
-
if (process.env.
|
|
25
|
+
if (process.env.EXPO_PUBLIC_WALLET_STACK_E2E === 'true') {
|
|
26
26
|
onboardingFeatures.push(ToggleableOnboardingFeatures.PhoneVerification)
|
|
27
27
|
}
|
|
28
28
|
if (onboardingConfig) {
|
package/src/public/navigate.ts
CHANGED
|
@@ -15,7 +15,7 @@ const TAG = 'public/navigate'
|
|
|
15
15
|
|
|
16
16
|
declare global {
|
|
17
17
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
18
|
-
namespace
|
|
18
|
+
namespace WalletNavigation {
|
|
19
19
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
20
20
|
interface RootParamList extends StackParamList {}
|
|
21
21
|
}
|
|
@@ -25,7 +25,7 @@ export type NavigatorScreen = ReturnType<
|
|
|
25
25
|
// TODO: this weird looking type works around a type error when checking the lib vs example app
|
|
26
26
|
// Maybe we can get rid of this once we're able to ship declaration files
|
|
27
27
|
typeof createNativeStackNavigator<
|
|
28
|
-
|
|
28
|
+
WalletNavigation.RootParamList extends ParamListBase ? WalletNavigation.RootParamList : never
|
|
29
29
|
>
|
|
30
30
|
>['Screen']
|
|
31
31
|
|
|
@@ -57,7 +57,7 @@ export type StackParamList = {
|
|
|
57
57
|
|
|
58
58
|
export type { NativeStackScreenProps } from '@react-navigation/native-stack'
|
|
59
59
|
|
|
60
|
-
type NavigateArgs<ParamList =
|
|
60
|
+
type NavigateArgs<ParamList = WalletNavigation.RootParamList> = {
|
|
61
61
|
[RouteName in keyof ParamList]: undefined extends ParamList[RouteName]
|
|
62
62
|
? [RouteName] | [RouteName, ParamList[RouteName]]
|
|
63
63
|
: [RouteName, ParamList[RouteName]]
|
package/src/public/types.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ImageSourcePropType } from 'react-native'
|
|
2
|
-
import { Address } from 'viem'
|
|
3
2
|
import type { NavigatorScreen } from './navigate'
|
|
4
3
|
|
|
5
4
|
// Type for tab configuration
|
|
@@ -262,10 +261,6 @@ export interface PublicAppConfig<tabScreenConfigs extends TabScreenConfig[] = Ta
|
|
|
262
261
|
showSwapTokenFilters?: boolean
|
|
263
262
|
enableSwapAppFee?: boolean
|
|
264
263
|
}
|
|
265
|
-
|
|
266
|
-
divviProtocol?: {
|
|
267
|
-
divviId: Address
|
|
268
|
-
}
|
|
269
264
|
}
|
|
270
265
|
|
|
271
266
|
// TODO: we'll use this type throughout the framework once we're able to make bigger refactor, eliminating the current NetworkId enum
|
|
@@ -66,6 +66,7 @@ import {
|
|
|
66
66
|
v233Schema,
|
|
67
67
|
v235Schema,
|
|
68
68
|
v251Schema,
|
|
69
|
+
v253Schema,
|
|
69
70
|
v28Schema,
|
|
70
71
|
v2Schema,
|
|
71
72
|
v35Schema,
|
|
@@ -1922,4 +1923,18 @@ describe('Redux persist migrations', () => {
|
|
|
1922
1923
|
expectedSchema.app = _.omit(oldSchema.app, 'inviterAddress')
|
|
1923
1924
|
expect(migratedSchema).toStrictEqual(expectedSchema)
|
|
1924
1925
|
})
|
|
1926
|
+
|
|
1927
|
+
it('works from 253 to 254', () => {
|
|
1928
|
+
const oldSchema = {
|
|
1929
|
+
...v253Schema,
|
|
1930
|
+
home: {
|
|
1931
|
+
...v253Schema.home,
|
|
1932
|
+
hasSeenDivviBottomSheet: false,
|
|
1933
|
+
},
|
|
1934
|
+
}
|
|
1935
|
+
const migratedSchema = migrations[254](oldSchema)
|
|
1936
|
+
const expectedSchema: any = _.cloneDeep(oldSchema)
|
|
1937
|
+
expectedSchema.home = _.omit(oldSchema.home, 'hasSeenDivviBottomSheet')
|
|
1938
|
+
expect(migratedSchema).toStrictEqual(expectedSchema)
|
|
1939
|
+
})
|
|
1925
1940
|
})
|
package/src/redux/migrations.ts
CHANGED
package/src/redux/store.test.ts
CHANGED
|
@@ -143,7 +143,7 @@ describe('store state', () => {
|
|
|
143
143
|
{
|
|
144
144
|
"_persist": {
|
|
145
145
|
"rehydrated": true,
|
|
146
|
-
"version":
|
|
146
|
+
"version": 254,
|
|
147
147
|
},
|
|
148
148
|
"account": {
|
|
149
149
|
"acceptedTerms": false,
|
|
@@ -230,7 +230,6 @@ describe('store state', () => {
|
|
|
230
230
|
"txHashToProvider": {},
|
|
231
231
|
},
|
|
232
232
|
"home": {
|
|
233
|
-
"hasSeenDivviBottomSheet": false,
|
|
234
233
|
"hasVisitedHome": true,
|
|
235
234
|
"loading": false,
|
|
236
235
|
"nftCelebration": null,
|
package/src/redux/store.ts
CHANGED
|
@@ -30,7 +30,7 @@ const persistConfig: PersistConfig<ReducersRootState> = {
|
|
|
30
30
|
key: 'root',
|
|
31
31
|
// default is -1, increment as we make migrations
|
|
32
32
|
// See https://github.com/valora-xyz/wallet/tree/main/WALLET.md#redux-state-migration
|
|
33
|
-
version:
|
|
33
|
+
version: 254,
|
|
34
34
|
keyPrefix: `reduxStore-`, // the redux-persist default is `persist:` which doesn't work with some file systems.
|
|
35
35
|
storage: FSStorage(),
|
|
36
36
|
blacklist: ['networkInfo', 'alert', 'imports', 'keylessBackup', transactionFeedV2Api.reducerPath],
|
package/src/statsig/constants.ts
CHANGED
|
@@ -33,7 +33,6 @@ export const FeatureGates = {
|
|
|
33
33
|
[StatsigFeatureGates.SHOW_NEW_ENTER_AMOUNT_FOR_SWAP]: true,
|
|
34
34
|
[StatsigFeatureGates.ALLOW_CROSS_CHAIN_SWAP_AND_DEPOSIT]: false,
|
|
35
35
|
[StatsigFeatureGates.DISABLE_WALLET_CONNECT_V2]: false,
|
|
36
|
-
[StatsigFeatureGates.SHOW_DIVVI_SLICES_BOTTOM_SHEET]: false,
|
|
37
36
|
[StatsigFeatureGates.RECAPTCHA_ENABLED]: false,
|
|
38
37
|
[StatsigFeatureGates.USE_SMART_ACCOUNT_CAPABILITIES]: false,
|
|
39
38
|
} satisfies { [key in StatsigFeatureGates]: boolean }
|
|
@@ -165,10 +164,6 @@ export const DynamicConfigs = {
|
|
|
165
164
|
inviteRewardsVersion: 'none',
|
|
166
165
|
},
|
|
167
166
|
},
|
|
168
|
-
[StatsigDynamicConfigs.DIVVI_SLICES_BOTTOM_SHEET_CONFIG]: {
|
|
169
|
-
configName: StatsigDynamicConfigs.DIVVI_SLICES_BOTTOM_SHEET_CONFIG,
|
|
170
|
-
defaultValues: {} as { url?: string },
|
|
171
|
-
},
|
|
172
167
|
} satisfies {
|
|
173
168
|
[key in StatsigDynamicConfigs]: {
|
|
174
169
|
configName: key
|
package/src/statsig/types.ts
CHANGED
|
@@ -11,7 +11,6 @@ export enum StatsigDynamicConfigs {
|
|
|
11
11
|
DEMO_MODE_CONFIG = 'demo_mode_config',
|
|
12
12
|
FIAT_CONNECT_CONFIG = 'fiat_connect_config',
|
|
13
13
|
INVITE_REWARDS_CONFIG = 'invite_rewards_config',
|
|
14
|
-
DIVVI_SLICES_BOTTOM_SHEET_CONFIG = 'divvi_slices_bottom_sheet_config',
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
export enum StatsigFeatureGates {
|
|
@@ -35,7 +34,6 @@ export enum StatsigFeatureGates {
|
|
|
35
34
|
SHOW_NEW_ENTER_AMOUNT_FOR_SWAP = 'show_new_enter_amount_for_swap',
|
|
36
35
|
ALLOW_CROSS_CHAIN_SWAP_AND_DEPOSIT = 'allow_cross_chain_swap_and_deposit',
|
|
37
36
|
DISABLE_WALLET_CONNECT_V2 = 'disable_wallet_connect_v2',
|
|
38
|
-
SHOW_DIVVI_SLICES_BOTTOM_SHEET = 'show_divvi_slices_bottom_sheet',
|
|
39
37
|
RECAPTCHA_ENABLED = 'recaptcha_enabled',
|
|
40
38
|
USE_SMART_ACCOUNT_CAPABILITIES = 'use_smart_account_capabilities',
|
|
41
39
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { getReferralTag } from '@divvi/referral-sdk'
|
|
2
1
|
import BigNumber from 'bignumber.js'
|
|
3
2
|
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
4
3
|
import { TransactionEvents } from 'src/analytics/Events'
|
|
5
|
-
import { getAppConfig } from 'src/appConfig'
|
|
6
4
|
import { TokenBalanceWithAddress } from 'src/tokens/slice'
|
|
7
5
|
import { Network, NetworkId } from 'src/transactions/types'
|
|
8
6
|
import { estimateFeesPerGas } from 'src/viem/estimateFeesPerGas'
|
|
@@ -22,7 +20,7 @@ import {
|
|
|
22
20
|
tryEstimateTransaction,
|
|
23
21
|
tryEstimateTransactions,
|
|
24
22
|
} from 'src/viem/prepareTransactions'
|
|
25
|
-
import {
|
|
23
|
+
import { mockCeloTokenBalance, mockEthTokenBalance } from 'test/values'
|
|
26
24
|
import {
|
|
27
25
|
Address,
|
|
28
26
|
BaseError,
|
|
@@ -37,7 +35,6 @@ import {
|
|
|
37
35
|
import { estimateGas } from 'viem/actions'
|
|
38
36
|
import mocked = jest.mocked
|
|
39
37
|
|
|
40
|
-
jest.mock('@divvi/referral-sdk')
|
|
41
38
|
jest.mock('src/viem/estimateFeesPerGas')
|
|
42
39
|
jest.mock('viem', () => ({
|
|
43
40
|
...jest.requireActual('viem'),
|
|
@@ -61,7 +58,6 @@ jest.mock('src/viem/index', () => ({
|
|
|
61
58
|
|
|
62
59
|
beforeEach(() => {
|
|
63
60
|
jest.clearAllMocks()
|
|
64
|
-
jest.mocked(getReferralTag).mockReturnValue('divviData')
|
|
65
61
|
})
|
|
66
62
|
|
|
67
63
|
describe('prepareTransactions module', () => {
|
|
@@ -144,67 +140,6 @@ describe('prepareTransactions module', () => {
|
|
|
144
140
|
}
|
|
145
141
|
const mockPublicClient = {} as unknown as jest.Mocked<(typeof publicClient)[Network.Celo]>
|
|
146
142
|
describe('prepareTransactions function', () => {
|
|
147
|
-
it.each([
|
|
148
|
-
{
|
|
149
|
-
description: 'is attached when data is provided',
|
|
150
|
-
inputData: '0xdata' as Hex,
|
|
151
|
-
expectedData: '0xdatadivviData',
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
description: 'is not attached when data is undefined',
|
|
155
|
-
inputData: undefined,
|
|
156
|
-
expectedData: undefined,
|
|
157
|
-
},
|
|
158
|
-
])('divvi data $description', async ({ inputData, expectedData }) => {
|
|
159
|
-
jest.mocked(getAppConfig).mockReturnValueOnce({
|
|
160
|
-
...mockAppConfig,
|
|
161
|
-
divviProtocol: {
|
|
162
|
-
divviId: '0xdivviId',
|
|
163
|
-
},
|
|
164
|
-
})
|
|
165
|
-
jest.mocked(getReferralTag).mockReturnValue('divviData')
|
|
166
|
-
mocked(estimateFeesPerGas).mockResolvedValue({
|
|
167
|
-
maxFeePerGas: BigInt(100),
|
|
168
|
-
maxPriorityFeePerGas: BigInt(2),
|
|
169
|
-
baseFeePerGas: BigInt(50),
|
|
170
|
-
})
|
|
171
|
-
mocked(estimateGas).mockResolvedValue(BigInt(1_000))
|
|
172
|
-
|
|
173
|
-
// max gas fee is 100 * 1k = 100k units, too high for either fee currency
|
|
174
|
-
|
|
175
|
-
const result = await prepareTransactions({
|
|
176
|
-
feeCurrencies: mockFeeCurrencies,
|
|
177
|
-
spendToken: mockSpendToken,
|
|
178
|
-
spendTokenAmount: new BigNumber(45_000),
|
|
179
|
-
decreasedAmountGasFeeMultiplier: 1,
|
|
180
|
-
baseTransactions: [
|
|
181
|
-
{
|
|
182
|
-
from: '0xfrom' as Address,
|
|
183
|
-
to: '0xto' as Address,
|
|
184
|
-
data: inputData,
|
|
185
|
-
},
|
|
186
|
-
],
|
|
187
|
-
isGasSubsidized: true,
|
|
188
|
-
origin: 'send',
|
|
189
|
-
})
|
|
190
|
-
expect(result).toStrictEqual({
|
|
191
|
-
type: 'possible',
|
|
192
|
-
feeCurrency: mockFeeCurrencies[0],
|
|
193
|
-
transactions: [
|
|
194
|
-
{
|
|
195
|
-
from: '0xfrom',
|
|
196
|
-
to: '0xto',
|
|
197
|
-
data: expectedData,
|
|
198
|
-
|
|
199
|
-
gas: BigInt(1000),
|
|
200
|
-
maxFeePerGas: BigInt(100),
|
|
201
|
-
maxPriorityFeePerGas: BigInt(2),
|
|
202
|
-
_baseFeePerGas: BigInt(50),
|
|
203
|
-
},
|
|
204
|
-
],
|
|
205
|
-
})
|
|
206
|
-
})
|
|
207
|
-
|
|
208
143
|
it('throws if trying to sendAmount > sendToken balance', async () => {
|
|
209
144
|
await expect(() =>
|
|
210
145
|
prepareTransactions({
|
|
@@ -1001,45 +936,6 @@ describe('prepareTransactions module', () => {
|
|
|
1001
936
|
expect(result?.data).toBe(originalTransferData)
|
|
1002
937
|
expect(result?.gas).toBe(BigInt(21000))
|
|
1003
938
|
})
|
|
1004
|
-
it('estimates with reduced amount for gas-token ERC20 transfers with divvi suffix and restores original amount', async () => {
|
|
1005
|
-
const originalTransferData =
|
|
1006
|
-
'0xa9059cbb0000000000000000000000000000742d35cc6634c0532925a3b844bc9e7595f000000000000000000000000000000000000000000000000000000000000003e8divviData' as Hex // 1000
|
|
1007
|
-
const baseTransaction: TransactionRequest = {
|
|
1008
|
-
from: '0x123' as Address,
|
|
1009
|
-
to: mockSpendToken.address as Address,
|
|
1010
|
-
data: originalTransferData,
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
// Mock estimateGas to capture what data is passed
|
|
1014
|
-
let capturedData: Hex | undefined
|
|
1015
|
-
mocked(estimateGas).mockImplementation(async (_client, tx: any) => {
|
|
1016
|
-
capturedData = tx.data
|
|
1017
|
-
return BigInt(21000)
|
|
1018
|
-
})
|
|
1019
|
-
|
|
1020
|
-
const result = await tryEstimateTransaction({
|
|
1021
|
-
client: mockPublicClient,
|
|
1022
|
-
baseTransaction,
|
|
1023
|
-
maxFeePerGas: BigInt(100),
|
|
1024
|
-
maxPriorityFeePerGas: BigInt(2),
|
|
1025
|
-
baseFeePerGas: BigInt(50),
|
|
1026
|
-
feeCurrencySymbol: mockSpendToken.symbol,
|
|
1027
|
-
feeCurrencyAddress: mockSpendToken.address as Address,
|
|
1028
|
-
spendToken: mockSpendToken,
|
|
1029
|
-
spendTokenAmount: new BigNumber(1000),
|
|
1030
|
-
isGasSubsidized: false,
|
|
1031
|
-
})
|
|
1032
|
-
|
|
1033
|
-
// The estimateGas should have been called with reduced amount (1)
|
|
1034
|
-
expect(capturedData).toContain(
|
|
1035
|
-
'0000000000000000000000000000000000000000000000000000000000000001divviData'
|
|
1036
|
-
) // 1 in hex
|
|
1037
|
-
|
|
1038
|
-
// But the returned transaction should have the original data
|
|
1039
|
-
expect(result).toBeDefined()
|
|
1040
|
-
expect(result?.data).toBe(originalTransferData)
|
|
1041
|
-
expect(result?.gas).toBe(BigInt(21000))
|
|
1042
|
-
})
|
|
1043
939
|
it('does not modify amount for gas-token transfers when gas is subsidized', async () => {
|
|
1044
940
|
const originalTransferData =
|
|
1045
941
|
'0xa9059cbb0000000000000000000000000000742d35cc6634c0532925a3b844bc9e7595f000000000000000000000000000000000000000000000000000000000000003e8' as Hex // 1000
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { getReferralTag } from '@divvi/referral-sdk'
|
|
2
1
|
import BigNumber from 'bignumber.js'
|
|
3
2
|
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
4
3
|
import { TransactionEvents } from 'src/analytics/Events'
|
|
5
4
|
import { TransactionOrigin } from 'src/analytics/types'
|
|
6
|
-
import { getAppConfig } from 'src/appConfig'
|
|
7
5
|
import { STATIC_GAS_PADDING } from 'src/config'
|
|
8
6
|
import {
|
|
9
7
|
NativeTokenBalance,
|
|
@@ -134,7 +132,7 @@ function modifyERC20TransferAmount(originalData: Hex, newAmount: BigNumber): Hex
|
|
|
134
132
|
const newAmountHex = newAmount.toString(16).padStart(AMOUNT_HEX_LENGTH, '0')
|
|
135
133
|
|
|
136
134
|
// Return the modified data, appending the original data after the expected
|
|
137
|
-
// length (for any suffix
|
|
135
|
+
// length (for any suffix)
|
|
138
136
|
return (recipientPart + newAmountHex + originalData.slice(expectedLength)) as Hex
|
|
139
137
|
}
|
|
140
138
|
|
|
@@ -413,23 +411,6 @@ export async function prepareTransactions({
|
|
|
413
411
|
)
|
|
414
412
|
}
|
|
415
413
|
|
|
416
|
-
// Attach divvi tag to all transactions if divvi is enabled
|
|
417
|
-
const config = getAppConfig()
|
|
418
|
-
if (config.divviProtocol) {
|
|
419
|
-
const walletAddress = baseTransactions[0].from
|
|
420
|
-
const referralTag =
|
|
421
|
-
walletAddress &&
|
|
422
|
-
getReferralTag({
|
|
423
|
-
consumer: config.divviProtocol.divviId,
|
|
424
|
-
user: walletAddress,
|
|
425
|
-
})
|
|
426
|
-
if (referralTag) {
|
|
427
|
-
baseTransactions.forEach((tx) => {
|
|
428
|
-
tx.data = tx.data && ((tx.data + referralTag) as Hex)
|
|
429
|
-
})
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
|
|
433
414
|
const gasFees: Array<{
|
|
434
415
|
feeCurrency: TokenBalance
|
|
435
416
|
maxGasFeeInDecimal: BigNumber
|
package/src/viem/saga.test.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { expectSaga } from 'redux-saga-test-plan'
|
|
|
3
3
|
import * as matchers from 'redux-saga-test-plan/matchers'
|
|
4
4
|
import { EffectProviders, StaticProvider, throwError } from 'redux-saga-test-plan/providers'
|
|
5
5
|
import { call } from 'redux-saga/effects'
|
|
6
|
-
import { submitDivviReferralSaga } from 'src/divviProtocol/saga'
|
|
7
6
|
import { BaseStandbyTransaction, addStandbyTransaction } from 'src/transactions/slice'
|
|
8
7
|
import { NetworkId, TokenTransactionTypeV2 } from 'src/transactions/types'
|
|
9
8
|
import { ViemWallet } from 'src/viem/getLockableWallet'
|
|
@@ -23,10 +22,6 @@ import {
|
|
|
23
22
|
} from 'test/values'
|
|
24
23
|
import { getTransactionCount } from 'viem/actions'
|
|
25
24
|
|
|
26
|
-
jest.mock('src/divviProtocol/saga', () => ({
|
|
27
|
-
submitDivviReferralSaga: jest.fn().mockResolvedValue(true),
|
|
28
|
-
}))
|
|
29
|
-
|
|
30
25
|
const preparedTransactions: TransactionRequest[] = [
|
|
31
26
|
{
|
|
32
27
|
from: '0xa',
|
|
@@ -121,14 +116,6 @@ describe('sendPreparedTransactions', () => {
|
|
|
121
116
|
.withState(createMockStore({}).getState())
|
|
122
117
|
.provide(createDefaultProviders())
|
|
123
118
|
.call(getViemWallet, networkConfig.viemChain.celo, false)
|
|
124
|
-
.call(submitDivviReferralSaga, {
|
|
125
|
-
txHash: '0xmockTxHash1',
|
|
126
|
-
chainId: 42220,
|
|
127
|
-
})
|
|
128
|
-
.call(submitDivviReferralSaga, {
|
|
129
|
-
txHash: '0xmockTxHash2',
|
|
130
|
-
chainId: 42220,
|
|
131
|
-
})
|
|
132
119
|
.put(
|
|
133
120
|
addStandbyTransaction({
|
|
134
121
|
...mockStandbyTransactions[0],
|
package/src/viem/saga.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { submitDivviReferralSaga } from 'src/divviProtocol/saga'
|
|
2
1
|
import { navigate } from 'src/navigator/NavigationService'
|
|
3
2
|
import { Screens } from 'src/navigator/Screens'
|
|
4
3
|
import { CANCELLED_PIN_INPUT } from 'src/pincode/authentication'
|
|
@@ -79,7 +78,6 @@ export function* sendPreparedTransactions(
|
|
|
79
78
|
blockTag: 'pending',
|
|
80
79
|
})
|
|
81
80
|
|
|
82
|
-
const chainId = yield* call([wallet, 'getChainId'])
|
|
83
81
|
const txHashes: Hash[] = []
|
|
84
82
|
for (let i = 0; i < preparedTransactions.length; i++) {
|
|
85
83
|
const preparedTransaction = preparedTransactions[i]
|
|
@@ -99,11 +97,6 @@ export function* sendPreparedTransactions(
|
|
|
99
97
|
hash
|
|
100
98
|
)
|
|
101
99
|
|
|
102
|
-
yield* call(submitDivviReferralSaga, {
|
|
103
|
-
txHash: hash,
|
|
104
|
-
chainId,
|
|
105
|
-
})
|
|
106
|
-
|
|
107
100
|
const tokensById = yield* select(tokensByIdSelector)
|
|
108
101
|
const feeCurrencyId = getFeeCurrencyToken([preparedTransaction], networkId, tokensById)?.tokenId
|
|
109
102
|
|
package/tsconfig.base.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
// This tsconfig is intended to be used by apps consuming the
|
|
2
|
+
// This tsconfig is intended to be used by apps consuming the wallet-stack package
|
|
3
3
|
// TODO: extend from "expo/tsconfig.base" once we're able to get rid of `src` absolute paths
|
|
4
4
|
"extends": "./tsconfig.json"
|
|
5
5
|
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { submitReferral } from '@divvi/referral-sdk'
|
|
2
|
-
import { expectSaga } from 'redux-saga-test-plan'
|
|
3
|
-
import * as matchers from 'redux-saga-test-plan/matchers'
|
|
4
|
-
import { call } from 'redux-saga-test-plan/matchers'
|
|
5
|
-
import { throwError } from 'redux-saga-test-plan/providers'
|
|
6
|
-
import { Address } from 'viem'
|
|
7
|
-
import { submitDivviReferralSaga } from './saga'
|
|
8
|
-
|
|
9
|
-
const provideDelay = ({ fn }: { fn: { name: string } }, next: () => void) =>
|
|
10
|
-
fn.name === 'delayP' || fn.name === 'delay' ? null : next()
|
|
11
|
-
|
|
12
|
-
describe('submitDivviReferralSaga', () => {
|
|
13
|
-
const mockParams = {
|
|
14
|
-
txHash: '0x123' as Address,
|
|
15
|
-
chainId: 1,
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
jest.useFakeTimers()
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
afterEach(() => {
|
|
23
|
-
jest.useRealTimers()
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('successfully submits a referral on first try', async () => {
|
|
27
|
-
await expectSaga(submitDivviReferralSaga, mockParams)
|
|
28
|
-
.provide([[matchers.call.fn(submitReferral), undefined]])
|
|
29
|
-
.run()
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
it('retries on server error and succeeds', async () => {
|
|
33
|
-
const serverError = new Error('Server error')
|
|
34
|
-
|
|
35
|
-
await expectSaga(submitDivviReferralSaga, mockParams)
|
|
36
|
-
.provide([
|
|
37
|
-
[call(submitReferral), throwError(serverError)],
|
|
38
|
-
{ call: provideDelay },
|
|
39
|
-
[call(submitReferral), undefined],
|
|
40
|
-
])
|
|
41
|
-
.run()
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('stops retrying on client error', async () => {
|
|
45
|
-
const clientError = new Error('Client error')
|
|
46
|
-
|
|
47
|
-
await expectSaga(submitDivviReferralSaga, mockParams)
|
|
48
|
-
.provide([[matchers.call.fn(submitReferral), throwError(clientError)]])
|
|
49
|
-
.run()
|
|
50
|
-
})
|
|
51
|
-
})
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Address, submitReferral } from '@divvi/referral-sdk'
|
|
2
|
-
import Logger from 'src/utils/Logger'
|
|
3
|
-
import { call, delay } from 'typed-redux-saga'
|
|
4
|
-
|
|
5
|
-
const TAG = 'divviProtocol/saga'
|
|
6
|
-
|
|
7
|
-
export function* submitDivviReferralSaga({
|
|
8
|
-
txHash,
|
|
9
|
-
chainId,
|
|
10
|
-
}: {
|
|
11
|
-
txHash: Address
|
|
12
|
-
chainId: number
|
|
13
|
-
}) {
|
|
14
|
-
let attempt = 0
|
|
15
|
-
const MAX_ATTEMPTS = 5
|
|
16
|
-
|
|
17
|
-
while (attempt < MAX_ATTEMPTS) {
|
|
18
|
-
try {
|
|
19
|
-
Logger.info(TAG, `Submitting divvi referral ${txHash} attempt ${attempt + 1}`)
|
|
20
|
-
yield* call(submitReferral, { txHash, chainId })
|
|
21
|
-
Logger.info(TAG, `Divvi referral ${txHash} successful`)
|
|
22
|
-
break // Exit on success
|
|
23
|
-
} catch (error: unknown) {
|
|
24
|
-
const message = error instanceof Error ? error.message : 'Unknown error'
|
|
25
|
-
if (message.includes('Client error')) {
|
|
26
|
-
// Do not retry on client errors
|
|
27
|
-
Logger.info(TAG, `Divvi referral ${txHash} cancelled due to client error`)
|
|
28
|
-
break
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Retry on server errors (5xx)
|
|
32
|
-
attempt += 1
|
|
33
|
-
if (attempt >= MAX_ATTEMPTS) {
|
|
34
|
-
// If we've reached the max attempts, pause. We'll retry on the next app load.
|
|
35
|
-
Logger.warn(TAG, `Divvi referral ${txHash} failed after ${MAX_ATTEMPTS} attempts`)
|
|
36
|
-
break
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const backoff = Math.min(2 ** attempt * 1000, 30000) // Exponential, capped at 30s
|
|
40
|
-
Logger.info(TAG, `Retrying divvi referral ${txHash} in ${backoff}ms`)
|
|
41
|
-
yield* delay(backoff)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { render } from '@testing-library/react-native'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import { Provider } from 'react-redux'
|
|
4
|
-
import { getFeatureGate } from 'src/statsig'
|
|
5
|
-
import { createMockStore } from 'test/utils'
|
|
6
|
-
import DivviBottomSheet from './DivviBottomSheet'
|
|
7
|
-
|
|
8
|
-
jest.mock('src/analytics/AppAnalytics')
|
|
9
|
-
jest.mock('src/statsig')
|
|
10
|
-
|
|
11
|
-
describe('DivviBottomSheet', () => {
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
jest.mocked(getFeatureGate).mockReturnValue(true)
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
afterEach(() => {
|
|
17
|
-
jest.clearAllMocks()
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('renders correctly when bottom sheet has not been seen before and feature gate is true', () => {
|
|
21
|
-
const store = createMockStore({
|
|
22
|
-
home: { hasSeenDivviBottomSheet: false },
|
|
23
|
-
})
|
|
24
|
-
const { getByText } = render(
|
|
25
|
-
<Provider store={store}>
|
|
26
|
-
<DivviBottomSheet />
|
|
27
|
-
</Provider>
|
|
28
|
-
)
|
|
29
|
-
expect(getByText('divviBottomSheet.title')).toBeTruthy()
|
|
30
|
-
expect(getByText('divviBottomSheet.cta')).toBeTruthy()
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('does not render when bottom sheet has been seen before', () => {
|
|
34
|
-
const store = createMockStore({
|
|
35
|
-
home: { hasSeenDivviBottomSheet: true },
|
|
36
|
-
})
|
|
37
|
-
const { queryByText } = render(
|
|
38
|
-
<Provider store={store}>
|
|
39
|
-
<DivviBottomSheet />
|
|
40
|
-
</Provider>
|
|
41
|
-
)
|
|
42
|
-
expect(queryByText('divviBottomSheet.title')).toBeNull()
|
|
43
|
-
expect(queryByText('divviBottomSheet.cta')).toBeNull()
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('does not render when bottom sheet has not been seen and feature gate is false', () => {
|
|
47
|
-
jest.mocked(getFeatureGate).mockReturnValue(false)
|
|
48
|
-
const store = createMockStore({
|
|
49
|
-
home: { hasSeenDivviBottomSheet: false },
|
|
50
|
-
})
|
|
51
|
-
const { queryByText } = render(
|
|
52
|
-
<Provider store={store}>
|
|
53
|
-
<DivviBottomSheet />
|
|
54
|
-
</Provider>
|
|
55
|
-
)
|
|
56
|
-
expect(queryByText('divviBottomSheet.title')).toBeNull()
|
|
57
|
-
expect(queryByText('divviBottomSheet.cta')).toBeNull()
|
|
58
|
-
})
|
|
59
|
-
})
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { BottomSheetView } from '@gorhom/bottom-sheet'
|
|
2
|
-
import { Image } from 'expo-image'
|
|
3
|
-
import React, { useEffect, useRef } from 'react'
|
|
4
|
-
import { useTranslation } from 'react-i18next'
|
|
5
|
-
import { StyleSheet, Text, View } from 'react-native'
|
|
6
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
7
|
-
import AppAnalytics from 'src/analytics/AppAnalytics'
|
|
8
|
-
import { HomeEvents } from 'src/analytics/Events'
|
|
9
|
-
import { BottomSheetModalRefType } from 'src/components/BottomSheet'
|
|
10
|
-
import BottomSheetBase from 'src/components/BottomSheetBase'
|
|
11
|
-
import Button, { BtnSizes, BtnTypes } from 'src/components/Button'
|
|
12
|
-
import { divviBottomSheetSeen } from 'src/home/actions'
|
|
13
|
-
import { showDivviBottomSheetSelector } from 'src/home/selectors'
|
|
14
|
-
import { divviPie } from 'src/images/Images'
|
|
15
|
-
import Logo from 'src/images/Logo'
|
|
16
|
-
import LogoHeart from 'src/images/LogoHeart'
|
|
17
|
-
import { navigate } from 'src/navigator/NavigationService'
|
|
18
|
-
import { Screens } from 'src/navigator/Screens'
|
|
19
|
-
import { useDispatch, useSelector } from 'src/redux/hooks'
|
|
20
|
-
import Colors from 'src/styles/colors'
|
|
21
|
-
import { typeScale } from 'src/styles/fonts'
|
|
22
|
-
import { Spacing } from 'src/styles/styles'
|
|
23
|
-
|
|
24
|
-
const DIVVI_SLICES_URL = 'https://slices.divvi.xyz'
|
|
25
|
-
|
|
26
|
-
export default function DivviBottomSheet() {
|
|
27
|
-
const dispatch = useDispatch()
|
|
28
|
-
const { t } = useTranslation()
|
|
29
|
-
|
|
30
|
-
const insets = useSafeAreaInsets()
|
|
31
|
-
const insetsStyle = { paddingBottom: Math.max(insets.bottom, Spacing.Regular16) }
|
|
32
|
-
|
|
33
|
-
const bottomSheetRef = useRef<BottomSheetModalRefType>(null)
|
|
34
|
-
|
|
35
|
-
const shouldShowBottomSheet = useSelector(showDivviBottomSheetSelector)
|
|
36
|
-
|
|
37
|
-
const handleBottomSheetPositionChange = (index: number) => {
|
|
38
|
-
if (index === -1) {
|
|
39
|
-
AppAnalytics.track(HomeEvents.divvi_bottom_sheet_displayed)
|
|
40
|
-
dispatch(divviBottomSheetSeen())
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const handleCtaPress = () => {
|
|
45
|
-
AppAnalytics.track(HomeEvents.divvi_bottom_sheet_cta_pressed)
|
|
46
|
-
bottomSheetRef.current?.close()
|
|
47
|
-
navigate(Screens.WebViewScreen, { uri: DIVVI_SLICES_URL })
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const handleBottomSheetClose = () => {
|
|
51
|
-
dispatch(divviBottomSheetSeen())
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
if (shouldShowBottomSheet) {
|
|
56
|
-
const timeoutId = setTimeout(() => {
|
|
57
|
-
bottomSheetRef.current?.expand()
|
|
58
|
-
}, 1000)
|
|
59
|
-
return () => clearTimeout(timeoutId)
|
|
60
|
-
}
|
|
61
|
-
}, [shouldShowBottomSheet, bottomSheetRef.current])
|
|
62
|
-
|
|
63
|
-
if (!shouldShowBottomSheet) {
|
|
64
|
-
return null
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<BottomSheetBase
|
|
69
|
-
forwardedRef={bottomSheetRef}
|
|
70
|
-
handleComponent={() => null} // handle is rendered within the content body
|
|
71
|
-
backgroundStyle={styles.bottomSheetBackground}
|
|
72
|
-
onChange={handleBottomSheetPositionChange}
|
|
73
|
-
onClose={handleBottomSheetClose}
|
|
74
|
-
>
|
|
75
|
-
<BottomSheetView style={[insetsStyle, styles.sheetContainer]}>
|
|
76
|
-
<View style={styles.topSection}>
|
|
77
|
-
<View style={styles.handleBar} />
|
|
78
|
-
<View style={styles.iconRow}>
|
|
79
|
-
<LogoHeart size={72} />
|
|
80
|
-
<Text style={styles.iconPlus}>+</Text>
|
|
81
|
-
<Logo
|
|
82
|
-
size={56}
|
|
83
|
-
color={Colors.secondaryAccent}
|
|
84
|
-
backgroundColor={Colors.contentPrimary}
|
|
85
|
-
/>
|
|
86
|
-
<Text style={styles.iconEquals}>=</Text>
|
|
87
|
-
<Text style={styles.emoji}>🎉</Text>
|
|
88
|
-
</View>
|
|
89
|
-
</View>
|
|
90
|
-
<View style={styles.bottomSection}>
|
|
91
|
-
<Text style={styles.title}>{t('divviBottomSheet.title')}</Text>
|
|
92
|
-
<View style={styles.descriptionRow}>
|
|
93
|
-
<Text style={styles.description}>
|
|
94
|
-
{t('divviBottomSheet.body_part1') + ' '}
|
|
95
|
-
<Logo size={Spacing.Regular16} translateY={3} />
|
|
96
|
-
{' ' + t('divviBottomSheet.body_part2') + ' '}
|
|
97
|
-
<LogoHeart size={Spacing.Regular16} translateY={3} />
|
|
98
|
-
{' ' + t('divviBottomSheet.body_part3')}
|
|
99
|
-
<View style={styles.inlineImageWrapper}>
|
|
100
|
-
<Image style={styles.inlineImage} source={divviPie} />
|
|
101
|
-
</View>
|
|
102
|
-
{t('divviBottomSheet.body_part4')}
|
|
103
|
-
</Text>
|
|
104
|
-
</View>
|
|
105
|
-
<Button
|
|
106
|
-
style={styles.button}
|
|
107
|
-
type={BtnTypes.PRIMARY}
|
|
108
|
-
size={BtnSizes.FULL}
|
|
109
|
-
onPress={handleCtaPress}
|
|
110
|
-
text={t('divviBottomSheet.cta')}
|
|
111
|
-
/>
|
|
112
|
-
</View>
|
|
113
|
-
</BottomSheetView>
|
|
114
|
-
</BottomSheetBase>
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const styles = StyleSheet.create({
|
|
119
|
-
sheetContainer: {
|
|
120
|
-
padding: 0,
|
|
121
|
-
backgroundColor: 'transparent',
|
|
122
|
-
},
|
|
123
|
-
topSection: {
|
|
124
|
-
backgroundColor: Colors.contentPrimary,
|
|
125
|
-
borderTopLeftRadius: Spacing.Thick24,
|
|
126
|
-
borderTopRightRadius: Spacing.Thick24,
|
|
127
|
-
alignItems: 'center',
|
|
128
|
-
paddingTop: Spacing.Small12,
|
|
129
|
-
paddingBottom: Spacing.Thick24,
|
|
130
|
-
},
|
|
131
|
-
handleBar: {
|
|
132
|
-
width: 40,
|
|
133
|
-
height: 4,
|
|
134
|
-
borderRadius: 4,
|
|
135
|
-
backgroundColor: Colors.borderPrimary,
|
|
136
|
-
marginBottom: Spacing.Regular16,
|
|
137
|
-
},
|
|
138
|
-
iconRow: {
|
|
139
|
-
flexDirection: 'row',
|
|
140
|
-
alignItems: 'center',
|
|
141
|
-
justifyContent: 'center',
|
|
142
|
-
gap: Spacing.Regular16,
|
|
143
|
-
},
|
|
144
|
-
iconPlus: {
|
|
145
|
-
...typeScale.titleMedium,
|
|
146
|
-
color: '#fff',
|
|
147
|
-
fontWeight: 'bold',
|
|
148
|
-
},
|
|
149
|
-
iconEquals: {
|
|
150
|
-
...typeScale.titleMedium,
|
|
151
|
-
color: '#fff',
|
|
152
|
-
fontWeight: 'bold',
|
|
153
|
-
},
|
|
154
|
-
emoji: {
|
|
155
|
-
fontSize: 50,
|
|
156
|
-
},
|
|
157
|
-
bottomSection: {
|
|
158
|
-
paddingHorizontal: Spacing.Thick24,
|
|
159
|
-
paddingTop: Spacing.Thick24,
|
|
160
|
-
paddingBottom: Spacing.Regular16,
|
|
161
|
-
alignItems: 'center',
|
|
162
|
-
},
|
|
163
|
-
title: {
|
|
164
|
-
...typeScale.titleSmall,
|
|
165
|
-
fontWeight: 'bold',
|
|
166
|
-
textAlign: 'center',
|
|
167
|
-
marginBottom: Spacing.Small12,
|
|
168
|
-
},
|
|
169
|
-
descriptionRow: {
|
|
170
|
-
flexDirection: 'row',
|
|
171
|
-
flexWrap: 'wrap',
|
|
172
|
-
alignItems: 'center',
|
|
173
|
-
justifyContent: 'center',
|
|
174
|
-
marginBottom: Spacing.Thick24,
|
|
175
|
-
textAlign: 'left',
|
|
176
|
-
},
|
|
177
|
-
description: {
|
|
178
|
-
...typeScale.bodySmall,
|
|
179
|
-
color: Colors.contentSecondary,
|
|
180
|
-
},
|
|
181
|
-
button: {
|
|
182
|
-
...typeScale.labelSemiBoldSmall,
|
|
183
|
-
width: '100%',
|
|
184
|
-
},
|
|
185
|
-
bottomSheetBackground: {
|
|
186
|
-
marginTop: Spacing.Thick24,
|
|
187
|
-
},
|
|
188
|
-
inlineImageWrapper: {
|
|
189
|
-
paddingLeft: 2,
|
|
190
|
-
paddingRight: 2,
|
|
191
|
-
},
|
|
192
|
-
inlineImage: {
|
|
193
|
-
width: Spacing.Regular16,
|
|
194
|
-
height: Spacing.Regular16,
|
|
195
|
-
transform: [{ translateY: 3 }],
|
|
196
|
-
},
|
|
197
|
-
})
|
package/src/images/DivviLogo.tsx
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import Svg, { Path } from 'react-native-svg'
|
|
3
|
-
import Colors from 'src/styles/colors'
|
|
4
|
-
|
|
5
|
-
const DivviLogo = () => (
|
|
6
|
-
<Svg width={85} height={29} viewBox="0 0 71 24" fill="none">
|
|
7
|
-
<Path
|
|
8
|
-
fill={Colors.contentPrimary}
|
|
9
|
-
d="M18.048 0H5.952A5.952 5.952 0 0 0 0 5.952v12.096A5.952 5.952 0 0 0 5.952 24h12.096A5.952 5.952 0 0 0 24 18.048V5.952A5.952 5.952 0 0 0 18.048 0Z"
|
|
10
|
-
/>
|
|
11
|
-
<Path
|
|
12
|
-
fill={Colors.backgroundPrimary}
|
|
13
|
-
d="M8.845 5.142 5.143 8.844a.807.807 0 0 0 0 1.142l8.876 8.875a.807.807 0 0 0 1.141 0l3.702-3.702a.807.807 0 0 0 0-1.141L9.987 5.142a.807.807 0 0 0-1.142 0ZM17.872 10.445V6.39a.257.257 0 0 0-.256-.256H13.56a.257.257 0 0 0-.18.441l4.056 4.057c.16.16.441.045.441-.18l-.005-.006ZM6.128 13.56v4.056c0 .14.115.256.256.256h4.056c.231 0 .346-.276.18-.441l-4.056-4.057c-.16-.16-.441-.045-.441.18l.005.006Z"
|
|
14
|
-
/>
|
|
15
|
-
<Path
|
|
16
|
-
fill={Colors.contentPrimary}
|
|
17
|
-
d="M28.763 7.95H28V2.72h.641l.21.402c.068-.083.142-.152.223-.21a1.304 1.304 0 0 1 .57-.227c.108-.016.223-.025.345-.025.276 0 .53.048.763.142.235.095.437.227.607.395a1.812 1.812 0 0 1 .546 1.312c0 .26-.048.504-.144.729a1.803 1.803 0 0 1-1.005.977 2.015 2.015 0 0 1-.767.143c-.122 0-.238-.01-.35-.029a1.825 1.825 0 0 1-.322-.078 1.585 1.585 0 0 1-.292-.146 1.55 1.55 0 0 1-.262-.217V7.95Zm0-3.438c0 .185.028.35.083.495.059.144.14.266.243.366.107.1.232.175.376.227.147.052.309.079.486.079s.339-.03.486-.09a1.107 1.107 0 0 0 .618-.614c.058-.143.088-.297.088-.463a1.137 1.137 0 0 0-.721-1.084 1.227 1.227 0 0 0-.471-.089c-.177 0-.34.028-.486.082-.144.052-.27.128-.376.228-.104.1-.184.222-.243.37-.055.144-.083.309-.083.493Zm3.674 0a1.724 1.724 0 0 1 .592-1.315c.185-.166.4-.296.649-.391.248-.095.516-.142.805-.142.288 0 .556.047.804.142.25.095.467.225.65.391.184.166.33.361.436.587.106.225.159.468.159.728 0 .261-.053.504-.16.73-.105.224-.251.42-.436.586a2.04 2.04 0 0 1-.649.387 2.235 2.235 0 0 1-.804.143c-.289 0-.557-.048-.805-.143a2.098 2.098 0 0 1-.649-.387 1.724 1.724 0 0 1-.592-1.315Zm.763 0a1.09 1.09 0 0 0 .376.832c.116.105.251.186.405.246.157.059.324.089.502.089.177 0 .344-.03.5-.09.158-.059.294-.14.41-.245a1.127 1.127 0 0 0 .376-.832 1.127 1.127 0 0 0-.376-.832 1.26 1.26 0 0 0-.41-.248 1.408 1.408 0 0 0-.5-.09c-.178 0-.345.03-.502.09a1.264 1.264 0 0 0-.683.618 1.09 1.09 0 0 0-.098.462Zm8.873-1.791h.816l-1.472 3.558h-.642l-.877-2.584-.94 2.584h-.638l-1.404-3.558h.815l.915 2.556.907-2.556h.71l.88 2.545.93-2.545Zm4.767 2.52v.729a1.947 1.947 0 0 1-.694.295 3.81 3.81 0 0 1-.854.093c-.301 0-.576-.048-.824-.143a1.975 1.975 0 0 1-.641-.39 1.77 1.77 0 0 1-.414-.587 1.835 1.835 0 0 1-.144-.73c0-.26.05-.502.148-.724a1.858 1.858 0 0 1 1.73-1.12c.269 0 .517.044.745.131.23.088.428.21.596.366a1.735 1.735 0 0 1 .539 1.276v.246h-2.98c.02.147.06.282.121.405.063.124.15.23.258.317.112.087.247.156.407.206.162.047.353.071.573.071.248 0 .497-.033.747-.1.251-.068.48-.182.687-.34Zm-1.692-1.898c-.147 0-.28.022-.399.067a1.08 1.08 0 0 0-.315.175.97.97 0 0 0-.338.536h2.1a.834.834 0 0 0-.323-.568.935.935 0 0 0-.315-.157 1.46 1.46 0 0 0-.41-.053Zm4.698-.64.232.764a1.197 1.197 0 0 0-.531-.124c-.18 0-.328.027-.445.082a.62.62 0 0 0-.269.23.952.952 0 0 0-.136.367 2.821 2.821 0 0 0-.039.49V6.28h-.763V2.721h.642l.209.401c.063-.073.124-.137.182-.192a.906.906 0 0 1 .402-.224 1.251 1.251 0 0 1 .516-.004Zm4.251 2.538v.729a1.95 1.95 0 0 1-.694.295 3.806 3.806 0 0 1-.854.093c-.302 0-.576-.048-.824-.143a1.97 1.97 0 0 1-.641-.39 1.763 1.763 0 0 1-.414-.587 1.835 1.835 0 0 1-.144-.73c0-.26.05-.502.148-.724a1.85 1.85 0 0 1 .998-.978c.23-.095.474-.142.732-.142.268 0 .517.044.745.131.23.088.428.21.595.366a1.735 1.735 0 0 1 .54 1.276v.246h-2.98c.02.147.06.282.121.405.064.124.15.23.258.317.112.087.247.156.407.206.161.047.352.071.573.071.248 0 .497-.033.748-.1.25-.068.479-.182.686-.34Zm-1.693-1.898a1.118 1.118 0 0 0-.713.242.962.962 0 0 0-.338.536h2.1a.847.847 0 0 0-.107-.323.744.744 0 0 0-.216-.245.942.942 0 0 0-.316-.157 1.457 1.457 0 0 0-.41-.053ZM57.957 1l.763.338v4.941h-.641l-.21-.401a1.18 1.18 0 0 1-.492.355 1.345 1.345 0 0 1-.304.082 2.215 2.215 0 0 1-1.109-.117 1.9 1.9 0 0 1-.607-.392 1.85 1.85 0 0 1-.542-1.315 1.837 1.837 0 0 1 .542-1.315c.17-.166.372-.297.607-.391a2.142 2.142 0 0 1 1.446-.032 1.317 1.317 0 0 1 .547.359V1Zm0 3.488c0-.185-.029-.35-.087-.495a.966.966 0 0 0-.243-.366 1.031 1.031 0 0 0-.376-.227 1.41 1.41 0 0 0-.482-.079c-.177 0-.339.03-.485.09a1.11 1.11 0 0 0-.377.245 1.125 1.125 0 0 0-.242.37 1.216 1.216 0 0 0-.087.462c0 .168.029.324.087.469.058.142.14.265.242.37.105.104.23.186.377.245.146.06.308.089.485.089s.338-.026.482-.078a.999.999 0 0 0 .618-.597 1.34 1.34 0 0 0 .088-.498Zm3.906 1.791V1l.762.338v1.774a1.256 1.256 0 0 1 .547-.36 2.15 2.15 0 0 1 .68-.11c.278 0 .533.048.766.143.235.094.438.225.607.39a1.835 1.835 0 0 1 .543 1.315 1.826 1.826 0 0 1-.546 1.316c-.17.166-.372.297-.608.392a2.002 2.002 0 0 1-.762.142 2.077 2.077 0 0 1-.661-.107 1.432 1.432 0 0 1-.281-.146 1.404 1.404 0 0 1-.246-.22v.412h-.801Zm.762-1.791c0 .184.029.35.084.497.058.145.14.268.243.37.106.1.232.175.376.228.147.052.308.078.486.078.176 0 .339-.03.485-.09a1.104 1.104 0 0 0 .619-.614c.058-.145.087-.301.087-.47 0-.165-.029-.32-.087-.462a1.104 1.104 0 0 0-.618-.615 1.287 1.287 0 0 0-.486-.089c-.178 0-.34.027-.486.079-.144.052-.27.128-.376.227a1.04 1.04 0 0 0-.243.366c-.056.145-.084.31-.084.495Zm5.04 1.653L66.11 2.72h.797l1.13 2.591 1.185-2.591H70L67.62 8l-.656-.292.702-1.567ZM35.217 9.06l2.238.943V23.2h-1.857l-.457-.933a2.896 2.896 0 0 1-.543.505c-.197.133-.41.244-.638.333a3.19 3.19 0 0 1-.714.19 5.4 5.4 0 0 1-.8.057 4.841 4.841 0 0 1-1.933-.38 4.703 4.703 0 0 1-1.533-1.048 5.101 5.101 0 0 1-1.009-1.58 5.181 5.181 0 0 1-.362-1.943c0-.698.121-1.349.362-1.952a4.983 4.983 0 0 1 1.01-1.57 4.595 4.595 0 0 1 1.523-1.048 4.909 4.909 0 0 1 1.942-.381c.273 0 .537.022.79.067.255.038.499.098.734.18.235.083.457.191.666.324.21.133.403.295.581.486V9.06Zm.02 9.332c0-.445-.068-.841-.2-1.19a2.384 2.384 0 0 0-1.4-1.438 3.056 3.056 0 0 0-1.105-.19c-.4 0-.768.072-1.105.218-.33.14-.612.337-.847.59-.235.255-.419.553-.552.896-.133.342-.2.714-.2 1.114 0 .406.067.784.2 1.133s.317.65.552.904c.235.248.517.445.847.59.337.14.705.21 1.105.21.406 0 .774-.06 1.105-.18.33-.128.612-.312.847-.553.241-.248.425-.546.552-.895.133-.356.2-.759.2-1.21Zm5.122-4.723h2.237V23.2H40.36v-9.531Zm-.248-3.39c0-.19.035-.371.105-.542.076-.172.175-.321.295-.448s.264-.225.428-.295a1.32 1.32 0 0 1 1.076 0 1.338 1.338 0 0 1 .743.743c.07.171.105.352.105.542 0 .19-.035.372-.105.543a1.342 1.342 0 0 1-.743.743 1.424 1.424 0 0 1-1.075 0 1.262 1.262 0 0 1-.429-.295 1.567 1.567 0 0 1-.295-.448 1.423 1.423 0 0 1-.105-.543ZM48.566 23.2l-4.16-9.531h2.39l2.57 6.275 2.704-6.275h2.39L50.128 23.2h-1.562Zm10.398 0-4.161-9.531h2.39l2.57 6.275 2.705-6.275h2.39L60.524 23.2h-1.561Zm7.54-9.531h2.238V23.2h-2.237v-9.531Zm-.247-3.39c0-.19.035-.371.105-.542.076-.172.174-.321.295-.448.12-.127.263-.225.428-.295a1.323 1.323 0 0 1 1.076 0 1.34 1.34 0 0 1 .743.743c.07.171.105.352.105.542 0 .19-.035.372-.105.543a1.342 1.342 0 0 1-.742.743 1.427 1.427 0 0 1-1.077 0 1.262 1.262 0 0 1-.428-.295 1.567 1.567 0 0 1-.295-.448 1.423 1.423 0 0 1-.105-.543Z"
|
|
18
|
-
/>
|
|
19
|
-
</Svg>
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
export default DivviLogo
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|