Skip to content

Commit

Permalink
Merge pull request #587 from enkryptcom/feat/recent-addresses
Browse files Browse the repository at this point in the history
feat: recent addresses
  • Loading branch information
NickKelly1 authored Jan 9, 2025
2 parents 48de0a5 + 584562d commit c630149
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 13 deletions.
41 changes: 41 additions & 0 deletions packages/extension/src/libs/recently-sent-addresses/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { InternalStorageNamespace } from "@/types/provider";
import BrowserStorage from "../common/browser-storage";
import { IState, } from "./types";
import { NetworkNames } from "@enkryptcom/types";
import { BaseNetwork } from "@/types/base-network";

class RecentlySentAddressesState {
#storage: BrowserStorage

constructor() {
this.#storage = new BrowserStorage(
InternalStorageNamespace.recentlySentAddresses,
);
}

async addRecentlySentAddress(
network: Pick<BaseNetwork, 'name' | 'displayAddress'>,
address: string,
): Promise<void> {
const key = network.name
const state: IState | undefined = await this.#storage.get(key)
const newState: IState = {
...state,
addresses: Array.from(new Set([
network.displayAddress(address),
...(state?.addresses ?? []),
])).slice(0, 5),
}
await this.#storage.set(key, newState)
}

async getRecentlySentAddresses(networkName: NetworkNames): Promise<string[]> {
const key = networkName
const out: IState | undefined = await this.#storage.get(key)
if (!out) return []
return out.addresses
}
}

export default RecentlySentAddressesState

3 changes: 3 additions & 0 deletions packages/extension/src/libs/recently-sent-addresses/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type IState = {
addresses: string[]
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ import { getTxInfo as getBTCTxInfo } from '@/providers/bitcoin/libs/utils';
import { NFTItem, NFTItemWithCollectionName, NFTType } from '@/types/nft';
import { trackSendEvents } from '@/libs/metrics';
import { SendEventType } from '@/libs/metrics/types';
import RecentlySentAddressesState from '@/libs/recently-sent-addresses';
const props = defineProps({
network: {
Expand Down Expand Up @@ -428,7 +429,14 @@ const selectNFT = (item: NFTItemWithCollectionName) => {
isOpenSelectNft.value = false;
};
const recentlySentAddresses = new RecentlySentAddressesState();
const sendAction = async () => {
await recentlySentAddresses.addRecentlySentAddress(
props.network,
addressTo.value,
);
const keyring = new PublicKeyRing();
const fromAccountInfo = await keyring.getAccount(addressFrom.value);
const currentFee = toBN(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<img :src="network.identicon(network.displayAddress(account.address))" />

<div class="send-address-item__name">
<h4>{{ account.name }}</h4>
<h4 v-if="account.name != null">{{ account.name }}</h4>
<p>
{{
$filters.replaceWithEllipsis(
Expand All @@ -32,13 +32,17 @@ import { EnkryptAccount } from '@enkryptcom/types';
const emit = defineEmits<{
(e: 'selected:account', address: string): void;
}>();
defineProps({
network: {
type: Object as PropType<BaseNetwork>,
default: () => ({}),
},
account: {
type: Object as PropType<EnkryptAccount>,
type: Object as PropType<{
name?: string;
address: string;
}>,
default: () => {
return {};
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
class="send-contacts-list__scroll-area"
:settings="scrollSettings({ suppressScrollX: true })"
>
<div v-if="!isMyAddress" class="send-contacts-list__block">
<div
v-if="recentlySentAddresses && !isMyAddress"
class="send-contacts-list__block"
>
<div class="send-contacts-list__buttons">
<base-button title="Send to my address" :click="sendToMyAddress" />

Expand All @@ -20,15 +23,43 @@
<paste-icon /> Paste
</a>
</div>
<h3>Recent</h3>
<template v-if="recentlySentAddresses.length">
<h3>Recent</h3>
<div class="send-contacts-list__list">
<send-address-item
v-for="(recentAddress, index) in recentlySentAddresses"
:key="index"
:account="{
address: recentAddress,
name: accountInfo.activeAccounts.find(
account =>
network.displayAddress(account.address) ===
network.displayAddress(recentAddress),
)?.name,
}"
:network="network"
v-bind="$attrs"
:is-checked="
!!address &&
network.displayAddress(address) ===
network.displayAddress(recentAddress)
"
/>
</div>
</template>
<h3>My accounts</h3>
<div class="send-contacts-list__list">
<send-address-item
v-for="(account, index) in accountInfo.activeAccounts"
:key="index"
:account="account"
:network="network"
v-bind="$attrs"
:is-checked="address == account.address"
:is-checked="
!!address &&
network.displayAddress(address) ===
network.displayAddress(account.address)
"
/>
</div>
</div>
Expand All @@ -39,15 +70,18 @@
</a>
<h4>My accounts</h4>
</div>

<div class="send-contacts-list__list">
<send-address-item
v-for="(account, index) in accountInfo.activeAccounts"
:key="index"
:account="account"
:network="network"
v-bind="$attrs"
:is-checked="address == account.address"
:is-checked="
!!address &&
network.displayAddress(address) ===
network.displayAddress(account.address)
"
/>
</div>
</div>
Expand All @@ -57,7 +91,7 @@
</template>

<script setup lang="ts">
import { PropType, ref } from 'vue';
import { onMounted, PropType, ref } from 'vue';
import SendAddressItem from './send-address-item.vue';
import CustomScrollbar from '@action/components/custom-scrollbar/index.vue';
import BaseButton from '@action/components/base-button/index.vue';
Expand All @@ -66,6 +100,7 @@ import scrollSettings from '@/libs/utils/scroll-settings';
import { BaseNetwork } from '@/types/base-network';
import PasteIcon from '@action/icons/actions/paste.vue';
import ArrowBack from '@action/icons/common/arrow-back.vue';
import RecentlySentAddressesState from '@/libs/recently-sent-addresses';
const emit = defineEmits<{
(e: 'update:pasteFromClipboard'): void;
Expand All @@ -74,7 +109,7 @@ const emit = defineEmits<{
const isMyAddress = ref(false);
defineProps({
const props = defineProps({
showAccounts: Boolean,
accountInfo: {
type: Object as PropType<AccountsHeaderData>,
Expand All @@ -90,6 +125,36 @@ defineProps({
},
});
const recentlySentAddressesState = new RecentlySentAddressesState();
const recentlySentAddresses = ref<null | string[]>(null);
onMounted(async function () {
let timedOut = false;
const timeout = setTimeout(function () {
console.error('Timed out getting recently sent addresses');
recentlySentAddresses.value = [];
timedOut = true;
}, 500);
try {
const addresses = await recentlySentAddressesState.getRecentlySentAddresses(
props.network.name,
);
if (!timedOut) {
recentlySentAddresses.value = Array.from(
new Set(
addresses.map(address => props.network.displayAddress(address)),
),
);
}
} catch (err) {
console.error('Error getting recently sent addresses', err);
recentlySentAddresses.value = [];
} finally {
clearTimeout(timeout);
}
});
const close = () => {
emit('close', false);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ import { GenericNameResolver, CoinType } from '@/libs/name-resolver';
import { NetworkNames } from '@enkryptcom/types';
import { trackSendEvents } from '@/libs/metrics';
import { SendEventType } from '@/libs/metrics/types';
import RecentlySentAddressesState from '@/libs/recently-sent-addresses';
const props = defineProps({
network: {
Expand Down Expand Up @@ -710,7 +711,14 @@ const selectFee = (type: GasPriceTypes) => {
updateTransactionFees(Tx.value);
};
const recentlySentAddresses = new RecentlySentAddressesState();
const sendAction = async () => {
await recentlySentAddresses.addRecentlySentAddress(
props.network,
addressTo.value,
);
const keyring = new PublicKeyRing();
const fromAccountInfo = await keyring.getAccount(
addressFrom.value.toLowerCase(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ import getUiPath from '@/libs/utils/get-ui-path';
import { ProviderName } from '@/types/provider';
import Browser from 'webextension-polyfill';
import { ICommandResult } from '@kadena/client';
import RecentlySentAddressesState from '@/libs/recently-sent-addresses';
const props = defineProps({
network: {
Expand Down Expand Up @@ -466,7 +467,14 @@ const isDisabled = computed(() => {
);
});
const recentlySentAddresses = new RecentlySentAddressesState();
const sendAction = async () => {
await recentlySentAddresses.addRecentlySentAddress(
props.network,
addressTo.value,
);
const keyring = new PublicKeyRing();
const fromAccount = await keyring.getAccount(addressFrom.value);
const networkApi = (await props.network.api()) as KadenaAPI;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ import { GenericNameResolver, CoinType } from '@/libs/name-resolver';
import { trackSendEvents } from '@/libs/metrics';
import { SendEventType } from '@/libs/metrics/types';
import { BNType } from '@/providers/common/types';
import RecentlySentAddressesState from '@/libs/recently-sent-addresses';
const props = defineProps({
network: {
Expand Down Expand Up @@ -497,7 +498,14 @@ const isDisabled = computed(() => {
return isDisabled;
});
const recentlySentAddresses = new RecentlySentAddressesState();
const sendAction = async () => {
await recentlySentAddresses.addRecentlySentAddress(
props.network,
addressTo.value,
);
const sendAmount = toBase(amount.value!, selectedAsset.value.decimals!);
const sendOptions: SendOptions | undefined = sendMax.value
Expand Down
4 changes: 2 additions & 2 deletions packages/extension/src/providers/solana/networks/solana.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ const solanaOptions: SolanaNetworkOptions = {
coingeckoPlatform: CoingeckoPlatform.Solana,
};

const bitcoin = new SolanaNetwork(solanaOptions);
const solana = new SolanaNetwork(solanaOptions);

export default bitcoin;
export default solana;
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ import {
import getPriorityFees from '../libs/get-priority-fees';
import bs58 from 'bs58';
import SolanaAPI from '@/providers/solana/libs/api';
import { ComputedRefSymbol } from '@vue/reactivity';
import RecentlySentAddressesState from '@/libs/recently-sent-addresses';
const props = defineProps({
network: {
Expand Down Expand Up @@ -718,7 +718,14 @@ const inputAmount = (inputAmount: string) => {
}
};
const recentlySentAddresses = new RecentlySentAddressesState();
const sendAction = async () => {
await recentlySentAddresses.addRecentlySentAddress(
props.network,
addressTo.value,
);
const keyring = new PublicKeyRing();
const fromAccountInfo = await keyring.getAccount(
addressFrom.value.toLowerCase(),
Expand Down
3 changes: 2 additions & 1 deletion packages/extension/src/types/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export enum InternalStorageNamespace {
tokensState = 'TokensState',
customNetworksState = 'CustomNetworksState',
rateState = 'RateState',
recentlySentAddresses = 'RecentlySentAddresses',
}
export enum EnkryptProviderEventMethods {
persistentEvents = 'PersistentEvents',
Expand Down Expand Up @@ -128,7 +129,7 @@ export abstract class BackgroundProviderInterface extends EventEmitter {
export abstract class ProviderAPIInterface {
abstract node: string;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
constructor(node: string, options?: unknown) {}
constructor(node: string, options?: unknown) { }
abstract init(): Promise<void>;
abstract getBalance(address: string): Promise<string>;
abstract getTransactionStatus(
Expand Down

0 comments on commit c630149

Please sign in to comment.