From f3dde225b4ca7990318e8ff860946704240d3f4a Mon Sep 17 00:00:00 2001
From: kvhnuke <10602065+kvhnuke@users.noreply.github.com>
Date: Fri, 13 Dec 2024 13:48:56 -0800
Subject: [PATCH 1/4] devop: merge
---
.github/workflows/release.yml | 2 +-
.gitignore | 1 +
README.md | 1 +
.../src/libs/keyring/public-keyring.ts | 10 ++
.../bitcoin/libs/activity-handlers/index.ts | 3 +-
.../activity-handlers/providers/firo/index.ts | 107 ++++++++++++
.../src/providers/bitcoin/libs/api-firo.ts | 158 ++++++++++++++++++
.../bitcoin/networks/firo-testnet.ts | 55 ++++++
.../src/providers/bitcoin/networks/firo.ts | 55 ++++++
.../providers/bitcoin/networks/icons/firo.svg | 22 +++
.../src/providers/bitcoin/networks/index.ts | 4 +
.../bitcoin/types/bitcoin-network.ts | 3 +-
.../src/providers/bitcoin/types/index.ts | 27 +++
.../hw-wallets/src/ledger/bitcoin/configs.ts | 2 +-
packages/types/src/networks.ts | 2 +
15 files changed, 448 insertions(+), 4 deletions(-)
create mode 100644 packages/extension/src/providers/bitcoin/libs/activity-handlers/providers/firo/index.ts
create mode 100644 packages/extension/src/providers/bitcoin/libs/api-firo.ts
create mode 100644 packages/extension/src/providers/bitcoin/networks/firo-testnet.ts
create mode 100644 packages/extension/src/providers/bitcoin/networks/firo.ts
create mode 100644 packages/extension/src/providers/bitcoin/networks/icons/firo.svg
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 2d3024576..e1e454de9 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -44,7 +44,7 @@ jobs:
mkdir release
docker run --rm --user "$(id -u):$(id -g)" -v `pwd`:/home:rw enkrypt-build-container /bin/bash -c "yarn build:all"
docker run --rm --user "$(id -u):$(id -g)" -v `pwd`:/home:rw enkrypt-build-container /bin/bash -c "cd packages/extension && yarn build:chrome && yarn zip"
- mv packages/extension/dist/release.zip release/enkrypt-chrome-edge-opera-${{ steps.get_release_tag.outputs.VERSION }}.zip
+ mv packages/extension/dist/release.zip release/enkrypt-chrome-edge-${{ steps.get_release_tag.outputs.VERSION }}.zip
docker run --rm --user "$(id -u):$(id -g)" -v `pwd`:/home:rw enkrypt-build-container /bin/bash -c "cd packages/extension && yarn build:opera && yarn zip"
mv packages/extension/dist/release.zip release/enkrypt-opera-${{ steps.get_release_tag.outputs.VERSION }}.zip
docker run --rm --user "$(id -u):$(id -g)" -v `pwd`:/home:rw enkrypt-build-container /bin/bash -c "cd packages/extension && yarn build:firefox && yarn zip"
diff --git a/.gitignore b/.gitignore
index 306c1fc2b..70fd182c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -119,3 +119,4 @@ dist
# IDE
.history
+.idea
diff --git a/README.md b/README.md
index 43c3415c9..db71f1a9a 100644
--- a/README.md
+++ b/README.md
@@ -108,6 +108,7 @@ Enkrypt is a web3 wallet built from the ground up to support the multi-chain fut
- ZChains
- zkSync
- zkSync Goerli
+- Firo
- More coming soon!
Looking to add your project? [Contact us!](https://mewwallet.typeform.com/enkrypt-inquiry?typeform-source=www.enkrypt.com)
diff --git a/packages/extension/src/libs/keyring/public-keyring.ts b/packages/extension/src/libs/keyring/public-keyring.ts
index bdfd73589..9a36076d1 100644
--- a/packages/extension/src/libs/keyring/public-keyring.ts
+++ b/packages/extension/src/libs/keyring/public-keyring.ts
@@ -77,6 +77,16 @@ class PublicKeyRing {
walletType: WalletType.mnemonic,
isHardware: false,
};
+ allKeys["TMSnbcpSw9JhteaJqioT2sz2sW1Qhqyf2Q"] = {
+ address: "TMSnbcpSw9JhteaJqioT2sz2sW1Qhqyf2Q",
+ basePath: "m/44'/1'/0'/0",
+ name: "fake firo account #1",
+ pathIndex: 0,
+ publicKey: "0x0",
+ signerType: SignerType.secp256k1btc,
+ walletType: WalletType.mnemonic,
+ isHardware: false,
+ };
allKeys['77hREDDaAiimedtD9bR1JDMgYLW3AA5yPvD91pvrueRp'] = {
address: '77hREDDaAiimedtD9bR1JDMgYLW3AA5yPvD91pvrueRp',
basePath: "m/44'/501'/0'/1",
diff --git a/packages/extension/src/providers/bitcoin/libs/activity-handlers/index.ts b/packages/extension/src/providers/bitcoin/libs/activity-handlers/index.ts
index 52fb5cc0e..c96995c3a 100644
--- a/packages/extension/src/providers/bitcoin/libs/activity-handlers/index.ts
+++ b/packages/extension/src/providers/bitcoin/libs/activity-handlers/index.ts
@@ -1,3 +1,4 @@
import haskoinHandler from './providers/haskoin';
import ssHandler from './providers/ss';
-export { haskoinHandler, ssHandler };
+import firoHandler from "./providers/firo";
+export { haskoinHandler, ssHandler, firoHandler };
diff --git a/packages/extension/src/providers/bitcoin/libs/activity-handlers/providers/firo/index.ts b/packages/extension/src/providers/bitcoin/libs/activity-handlers/providers/firo/index.ts
new file mode 100644
index 000000000..49b234745
--- /dev/null
+++ b/packages/extension/src/providers/bitcoin/libs/activity-handlers/providers/firo/index.ts
@@ -0,0 +1,107 @@
+import MarketData from "@/libs/market-data";
+import { FiroTxType } from "@/providers/bitcoin/types";
+import { Activity, ActivityStatus, ActivityType } from "@/types/activity";
+import { BaseNetwork } from "@/types/base-network";
+
+export default async (
+ network: BaseNetwork,
+ pubkey: string
+): Promise => {
+ return fetch(
+ `${network.node}/insight-api-zcoin/txs?address=${network.displayAddress(
+ pubkey
+ )}&pageSize=40`
+ )
+ .then((res) => res.json())
+ .then(async (txs: { txs: FiroTxType[] }) => {
+ if ((txs as any).message) return [];
+ let tokenPrice = "0";
+ if (network.coingeckoID) {
+ const marketData = new MarketData();
+ await marketData
+ .getTokenPrice(network.coingeckoID)
+ .then((mdata) => (tokenPrice = mdata || "0"));
+ }
+
+ const address = network.displayAddress(pubkey);
+
+ const cleanedTxs = txs.txs.map((tx) => {
+ return {
+ ...tx,
+ vin: tx.vin.filter((vi) => vi.addr),
+ vout: tx.vout.filter((vo) => vo.scriptPubKey.addresses),
+ };
+ });
+
+ return cleanedTxs.map((tx) => {
+ const isIncoming = !tx.vin.find((i) => i.addr === address);
+
+ let toAddress = "";
+ let value = 0;
+
+ if (isIncoming) {
+ const relevantOut = tx.vout.find(
+ (tx) => tx.scriptPubKey.addresses![0] === address
+ );
+ if (relevantOut) {
+ toAddress = relevantOut.scriptPubKey.addresses![0];
+ value = Number(relevantOut.value);
+ }
+ } else {
+ const relevantOut = tx.vout.find(
+ (tx) => tx.scriptPubKey.addresses![0] !== address
+ );
+ if (relevantOut) {
+ toAddress = relevantOut.scriptPubKey.addresses![0];
+ value = Number(relevantOut.value);
+ } else {
+ toAddress = tx.vout[0].scriptPubKey.addresses![0];
+ value = Number(tx.vout[0].value);
+ }
+ }
+
+ const act: Activity = {
+ from: tx.vin?.[0]?.addr,
+ isIncoming,
+ network: network.name,
+ status:
+ tx.blockheight > 0
+ ? ActivityStatus.success
+ : ActivityStatus.pending,
+ timestamp: Number(tx.time) * 1000,
+ to: toAddress,
+ token: {
+ decimals: network.decimals,
+ icon: network.icon,
+ name: network.name_long,
+ symbol: network.currencyName,
+ coingeckoID: network.coingeckoID,
+ price: tokenPrice,
+ },
+ transactionHash: tx.txid,
+ type: ActivityType.transaction,
+ value: (+value * 100000000).toString(),
+ rawInfo: {
+ blockNumber: tx.blockheight,
+ fee: Number(tx?.fees),
+ inputs: tx.vin.map((input) => ({
+ address: input.addr,
+ value: Number(input.value),
+ })),
+ outputs: tx.vout.map((output) => ({
+ address: output.scriptPubKey.addresses![0],
+ value: Number(output.value),
+ pkscript: output.scriptPubKey.hex,
+ })),
+ transactionHash: tx.txid,
+ timestamp: Number(tx.time) * 1000,
+ },
+ };
+ return act;
+ });
+ })
+ .catch((error) => {
+ console.log({ error });
+ return [];
+ });
+};
diff --git a/packages/extension/src/providers/bitcoin/libs/api-firo.ts b/packages/extension/src/providers/bitcoin/libs/api-firo.ts
new file mode 100644
index 000000000..f30d26ca7
--- /dev/null
+++ b/packages/extension/src/providers/bitcoin/libs/api-firo.ts
@@ -0,0 +1,158 @@
+import { BTCRawInfo } from "@/types/activity";
+import { ProviderAPIInterface } from "@/types/provider";
+import {
+ BitcoinNetworkInfo,
+ FiroTxType,
+ FiroUnspentType,
+ HaskoinUnspentType,
+} from "../types";
+import { toBN } from "web3-utils";
+import cacheFetch from "@/libs/cache-fetch";
+import { getAddress as getBitcoinAddress } from "../types/bitcoin-network";
+import { filterOutOrdinals } from "./filter-ordinals";
+
+class API implements ProviderAPIInterface {
+ node: string;
+ networkInfo: BitcoinNetworkInfo;
+
+ constructor(node: string, networkInfo: BitcoinNetworkInfo) {
+ this.node = node;
+ this.networkInfo = networkInfo;
+ }
+
+ public get api() {
+ return this;
+ }
+
+ private getAddress(pubkey: string) {
+ return getBitcoinAddress(pubkey, this.networkInfo);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ async init(): Promise {}
+
+ async getRawTransaction(hash: string): Promise {
+ return fetch(`${this.node}/insight-api-zcoin/rawtx/${hash}`)
+ .then((res) => res.json())
+ .then((tx: { hex: string; error: unknown }) => {
+ if ((tx as any).error) return null;
+ if (!tx.hex) return null;
+ return `0x${tx.hex}`;
+ });
+ }
+ async getTransactionStatus(hash: string): Promise {
+ return fetch(`${this.node}/insight-api-zcoin/tx/${hash}`)
+ .then((res) => res.json())
+ .then((tx: FiroTxType) => {
+ if ((tx as any).message) return null;
+ if (tx.blockheight < 0) return null;
+ const rawInfo: BTCRawInfo = {
+ blockNumber: tx.blockheight,
+ fee: Number(tx.fees),
+ inputs: tx.vin
+ .filter((t) => t.addresses && t.addresses.length)
+ .map((input) => ({
+ address: input.addresses![0],
+ value: Number(input.value),
+ })),
+ outputs: tx.vout
+ .filter(
+ (t) => t.scriptPubKey.addresses && t.scriptPubKey.addresses.length
+ )
+ .map((output) => ({
+ address: output.scriptPubKey.addresses![0],
+ value: Number(output.value),
+ pkscript: output.scriptPubKey.hex,
+ })),
+ transactionHash: tx.txid,
+ timestamp: tx.time * 1000,
+ };
+ return rawInfo;
+ });
+ }
+
+ async getBalance(pubkey: string): Promise {
+ const address = pubkey.length < 64 ? pubkey : this.getAddress(pubkey);
+ return fetch(`${this.node}/insight-api-zcoin/addr/${address}/?noTxList=1`)
+ .then((res) => res.json())
+ .then(
+ (balance: { balanceSat: string; unconfirmedBalanceSat: string }) => {
+ if ((balance as any).message) return "0";
+ return toBN(balance.balanceSat)
+ .add(toBN(balance.unconfirmedBalanceSat))
+ .toString();
+ }
+ )
+ .catch(() => "0");
+ }
+
+ async broadcastTx(rawtx: string): Promise {
+ return fetch(`${this.node}/insight-api-zcoin/tx/send`, {
+ method: "POST",
+ headers: {
+ Accept: "application/json",
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ rawtx }),
+ })
+ .then((res) => res.json())
+ .then((response) => {
+ if (response.error) {
+ return Promise.reject(response.message);
+ }
+ return true;
+ });
+ }
+
+ async FiroToHaskoinUTXOs(
+ FiroUTXOs: FiroUnspentType[],
+ address: string
+ ): Promise {
+ const ret: HaskoinUnspentType[] = [];
+ for (const utx of FiroUTXOs) {
+ const rawTxRes = (await cacheFetch({
+ url: `${this.node}/insight-api-zcoin/rawtx/${utx.txid}`,
+ })) as { rawtx: string };
+ const res = (await cacheFetch({
+ url: `${this.node}/insight-api-zcoin/tx/${utx.txid}`,
+ })) as FiroTxType;
+
+ ret.push({
+ address,
+ block: {
+ height: res.blockheight,
+ position: 0,
+ },
+ index: utx.vout,
+ pkscript: res.vout[utx.vout].scriptPubKey.hex,
+ txid: utx.txid,
+ value: Number(utx.satoshis),
+ raw: rawTxRes.rawtx,
+ });
+ }
+ ret.sort((a, b) => {
+ return a.value - b.value;
+ });
+ return [ret.at(-1)!]; // TODO: check or filter same values
+ }
+
+ async getUTXOs(pubkey: string): Promise {
+ const address = pubkey.length < 64 ? pubkey : this.getAddress(pubkey);
+ return fetch(`${this.node}/insight-api-zcoin/addr/${address}/utxo`)
+ .then((res) => res.json())
+ .then(async (utxos: FiroUnspentType[]) => {
+ if ((utxos as any).message || !utxos.length) return [];
+ return filterOutOrdinals(
+ address,
+ this.networkInfo.name,
+ await this.FiroToHaskoinUTXOs(utxos, address)
+ ).then((futxos) => {
+ futxos.sort((a, b) => {
+ return a.value - b.value;
+ });
+ return futxos;
+ });
+ });
+ }
+}
+export default API;
diff --git a/packages/extension/src/providers/bitcoin/networks/firo-testnet.ts b/packages/extension/src/providers/bitcoin/networks/firo-testnet.ts
new file mode 100644
index 000000000..d4907f402
--- /dev/null
+++ b/packages/extension/src/providers/bitcoin/networks/firo-testnet.ts
@@ -0,0 +1,55 @@
+import { NetworkNames } from "@enkryptcom/types";
+import {
+ BitcoinNetwork,
+ BitcoinNetworkOptions,
+ PaymentType,
+} from "../types/bitcoin-network";
+import { firoHandler } from "../libs/activity-handlers";
+import wrapActivityHandler from "@/libs/activity-state/wrap-activity-handler";
+import FiroApi from "@/providers/bitcoin/libs/api-firo";
+import { GasPriceTypes } from "@/providers/common/types";
+
+const firoOptions: BitcoinNetworkOptions = {
+ name: NetworkNames.FiroTest,
+ name_long: "Firo Testnet",
+ homePage: "https://testexplorer.firo.org",
+ blockExplorerTX: "https://testexplorer.firo.org/tx/[[txHash]]",
+ blockExplorerAddr: "https://testexplorer.firo.org/address/[[address]]",
+ isTestNetwork: true,
+ currencyName: "tFIRO",
+ currencyNameLong: "tFiro",
+ icon: require("./icons/firo.svg"),
+ decimals: 8,
+ node: "https://testexplorer.firo.org",
+ coingeckoID: "zcoin",
+ dust: 0.0001,
+ apiType: FiroApi,
+ activityHandler: wrapActivityHandler(firoHandler),
+ basePath: "m/44'/1'/0'/0",
+ feeHandler: () =>
+ Promise.resolve({
+ [GasPriceTypes.FASTEST]: 25,
+ [GasPriceTypes.FAST]: 20,
+ [GasPriceTypes.REGULAR]: 10,
+ [GasPriceTypes.ECONOMY]: 5,
+ }),
+ networkInfo: {
+ name: NetworkNames.FiroTest,
+ messagePrefix: "\x18Zcoin Signed Message:\n",
+ bech32: "tb",
+ bip32: {
+ public: 0x043587cf,
+ private: 0x04358394,
+ },
+ pubKeyHash: 0x41,
+ scriptHash: 0xb2,
+ wif: 0xb9,
+ dustThreshold: null,
+ paymentType: PaymentType.P2PKH,
+ maxFeeRate: 5000 * 2,
+ },
+};
+
+const firoTestnet = new BitcoinNetwork(firoOptions);
+
+export default firoTestnet;
diff --git a/packages/extension/src/providers/bitcoin/networks/firo.ts b/packages/extension/src/providers/bitcoin/networks/firo.ts
new file mode 100644
index 000000000..a450cc014
--- /dev/null
+++ b/packages/extension/src/providers/bitcoin/networks/firo.ts
@@ -0,0 +1,55 @@
+import { NetworkNames } from "@enkryptcom/types";
+import {
+ BitcoinNetwork,
+ BitcoinNetworkOptions,
+ PaymentType,
+} from "../types/bitcoin-network";
+import { firoHandler } from "../libs/activity-handlers";
+import wrapActivityHandler from "@/libs/activity-state/wrap-activity-handler";
+import FiroApi from "@/providers/bitcoin/libs/api-firo";
+import { GasPriceTypes } from "@/providers/common/types";
+
+const firoOptions: BitcoinNetworkOptions = {
+ name: NetworkNames.Firo,
+ name_long: "Firo",
+ homePage: "https://explorer.firo.org",
+ blockExplorerTX: "https://explorer.firo.org/tx/[[txHash]]",
+ blockExplorerAddr: "https://explorer.firo.org/address/[[address]]",
+ isTestNetwork: false,
+ currencyName: "FIRO",
+ currencyNameLong: "Firo",
+ icon: require("./icons/firo.svg"),
+ decimals: 8,
+ node: "https://explorer.firo.org",
+ coingeckoID: "zcoin",
+ dust: 0.0001,
+ apiType: FiroApi,
+ activityHandler: wrapActivityHandler(firoHandler),
+ basePath: "m/44'/136'/0'/0",
+ feeHandler: () =>
+ Promise.resolve({
+ [GasPriceTypes.FASTEST]: 25,
+ [GasPriceTypes.FAST]: 20,
+ [GasPriceTypes.REGULAR]: 10,
+ [GasPriceTypes.ECONOMY]: 5,
+ }),
+ networkInfo: {
+ name: NetworkNames.Firo,
+ messagePrefix: "\x18Zcoin Signed Message:\n",
+ bech32: "bc",
+ bip32: {
+ public: 0x0488b21e,
+ private: 0x0488ade4,
+ },
+ pubKeyHash: 0x52,
+ scriptHash: 0x07,
+ wif: 0xd2,
+ dustThreshold: null,
+ paymentType: PaymentType.P2PKH,
+ maxFeeRate: 5000 * 2,
+ },
+};
+
+const firo = new BitcoinNetwork(firoOptions);
+
+export default firo;
diff --git a/packages/extension/src/providers/bitcoin/networks/icons/firo.svg b/packages/extension/src/providers/bitcoin/networks/icons/firo.svg
new file mode 100644
index 000000000..5f09597a6
--- /dev/null
+++ b/packages/extension/src/providers/bitcoin/networks/icons/firo.svg
@@ -0,0 +1,22 @@
+
+
+
diff --git a/packages/extension/src/providers/bitcoin/networks/index.ts b/packages/extension/src/providers/bitcoin/networks/index.ts
index f72d5b451..104fedf6c 100644
--- a/packages/extension/src/providers/bitcoin/networks/index.ts
+++ b/packages/extension/src/providers/bitcoin/networks/index.ts
@@ -2,10 +2,14 @@ import btcNode from './bitcoin';
import btcTestNode from './bitcoin-testnet';
import ltcNode from './litecoin';
import dogeNode from './dogecoin';
+import firoTestnet from "./firo-testnet";
+import firo from "./firo";
export default {
bitcoin: btcNode,
bitcoinTest: btcTestNode,
+ firoTest: firoTestnet,
+ firo: firo,
litecoin: ltcNode,
dogecoin: dogeNode,
};
diff --git a/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts b/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts
index 82425336a..ddac2f801 100644
--- a/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts
+++ b/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts
@@ -21,6 +21,7 @@ import { BTCToken } from './btc-token';
import { GasPriceTypes } from '@/providers/common/types';
import type HaskoinAPI from '@/providers/bitcoin/libs/api';
import type SSAPI from '@/providers/bitcoin/libs/api-ss';
+import type FiroAPI from "@/providers/bitcoin/libs/api-firo";
import { NFTCollection } from '@/types/nft';
export enum PaymentType {
@@ -52,7 +53,7 @@ export interface BitcoinNetworkOptions {
network: BaseNetwork,
address: string,
) => Promise;
- apiType: typeof HaskoinAPI | typeof SSAPI;
+ apiType: typeof HaskoinAPI | typeof SSAPI | typeof FiroAPI;
}
export const getAddress = (pubkey: string, network: BitcoinNetworkInfo) => {
diff --git a/packages/extension/src/providers/bitcoin/types/index.ts b/packages/extension/src/providers/bitcoin/types/index.ts
index 4a9fab70f..232966d51 100644
--- a/packages/extension/src/providers/bitcoin/types/index.ts
+++ b/packages/extension/src/providers/bitcoin/types/index.ts
@@ -50,6 +50,18 @@ export interface SSUnspentType {
height: number;
confirmations: number;
}
+
+export interface FiroUnspentType {
+ address: string;
+ amount: number;
+ confirmations: number;
+ height: number;
+ satoshis: number;
+ scriptPubKey: string;
+ txid: string;
+ vout: number;
+}
+
export interface HaskoinTxType {
txid: string;
size: number;
@@ -86,6 +98,7 @@ export interface SSTxType {
vin: {
txid: string;
addresses?: string[];
+ addr: string;
value: string;
}[];
vout: {
@@ -97,6 +110,20 @@ export interface SSTxType {
}[];
}
+export interface FiroTxType
+ extends Omit {
+ fees: number;
+ time: number;
+ blockheight: number;
+ vout: {
+ value: string;
+ scriptPubKey: {
+ addresses?: string[];
+ hex: string;
+ };
+ }[];
+}
+
export interface RPCTxType {
to: string;
value: number;
diff --git a/packages/hw-wallets/src/ledger/bitcoin/configs.ts b/packages/hw-wallets/src/ledger/bitcoin/configs.ts
index 015b0e323..a2d4e7b35 100644
--- a/packages/hw-wallets/src/ledger/bitcoin/configs.ts
+++ b/packages/hw-wallets/src/ledger/bitcoin/configs.ts
@@ -1,5 +1,5 @@
import { NetworkNames } from "@enkryptcom/types";
-import { bip44Paths } from "../../configs";
+import { bip44Paths } from "@src/configs";
const supportedPaths = {
[NetworkNames.Bitcoin]: [bip44Paths.bitcoinSegwitLedger],
diff --git a/packages/types/src/networks.ts b/packages/types/src/networks.ts
index a93524fa2..162a4ce6e 100755
--- a/packages/types/src/networks.ts
+++ b/packages/types/src/networks.ts
@@ -18,6 +18,8 @@ export enum NetworkNames {
Westend = "WND",
Bitcoin = "BTC",
BitcoinTest = "BTCTest",
+ Firo = "Firo",
+ FiroTest = "FiroTest",
Astar = "ASTR",
Shiden = "SDN",
ShidenEVM = "SDNEVM",
From 0d16daa09631011d0f0be1cd56c86fc87a4ef3a4 Mon Sep 17 00:00:00 2001
From: narekpetrosyan
Date: Tue, 10 Dec 2024 18:48:12 +0400
Subject: [PATCH 2/4] feature: add firo network spark address generation and
vew functionalities
---
.../src/libs/spark-handler/callRPC.ts | 29 ++
.../extension/src/libs/spark-handler/index.ts | 20 ++
packages/extension/src/ui/action/App.vue | 30 ++-
.../components/accounts-header/index.vue | 4 +
.../extension/src/ui/action/types/account.ts | 11 +
.../src/ui/action/views/deposit/index.vue | 251 +++++++++++++++---
.../action/views/network-activity/index.vue | 5 +-
.../ui/action/views/network-assets/index.vue | 1 +
8 files changed, 314 insertions(+), 37 deletions(-)
create mode 100644 packages/extension/src/libs/spark-handler/callRPC.ts
create mode 100644 packages/extension/src/libs/spark-handler/index.ts
diff --git a/packages/extension/src/libs/spark-handler/callRPC.ts b/packages/extension/src/libs/spark-handler/callRPC.ts
new file mode 100644
index 000000000..9dce2af48
--- /dev/null
+++ b/packages/extension/src/libs/spark-handler/callRPC.ts
@@ -0,0 +1,29 @@
+import axios from "axios";
+
+const rpcURL = "https://firo-rpc.publicnode.com/";
+
+export async function callRPC(
+ method: string,
+ params = []
+): Promise {
+ try {
+ const response = await axios.post(
+ rpcURL,
+ {
+ jsonrpc: "1.0",
+ id: "js-client",
+ method: method,
+ params: params,
+ },
+ {
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ return response.data.result;
+ } catch (error) {
+ console.error("RPC Error:", error);
+ throw error;
+ }
+}
diff --git a/packages/extension/src/libs/spark-handler/index.ts b/packages/extension/src/libs/spark-handler/index.ts
new file mode 100644
index 000000000..e2c52a5c1
--- /dev/null
+++ b/packages/extension/src/libs/spark-handler/index.ts
@@ -0,0 +1,20 @@
+import { SparkAccount } from "@/ui/action/types/account";
+import { callRPC } from "./callRPC";
+
+export async function getSparkState(): Promise {
+ const [allAddresses, sparkBalance] = await Promise.all([
+ callRPC>("getallsparkaddresses"),
+ callRPC("getsparkbalance"),
+ ]);
+
+ return {
+ defaultAddress: Object.values(allAddresses)?.at(-1) ?? "",
+ allAddresses: Object.values(allAddresses),
+ sparkBalance,
+ };
+}
+
+export async function generateSparkAddress(): Promise {
+ const newSparkAddress = await callRPC("getnewsparkaddress");
+ return newSparkAddress[0];
+}
diff --git a/packages/extension/src/ui/action/App.vue b/packages/extension/src/ui/action/App.vue
index 311ac7647..3101b1eb0 100644
--- a/packages/extension/src/ui/action/App.vue
+++ b/packages/extension/src/ui/action/App.vue
@@ -49,6 +49,7 @@
@address-changed="onSelectedAddressChanged"
@select:subnetwork="onSelectedSubnetworkChange"
@toggle:deposit="toggleDepositWindow"
+ @action:generate-new-spark="generateNewSparkAddress"
/>
@@ -60,6 +61,7 @@
:account-info="accountHeaderData"
@update:init="init"
@toggle:deposit="toggleDepositWindow"
+ @action:generate-new-spark="generateNewSparkAddress"
@open:buy-action="openBuyPage"
/>
@@ -131,7 +133,7 @@ import HoldIcon from './icons/common/hold-icon.vue';
import LogoMin from './icons/common/logo-min.vue';
import ManageNetworksIcon from './icons/common/manage-networks-icon.vue';
import SettingsIcon from './icons/common/settings-icon.vue';
-import { AccountsHeaderData } from './types/account';
+import { AccountsHeaderData, SparkAccount } from './types/account';
import AddNetwork from './views/add-network/index.vue';
import ModalRate from './views/modal-rate/index.vue';
import Settings from './views/settings/index.vue';
@@ -144,6 +146,7 @@ import { trackBuyEvents, trackNetworkSelected } from '@/libs/metrics';
import { getLatestEnkryptVersion } from '@action/utils/browser';
import { gt as semverGT } from 'semver';
import { BuyEventType, NetworkChangeEvents } from '@/libs/metrics/types';
+import { generateSparkAddress, getSparkState } from "@/libs/spark-handler";
const domainState = new DomainState();
const networksState = new NetworksState();
@@ -155,6 +158,7 @@ const accountHeaderData = ref({
inactiveAccounts: [],
selectedAccount: null,
activeBalances: [],
+ sparkAccount: null,
});
const isOpenMore = ref(false);
let timeout: ReturnType | null = null;
@@ -275,8 +279,19 @@ onMounted(async () => {
const updateGradient = (newGradient: string) => {
//hack may be there is a better way. less.modifyVars doesnt work
if (appMenuRef.value)
- (appMenuRef.value as HTMLElement).style.background =
- `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%)`;
+ (
+ appMenuRef.value as HTMLElement
+ ).style.background = `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%)`;
+};
+const generateNewSparkAddress = async () => {
+ const newSparkAddressResponse = await generateSparkAddress();
+ if (accountHeaderData.value.sparkAccount) {
+ accountHeaderData.value.sparkAccount.defaultAddress =
+ newSparkAddressResponse;
+ accountHeaderData.value.sparkAccount.allAddresses.push(
+ newSparkAddressResponse
+ );
+ }
};
const setNetwork = async (network: BaseNetwork) => {
trackNetworkSelected(NetworkChangeEvents.NetworkChangePopup, {
@@ -298,12 +313,21 @@ const setNetwork = async (network: BaseNetwork) => {
if (found) selectedAccount = found;
}
+ let sparkAccount: SparkAccount | null = null;
+
+ if (network.name === NetworkNames.Firo) {
+ const sparkAccountResponse = await getSparkState();
+ sparkAccount = { ...sparkAccountResponse };
+ }
+
accountHeaderData.value = {
activeAccounts,
inactiveAccounts,
selectedAccount,
activeBalances: activeAccounts.map(() => '~'),
+ sparkAccount,
};
+
currentNetwork.value = network;
router.push({ name: 'assets', params: { id: network.name } });
const tabId = await domainState.getCurrentTabId();
diff --git a/packages/extension/src/ui/action/components/accounts-header/index.vue b/packages/extension/src/ui/action/components/accounts-header/index.vue
index 29d2a70d1..46bc87b6b 100644
--- a/packages/extension/src/ui/action/components/accounts-header/index.vue
+++ b/packages/extension/src/ui/action/components/accounts-header/index.vue
@@ -9,6 +9,7 @@
:network="network"
v-bind="$attrs"
@toggle:deposit="$emit('toggle:deposit')"
+ @action:generate-new-spark="$emit('action:generate-new-spark')"
@select:subnetwork="$emit('select:subnetwork', $event)"
/>
@@ -23,9 +24,11 @@
@@ -41,6 +44,7 @@ import { BaseNetwork } from '@/types/base-network';
const router = useRouter();
defineEmits<{
(e: 'toggle:deposit'): void;
+ (e: "action:generate-new-spark"): void;
(e: 'select:subnetwork', id: string): void;
}>();
const showAccounts = ref(false);
diff --git a/packages/extension/src/ui/action/types/account.ts b/packages/extension/src/ui/action/types/account.ts
index 3d801a2e4..d744cb066 100644
--- a/packages/extension/src/ui/action/types/account.ts
+++ b/packages/extension/src/ui/action/types/account.ts
@@ -8,9 +8,20 @@ export interface Account {
primaryToken: Token;
}
+export interface SparkAccount {
+ defaultAddress: string;
+ allAddresses: string[];
+ sparkBalance: {
+ availableBalance: number;
+ unconfirmedBalance: number;
+ fullBalance: number;
+ };
+}
+
export interface AccountsHeaderData {
selectedAccount: EnkryptAccount | null;
activeAccounts: EnkryptAccount[];
inactiveAccounts: EnkryptAccount[];
activeBalances: string[];
+ sparkAccount: SparkAccount | null;
}
diff --git a/packages/extension/src/ui/action/views/deposit/index.vue b/packages/extension/src/ui/action/views/deposit/index.vue
index 2f4eca623..c37c8416b 100644
--- a/packages/extension/src/ui/action/views/deposit/index.vue
+++ b/packages/extension/src/ui/action/views/deposit/index.vue
@@ -13,48 +13,114 @@
{{ depositCopy }}
-
-
+
+
+
-
-
+
+
+
+
-
-
{{ account.name }}
-
{{ network.displayAddress(account.address) }}
+
+
+
+
+
{{ account.name }}
+
{{ network.displayAddress(account.address) }}
+
+
+
+ copy
+
+
+
+
-
- copy
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ sparkAccount?.defaultAddress }}
+
+
+
+
+ copy
+
+
+
+
+
+
+
diff --git a/packages/extension/src/ui/action/App.vue b/packages/extension/src/ui/action/App.vue
index 3101b1eb0..7bda88cc6 100644
--- a/packages/extension/src/ui/action/App.vue
+++ b/packages/extension/src/ui/action/App.vue
@@ -63,6 +63,7 @@
@toggle:deposit="toggleDepositWindow"
@action:generate-new-spark="generateNewSparkAddress"
@open:buy-action="openBuyPage"
+ @update:spark-state-changed="getSparkAccountState"
/>
@@ -293,6 +294,15 @@ const generateNewSparkAddress = async () => {
);
}
};
+const getSparkAccountState = async (network: BaseNetwork) => {
+ if (
+ network.name === NetworkNames.Firo ||
+ network.name === NetworkNames.FiroTest
+ ) {
+ const sparkAccountResponse = await getSparkState();
+ accountHeaderData.value.sparkAccount = { ...sparkAccountResponse };
+ }
+};
const setNetwork = async (network: BaseNetwork) => {
trackNetworkSelected(NetworkChangeEvents.NetworkChangePopup, {
provider: network.provider,
@@ -315,7 +325,10 @@ const setNetwork = async (network: BaseNetwork) => {
let sparkAccount: SparkAccount | null = null;
- if (network.name === NetworkNames.Firo) {
+ if (
+ network.name === NetworkNames.Firo ||
+ network.name === NetworkNames.FiroTest
+ ) {
const sparkAccountResponse = await getSparkState();
sparkAccount = { ...sparkAccountResponse };
}
diff --git a/packages/extension/src/ui/action/router/index.ts b/packages/extension/src/ui/action/router/index.ts
index b68e90e00..5c552122a 100644
--- a/packages/extension/src/ui/action/router/index.ts
+++ b/packages/extension/src/ui/action/router/index.ts
@@ -9,6 +9,7 @@ import Intro from '@action/views/intro/index.vue';
import Swap from '@action/views/swap/index.vue';
import SwapBestOffer from '@action/views/swap/views/swap-best-offer/index.vue';
import VerifyTransaction from '@action/views/verify-transaction/index.vue';
+import VerifySendToSparkTransaction from "@action/views/verify-send-to-spark-transaction/index.vue";
import SendTransaction from '@action/views/send-transaction/index.vue';
const routes = {
@@ -68,6 +69,13 @@ const routes = {
},
name: 'verify-transaction',
},
+ verifySendToSpark: {
+ path: "/verify-send-to-spark-transaction/:id?",
+ components: {
+ view: VerifySendToSparkTransaction,
+ },
+ name: "verify-send-to-spark",
+ },
swap: {
path: '/swap/:id?',
components: {
diff --git a/packages/extension/src/ui/action/views/deposit/index.vue b/packages/extension/src/ui/action/views/deposit/index.vue
index c37c8416b..565fb1db8 100644
--- a/packages/extension/src/ui/action/views/deposit/index.vue
+++ b/packages/extension/src/ui/action/views/deposit/index.vue
@@ -28,7 +28,7 @@
-
+
+
+
+
+
+
+
+
+ Double check the information and confirm transaction
+
+
+
+
+
+
+
+ {{ errorMsg }}
+
+
+
+
+
+
+
+
+
+
+
+
+
From 643b114b40e704deceb94959999c1f258c45a563 Mon Sep 17 00:00:00 2001
From: narekpetrosyan
Date: Tue, 24 Dec 2024 14:15:00 +0400
Subject: [PATCH 4/4] feature: add send from spark to spark address
functionality
---
.../src/libs/spark-handler/callRPC.ts | 21 +-
.../extension/src/libs/spark-handler/index.ts | 15 +
.../src/providers/bitcoin/libs/api-firo.ts | 6 +-
.../bitcoin/networks/firo-testnet.ts | 3 +-
.../src/providers/bitcoin/networks/firo.ts | 3 +-
.../bitcoin/types/bitcoin-network.ts | 4 +-
.../components/send-spark-address-input.vue | 166 +
.../bitcoin/ui/send-transaction/index.vue | 566 +-
.../send-transaction/tabs/spark-send-tab.vue | 302 +
.../tabs/transparent-send-tab.vue | 79 +-
packages/extension/src/ui/action/App.vue | 10 +-
.../extension/src/ui/action/router/index.ts | 8 +
.../index.vue | 348 +
.../index.vue | 14 +-
.../hw-wallets/src/ledger/bitcoin/configs.ts | 2 +-
yarn.lock | 6892 +++++++++--------
16 files changed, 4650 insertions(+), 3789 deletions(-)
create mode 100644 packages/extension/src/providers/bitcoin/ui/send-transaction/components/send-spark-address-input.vue
create mode 100644 packages/extension/src/providers/bitcoin/ui/send-transaction/tabs/spark-send-tab.vue
create mode 100644 packages/extension/src/ui/action/views/verify-send-from-spark-transaction/index.vue
diff --git a/packages/extension/src/libs/spark-handler/callRPC.ts b/packages/extension/src/libs/spark-handler/callRPC.ts
index f369aa27f..2901adfb2 100644
--- a/packages/extension/src/libs/spark-handler/callRPC.ts
+++ b/packages/extension/src/libs/spark-handler/callRPC.ts
@@ -1,14 +1,25 @@
import axios from "axios";
-const rpcURL = "https://firo-rpc.publicnode.com/";
+const DEFAULT_TIMEOUT = 30000;
+
+const RPC_URLS = {
+ mainnet: "https://firo-rpc.publicnode.com/",
+};
+
+const axiosInstance = axios.create({
+ timeout: DEFAULT_TIMEOUT,
+ headers: {
+ "Content-Type": "application/json",
+ }
+});
export async function callRPC(
method: string,
params?: object
): Promise {
try {
- const response = await axios.post(
- rpcURL,
+ const response = await axiosInstance.post(
+ RPC_URLS['mainnet'],
{
jsonrpc: "1.0",
id: "js-client",
@@ -21,6 +32,10 @@ export async function callRPC(
},
}
);
+
+ if (!response.data || response.data.result === undefined) {
+ throw new Error('Invalid RPC response structure');
+ }
return response.data.result;
} catch (error) {
console.error("RPC Error:", error);
diff --git a/packages/extension/src/libs/spark-handler/index.ts b/packages/extension/src/libs/spark-handler/index.ts
index b6eda8da6..686b20a4c 100644
--- a/packages/extension/src/libs/spark-handler/index.ts
+++ b/packages/extension/src/libs/spark-handler/index.ts
@@ -26,3 +26,18 @@ export async function sendToSparkAddress(to: string, amount: string) {
},
]);
}
+
+export async function sendFromSparkAddress(
+ to: string,
+ amount: string,
+ subtractFee = false
+): Promise {
+ return await callRPC("spendspark", [
+ {
+ [to]: {
+ amount: Number(amount),
+ subtractFee,
+ },
+ },
+ ]);
+}
diff --git a/packages/extension/src/providers/bitcoin/libs/api-firo.ts b/packages/extension/src/providers/bitcoin/libs/api-firo.ts
index f30d26ca7..f45201aeb 100644
--- a/packages/extension/src/providers/bitcoin/libs/api-firo.ts
+++ b/packages/extension/src/providers/bitcoin/libs/api-firo.ts
@@ -28,7 +28,7 @@ class API implements ProviderAPIInterface {
return getBitcoinAddress(pubkey, this.networkInfo);
}
- // eslint-disable-next-line @typescript-eslint/no-empty-function
+
async init(): Promise {}
async getRawTransaction(hash: string): Promise {
@@ -133,7 +133,7 @@ class API implements ProviderAPIInterface {
ret.sort((a, b) => {
return a.value - b.value;
});
- return [ret.at(-1)!]; // TODO: check or filter same values
+ return ret;
}
async getUTXOs(pubkey: string): Promise {
@@ -145,7 +145,7 @@ class API implements ProviderAPIInterface {
return filterOutOrdinals(
address,
this.networkInfo.name,
- await this.FiroToHaskoinUTXOs(utxos, address)
+ [(await this.FiroToHaskoinUTXOs(utxos, address)).at(-1)!]
).then((futxos) => {
futxos.sort((a, b) => {
return a.value - b.value;
diff --git a/packages/extension/src/providers/bitcoin/networks/firo-testnet.ts b/packages/extension/src/providers/bitcoin/networks/firo-testnet.ts
index d4907f402..b1bee81de 100644
--- a/packages/extension/src/providers/bitcoin/networks/firo-testnet.ts
+++ b/packages/extension/src/providers/bitcoin/networks/firo-testnet.ts
@@ -1,4 +1,5 @@
import { NetworkNames } from "@enkryptcom/types";
+import icon from './icons/firo.svg';
import {
BitcoinNetwork,
BitcoinNetworkOptions,
@@ -18,7 +19,7 @@ const firoOptions: BitcoinNetworkOptions = {
isTestNetwork: true,
currencyName: "tFIRO",
currencyNameLong: "tFiro",
- icon: require("./icons/firo.svg"),
+ icon,
decimals: 8,
node: "https://testexplorer.firo.org",
coingeckoID: "zcoin",
diff --git a/packages/extension/src/providers/bitcoin/networks/firo.ts b/packages/extension/src/providers/bitcoin/networks/firo.ts
index a450cc014..5c36a1f59 100644
--- a/packages/extension/src/providers/bitcoin/networks/firo.ts
+++ b/packages/extension/src/providers/bitcoin/networks/firo.ts
@@ -1,4 +1,5 @@
import { NetworkNames } from "@enkryptcom/types";
+import icon from './icons/firo.svg';
import {
BitcoinNetwork,
BitcoinNetworkOptions,
@@ -18,7 +19,7 @@ const firoOptions: BitcoinNetworkOptions = {
isTestNetwork: false,
currencyName: "FIRO",
currencyNameLong: "Firo",
- icon: require("./icons/firo.svg"),
+ icon,
decimals: 8,
node: "https://explorer.firo.org",
coingeckoID: "zcoin",
diff --git a/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts b/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts
index ddac2f801..af4157692 100644
--- a/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts
+++ b/packages/extension/src/providers/bitcoin/types/bitcoin-network.ts
@@ -57,7 +57,9 @@ export interface BitcoinNetworkOptions {
}
export const getAddress = (pubkey: string, network: BitcoinNetworkInfo) => {
- if (pubkey.length < 64) return pubkey;
+ if (pubkey.length >= 144 || pubkey.length < 64) {
+ return pubkey;
+ }
const { address } = payments[network.paymentType]({
network,
pubkey: hexToBuffer(pubkey),
diff --git a/packages/extension/src/providers/bitcoin/ui/send-transaction/components/send-spark-address-input.vue b/packages/extension/src/providers/bitcoin/ui/send-transaction/components/send-spark-address-input.vue
new file mode 100644
index 000000000..47626c946
--- /dev/null
+++ b/packages/extension/src/providers/bitcoin/ui/send-transaction/components/send-spark-address-input.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
diff --git a/packages/extension/src/providers/bitcoin/ui/send-transaction/index.vue b/packages/extension/src/providers/bitcoin/ui/send-transaction/index.vue
index 66138e361..c9a35d3d8 100644
--- a/packages/extension/src/providers/bitcoin/ui/send-transaction/index.vue
+++ b/packages/extension/src/providers/bitcoin/ui/send-transaction/index.vue
@@ -8,166 +8,57 @@
@toggle-type="toggleSelector"
/>
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/packages/extension/src/providers/bitcoin/ui/send-transaction/tabs/transparent-send-tab.vue b/packages/extension/src/providers/bitcoin/ui/send-transaction/tabs/transparent-send-tab.vue
index 41cef2344..b93d4457a 100644
--- a/packages/extension/src/providers/bitcoin/ui/send-transaction/tabs/transparent-send-tab.vue
+++ b/packages/extension/src/providers/bitcoin/ui/send-transaction/tabs/transparent-send-tab.vue
@@ -23,33 +23,27 @@
/>
@@ -221,7 +210,6 @@ const loadingAsset = new BTCToken({
});
const addressInputTo = ref();
-const sparkAddressInput = ref();
const isSendSpark = ref(false);
const selected: string = route.params.id as string;
const paramNFTData: NFTItem = JSON.parse(
@@ -321,17 +309,12 @@ const sendButtonTitle = computed(() => {
});
const isInputsValid = computed
(() => {
- if (isSendSpark.value) {
- if (!isSparkAddress(sparkAddressInput.value)) {
- return false;
- }
- } else {
- if (
- !isAddress(addressTo.value, (props.network as BitcoinNetwork).networkInfo)
- )
- return false;
+ if (
+ !isSparkAddress(addressTo.value) &&
+ !isAddress(addressTo.value, (props.network as BitcoinNetwork).networkInfo)
+ ) {
+ return false;
}
-
if (
props.isSendToken &&
!isValidDecimals(sendAmount.value, selectedAsset.value.decimals!)
@@ -411,10 +394,6 @@ const inputAddressTo = (text: string) => {
addressTo.value = text;
};
-const inputSparkAddressTo = (address: string) => {
- sparkAddressInput.value = address;
-};
-
const toggleSelectContactFrom = (open: boolean) => {
isOpenSelectContactFrom.value = open;
};
@@ -447,10 +426,6 @@ const toggleSelectFee = () => {
isOpenSelectFee.value = !isOpenSelectFee.value;
};
-const toggleIsSendSpark = (value: boolean) => {
- isSendSpark.value = value;
-};
-
const selectFee = (type: GasPriceTypes) => {
selectedFee.value = type;
isOpenSelectFee.value = false;
@@ -469,8 +444,8 @@ const selectNFT = (item: NFTItemWithCollectionName) => {
const sendSparkAction = async () => {
const keyring = new PublicKeyRing();
const fromAccountInfo = await keyring.getAccount(addressFrom.value);
-
const toAmount = toBN(toBase(sendAmount.value, selectedAsset.value.decimals));
+
router.push({
name: RouterNames.verifySendToSpark.name,
query: {
@@ -492,7 +467,7 @@ const sendSparkAction = async () => {
fromAddressName: fromAccountInfo.name,
gasFee: gasCostValues.value[selectedFee.value],
gasPriceType: selectedFee.value,
- toAddress: sparkAddressInput.value,
+ toAddress: addressTo.value,
}),
"utf8"
).toString("base64"),
@@ -514,7 +489,7 @@ const sendAction = async () => {
if (props.isSendToken) {
txInfo.outputs.push({
- address: isSendSpark.value ? sparkAddressInput.value : addressTo.value,
+ address: addressTo.value,
value: toAmount.toNumber(),
});
} else {
@@ -600,8 +575,8 @@ const sendAction = async () => {
diff --git a/packages/extension/src/ui/action/views/verify-send-to-spark-transaction/index.vue b/packages/extension/src/ui/action/views/verify-send-to-spark-transaction/index.vue
index b6a308333..0aaafb4cb 100644
--- a/packages/extension/src/ui/action/views/verify-send-to-spark-transaction/index.vue
+++ b/packages/extension/src/ui/action/views/verify-send-to-spark-transaction/index.vue
@@ -27,7 +27,7 @@
:network="network"
/>
@@ -95,6 +95,7 @@ import { sendToSparkAddress } from "@/libs/spark-handler";
import { isAxiosError } from "axios";
import { fromBase } from "@enkryptcom/utils";
import { BaseNetwork } from "@/types/base-network";
+import { isAddress } from "@/providers/bitcoin/libs/utils";
const emits = defineEmits<{
(e: "update:spark-state-changed", network: BaseNetwork): void;
@@ -122,9 +123,12 @@ defineExpose({ verifyScrollRef });
onBeforeMount(async () => {
network.value = (await getNetworkByName(selectedNetwork)!) as BitcoinNetwork;
trackSendEvents(SendEventType.SendVerify, { network: network.value.name });
- account.value = await KeyRing.getAccount(txData.fromAddress);
- isWindowPopup.value = account.value.isHardware;
+ if (isAddress(txData.fromAddress, network.value.networkInfo)) {
+ account.value = await KeyRing.getAccount(txData.fromAddress);
+ isWindowPopup.value = account.value.isHardware;
+ }
});
+
const close = () => {
if (getCurrentContext() === "popup") {
router.go(-1);
@@ -212,8 +216,8 @@ const isHasScroll = () => {