diff --git a/src/composables/currencies.ts b/src/composables/currencies.ts
index da146ccd2..3e58ee30f 100644
--- a/src/composables/currencies.ts
+++ b/src/composables/currencies.ts
@@ -66,7 +66,7 @@ export function useCurrencies({
function getCoinGeckoCoinIdList() {
return protocolsInUse.value.map(
- (protocol) => ProtocolAdapterFactory.getAdapter(protocol).getCoinGeckoCoinId(),
+ (protocol) => ProtocolAdapterFactory.getAdapter(protocol).coinGeckoCoinId,
).join(',');
}
diff --git a/src/constants/common.ts b/src/constants/common.ts
index 404fd104d..666a17510 100644
--- a/src/constants/common.ts
+++ b/src/constants/common.ts
@@ -13,6 +13,7 @@ export const PROTOCOLS = {
aeternity: 'aeternity',
bitcoin: 'bitcoin',
ethereum: 'ethereum',
+ solana: 'solana',
} as const;
export const PROTOCOL_LIST = Object.values(PROTOCOLS);
diff --git a/src/icons/coin/bitcoin.svg b/src/icons/coin/bitcoin.svg
index 0b74984b5..9b9b3925f 100644
--- a/src/icons/coin/bitcoin.svg
+++ b/src/icons/coin/bitcoin.svg
@@ -1,11 +1,4 @@
\ No newline at end of file
+
+
+
diff --git a/src/icons/coin/dogecoin.svg b/src/icons/coin/dogecoin.svg
index f849ffd03..6dc531adc 100644
--- a/src/icons/coin/dogecoin.svg
+++ b/src/icons/coin/dogecoin.svg
@@ -1,133 +1,126 @@
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/icons/coin/ethereum.svg b/src/icons/coin/ethereum.svg
index d9c14d318..e698fe42f 100644
--- a/src/icons/coin/ethereum.svg
+++ b/src/icons/coin/ethereum.svg
@@ -1,15 +1,8 @@
diff --git a/src/icons/coin/solana.svg b/src/icons/coin/solana.svg
new file mode 100644
index 000000000..9ceb89463
--- /dev/null
+++ b/src/icons/coin/solana.svg
@@ -0,0 +1,14 @@
+
diff --git a/src/popup/components/AssetIcon.vue b/src/popup/components/AssetIcon.vue
index 12d8ab78b..953421cc9 100644
--- a/src/popup/components/AssetIcon.vue
+++ b/src/popup/components/AssetIcon.vue
@@ -36,6 +36,7 @@ import { AE_AVATAR_URL } from '@/protocols/aeternity/config';
import AeternityIcon from '@/icons/coin/aeternity.svg?vue-component';
import BitcoinIcon from '@/icons/coin/bitcoin.svg?vue-component';
import EthereumIcon from '@/icons/coin/ethereum.svg?vue-component';
+import SolanaIcon from '@/icons/coin/solana.svg?vue-component';
import LexonTokenIcon from '@/icons/tokens/ct_xtk8rSz9suPb6D6VLquyfVji25FcnFRDjn3dnn5mmvHsPiESt.svg?vue-component';
const SIZES = [ICON_SIZES.sm, ICON_SIZES.rg, ICON_SIZES.md, ICON_SIZES.lg, ICON_SIZES.xxl] as const;
@@ -46,6 +47,7 @@ const COIN_ICONS: Record = {
[PROTOCOLS.aeternity]: AeternityIcon,
[PROTOCOLS.bitcoin]: BitcoinIcon,
[PROTOCOLS.ethereum]: EthereumIcon,
+ [PROTOCOLS.solana]: SolanaIcon,
};
const ASSET_ICONS: Dictionary = {
diff --git a/src/popup/components/Modals/AccountCreate.vue b/src/popup/components/Modals/AccountCreate.vue
index b42912935..2c2b36a63 100644
--- a/src/popup/components/Modals/AccountCreate.vue
+++ b/src/popup/components/Modals/AccountCreate.vue
@@ -58,7 +58,7 @@ export default defineComponent({
setup(props) {
const { addRawAccount, setActiveAccountByGlobalIdx } = useAccounts();
const { isOnline } = useConnection();
- const { openModal } = useModals();
+ const { openModal, openDefaultModal } = useModals();
const { setLoaderVisible } = useUi();
async function createAccount(protocol: Protocol) {
@@ -82,7 +82,7 @@ export default defineComponent({
break;
default:
- throw new Error(`createAccount not implemented for protocol: ${protocol}`);
+ openDefaultModal({ icon: 'alert', msg: `Account creation not possible for protocol: ${protocol}` });
}
setLoaderVisible(false);
props.resolve();
diff --git a/src/popup/components/ProtocolIcon.vue b/src/popup/components/ProtocolIcon.vue
index c95da560c..2fafff127 100644
--- a/src/popup/components/ProtocolIcon.vue
+++ b/src/popup/components/ProtocolIcon.vue
@@ -16,9 +16,11 @@ import {
} from 'vue';
import { ICON_SIZES, PROTOCOLS } from '@/constants';
import type { Protocol } from '@/types';
+
import AeternityLogo from '@/icons/logo/aeternity.svg?vue-component';
import BitcoinIcon from '@/icons/coin/bitcoin.svg?vue-component';
import EthereumIcon from '@/icons/coin/ethereum.svg?vue-component';
+import SolanaIcon from '@/icons/coin/solana.svg?vue-component';
const SIZES = [ICON_SIZES.xs, ICON_SIZES.md, ICON_SIZES.rg, ICON_SIZES.lg, ICON_SIZES.xl] as const;
@@ -41,6 +43,7 @@ export default defineComponent({
[PROTOCOLS.aeternity]: AeternityLogo,
[PROTOCOLS.bitcoin]: BitcoinIcon,
[PROTOCOLS.ethereum]: EthereumIcon,
+ [PROTOCOLS.solana]: SolanaIcon,
};
const selectedIcon = computed((): Component => iconsMap[props.protocol]);
diff --git a/src/popup/components/ProtocolSpecificView.vue b/src/popup/components/ProtocolSpecificView.vue
index dca17aa30..bc92cdc35 100644
--- a/src/popup/components/ProtocolSpecificView.vue
+++ b/src/popup/components/ProtocolSpecificView.vue
@@ -27,6 +27,14 @@ import {
defineComponent,
ref,
} from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+import {
+ onIonViewDidEnter,
+ onIonViewDidLeave,
+ onIonViewWillEnter,
+ onIonViewWillLeave,
+} from '@ionic/vue';
+
import type {
WalletRouteMeta,
Protocol,
@@ -41,14 +49,8 @@ import { ProtocolAdapterFactory } from '@/lib/ProtocolAdapterFactory';
import aeternityViews from '@/protocols/aeternity/views';
import bitcoinViews from '@/protocols/bitcoin/views';
import ethereumViews from '@/protocols/ethereum/views';
+import solanaViews from '@/protocols/solana/views';
-import { useRoute, useRouter } from 'vue-router';
-import {
- onIonViewDidEnter,
- onIonViewDidLeave,
- onIonViewWillEnter,
- onIonViewWillLeave,
-} from '@ionic/vue';
import InfoBox from './InfoBox.vue';
/**
@@ -58,6 +60,7 @@ const views: Record = {
aeternity: aeternityViews,
bitcoin: bitcoinViews,
ethereum: ethereumViews,
+ solana: solanaViews,
};
export default defineComponent({
diff --git a/src/popup/pages/Assets/AssetDetailsInfo.vue b/src/popup/pages/Assets/AssetDetailsInfo.vue
index bc4be1188..fef553ca6 100644
--- a/src/popup/pages/Assets/AssetDetailsInfo.vue
+++ b/src/popup/pages/Assets/AssetDetailsInfo.vue
@@ -231,7 +231,7 @@ export default defineComponent({
const tokenBalance = computed(() => sharedAssetDetails.tokenBalance);
const isCoin = computed(() => isAssetCoin(assetContractId.value));
const decimals = computed(() => assetData.value?.decimals || tokenBalance.value?.decimals);
- const coinGeckoLinkUrl = computed(() => `https://www.coingecko.com/en/coins/${adapter.value.getCoinGeckoCoinId()}`);
+ const coinGeckoLinkUrl = computed(() => `https://www.coingecko.com/en/coins/${adapter.value.coinGeckoCoinId}`);
const coinGeckoLinkLabel = computed(() => coinGeckoLinkUrl.value.replace('https://', '').replace('en/coins', '...'));
const poolShare = computed(() => {
diff --git a/src/protocols/BaseProtocolAdapter.ts b/src/protocols/BaseProtocolAdapter.ts
index 58e3173fd..b91bd4196 100644
--- a/src/protocols/BaseProtocolAdapter.ts
+++ b/src/protocols/BaseProtocolAdapter.ts
@@ -39,6 +39,8 @@ export abstract class BaseProtocolAdapter {
abstract coinPrecision: number;
+ abstract coinGeckoCoinId: string;
+
/**
* Defines if the protocol supports fungible tokens (token contracts).
*/
@@ -57,8 +59,6 @@ export abstract class BaseProtocolAdapter {
abstract getUrlTokenKey(): string;
- abstract getCoinGeckoCoinId(): string;
-
abstract getDefaultCoin(
marketData?: MarketData,
convertedBalance?: number | BigNumber,
diff --git a/src/protocols/aeternity/libs/AeternityAdapter.ts b/src/protocols/aeternity/libs/AeternityAdapter.ts
index 2455274f4..2089027d5 100644
--- a/src/protocols/aeternity/libs/AeternityAdapter.ts
+++ b/src/protocols/aeternity/libs/AeternityAdapter.ts
@@ -81,6 +81,8 @@ export class AeternityAdapter extends BaseProtocolAdapter {
override coinPrecision = AE_COIN_PRECISION;
+ override coinGeckoCoinId = AE_COINGECKO_COIN_ID;
+
override hasTokensSupport = true;
override mdwToNodeApproxDelayTime = AE_MDW_TO_NODE_APPROX_DELAY_TIME;
@@ -128,10 +130,6 @@ export class AeternityAdapter extends BaseProtocolAdapter {
return AE_SYMBOL;
}
- override getCoinGeckoCoinId() {
- return AE_COINGECKO_COIN_ID;
- }
-
override getDefaultCoin(
marketData?: MarketData,
convertedBalance?: number,
diff --git a/src/protocols/bitcoin/libs/BitcoinAdapter.ts b/src/protocols/bitcoin/libs/BitcoinAdapter.ts
index 37a557f04..079b94478 100644
--- a/src/protocols/bitcoin/libs/BitcoinAdapter.ts
+++ b/src/protocols/bitcoin/libs/BitcoinAdapter.ts
@@ -69,6 +69,8 @@ export class BitcoinAdapter extends BaseProtocolAdapter {
override coinPrecision = BTC_COIN_PRECISION;
+ override coinGeckoCoinId = BTC_COINGECKO_COIN_ID;
+
override hasTokensSupport = false;
override mdwToNodeApproxDelayTime = 0;
@@ -115,10 +117,6 @@ export class BitcoinAdapter extends BaseProtocolAdapter {
return BTC_NETWORK_DEFAULT_SETTINGS[networkType];
}
- override getCoinGeckoCoinId() {
- return BTC_COINGECKO_COIN_ID;
- }
-
override getDefaultCoin(
marketData?: MarketData,
convertedBalance?: number,
diff --git a/src/protocols/ethereum/libs/EthereumAdapter.ts b/src/protocols/ethereum/libs/EthereumAdapter.ts
index fb487b5cd..bdfb124be 100644
--- a/src/protocols/ethereum/libs/EthereumAdapter.ts
+++ b/src/protocols/ethereum/libs/EthereumAdapter.ts
@@ -84,6 +84,8 @@ export class EthereumAdapter extends BaseProtocolAdapter {
override coinPrecision = ETH_COIN_PRECISION;
+ override coinGeckoCoinId = ETH_COINGECKO_COIN_ID;
+
override hasTokensSupport = true;
override mdwToNodeApproxDelayTime = ETH_MDW_TO_NODE_APPROX_DELAY_TIME;
@@ -124,10 +126,6 @@ export class EthereumAdapter extends BaseProtocolAdapter {
return 9;
}
- override getCoinGeckoCoinId() {
- return ETH_COINGECKO_COIN_ID;
- }
-
override getExplorer() {
const { ethActiveNetworkPredefinedSettings } = useEthNetworkSettings();
return new EtherscanExplorer(ethActiveNetworkPredefinedSettings.value.explorerUrl!);
@@ -492,7 +490,7 @@ export class EthereumAdapter extends BaseProtocolAdapter {
};
}
- async constructAndSignTx(
+ override async constructAndSignTx(
amount: number,
recipient: string,
options: Record,
diff --git a/src/protocols/registerAdapters.ts b/src/protocols/registerAdapters.ts
index 2deb5c6c1..b61556ba6 100644
--- a/src/protocols/registerAdapters.ts
+++ b/src/protocols/registerAdapters.ts
@@ -4,12 +4,14 @@ import { ProtocolAdapterFactory } from '@/lib/ProtocolAdapterFactory';
import { AeternityAdapter } from '@/protocols/aeternity/libs/AeternityAdapter';
import { BitcoinAdapter } from '@/protocols/bitcoin/libs/BitcoinAdapter';
import { EthereumAdapter } from '@/protocols/ethereum/libs/EthereumAdapter';
+import { SolanaAdapter } from '@/protocols/solana/libs/SolanaAdapter';
import { BaseProtocolAdapter } from './BaseProtocolAdapter';
const protocolAdapters: Record> = {
[PROTOCOLS.aeternity]: AeternityAdapter,
[PROTOCOLS.bitcoin]: BitcoinAdapter,
[PROTOCOLS.ethereum]: EthereumAdapter,
+ [PROTOCOLS.solana]: SolanaAdapter,
};
Object.entries(protocolAdapters).forEach(([protocol, adapter]) => {
diff --git a/src/protocols/solana/config.ts b/src/protocols/solana/config.ts
new file mode 100644
index 000000000..319118ed7
--- /dev/null
+++ b/src/protocols/solana/config.ts
@@ -0,0 +1,8 @@
+export const SOL_PROTOCOL_NAME = 'Solana';
+
+export const SOL_CONTRACT_ID = 'solana';
+
+export const SOL_COIN_SYMBOL = 'SOL';
+export const SOL_COIN_PRECISION = 18; // Amount of decimals
+
+export const SOL_COINGECKO_COIN_ID = 'solana';
diff --git a/src/protocols/solana/libs/SolanaAdapter.ts b/src/protocols/solana/libs/SolanaAdapter.ts
new file mode 100644
index 000000000..60bac2d54
--- /dev/null
+++ b/src/protocols/solana/libs/SolanaAdapter.ts
@@ -0,0 +1,164 @@
+/* eslint-disable class-methods-use-this */
+
+import { PROTOCOLS } from '@/constants';
+import type {
+ AdapterNetworkSettingList,
+ IAccount,
+ ICoin,
+ IFetchTransactionResult,
+ INetworkProtocolSettings,
+ IToken,
+ ITokenBalance,
+ ITransaction,
+ ITransferResponse,
+ MarketData,
+} from '@/types';
+import { BaseProtocolAdapter } from '@/protocols/BaseProtocolAdapter';
+import {
+ SOL_COIN_PRECISION,
+ SOL_COIN_SYMBOL,
+ SOL_COINGECKO_COIN_ID,
+ SOL_CONTRACT_ID,
+ SOL_PROTOCOL_NAME,
+} from '@/protocols/solana/config';
+
+export class SolanaAdapter extends BaseProtocolAdapter {
+ override protocol = PROTOCOLS.solana;
+
+ override protocolName = SOL_PROTOCOL_NAME;
+
+ override coinName = SOL_PROTOCOL_NAME;
+
+ override coinSymbol = SOL_COIN_SYMBOL;
+
+ override coinContractId = SOL_CONTRACT_ID;
+
+ override coinPrecision = SOL_COIN_PRECISION;
+
+ override coinGeckoCoinId = SOL_COINGECKO_COIN_ID;
+
+ override hasTokensSupport = true;
+
+ override mdwToNodeApproxDelayTime = 0; // TODO
+
+ private networkSettings: AdapterNetworkSettingList = [
+ // TODO
+ ];
+
+ override getAccountPrefix() {
+ return ''; // TODO
+ }
+
+ override getAmountPrecision(): number {
+ return 0; // TODO
+ }
+
+ override getExplorer() {
+ return {} as any; // TODO
+ }
+
+ override getUrlTokenKey() {
+ return SOL_CONTRACT_ID;
+ }
+
+ override getDefaultCoin(
+ marketData?: MarketData,
+ convertedBalance?: number,
+ ): ICoin {
+ return {
+ ...(marketData?.[PROTOCOLS.solana]! || {} as MarketData),
+ protocol: PROTOCOLS.solana,
+ contractId: this.coinContractId,
+ symbol: this.coinSymbol,
+ decimals: this.coinPrecision,
+ name: this.coinName,
+ convertedBalance,
+ };
+ }
+
+ override getNetworkSettings() {
+ return this.networkSettings;
+ }
+
+ override getNetworkTypeDefaultValues(): INetworkProtocolSettings {
+ return {} as any; // TODO
+ }
+
+ override async fetchBalance(): Promise {
+ return '0'; // TODO
+ }
+
+ override isAccountAddressValid() {
+ return false; // TODO
+ }
+
+ override isValidAddressOrNameEncoding() {
+ return false; // TODO
+ }
+
+ override async isAccountUsed(): Promise {
+ return false; // TODO
+ }
+
+ override getHdWalletAccountFromMnemonicSeed() {
+ return {} as any; // TODO
+ }
+
+ override resolveAccountRaw(): IAccount | null {
+ return null; // TODO
+ }
+
+ override async discoverLastUsedAccountIndex(): Promise {
+ return 0; // TODO
+ }
+
+ override async fetchAvailableTokens(): Promise {
+ return []; // TODO
+ }
+
+ override async fetchAccountTokenBalances(): Promise {
+ return []; // TODO
+ }
+
+ override async fetchTokenInfo(): Promise {
+ return undefined; // TODO
+ }
+
+ override async transferPreparedTransaction(): Promise {
+ return {} as any; // TODO
+ }
+
+ override async transferToken(): Promise {
+ return {} as any; // TODO
+ }
+
+ override async fetchTransactionByHash(): Promise {
+ return {} as any; // TODO
+ }
+
+ override async fetchAccountTransactions(): Promise {
+ return {
+ regularTransactions: [], // TODO
+ paginationParams: {}, // TODO
+ };
+ }
+
+ override async fetchAccountAssetTransactions(): Promise {
+ return {
+ regularTransactions: [], // TODO
+ paginationParams: {}, // TODO
+ };
+ }
+
+ override async constructAndSignTx(): Promise {
+ return {} as any; // TODO
+ }
+
+ override async spend(): Promise {
+ return {} as any; // TODO
+ }
+
+ override async waitTransactionMined(): Promise {
+ return null; // TODO
+ }
+}
diff --git a/src/protocols/solana/views/index.ts b/src/protocols/solana/views/index.ts
new file mode 100644
index 000000000..4523380d8
--- /dev/null
+++ b/src/protocols/solana/views/index.ts
@@ -0,0 +1,12 @@
+import type { ProtocolViewsConfig } from '@/types';
+
+const protocolViews: ProtocolViewsConfig = {
+ AccountDetails: null,
+ AccountDetailsTokens: null,
+ AccountDetailsNames: null,
+ TransactionDetails: null,
+ TransferReceiveModal: null,
+ TransferSendModal: null,
+};
+
+export default protocolViews;