Skip to content

Commit e694cbf

Browse files
authored
Merge pull request #708 from enkryptcom/feature/solana-staking-banner
Created Solana staking banners
2 parents dc644eb + caf9330 commit e694cbf

17 files changed

Lines changed: 568 additions & 25 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import BrowserStorage from '../common/browser-storage';
2+
import { InternalStorageNamespace } from '@/types/provider';
3+
import { StorageKeys, IState } from './types';
4+
5+
export default class BannersState {
6+
private storage: BrowserStorage;
7+
8+
constructor() {
9+
this.storage = new BrowserStorage(InternalStorageNamespace.bannersState);
10+
}
11+
12+
private async getOrInitializeState(): Promise<IState> {
13+
const state: IState | undefined = await this.storage.get(
14+
StorageKeys.bannersInfo,
15+
);
16+
if (state) {
17+
return state;
18+
}
19+
const newState: IState = {
20+
isHideSolanStakingBanner: false,
21+
isHideNetworkAssetSolanStakingBanner: false,
22+
};
23+
await this.storage.set(StorageKeys.bannersInfo, newState);
24+
return newState;
25+
}
26+
27+
async resetBanners(): Promise<void> {
28+
const state = await this.getOrInitializeState();
29+
state.isHideNetworkAssetSolanStakingBanner = false;
30+
state.isHideSolanStakingBanner = false;
31+
await this.storage.set(StorageKeys.bannersInfo, state);
32+
}
33+
34+
async showSolanaStakingBanner(): Promise<boolean> {
35+
const state = await this.getOrInitializeState();
36+
return !state.isHideSolanStakingBanner;
37+
}
38+
39+
async showNetworkAssetsSolanaStakingBanner(): Promise<boolean> {
40+
const state = await this.getOrInitializeState();
41+
return !state.isHideNetworkAssetSolanStakingBanner;
42+
}
43+
44+
async hideNetworkAssetsSolanaStakingBanner() {
45+
const state = await this.getOrInitializeState();
46+
state.isHideNetworkAssetSolanStakingBanner = true;
47+
await this.storage.set(StorageKeys.bannersInfo, state);
48+
}
49+
50+
async hideSolanaStakingBanner() {
51+
const state = await this.getOrInitializeState();
52+
state.isHideSolanStakingBanner = true;
53+
this.storage.set(StorageKeys.bannersInfo, state);
54+
}
55+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export enum StorageKeys {
2+
bannersInfo = 'banners-info',
3+
}
4+
5+
export type IState = {
6+
isHideSolanStakingBanner: boolean;
7+
isHideNetworkAssetSolanStakingBanner: boolean;
8+
};

packages/extension/src/libs/metrics/index.ts

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import {
1212
SettingEventType,
1313
SwapEventType,
1414
UpdatesEventType,
15-
UpdatesOpenLocation
15+
UpdatesOpenLocation,
16+
SolanaStakingBannerEvents,
1617
} from './types';
1718

1819
const metrics = new Metrics();
@@ -25,19 +26,19 @@ const trackNetwork = (
2526
event: NetworkChangeEvents,
2627
options: {
2728
provider?: ProviderName;
28-
network?: NetworkNames,
29-
networkTab?: string,
30-
networkType?: NetworkType,
31-
isPinned?: boolean,
32-
sortOption?: string,
33-
customRpcUrl?: string,
34-
customNetworkName?: string,
35-
customNetworkNameLong?: string,
36-
customNetworkCurrency?: string,
37-
customNetworkCurrencyLong?: string,
38-
customChainId?: string,
39-
customBlockExplorerUrlTx?: string
40-
customBlockExplorerUrlAddr?: string
29+
network?: NetworkNames;
30+
networkTab?: string;
31+
networkType?: NetworkType;
32+
isPinned?: boolean;
33+
sortOption?: string;
34+
customRpcUrl?: string;
35+
customNetworkName?: string;
36+
customNetworkNameLong?: string;
37+
customNetworkCurrency?: string;
38+
customNetworkCurrencyLong?: string;
39+
customChainId?: string;
40+
customBlockExplorerUrlTx?: string;
41+
customBlockExplorerUrlAddr?: string;
4142
},
4243
) => {
4344
metrics.track('network', { event, ...options });
@@ -93,14 +94,16 @@ const trackDAppsEvents = (
9394
metrics.track('dapps', { event, ...options });
9495
};
9596

96-
const trackUpdatesEvents = (event: UpdatesEventType, options: {
97-
network: NetworkNames;
98-
location?: UpdatesOpenLocation;
99-
duration?: number;
100-
}): void => {
97+
const trackUpdatesEvents = (
98+
event: UpdatesEventType,
99+
options: {
100+
network: NetworkNames;
101+
location?: UpdatesOpenLocation;
102+
duration?: number;
103+
},
104+
): void => {
101105
metrics.track('updatesClick', { event, ...options });
102-
103-
}
106+
};
104107
const optOutofMetrics = (optOut: boolean) => {
105108
if (!__IS_FIREFOX__) {
106109
metrics.setOptOut(false);
@@ -112,6 +115,10 @@ const optOutofMetrics = (optOut: boolean) => {
112115
metrics.setOptOut(optOut);
113116
};
114117

118+
const trackSolanaStakingBanner = (event: SolanaStakingBannerEvents) => {
119+
metrics.track('solStakingBanner', { event });
120+
};
121+
115122
export {
116123
trackNetwork,
117124
trackSwapEvents,
@@ -121,5 +128,6 @@ export {
121128
trackDAppsEvents,
122129
optOutofMetrics,
123130
trackGenericEvents,
124-
trackUpdatesEvents
131+
trackUpdatesEvents,
132+
trackSolanaStakingBanner,
125133
};

packages/extension/src/libs/metrics/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,10 @@ export enum UpdatesEventType {
6969

7070
export enum UpdatesOpenLocation {
7171
settings = 'settings',
72-
logo = "logo",
72+
logo = 'logo',
73+
}
74+
75+
export enum SolanaStakingBannerEvents {
76+
SolanaWalletClicked = 'sol_staking_banner.solana_wallet.clicked',
77+
NetworkListClicked = 'sol_staking_banner.network_list.clicked',
7378
}

packages/extension/src/types/provider.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export enum InternalStorageNamespace {
5555
updatesState = 'UpdatesState',
5656
backupState = 'BackupState',
5757
menuState = 'MenuState',
58+
bannersState = 'BannersState',
5859
}
5960
export enum EnkryptProviderEventMethods {
6061
persistentEvents = 'PersistentEvents',
@@ -132,7 +133,7 @@ export abstract class BackgroundProviderInterface extends EventEmitter {
132133
export abstract class ProviderAPIInterface {
133134
abstract node: string;
134135
// eslint-disable-next-line @typescript-eslint/no-unused-vars
135-
constructor(node: string, options?: unknown) { }
136+
constructor(node: string, options?: unknown) {}
136137
abstract init(): Promise<void>;
137138
abstract getBalance(address: string): Promise<string>;
138139
abstract getTransactionStatus(
17.4 KB
Loading
57.5 KB
Loading
106 KB
Loading
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<template>
2+
<div class="solana-stacking-banner">
3+
<img src="@action/assets/banners/solana-stacking-banner.png" alt="" />
4+
5+
<div class="solana-stacking-banner__content">
6+
<enkrypt-staking-logo />
7+
<h5>Put your SOL to work — safely & easily.</h5>
8+
<a href="javascript:void(0);" @click="openStakingLink" class="button"
9+
><span>Start Staking Now</span></a
10+
>
11+
</div>
12+
13+
<a class="solana-stacking-banner__close" @click="close">
14+
<close-icon />
15+
</a>
16+
</div>
17+
</template>
18+
19+
<script setup lang="ts">
20+
import CloseIcon from '@action/icons/common/close-icon.vue';
21+
import EnkryptStakingLogo from '@action/icons/common/enkrypt-staking-logo.vue';
22+
import { trackSolanaStakingBanner } from '@/libs/metrics';
23+
import { openLink } from '@action/utils/browser';
24+
import { SolanaStakingBannerEvents } from '@/libs/metrics/types';
25+
26+
const emit = defineEmits<{
27+
(e: 'close'): void;
28+
}>();
29+
30+
const close = () => {
31+
emit('close');
32+
};
33+
const openStakingLink = async () => {
34+
trackSolanaStakingBanner(SolanaStakingBannerEvents.SolanaWalletClicked);
35+
setTimeout(() => {
36+
openLink('https://staking.enkrypt.com');
37+
}, 1000);
38+
};
39+
</script>
40+
41+
<style lang="less">
42+
@import '@action/styles/theme.less';
43+
44+
.solana-stacking-banner {
45+
position: absolute;
46+
width: 324px;
47+
height: 128px;
48+
left: 8px;
49+
bottom: 8px;
50+
background: #ffffff;
51+
box-shadow:
52+
0px 8px 16px -6px rgba(0, 0, 0, 0.12),
53+
0px 6px 8px -6px rgba(0, 0, 0, 0.12);
54+
border-radius: 12px;
55+
padding: 0 129px 0 12px;
56+
box-sizing: border-box;
57+
overflow: hidden;
58+
59+
img {
60+
height: 128px;
61+
position: absolute;
62+
right: 0;
63+
top: 0;
64+
}
65+
66+
&__content {
67+
padding: 8px 0 0 0;
68+
69+
svg {
70+
margin-bottom: 4px;
71+
}
72+
73+
h5 {
74+
font-size: 16px;
75+
font-style: normal;
76+
font-weight: 700;
77+
line-height: 20px;
78+
/* 125% */
79+
letter-spacing: 0.15px;
80+
color: @primaryLabel;
81+
margin: 0 0 8px 0;
82+
background: linear-gradient(to left, #14f195, #64abf2, #9945ff);
83+
-webkit-background-clip: text;
84+
background-clip: text;
85+
-webkit-text-fill-color: transparent;
86+
}
87+
88+
.button {
89+
text-decoration: none;
90+
width: auto;
91+
width: 163px;
92+
height: 32px;
93+
font-size: 12px;
94+
line-height: 32px;
95+
}
96+
}
97+
98+
&__close {
99+
position: absolute;
100+
top: 0;
101+
right: 0;
102+
cursor: pointer;
103+
transition: opacity 300ms ease-in-out;
104+
opacity: 1;
105+
font-size: 0;
106+
width: 32px;
107+
height: 32px;
108+
109+
svg {
110+
width: 32px;
111+
height: 32px;
112+
}
113+
114+
&:hover {
115+
opacity: 0.7;
116+
}
117+
}
118+
}
119+
</style>

packages/extension/src/ui/action/components/app-menu/index.vue

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@
156156
</div>
157157
</div>
158158
</div>
159+
160+
<!-- Banners -->
161+
<solana-staking-banner
162+
v-if="isSolanaStackingBanner"
163+
@close="closeSolanaStackingBanner"
164+
/>
159165
</div>
160166
</template>
161167

@@ -199,6 +205,8 @@ import { storeToRefs } from 'pinia';
199205
import { onClickOutside } from '@vueuse/core';
200206
import SearchIcon from '@action/icons/common/search.vue';
201207
import { useMenuStore } from '@action/store/menu-store';
208+
import SolanaStakingBanner from './components/solana-staking-banner.vue';
209+
import BannersState from '@/libs/banners-state';
202210
203211
const appMenuRef = ref(null);
204212
@@ -260,6 +268,9 @@ onMounted(async () => {
260268
newNetworksWithTags.value.swap = newSwaps.filter(
261269
net => !usedNetworks.swap.includes(net),
262270
);
271+
// if (await bannersState.showSolanaStakingBanner()) {
272+
// isSolanaStackingBanner.value = true;
273+
// }
263274
});
264275
265276
/** -------------------
@@ -526,6 +537,17 @@ const updateGradient = (newGradient: string) => {
526537
(appMenuRef.value as HTMLElement).style.background =
527538
`radial-gradient(137.35% 97% at 100% 50%, rgba(250, 250, 250, 0.94) 0%, rgba(250, 250, 250, 0.96) 28.91%, rgba(250, 250, 250, 0.98) 100%), linear-gradient(180deg, ${newGradient} 80%, #684CFF 100%)`;
528539
};
540+
541+
/** ------------------
542+
* Banners
543+
------------------*/
544+
const isSolanaStackingBanner = ref(false);
545+
const bannersState = new BannersState();
546+
547+
const closeSolanaStackingBanner = () => {
548+
isSolanaStackingBanner.value = false;
549+
bannersState.hideSolanaStakingBanner();
550+
};
529551
</script>
530552

531553
<style lang="less">

0 commit comments

Comments
 (0)