diff --git a/packages/extension/package.json b/packages/extension/package.json index cf8b96a3c..c672bf844 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -1,6 +1,6 @@ { "name": "@enkryptcom/extension", - "version": "1.6.0", + "version": "1.7.0", "private": true, "scripts": { "zip": "cd dist; zip -r release.zip *;", diff --git a/packages/extension/src/libs/dapp-list/index.ts b/packages/extension/src/libs/dapp-list/index.ts index 5cf861246..c45a3650e 100644 --- a/packages/extension/src/libs/dapp-list/index.ts +++ b/packages/extension/src/libs/dapp-list/index.ts @@ -2,35 +2,43 @@ import { NetworkNames } from "@enkryptcom/types"; const lists: Partial> = { [NetworkNames.Ethereum]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/eth.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/eth.json", [NetworkNames.Binance]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/bsc.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/bsc.json", [NetworkNames.Matic]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/matic.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/matic.json", [NetworkNames.EthereumClassic]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/etc.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/etc.json", [NetworkNames.Kusama]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/ksm.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/ksm.json", [NetworkNames.Polkadot]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/dot.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/dot.json", [NetworkNames.Acala]: "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/aca.json", [NetworkNames.Karura]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/kar.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/kar.json", [NetworkNames.Moonbeam]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/glmr.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/glmr.json", [NetworkNames.Moonriver]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/movr.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/movr.json", [NetworkNames.Astar]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/astr.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/astr.json", [NetworkNames.AstarEVM]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/astr.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/astr.json", [NetworkNames.Shiden]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/sdn.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/sdn.json", [NetworkNames.ShidenEVM]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/sdn.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/sdn.json", [NetworkNames.Okc]: - "https://github.com/enkryptcom/dynamic-data/raw/main/dapps/okc.json", + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/okc.json", + [NetworkNames.Optimism]: + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/op.json", + [NetworkNames.Canto]: + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/canto.json", + [NetworkNames.Bifrost]: + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/bifrost.json", + [NetworkNames.BifrostKusama]: + "https://raw.githubusercontent.com/enkryptcom/dynamic-data/main/dapps/bifrost.json", }; export default lists; diff --git a/packages/extension/src/manifest/base.json b/packages/extension/src/manifest/base.json index 4f6e2c8d8..096ecd316 100644 --- a/packages/extension/src/manifest/base.json +++ b/packages/extension/src/manifest/base.json @@ -2,7 +2,7 @@ "author": "https://www.enkrypt.com", "homepage_url": "https://www.enkrypt.com", "version": "", - "name": "Enkrypt: Ethereum, Polkadot and OKX Wallet", + "name": "Enkrypt: Ethereum, Polkadot and Canto Wallet", "short_name": "Enkrypt", "permissions": [ "storage", diff --git a/packages/extension/src/providers/ethereum/index.ts b/packages/extension/src/providers/ethereum/index.ts index 2fb2d6536..5baaab7e6 100644 --- a/packages/extension/src/providers/ethereum/index.ts +++ b/packages/extension/src/providers/ethereum/index.ts @@ -43,8 +43,13 @@ class EthereumProvider this.middlewares = Middlewares.map((mw) => mw.bind(this)); } setRequestProvider(network: BaseNetwork): void { + const prevURL = new URL(this.network.node); + const newURL = new URL(network.node); this.network = network as EvmNetwork; - this.requestProvider.changeNetwork(network.node); + if (prevURL.protocol === newURL.protocol) + this.requestProvider.changeNetwork(network.node); + else + this.requestProvider = getRequestProvider(network.node, this.middlewares); } async isPersistentEvent(request: ProviderRPCRequest): Promise { if (request.method === "eth_subscribe") return true; diff --git a/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts b/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts index 73ed83c02..e92de0a0b 100644 --- a/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts +++ b/packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts @@ -13,6 +13,8 @@ const NetworkEndpoints = { [NetworkNames.KaruraEVM]: "https://blockscout.karura.network/", [NetworkNames.AstarEVM]: "https://blockscout.com/astar/", [NetworkNames.ShidenEVM]: "https://blockscout.com/shiden/", + [NetworkNames.Optimism]: "https://api-optimistic.etherscan.io/", + [NetworkNames.Canto]: "https://evm.explorer.canto.io/", }; export { NetworkEndpoints }; diff --git a/packages/extension/src/providers/ethereum/libs/assets-handlers/types/tokenbalance-mew.ts b/packages/extension/src/providers/ethereum/libs/assets-handlers/types/tokenbalance-mew.ts index 89b766bdb..0d712e8ba 100644 --- a/packages/extension/src/providers/ethereum/libs/assets-handlers/types/tokenbalance-mew.ts +++ b/packages/extension/src/providers/ethereum/libs/assets-handlers/types/tokenbalance-mew.ts @@ -10,7 +10,7 @@ export interface SupportedNetwork { cgPlatform: string; } export interface CGToken { - chainId: number; + chainId: `0x${string}`; address: string; name: string; symbol: string; diff --git a/packages/extension/src/providers/ethereum/libs/tx-broadcaster.ts b/packages/extension/src/providers/ethereum/libs/tx-broadcaster.ts new file mode 100644 index 000000000..d9fdc8a9e --- /dev/null +++ b/packages/extension/src/providers/ethereum/libs/tx-broadcaster.ts @@ -0,0 +1,28 @@ +import { NetworkNames } from "@enkryptcom/types"; +import { v4 } from "uuid"; + +const broadcastTx = (hexTx: string, network: NetworkNames): Promise => { + if (network === NetworkNames.Ethereum) { + const burl = "https://broadcast.mewapi.io/eth?product=enkrypt"; + return fetch(burl, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + jsonrpc: "2.0", + method: "eth_sendRawTransaction", + params: [hexTx], + id: v4(), + }), + }) + .then((response) => response.json()) + .then((jRes) => { + if (jRes.error) return Promise.reject(jRes.error); + else return jRes.result as string; + }); + } + return Promise.reject("Not valid network"); +}; + +export default broadcastTx; diff --git a/packages/extension/src/providers/ethereum/methods/eth_sendRawTransaction.ts b/packages/extension/src/providers/ethereum/methods/eth_sendRawTransaction.ts new file mode 100644 index 000000000..433b0bfbc --- /dev/null +++ b/packages/extension/src/providers/ethereum/methods/eth_sendRawTransaction.ts @@ -0,0 +1,25 @@ +import { getCustomError } from "@/libs/error"; +import { MiddlewareFunction } from "@enkryptcom/types"; +import EthereumProvider from ".."; +import broadcastTx from "../libs/tx-broadcaster"; +const method: MiddlewareFunction = function ( + this: EthereumProvider, + payload, + res, + next +): void { + if (payload.method !== "eth_sendRawTransaction") return next(); + else { + if (!payload.params || payload.params.length < 1) { + return res( + getCustomError("eth_sendTransaction: invalid request not enough params") + ); + } + broadcastTx(payload.params[0], this.network.name) + .then((hash) => { + res(null, hash); + }) + .catch(() => next()); + } +}; +export default method; diff --git a/packages/extension/src/providers/ethereum/methods/index.ts b/packages/extension/src/providers/ethereum/methods/index.ts index af8dc5e3b..918debe54 100644 --- a/packages/extension/src/providers/ethereum/methods/index.ts +++ b/packages/extension/src/providers/ethereum/methods/index.ts @@ -11,6 +11,7 @@ import addEthereumChain from "./wallet_addEthereumChain"; import switchEthereumChain from "./wallet_switchEthereumChain"; import watchAsset from "./wallet_watchAsset"; import walletRequestPermissions from "./wallet_requestPermissions"; +import ethSendRawTransaction from "./eth_sendRawTransaction"; export default [ ethSendTransaction, ethSign, @@ -25,4 +26,5 @@ export default [ switchEthereumChain, addEthereumChain, walletRequestPermissions, + ethSendRawTransaction, ]; diff --git a/packages/extension/src/providers/ethereum/methods/wallet_addEthereumChain.ts b/packages/extension/src/providers/ethereum/methods/wallet_addEthereumChain.ts index 0132d4c42..0c00ffa1e 100644 --- a/packages/extension/src/providers/ethereum/methods/wallet_addEthereumChain.ts +++ b/packages/extension/src/providers/ethereum/methods/wallet_addEthereumChain.ts @@ -2,7 +2,6 @@ import { getCustomError } from "@/libs/error"; import { MiddlewareFunction } from "@enkryptcom/types"; import EthNetworks from "../networks"; import EthereumProvider from ".."; -import { numberToHex } from "web3-utils"; import { sendToBackgroundFromBackground } from "@/libs/messenger/extension"; import { InternalMethods } from "@/types/messenger"; import { ProviderRPCRequest } from "@/types/provider"; @@ -26,7 +25,7 @@ const method: MiddlewareFunction = function ( } const allNetworks = Object.values(EthNetworks); const validNetwork = allNetworks.find( - (net) => numberToHex(net.chainID) === payload.params![0].chainId + (net) => net.chainID === payload.params![0].chainId ); if (validNetwork) { sendToBackgroundFromBackground({ diff --git a/packages/extension/src/providers/ethereum/methods/wallet_switchEthereumChain.ts b/packages/extension/src/providers/ethereum/methods/wallet_switchEthereumChain.ts index 84f767538..f91d4b8be 100644 --- a/packages/extension/src/providers/ethereum/methods/wallet_switchEthereumChain.ts +++ b/packages/extension/src/providers/ethereum/methods/wallet_switchEthereumChain.ts @@ -5,7 +5,6 @@ import { ProviderRPCRequest } from "@/types/provider"; import { MiddlewareFunction } from "@enkryptcom/types"; import EthNetworks from "../networks"; import EthereumProvider from ".."; -import { numberToHex } from "web3-utils"; import { MessageMethod } from "../types"; import DomainState from "@/libs/domain-state"; const method: MiddlewareFunction = function ( @@ -25,7 +24,7 @@ const method: MiddlewareFunction = function ( } const allNetworks = Object.values(EthNetworks); const validNetwork = allNetworks.find( - (net) => numberToHex(net.chainID) === payload.params![0].chainId + (net) => net.chainID === payload.params![0].chainId ); if (validNetwork) { sendToBackgroundFromBackground({ diff --git a/packages/extension/src/providers/ethereum/networks/astr.ts b/packages/extension/src/providers/ethereum/networks/astr.ts index 8af5a4adf..2478a618d 100644 --- a/packages/extension/src/providers/ethereum/networks/astr.ts +++ b/packages/extension/src/providers/ethereum/networks/astr.ts @@ -9,9 +9,10 @@ const astrOptions: EvmNetworkOptions = { homePage: "https://astar.network/", blockExplorerTX: "https://blockscout.com/astar/tx/[[txHash]]", blockExplorerAddr: "https://blockscout.com/astar/address/[[address]]", - chainID: 592, + chainID: "0x250", isTestNetwork: false, currencyName: "ASTR", + currencyNameLong: "Astar", node: "wss://astar.public.blastapi.io/", icon: require("./icons/astr.png"), gradient: "linear-gradient(180deg, #C549FF 0%, #684CFF 100%)", diff --git a/packages/extension/src/providers/ethereum/networks/bsc.ts b/packages/extension/src/providers/ethereum/networks/bsc.ts index 55fa73722..709be7266 100644 --- a/packages/extension/src/providers/ethereum/networks/bsc.ts +++ b/packages/extension/src/providers/ethereum/networks/bsc.ts @@ -10,9 +10,10 @@ const bscOptions: EvmNetworkOptions = { homePage: "https://www.binance.org/en/smartChain", blockExplorerTX: "https://bscscan.com/tx/[[txHash]]", blockExplorerAddr: "https://bscscan.com/address/[[address]]", - chainID: 56, + chainID: "0x38", isTestNetwork: false, currencyName: "BNB", + currencyNameLong: "Binance", node: "wss://nodes.mewapi.io/ws/bsc", icon: require("./icons/bsc.svg"), gradient: "#F0B90B", diff --git a/packages/extension/src/providers/ethereum/networks/canto.ts b/packages/extension/src/providers/ethereum/networks/canto.ts new file mode 100644 index 000000000..da6ef2a59 --- /dev/null +++ b/packages/extension/src/providers/ethereum/networks/canto.ts @@ -0,0 +1,26 @@ +import wrapActivityHandler from "@/libs/activity-state/wrap-activity-handler"; +import { CoingeckoPlatform, NetworkNames } from "@enkryptcom/types"; +import { EtherscanActivity } from "../libs/activity-handlers"; +import { EvmNetwork, EvmNetworkOptions } from "../types/evm-network"; + +const cantoOptions: EvmNetworkOptions = { + name: NetworkNames.Canto, + name_long: "Canto", + homePage: "https://canto.io/", + blockExplorerTX: "https://evm.explorer.canto.io/tx/[[txHash]]", + blockExplorerAddr: "https://evm.explorer.canto.io/address/[[address]]", + chainID: "0x1e14", + isTestNetwork: false, + currencyName: "CANTO", + currencyNameLong: "Canto", + node: "https://canto.evm.chandrastation.com/", + icon: require("./icons/canto.svg"), + gradient: "linear-gradient(180deg, #C549FF 0%, #684CFF 100%)", + coingeckoID: "canto", + coingeckoPlatform: CoingeckoPlatform.Canto, + activityHandler: wrapActivityHandler(EtherscanActivity), +}; + +const canto = new EvmNetwork(cantoOptions); + +export default canto; diff --git a/packages/extension/src/providers/ethereum/networks/etc.ts b/packages/extension/src/providers/ethereum/networks/etc.ts index cad57b327..e060efe37 100644 --- a/packages/extension/src/providers/ethereum/networks/etc.ts +++ b/packages/extension/src/providers/ethereum/networks/etc.ts @@ -9,9 +9,10 @@ const etcOptions: EvmNetworkOptions = { homePage: "https://ethereumclassic.org/", blockExplorerTX: "https://blockscout.com/etc/mainnet/tx/[[txHash]]", blockExplorerAddr: "https://blockscout.com/etc/mainnet/address/[[address]]", - chainID: 61, + chainID: "0x3d", isTestNetwork: false, currencyName: "ETC", + currencyNameLong: "Ethereum Classic", node: "wss://nodes.mewapi.io/ws/etc", icon: require("./icons/etc.svg"), gradient: "linear-gradient(180deg, #C549FF 0%, #684CFF 100%)", diff --git a/packages/extension/src/providers/ethereum/networks/eth.ts b/packages/extension/src/providers/ethereum/networks/eth.ts index ddececb67..29f8821bb 100644 --- a/packages/extension/src/providers/ethereum/networks/eth.ts +++ b/packages/extension/src/providers/ethereum/networks/eth.ts @@ -11,9 +11,10 @@ const ethOptions: EvmNetworkOptions = { homePage: "https://ethereum.org", blockExplorerTX: "https://www.ethvm.com/tx/[[txHash]]", blockExplorerAddr: "https://www.ethvm.com/address/[[address]]", - chainID: 1, + chainID: "0x1", isTestNetwork: false, currencyName: "ETH", + currencyNameLong: "Ethereum", node: "wss://nodes.mewapi.io/ws/eth", icon: require("./icons/eth.svg"), gradient: "linear-gradient(180deg, #C549FF 0%, #684CFF 100%)", diff --git a/packages/extension/src/providers/ethereum/networks/goerli.ts b/packages/extension/src/providers/ethereum/networks/goerli.ts index 7aa0d429a..b66ca0da0 100644 --- a/packages/extension/src/providers/ethereum/networks/goerli.ts +++ b/packages/extension/src/providers/ethereum/networks/goerli.ts @@ -9,9 +9,10 @@ const goerliOptions: EvmNetworkOptions = { homePage: "https://github.com/goerli/testnet", blockExplorerTX: "https://goerli.etherscan.io/tx/[[txHash]]", blockExplorerAddr: "https://goerli.etherscan.io/address/[[address]]", - chainID: 5, + chainID: "0x5", isTestNetwork: true, currencyName: "GöETH", + currencyNameLong: "Goerli", node: "wss://nodes.mewapi.io/ws/goerli", icon: require("./icons/eth.svg"), gradient: "linear-gradient(180deg, #C549FF 0%, #684CFF 100%)", diff --git a/packages/extension/src/providers/ethereum/networks/icons/canto.svg b/packages/extension/src/providers/ethereum/networks/icons/canto.svg new file mode 100644 index 000000000..029028234 --- /dev/null +++ b/packages/extension/src/providers/ethereum/networks/icons/canto.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/extension/src/providers/ethereum/networks/icons/op.svg b/packages/extension/src/providers/ethereum/networks/icons/op.svg new file mode 100644 index 000000000..336c6f8c0 --- /dev/null +++ b/packages/extension/src/providers/ethereum/networks/icons/op.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/extension/src/providers/ethereum/networks/index.ts b/packages/extension/src/providers/ethereum/networks/index.ts index 425665a44..d538760ce 100644 --- a/packages/extension/src/providers/ethereum/networks/index.ts +++ b/packages/extension/src/providers/ethereum/networks/index.ts @@ -12,6 +12,8 @@ import karuraEvmNode from "./karura"; import okcNode from "./okc"; import shidenEvmNode from "./sdn"; import astarEvmNode from "./astr"; +import optimismNode from "./op"; +import cantoNode from "./canto"; export default { goerli: goerliNode, @@ -28,4 +30,6 @@ export default { okc: okcNode, shidenEvm: shidenEvmNode, astarEvm: astarEvmNode, + op: optimismNode, + canto: cantoNode, }; diff --git a/packages/extension/src/providers/ethereum/networks/karura.ts b/packages/extension/src/providers/ethereum/networks/karura.ts index ffd305aa4..b8d334971 100644 --- a/packages/extension/src/providers/ethereum/networks/karura.ts +++ b/packages/extension/src/providers/ethereum/networks/karura.ts @@ -9,9 +9,10 @@ const karuraOptions: EvmNetworkOptions = { homePage: "https://karura.network", blockExplorerTX: "https://blockscout.karura.network/tx/[[txHash]]", blockExplorerAddr: "https://blockscout.karura.network/address/[[address]]", - chainID: 686, + chainID: "0x2ae", isTestNetwork: false, currencyName: "KAR", + currencyNameLong: "Karura", node: "wss://eth-rpc-karura.aca-api.network/ws", icon: require("./icons/karura-evm.svg"), gradient: "linear-gradient(330.21deg, #E40C5B -26.31%, #FF4C3B 88.17%)", diff --git a/packages/extension/src/providers/ethereum/networks/kov.ts b/packages/extension/src/providers/ethereum/networks/kov.ts index 4fbbd0af5..3d123379c 100644 --- a/packages/extension/src/providers/ethereum/networks/kov.ts +++ b/packages/extension/src/providers/ethereum/networks/kov.ts @@ -9,9 +9,10 @@ const kovOptions: EvmNetworkOptions = { homePage: "https://github.com/kovan-testnet", blockExplorerTX: "https://kovan.etherscan.io/tx/[[txHash]]", blockExplorerAddr: "https://kovan.etherscan.io/address/[[address]]", - chainID: 42, + chainID: "0x2a", isTestNetwork: true, currencyName: "KOV", + currencyNameLong: "Kovan", node: "wss://nodes.mewapi.io/ws/kovan", icon: require("./icons/eth.svg"), gradient: "linear-gradient(180deg, #C549FF 0%, #684CFF 100%)", diff --git a/packages/extension/src/providers/ethereum/networks/matic.ts b/packages/extension/src/providers/ethereum/networks/matic.ts index ad6a6b15b..b5b9e8858 100644 --- a/packages/extension/src/providers/ethereum/networks/matic.ts +++ b/packages/extension/src/providers/ethereum/networks/matic.ts @@ -11,9 +11,10 @@ const maticOptions: EvmNetworkOptions = { homePage: "https://polygonscan.com/", blockExplorerTX: "https://polygonscan.com/tx/[[txHash]]", blockExplorerAddr: "https://polygonscan.com/address/[[address]]", - chainID: 137, + chainID: "0x89", isTestNetwork: false, currencyName: "MATIC", + currencyNameLong: "Polygon Matic", node: "wss://nodes.mewapi.io/ws/matic", icon: require("./icons/matic.svg"), gradient: "#7B3FE4", diff --git a/packages/extension/src/providers/ethereum/networks/moonbeam/index.ts b/packages/extension/src/providers/ethereum/networks/moonbeam/index.ts index 1816c0035..355e37f8b 100644 --- a/packages/extension/src/providers/ethereum/networks/moonbeam/index.ts +++ b/packages/extension/src/providers/ethereum/networks/moonbeam/index.ts @@ -10,9 +10,10 @@ const moonbeamOptions: EvmNetworkOptions = { homePage: "https://moonbeam.network", blockExplorerTX: "https://moonscan.io/tx/[[txHash]]", blockExplorerAddr: "https://moonscan.io/address/[[address]]", - chainID: 1284, + chainID: "0x504", isTestNetwork: false, currencyName: "GLMR", + currencyNameLong: "Moonbeam", node: "wss://wss.api.moonbeam.network/", icon: require("../icons/moonbeam.svg"), gradient: "#53CBC9", diff --git a/packages/extension/src/providers/ethereum/networks/moonriver/index.ts b/packages/extension/src/providers/ethereum/networks/moonriver/index.ts index 10e62de9d..13c2d8275 100644 --- a/packages/extension/src/providers/ethereum/networks/moonriver/index.ts +++ b/packages/extension/src/providers/ethereum/networks/moonriver/index.ts @@ -10,9 +10,10 @@ const moonriverOptions: EvmNetworkOptions = { homePage: "https://moonbeam.network/networks/moonriver/", blockExplorerTX: "https://moonriver.moonscan.io//tx/[[txHash]]", blockExplorerAddr: "https://moonriver.moonscan.io/address/[[address]]", - chainID: 1285, + chainID: "0x505", isTestNetwork: false, currencyName: "MOVR", + currencyNameLong: "Moonriver", node: "wss://wss.api.moonriver.moonbeam.network", icon: require("../icons/moonriver.svg"), gradient: "linear-gradient(180deg, #F2B705 0%, #53CBC8 100%)", diff --git a/packages/extension/src/providers/ethereum/networks/okc.ts b/packages/extension/src/providers/ethereum/networks/okc.ts index c2b99bcdf..211fc90f2 100644 --- a/packages/extension/src/providers/ethereum/networks/okc.ts +++ b/packages/extension/src/providers/ethereum/networks/okc.ts @@ -9,9 +9,10 @@ const okcOptions: EvmNetworkOptions = { homePage: "https://www.oklink.com/en/okc", blockExplorerTX: "https://www.oklink.com/en/okc/tx/[[txHash]]", blockExplorerAddr: "https://www.oklink.com/en/okc/address/[[address]]", - chainID: 66, + chainID: "0x42", isTestNetwork: false, currencyName: "OKT", + currencyNameLong: "OKX Chain", node: "https://exchainrpc.okex.org", icon: require("./icons/okc.svg"), gradient: "linear-gradient(180deg, #C549FF 0%, #684CFF 100%)", diff --git a/packages/extension/src/providers/ethereum/networks/op.ts b/packages/extension/src/providers/ethereum/networks/op.ts new file mode 100644 index 000000000..7e6efed09 --- /dev/null +++ b/packages/extension/src/providers/ethereum/networks/op.ts @@ -0,0 +1,26 @@ +import { CoingeckoPlatform, NetworkNames } from "@enkryptcom/types"; +import { EvmNetwork, EvmNetworkOptions } from "../types/evm-network"; +import { EtherscanActivity } from "../libs/activity-handlers"; +import wrapActivityHandler from "@/libs/activity-state/wrap-activity-handler"; + +const opOptions: EvmNetworkOptions = { + name: NetworkNames.Optimism, + name_long: "Optimism", + homePage: "https://www.optimism.io/", + blockExplorerTX: "https://optimistic.etherscan.io/tx/[[txHash]]", + blockExplorerAddr: "https://optimistic.etherscan.io/address/[[address]]", + chainID: "0xa", + isTestNetwork: false, + currencyName: "ETH", + currencyNameLong: "Ethereum", + node: "https://mainnet.optimism.io", + icon: require("./icons/op.svg"), + gradient: "linear-gradient(180deg, #C549FF 0%, #684CFF 100%)", + coingeckoID: "ethereum", + coingeckoPlatform: CoingeckoPlatform.Optimism, + activityHandler: wrapActivityHandler(EtherscanActivity), +}; + +const op = new EvmNetwork(opOptions); + +export default op; diff --git a/packages/extension/src/providers/ethereum/networks/rin.ts b/packages/extension/src/providers/ethereum/networks/rin.ts index 43cbdf689..47a96dcf8 100644 --- a/packages/extension/src/providers/ethereum/networks/rin.ts +++ b/packages/extension/src/providers/ethereum/networks/rin.ts @@ -9,9 +9,10 @@ const rinOptions: EvmNetworkOptions = { homePage: "https://www.rinkeby.io/", blockExplorerTX: "https://rinkeby.etherscan.io/tx/[[txHash]]", blockExplorerAddr: "https://rinkeby.etherscan.io/address/[[address]]", - chainID: 4, + chainID: "0x4", isTestNetwork: true, currencyName: "RIN", + currencyNameLong: "Rinkeby", node: "wss://nodes.mewapi.io/ws/rinkeby", icon: require("./icons/eth.svg"), gradient: "linear-gradient(180deg, #C549FF 0%, #684CFF 100%)", diff --git a/packages/extension/src/providers/ethereum/networks/rop.ts b/packages/extension/src/providers/ethereum/networks/rop.ts index 1773a7fd6..bd64a3e4c 100644 --- a/packages/extension/src/providers/ethereum/networks/rop.ts +++ b/packages/extension/src/providers/ethereum/networks/rop.ts @@ -9,9 +9,10 @@ const ropOptions: EvmNetworkOptions = { homePage: "https://github.com/ethereum/ropsten", blockExplorerTX: "https://ropsten.etherscan.io/tx/[[txHash]]", blockExplorerAddr: "https://ropsten.etherscan.io/address/[[address]]", - chainID: 3, + chainID: "0x3", isTestNetwork: true, currencyName: "ROP", + currencyNameLong: "Ropsten", node: "wss://nodes.mewapi.io/ws/rop", icon: require("./icons/eth.svg"), basePath: "m/44'/1'/0'/0", diff --git a/packages/extension/src/providers/ethereum/networks/sdn.ts b/packages/extension/src/providers/ethereum/networks/sdn.ts index 250c613ae..b93445da9 100644 --- a/packages/extension/src/providers/ethereum/networks/sdn.ts +++ b/packages/extension/src/providers/ethereum/networks/sdn.ts @@ -9,9 +9,10 @@ const sdnOptions: EvmNetworkOptions = { homePage: "https://shiden.astar.network/", blockExplorerTX: "https://blockscout.com/shiden/tx/[[txHash]]", blockExplorerAddr: "https://blockscout.com/shiden/address/[[address]]", - chainID: 336, + chainID: "0x150", isTestNetwork: false, currencyName: "SDN", + currencyNameLong: "Shiden", node: "wss://shiden.public.blastapi.io", icon: require("./icons/sdn.png"), gradient: "linear-gradient(180deg, #C549FF 0%, #684CFF 100%)", diff --git a/packages/extension/src/providers/ethereum/types/evm-network.ts b/packages/extension/src/providers/ethereum/types/evm-network.ts index edbeb740c..169162943 100644 --- a/packages/extension/src/providers/ethereum/types/evm-network.ts +++ b/packages/extension/src/providers/ethereum/types/evm-network.ts @@ -26,9 +26,10 @@ export interface EvmNetworkOptions { homePage: string; blockExplorerTX: string; blockExplorerAddr: string; - chainID: number; + chainID: `0x${string}`; isTestNetwork: boolean; currencyName: string; + currencyNameLong: string; node: string; icon: string; gradient: string; @@ -51,7 +52,7 @@ export interface EvmNetworkOptions { } export class EvmNetwork extends BaseNetwork { - public chainID: number; + public chainID: `0x${string}`; private assetsInfoHandler?: ( network: BaseNetwork, @@ -131,8 +132,8 @@ export class EvmNetwork extends BaseNetwork { fromBase(balance, this.decimals) ).times(nativeMarketData?.current_price ?? 0); const nativeAsset: AssetsType = { - name: this.name_long, - symbol: this.name, + name: this.currencyNameLong, + symbol: this.currencyName, icon: this.icon, balance, balancef: formatFloatingPointValue(fromBase(balance, this.decimals)) @@ -208,10 +209,15 @@ export class EvmNetwork extends BaseNetwork { return true; }) as CustomErc20Token[]; - return erc20Tokens.map( - ({ name, symbol, address, icon, decimals }) => - new Erc20Token({ name, symbol, contract: address, icon, decimals }) - ); + return erc20Tokens.map(({ name, symbol, address, icon, decimals }) => { + return new Erc20Token({ + name, + symbol, + contract: address, + icon, + decimals, + }); + }); }); const balancePromises = customTokens.map((token) => @@ -238,7 +244,7 @@ export class EvmNetwork extends BaseNetwork { balanceUSDf: "0", value: "0", valuef: "0", - decimals: this.decimals, + decimals: token.decimals, sparkline: "", priceChangePercentage: 0, icon: token.icon, @@ -247,9 +253,9 @@ export class EvmNetwork extends BaseNetwork { const marketInfo = marketInfos[token.contract.toLowerCase()]; if (marketInfo) { - const usdBalance = new BigNumber(token.balance ?? "0").times( - marketInfo.current_price - ); + const usdBalance = new BigNumber( + fromBase(token.balance ?? "0", token.decimals) + ).times(marketInfo.current_price); asset.balanceUSD = usdBalance.toNumber(); asset.balanceUSDf = formatFiatValue(usdBalance.toString()).value; asset.value = marketInfo.current_price.toString(); diff --git a/packages/extension/src/providers/ethereum/types/index.ts b/packages/extension/src/providers/ethereum/types/index.ts index 119c520ed..0bf74229c 100644 --- a/packages/extension/src/providers/ethereum/types/index.ts +++ b/packages/extension/src/providers/ethereum/types/index.ts @@ -52,7 +52,7 @@ export interface EthereumRequest { export interface EthereumNodeType extends NodeType { signer: [SignerType.secp256k1]; - chainID: number; + chainID: `0x${string}`; } export interface ERC20TokenInfo { diff --git a/packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue b/packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue index ac0a780e8..c8477db68 100644 --- a/packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue +++ b/packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue @@ -157,6 +157,7 @@ import { Activity, ActivityStatus, ActivityType } from "@/types/activity"; import { generateAddress } from "ethereumjs-util"; import ActivityState from "@/libs/activity-state"; import { bigIntToBuffer } from "@enkryptcom/utils"; +import broadcastTx from "../libs/tx-broadcaster"; const isProcessing = ref(false); const isOpenSelectFee = ref(false); @@ -280,62 +281,66 @@ const approve = async () => { account: account.value, network: network.value, payload: finalizedTx, - }) - .then((tx) => { - const txActivity: Activity = { - from: account.value.address, - to: tx.to - ? tx.to.toString() - : `0x${generateAddress( - tx.getSenderAddress().toBuffer(), - bigIntToBuffer(tx.nonce) - ).toString("hex")}`, - isIncoming: tx.getSenderAddress().toString() === tx.to?.toString(), - network: network.value.name, - status: ActivityStatus.pending, - timestamp: new Date().getTime(), - token: { - decimals: decodedTx.value?.tokenDecimals || 18, - icon: decodedTx.value?.tokenImage || "", - name: decodedTx.value?.tokenName || "Unknown", - symbol: decodedTx.value?.tokenSymbol || "UKNWN", - price: decodedTx.value?.currentPriceUSD.toString() || "0", - }, - type: ActivityType.transaction, - value: decodedTx.value?.tokenValue || "0x0", - transactionHash: "", - }; - web3 - .sendSignedTransaction("0x" + tx.serialize().toString("hex")) - .on("transactionHash", (hash) => { - activityState - .addActivities( - [{ ...txActivity, ...{ transactionHash: hash } }], - { address: txActivity.from, network: network.value.name } - ) - .then(() => { - Resolve.value({ - result: JSON.stringify(hash), - }); - }); + }).then((tx) => { + const txActivity: Activity = { + from: account.value.address, + to: tx.to + ? tx.to.toString() + : `0x${generateAddress( + tx.getSenderAddress().toBuffer(), + bigIntToBuffer(tx.nonce) + ).toString("hex")}`, + isIncoming: tx.getSenderAddress().toString() === tx.to?.toString(), + network: network.value.name, + status: ActivityStatus.pending, + timestamp: new Date().getTime(), + token: { + decimals: decodedTx.value?.tokenDecimals || 18, + icon: decodedTx.value?.tokenImage || "", + name: decodedTx.value?.tokenName || "Unknown", + symbol: decodedTx.value?.tokenSymbol || "UKNWN", + price: decodedTx.value?.currentPriceUSD.toString() || "0", + }, + type: ActivityType.transaction, + value: decodedTx.value?.tokenValue || "0x0", + transactionHash: "", + }; + const onHash = (hash: string) => { + activityState + .addActivities([{ ...txActivity, ...{ transactionHash: hash } }], { + address: txActivity.from, + network: network.value.name, }) - .on("error", (error) => { - txActivity.status = ActivityStatus.failed; - activityState - .addActivities([txActivity], { - address: txActivity.from, - network: network.value.name, - }) - .then(() => { - Resolve.value({ - error: getCustomError(error.message), - }); - }); + .then(() => { + Resolve.value({ + result: JSON.stringify(hash), + }); }); - }) - .catch((err) => { - Resolve.value(err); - }); + }; + broadcastTx("0x" + tx.serialize().toString("hex"), network.value.name) + .then(onHash) + .catch(() => { + web3 + .sendSignedTransaction("0x" + tx.serialize().toString("hex")) + .on("transactionHash", onHash) + .on("error", (error) => { + txActivity.status = ActivityStatus.failed; + activityState + .addActivities([txActivity], { + address: txActivity.from, + network: network.value.name, + }) + .then(() => { + Resolve.value({ + error: getCustomError(error.message), + }); + }); + }); + }) + .catch((err) => { + Resolve.value(err); + }); + }); } ); }; diff --git a/packages/extension/src/providers/ethereum/ui/send-transaction/index.vue b/packages/extension/src/providers/ethereum/ui/send-transaction/index.vue index 0dc21331e..7e2042764 100644 --- a/packages/extension/src/providers/ethereum/ui/send-transaction/index.vue +++ b/packages/extension/src/providers/ethereum/ui/send-transaction/index.vue @@ -259,7 +259,7 @@ const TxInfo = computed(() => { ) .encodeABI(); return { - chainId: numberToHex(props.network.chainID) as `0x{string}`, + chainId: props.network.chainID, from: addressFrom.value as `0x{string}`, value: value as `0x${string}`, to: toAddress as `0x${string}`, @@ -349,7 +349,7 @@ const setBaseCosts = () => { const web3 = new Web3Eth(props.network.node); const tx = new Transaction( { - chainId: numberToHex(props.network.chainID) as `0x{string}`, + chainId: props.network.chainID, from: props.accountInfo.selectedAccount!.address as `0x{string}`, value: "0x0", to: NATIVE_TOKEN_ADDRESS, diff --git a/packages/extension/src/providers/ethereum/ui/send-transaction/verify-transaction/index.vue b/packages/extension/src/providers/ethereum/ui/send-transaction/verify-transaction/index.vue index 8995b4d3a..673197fc9 100644 --- a/packages/extension/src/providers/ethereum/ui/send-transaction/verify-transaction/index.vue +++ b/packages/extension/src/providers/ethereum/ui/send-transaction/verify-transaction/index.vue @@ -95,6 +95,7 @@ import { ActivityStatus, Activity, ActivityType } from "@/types/activity"; import ActivityState from "@/libs/activity-state"; import { EnkryptAccount } from "@enkryptcom/types"; import CustomScrollbar from "@action/components/custom-scrollbar/index.vue"; +import broadcastTx from "@/providers/ethereum/libs/tx-broadcaster"; const KeyRing = new PublicKeyRing(); const route = useRoute(); @@ -149,6 +150,24 @@ const sendAction = async () => { transactionHash: "", }; const activityState = new ActivityState(); + const onHash = (hash: string) => { + activityState.addActivities( + [{ ...txActivity, ...{ transactionHash: hash } }], + { address: txData.fromAddress, network: network.name } + ); + isSendDone.value = true; + if (getCurrentContext() === "popup") { + setTimeout(() => { + isProcessing.value = false; + router.go(-2); + }, 4500); + } else { + setTimeout(() => { + isProcessing.value = false; + window.close(); + }, 1500); + } + }; await tx .getFinalizedTransaction({ gasPriceType: txData.gasPriceType }) .then(async (finalizedTx) => { @@ -156,42 +175,30 @@ const sendAction = async () => { account: account.value!, network, payload: finalizedTx, - }) - .then((signedTx) => { - web3 - .sendSignedTransaction("0x" + signedTx.serialize().toString("hex")) - .on("transactionHash", (hash: string) => { - activityState.addActivities( - [{ ...txActivity, ...{ transactionHash: hash } }], - { address: txData.fromAddress, network: network.name } - ); - isSendDone.value = true; - if (getCurrentContext() === "popup") { - setTimeout(() => { - isProcessing.value = false; - router.go(-2); - }, 4500); - } else { - setTimeout(() => { - isProcessing.value = false; - window.close(); - }, 1500); - } - }) - .on("error", (error: any) => { - txActivity.status = ActivityStatus.failed; - activityState.addActivities([txActivity], { - address: txData.fromAddress, - network: network.name, + }).then((signedTx) => { + broadcastTx("0x" + signedTx.serialize().toString("hex"), network.name) + .then(onHash) + .catch(() => { + web3 + .sendSignedTransaction( + "0x" + signedTx.serialize().toString("hex") + ) + .on("transactionHash", onHash) + .on("error", (error: any) => { + txActivity.status = ActivityStatus.failed; + activityState.addActivities([txActivity], { + address: txData.fromAddress, + network: network.name, + }); + console.error("ERROR", error); }); - console.error("ERROR", error); - }); - }) - .catch((error) => { - isProcessing.value = false; - console.error("error", error); - errorMsg.value = JSON.stringify(error); - }); + }) + .catch((error) => { + isProcessing.value = false; + console.error("error", error); + errorMsg.value = JSON.stringify(error); + }); + }); }); }; const isHasScroll = () => { diff --git a/packages/extension/src/providers/polkadot/index.ts b/packages/extension/src/providers/polkadot/index.ts index 1b6d68661..88b537053 100644 --- a/packages/extension/src/providers/polkadot/index.ts +++ b/packages/extension/src/providers/polkadot/index.ts @@ -36,6 +36,7 @@ class PolkadotProvider this.middlewares = Middlewares.map((mw) => mw.bind(this)); } setRequestProvider(network: BaseNetwork): void { + this.requestProvider.disconnect(); this.requestProvider.changeNetwork(network.node); } request(request: ProviderRPCRequest): Promise { diff --git a/packages/extension/src/providers/polkadot/libs/activity-handlers/providers/subscan/configs.ts b/packages/extension/src/providers/polkadot/libs/activity-handlers/providers/subscan/configs.ts index 28fe06bb3..17fb554bd 100644 --- a/packages/extension/src/providers/polkadot/libs/activity-handlers/providers/subscan/configs.ts +++ b/packages/extension/src/providers/polkadot/libs/activity-handlers/providers/subscan/configs.ts @@ -8,6 +8,8 @@ const NetworkEndpoints = { [NetworkNames.Karura]: "https://karura.api.subscan.io/", [NetworkNames.Astar]: "https://astar.api.subscan.io/", [NetworkNames.Shiden]: "https://shiden.api.subscan.io/", + [NetworkNames.Bifrost]: "https://bifrost.api.subscan.io/", + [NetworkNames.BifrostKusama]: "https://bifrost-kusama.api.subscan.io/", }; export { NetworkEndpoints }; diff --git a/packages/extension/src/providers/polkadot/libs/activity-handlers/providers/subscan/index.ts b/packages/extension/src/providers/polkadot/libs/activity-handlers/providers/subscan/index.ts index 3a2f31082..325b443e4 100644 --- a/packages/extension/src/providers/polkadot/libs/activity-handlers/providers/subscan/index.ts +++ b/packages/extension/src/providers/polkadot/libs/activity-handlers/providers/subscan/index.ts @@ -54,7 +54,7 @@ export default async ( token: { decimals: network.decimals, icon: network.icon, - name: network.name_long, + name: network.currencyNameLong, symbol: activity.asset_symbol !== "" ? activity.asset_symbol diff --git a/packages/extension/src/providers/polkadot/networks/acala/acala.ts b/packages/extension/src/providers/polkadot/networks/acala/acala.ts index d04a9b788..4ebaa0017 100644 --- a/packages/extension/src/providers/polkadot/networks/acala/acala.ts +++ b/packages/extension/src/providers/polkadot/networks/acala/acala.ts @@ -17,6 +17,7 @@ const acalaOptions: SubstrateNetworkOptions = { blockExplorerAddr: "https://acala.subscan.io/account/[[address]]", isTestNetwork: false, currencyName: "ACA", + currencyNameLong: "Acala", icon: require("../icons/acala.svg"), decimals: 12, prefix: 12, diff --git a/packages/extension/src/providers/polkadot/networks/acala/karura.ts b/packages/extension/src/providers/polkadot/networks/acala/karura.ts index 40b355663..42be71096 100644 --- a/packages/extension/src/providers/polkadot/networks/acala/karura.ts +++ b/packages/extension/src/providers/polkadot/networks/acala/karura.ts @@ -16,6 +16,7 @@ const karuraOptions: SubstrateNetworkOptions = { blockExplorerAddr: "https://karura.subscan.io/account/[[address]]", isTestNetwork: false, currencyName: "KAR", + currencyNameLong: "Karura", icon: require("../icons/karura.svg"), decimals: 12, prefix: 8, diff --git a/packages/extension/src/providers/polkadot/networks/acala/libs/assetinfo-orml.ts b/packages/extension/src/providers/polkadot/networks/acala/libs/assetinfo-orml.ts index f7bbf59d8..7f72cd55f 100644 --- a/packages/extension/src/providers/polkadot/networks/acala/libs/assetinfo-orml.ts +++ b/packages/extension/src/providers/polkadot/networks/acala/libs/assetinfo-orml.ts @@ -130,7 +130,7 @@ export default async ( }); const nativeAsset = new SubstrateNativeToken({ - name: network.name_long, + name: network.currencyNameLong, symbol: network.name, decimals: network.decimals, existentialDeposit: network.existentialDeposit, diff --git a/packages/extension/src/providers/polkadot/networks/astar/astar.ts b/packages/extension/src/providers/polkadot/networks/astar/astar.ts index 9db8cc40f..bc6d1ce42 100644 --- a/packages/extension/src/providers/polkadot/networks/astar/astar.ts +++ b/packages/extension/src/providers/polkadot/networks/astar/astar.ts @@ -17,6 +17,7 @@ const astarOptions: SubstrateNetworkOptions = { blockExplorerAddr: "https://astar.subscan.io/account/[[address]]", isTestNetwork: false, currencyName: "ASTR", + currencyNameLong: "Astar", icon: require("../icons/astar.png"), decimals: 18, prefix: 5, diff --git a/packages/extension/src/providers/polkadot/networks/astar/libs/assetinfo.ts b/packages/extension/src/providers/polkadot/networks/astar/libs/assetinfo.ts index 8941d825c..73edbcbe9 100644 --- a/packages/extension/src/providers/polkadot/networks/astar/libs/assetinfo.ts +++ b/packages/extension/src/providers/polkadot/networks/astar/libs/assetinfo.ts @@ -106,7 +106,7 @@ export default async ( } const nativeAsset = new SubstrateNativeToken({ - name: network.name_long, + name: network.currencyNameLong, symbol: network.name, decimals: network.decimals, existentialDeposit: network.existentialDeposit, diff --git a/packages/extension/src/providers/polkadot/networks/astar/shiden.ts b/packages/extension/src/providers/polkadot/networks/astar/shiden.ts index 686d4da79..4b615082a 100644 --- a/packages/extension/src/providers/polkadot/networks/astar/shiden.ts +++ b/packages/extension/src/providers/polkadot/networks/astar/shiden.ts @@ -17,6 +17,7 @@ const shidenOptions: SubstrateNetworkOptions = { blockExplorerAddr: "https://shiden.subscan.io/account/[[address]]", isTestNetwork: false, currencyName: "SDN", + currencyNameLong: "Shiden", icon: require("../icons/shiden.png"), decimals: 18, prefix: 5, diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/bifrost-assets.ts b/packages/extension/src/providers/polkadot/networks/bifrost/assets/bifrost-assets.ts new file mode 100644 index 000000000..4f3dd31a5 --- /dev/null +++ b/packages/extension/src/providers/polkadot/networks/bifrost/assets/bifrost-assets.ts @@ -0,0 +1,72 @@ +import { KnownTokenDisplay } from "@/providers/polkadot/types"; + +const assets: KnownTokenDisplay[] = [ + { + name: "Bifrost", + symbol: "BNC", + coingeckoID: "bifrost-native-coin", + icon: require("./icons/BNC.png"), + }, + { + name: "Polkadot", + symbol: "DOT", + coingeckoID: "polkadot", + icon: require("../../icons/polkadot.svg"), + }, + { + name: "Kusama", + symbol: "KSM", + coingeckoID: "kusama", + icon: require("../../icons/kusama.svg"), + }, + { + name: "Acala Dollar", + symbol: "aUSD", + icon: require("./icons/AUSD.png"), + coingeckoID: "acala-dollar", + }, + { + name: "Moonriver", + symbol: "MOVR", + icon: require("./icons/MOVR.png"), + coingeckoID: "moonriver", + }, + { + name: "Karura", + symbol: "KAR", + icon: require("./icons/KAR.png"), + coingeckoID: "karura", + }, + { + name: "RMRK", + symbol: "RMRK", + icon: require("./icons/RMRK.png"), + coingeckoID: "rmrk", + }, + { + name: "Zenlink", + symbol: "ZLK", + icon: require("./icons/ZLK.png"), + coingeckoID: "zenlink-network-token", + }, + { + name: "USDT", + symbol: "USDT", + icon: require("./icons/USDT.png"), + coingeckoID: "usdt", + }, + { + name: "Turing Network", + symbol: "TUR", + icon: require("./icons/TUR.png"), + coingeckoID: "", + }, + { + name: "Darwinia Crab", + symbol: "CRAB", + icon: require("./icons/CRAB.png"), + coingeckoID: "", + }, +]; + +export default assets; diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/AUSD.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/AUSD.png new file mode 100644 index 000000000..085636783 Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/AUSD.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/BNC.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/BNC.png new file mode 100644 index 000000000..002ca36a8 Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/BNC.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/CRAB.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/CRAB.png new file mode 100644 index 000000000..7a92a0efb Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/CRAB.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/CSM.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/CSM.png new file mode 100644 index 000000000..24a357e30 Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/CSM.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/KAR.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/KAR.png new file mode 100644 index 000000000..b10943944 Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/KAR.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/KSM.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/KSM.png new file mode 100644 index 000000000..00dd41637 Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/KSM.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/MOVR.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/MOVR.png new file mode 100644 index 000000000..40ba8a7c6 Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/MOVR.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/PHA.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/PHA.png new file mode 100644 index 000000000..250065ef1 Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/PHA.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/RMRK.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/RMRK.png new file mode 100644 index 000000000..12513dc5b Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/RMRK.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/TUR.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/TUR.png new file mode 100644 index 000000000..05799bb22 Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/TUR.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/USDT.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/USDT.png new file mode 100644 index 000000000..b5733e33e Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/USDT.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/ZLK.png b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/ZLK.png new file mode 100644 index 000000000..99f67c908 Binary files /dev/null and b/packages/extension/src/providers/polkadot/networks/bifrost/assets/icons/ZLK.png differ diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/kusama.ts b/packages/extension/src/providers/polkadot/networks/bifrost/kusama.ts new file mode 100644 index 000000000..7751dab15 --- /dev/null +++ b/packages/extension/src/providers/polkadot/networks/bifrost/kusama.ts @@ -0,0 +1,39 @@ +import assetHandler from "./libs/assetinfo-orml"; +import { CoingeckoPlatform, NetworkNames } from "@enkryptcom/types"; +import assets from "./assets/bifrost-assets"; +import { + SubstrateNetwork, + SubstrateNetworkOptions, +} from "../../types/substrate-network"; +import { subscanActivity } from "../../libs/activity-handlers"; +import wrapActivityHandler from "@/libs/activity-state/wrap-activity-handler"; +import { toBN } from "web3-utils"; + +const bifrostKusamaOptions: SubstrateNetworkOptions = { + name: NetworkNames.BifrostKusama, + name_long: "Bifrost (Kusama)", + homePage: "https://bifrost.finance/", + blockExplorerTX: "https://bifrost-kusama.subscan.io/extrinsic/[[txHash]]", + blockExplorerAddr: "https://bifrost-kusama.subscan.io/account/[[address]]", + isTestNetwork: false, + currencyName: "BNC", + currencyNameLong: "Kusama Bifrost", + icon: require("../icons/bifrost.svg"), + decimals: 12, + prefix: 6, + gradient: + "linear-gradient(326.87deg, #5a25f0 12.53%, #5a25f0 50.89%, #5a25f0 89.24%)", + node: "wss://bifrost-rpc.liebi.com/ws", + coingeckoID: "bifrost-native-coin", + coingeckoPlatform: CoingeckoPlatform.Bifrost, + genesisHash: + "0x9f28c6a68e0fc9646eff64935684f6eeeece527e37bbe1f213d22caa1d9d6bed", + activityHandler: wrapActivityHandler(subscanActivity), + assetHandler: assetHandler, + knownTokens: assets, + existentialDeposit: toBN("100000000000"), +}; + +const bifrostKusama = new SubstrateNetwork(bifrostKusamaOptions); + +export default bifrostKusama; diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/libs/assetinfo-orml.ts b/packages/extension/src/providers/polkadot/networks/bifrost/libs/assetinfo-orml.ts new file mode 100644 index 000000000..6dc9a8148 --- /dev/null +++ b/packages/extension/src/providers/polkadot/networks/bifrost/libs/assetinfo-orml.ts @@ -0,0 +1,160 @@ +import API from "@/providers/polkadot/libs/api"; +import { SubstrateNetwork } from "@/providers/polkadot/types/substrate-network"; +import { hexToString, hexToBn } from "@polkadot/util"; +import { + BifrostOrmlAsset, + BifrostOrmlAssetOptions, + OrmlAssetType, +} from "../types/bifrost-orml-asset"; +import { OrmlTokensAccountData } from "@acala-network/types/interfaces/types-lookup"; +import { toBN } from "web3-utils"; +import { KnownTokenDisplay } from "@/providers/polkadot/types"; +import { SubstrateNativeToken } from "@/providers/polkadot/types/substrate-native-token"; + +type AssetMetadata = { + name: `0x${string}`; + symbol: `0x${string}`; + decimals: number; + minimalBalance: number | `0x${string}`; +}; + +type NativeAsset = Record; + +type ForeignAsset = string; + +type StableAsset = string; + +type Erc20 = string; + +enum AssetIds { + NATIVE_ASSET = "NativeAssetId", + FOREIGN_ASSET = "ForeignAssetId", + STABLE_ASSET = "StableAssetId", + ERC20_ASSET = "Erc20", +} + +type AssetKey = Record< + AssetIds, + NativeAsset | ForeignAsset | StableAsset | Erc20 +>; + +export default async ( + network: SubstrateNetwork, + address: string | null, + knownTokens?: KnownTokenDisplay[] +) => { + const api = (await network.api()) as API; + + const apiPromise = api.api; + + const metadata = + await apiPromise.query.assetRegistry.assetMetadatas.entries(); + + const assets = metadata + .map(([key, value]) => { + const assetKey = (key.toHuman() as [AssetKey])[0]; + const assetMetadata = value.toJSON() as AssetMetadata; + const decimals = assetMetadata.decimals; + const minimalBalance = + typeof assetMetadata.minimalBalance === "string" + ? hexToBn(assetMetadata.minimalBalance) + : toBN(assetMetadata.minimalBalance); + + let assetLookupId: OrmlAssetType | null = null; + let assetLookupValue: string | null = null; + + if (assetKey[AssetIds.FOREIGN_ASSET]) { + assetLookupId = "foreignAsset"; + assetLookupValue = assetKey[AssetIds.FOREIGN_ASSET] as string; + } else if (assetKey[AssetIds.NATIVE_ASSET]) { + assetLookupId = Object.keys( + assetKey[AssetIds.NATIVE_ASSET] + )[0] as "token"; + + assetLookupValue = (assetKey[AssetIds.NATIVE_ASSET] as NativeAsset)[ + assetLookupId + ] as string; + } else if (assetKey[AssetIds.STABLE_ASSET]) { + assetLookupId = "stableAssetPoolToken"; + assetLookupValue = assetKey[AssetIds.STABLE_ASSET] as string; + } else if (assetKey[AssetIds.ERC20_ASSET]) { + // TODO add Erc20 support, required special RPC call + } + + if (assetLookupId && assetLookupValue) { + const assetInfo = { + name: assetMetadata.name, + symbol: assetMetadata.symbol, + decimals, + minimalBalance, + assetLookupId, + assetLookupValue, + }; + + return assetInfo; + } else { + // Unhandled token types, right now just Erc20 + return null; + } + }) + .filter((asset) => asset !== null); + + const tokenOptions: BifrostOrmlAssetOptions[] = assets + .map((asset) => { + const ormlOptions: BifrostOrmlAssetOptions = { + name: hexToString(asset!.name), + symbol: hexToString(asset!.symbol), + existentialDeposit: asset!.minimalBalance, + assetType: asset!.assetLookupId, + lookupValue: asset!.assetLookupValue, + icon: network.icon, + decimals: asset!.decimals, + }; + + return ormlOptions; + }) + .map((tokenOptions) => { + if (knownTokens) { + const knownToken = knownTokens.find( + (knownToken) => + knownToken.name === tokenOptions.name && + knownToken.symbol === tokenOptions.symbol + ); + + if (knownToken) { + tokenOptions.coingeckoID = knownToken.coingeckoID; + tokenOptions.icon = knownToken.icon; + } + } + return tokenOptions; + }); + + const nativeAsset = new SubstrateNativeToken({ + name: network.currencyNameLong, + symbol: network.name, + decimals: network.decimals, + existentialDeposit: network.existentialDeposit, + icon: network.icon, + coingeckoID: network.coingeckoID, + }); + + if (address) { + await nativeAsset.getLatestUserBalance(apiPromise, address); + const queries = tokenOptions.map((asset) => { + const token = { [asset.assetType]: asset.lookupValue }; + const query = [address, token]; + + return query; + }); + + const tokenBalances = await apiPromise.query.tokens.accounts.multi(queries); + + tokenBalances.forEach((tokenData, index) => { + const data = tokenData as unknown as OrmlTokensAccountData; + + tokenOptions[index].balance = data.free.toString(); + }); + } + + return [nativeAsset, ...tokenOptions.map((o) => new BifrostOrmlAsset(o))]; +}; diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/polkadot.ts b/packages/extension/src/providers/polkadot/networks/bifrost/polkadot.ts new file mode 100644 index 000000000..4984c8d2e --- /dev/null +++ b/packages/extension/src/providers/polkadot/networks/bifrost/polkadot.ts @@ -0,0 +1,39 @@ +import assetHandler from "./libs/assetinfo-orml"; +import { CoingeckoPlatform, NetworkNames } from "@enkryptcom/types"; +import assets from "./assets/bifrost-assets"; +import { + SubstrateNetwork, + SubstrateNetworkOptions, +} from "../../types/substrate-network"; +import { subscanActivity } from "../../libs/activity-handlers"; +import wrapActivityHandler from "@/libs/activity-state/wrap-activity-handler"; +import { toBN } from "web3-utils"; + +const bifrostPolkadotOptions: SubstrateNetworkOptions = { + name: NetworkNames.Bifrost, + name_long: "Bifrost", + homePage: "https://bifrost.finance/", + blockExplorerTX: "https://bifrost.subscan.io/extrinsic/[[txHash]]", + blockExplorerAddr: "https://bifrost.subscan.io/account/[[address]]", + isTestNetwork: false, + currencyName: "BNC", + currencyNameLong: "Bifrost", + icon: require("../icons/bifrost.svg"), + decimals: 12, + prefix: 6, + gradient: + "linear-gradient(326.87deg, #5a25f0 12.53%, #5a25f0 50.89%, #5a25f0 89.24%)", + node: "wss://hk.p.bifrost-rpc.liebi.com/ws", + coingeckoID: "bifrost-native-coin", + coingeckoPlatform: CoingeckoPlatform.Bifrost, + genesisHash: + "0x262e1b2ad728475fd6fe88e62d34c200abe6fd693931ddad144059b1eb884e5b", + activityHandler: wrapActivityHandler(subscanActivity), + assetHandler: assetHandler, + knownTokens: assets, + existentialDeposit: toBN("100000000000"), +}; + +const bifrostPolkadot = new SubstrateNetwork(bifrostPolkadotOptions); + +export default bifrostPolkadot; diff --git a/packages/extension/src/providers/polkadot/networks/bifrost/types/bifrost-orml-asset.ts b/packages/extension/src/providers/polkadot/networks/bifrost/types/bifrost-orml-asset.ts new file mode 100644 index 000000000..298122183 --- /dev/null +++ b/packages/extension/src/providers/polkadot/networks/bifrost/types/bifrost-orml-asset.ts @@ -0,0 +1,54 @@ +import { ApiPromise } from "@polkadot/api"; +import { OrmlTokensAccountData } from "@acala-network/types/interfaces/types-lookup"; +import { SubmittableExtrinsic } from "@polkadot/api/types"; +import { ISubmittableResult } from "@polkadot/types/types"; +import { SubstrateToken } from "@/providers/polkadot/types/substrate-token"; +import { BaseTokenOptions } from "@/types/base-token"; + +export type OrmlAssetType = + | "token" + | "foreignAsset" + | "stableAssetPoolToken" + | "liquidCrowdloan"; + +export interface BifrostOrmlAssetOptions extends BaseTokenOptions { + assetType: OrmlAssetType; + lookupValue: string | number; +} + +export class BifrostOrmlAsset extends SubstrateToken { + public assetType: OrmlAssetType; + public lookupValue: string | number; + + constructor(options: BifrostOrmlAssetOptions) { + super(options); + + this.assetType = options.assetType; + this.lookupValue = options.lookupValue; + } + + public async getLatestUserBalance( + api: ApiPromise, + address: any + ): Promise { + const tokenLookup: Record = {}; + tokenLookup[this.assetType] = this.lookupValue; + + return api.query.tokens.accounts(address, tokenLookup).then((res) => { + const balance = (res as unknown as OrmlTokensAccountData).free.toString(); + this.balance = balance; + return balance; + }); + } + + public async send( + api: ApiPromise, + to: string, + amount: string + ): Promise> { + const currencyId: Record = {}; + currencyId[this.assetType] = this.lookupValue; + + return (api as ApiPromise).tx.currencies.transfer(to, currencyId, amount); + } +} diff --git a/packages/extension/src/providers/polkadot/networks/icons/bifrost.svg b/packages/extension/src/providers/polkadot/networks/icons/bifrost.svg new file mode 100644 index 000000000..3f2a9b5e1 --- /dev/null +++ b/packages/extension/src/providers/polkadot/networks/icons/bifrost.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/packages/extension/src/providers/polkadot/networks/index.ts b/packages/extension/src/providers/polkadot/networks/index.ts index b5386e93f..d05d7e7ba 100644 --- a/packages/extension/src/providers/polkadot/networks/index.ts +++ b/packages/extension/src/providers/polkadot/networks/index.ts @@ -5,6 +5,8 @@ import karNode from "./acala/karura"; import wndNode from "./westend"; import astrNode from "./astar/astar"; import sdnNode from "./astar/shiden"; +import bncNode from "./bifrost/polkadot"; +import bncKusamaNode from "./bifrost/kusama"; export default { acala: acaNode, @@ -14,4 +16,6 @@ export default { westend: wndNode, astar: astrNode, shiden: sdnNode, + bifrost: bncNode, + bifrostKusama: bncKusamaNode, }; diff --git a/packages/extension/src/providers/polkadot/networks/kusama.ts b/packages/extension/src/providers/polkadot/networks/kusama.ts index 1279f5118..40b4424a7 100644 --- a/packages/extension/src/providers/polkadot/networks/kusama.ts +++ b/packages/extension/src/providers/polkadot/networks/kusama.ts @@ -15,6 +15,7 @@ const ksmOptions: SubstrateNetworkOptions = { blockExplorerAddr: "https://kusama.subscan.io/account/[[address]]", isTestNetwork: false, currencyName: "KSM", + currencyNameLong: "Kusama", icon: require("./icons/kusama.svg"), decimals: 12, prefix: 2, diff --git a/packages/extension/src/providers/polkadot/networks/polkadot.ts b/packages/extension/src/providers/polkadot/networks/polkadot.ts index 28ef04547..e24b8da74 100644 --- a/packages/extension/src/providers/polkadot/networks/polkadot.ts +++ b/packages/extension/src/providers/polkadot/networks/polkadot.ts @@ -15,6 +15,7 @@ const polkadotOptions: SubstrateNetworkOptions = { blockExplorerAddr: "https://polkadot.subscan.io/account/[[address]]", isTestNetwork: false, currencyName: "DOT", + currencyNameLong: "Polkadot", icon: require("./icons/polkadot.svg"), decimals: 10, prefix: 0, diff --git a/packages/extension/src/providers/polkadot/networks/westend.ts b/packages/extension/src/providers/polkadot/networks/westend.ts index 9c7b93538..51ef1b9f6 100644 --- a/packages/extension/src/providers/polkadot/networks/westend.ts +++ b/packages/extension/src/providers/polkadot/networks/westend.ts @@ -15,6 +15,7 @@ const wndOptions: SubstrateNetworkOptions = { blockExplorerAddr: "https://westend.subscan.io/extrinsic/[[address]]", isTestNetwork: true, currencyName: "WND", + currencyNameLong: "Westend", icon: require("./icons/westend.svg"), decimals: 12, prefix: 42, diff --git a/packages/extension/src/providers/polkadot/types/substrate-network.ts b/packages/extension/src/providers/polkadot/types/substrate-network.ts index 8adaa4358..e37c9d2a8 100644 --- a/packages/extension/src/providers/polkadot/types/substrate-network.ts +++ b/packages/extension/src/providers/polkadot/types/substrate-network.ts @@ -28,6 +28,7 @@ export interface SubstrateNetworkOptions { blockExplorerAddr: string; isTestNetwork: boolean; currencyName: string; + currencyNameLong: string; icon: string; decimals: number; prefix: number; @@ -105,7 +106,7 @@ export class SubstrateNetwork extends BaseNetwork { return Promise.resolve(this.assets); } else { const nativeToken = new SubstrateNativeToken({ - name: this.name_long, + name: this.currencyNameLong, symbol: this.name, coingeckoID: this.coingeckoID, decimals: this.decimals, @@ -124,7 +125,7 @@ export class SubstrateNetwork extends BaseNetwork { if (supported.length === 0) { const nativeToken = new SubstrateNativeToken({ - name: this.name_long, + name: this.currencyNameLong, symbol: this.name, coingeckoID: this.coingeckoID, decimals: this.decimals, diff --git a/packages/extension/src/providers/polkadot/ui/custom-views/mappings/acala.ts b/packages/extension/src/providers/polkadot/ui/custom-views/mappings/acala.ts index d78db0a5c..63896668d 100644 --- a/packages/extension/src/providers/polkadot/ui/custom-views/mappings/acala.ts +++ b/packages/extension/src/providers/polkadot/ui/custom-views/mappings/acala.ts @@ -57,7 +57,7 @@ const transferNativeCurrency = ( const token = new SubstrateNativeToken({ decimals: network.decimals, icon: network.icon, - name: network.name_long, + name: network.currencyNameLong, symbol: network.name, }); const rawAmount: string | null = args.amount ?? null; diff --git a/packages/extension/src/providers/polkadot/ui/custom-views/mappings/substrate.ts b/packages/extension/src/providers/polkadot/ui/custom-views/mappings/substrate.ts index 9e060cf8d..89670a10d 100644 --- a/packages/extension/src/providers/polkadot/ui/custom-views/mappings/substrate.ts +++ b/packages/extension/src/providers/polkadot/ui/custom-views/mappings/substrate.ts @@ -5,7 +5,7 @@ import { polkadotEncodeAddress } from "@enkryptcom/utils"; export const nativeTransfer = (network: SubstrateNetwork, data: any) => { const to = polkadotEncodeAddress(data.dest["Id"], network.prefix); const token = new SubstrateNativeToken({ - name: network.name_long, + name: network.currencyNameLong, symbol: network.name, coingeckoID: network.coingeckoID, decimals: network.decimals, diff --git a/packages/extension/src/providers/polkadot/ui/send-transaction/index.vue b/packages/extension/src/providers/polkadot/ui/send-transaction/index.vue index 35135d7ad..515c0f005 100644 --- a/packages/extension/src/providers/polkadot/ui/send-transaction/index.vue +++ b/packages/extension/src/providers/polkadot/ui/send-transaction/index.vue @@ -168,8 +168,6 @@ const sendMax = ref(false); const selected: string = route.params.id as string; const isLoadingAssets = ref(true); -const resolveTimeoutId = ref | null>(null); - const edWarn = computed(() => { if (!fee.value) { return undefined; diff --git a/packages/extension/src/providers/swap/types/ChangellySwapProvider.ts b/packages/extension/src/providers/swap/types/ChangellySwapProvider.ts index cdfc11920..e35bb08cb 100644 --- a/packages/extension/src/providers/swap/types/ChangellySwapProvider.ts +++ b/packages/extension/src/providers/swap/types/ChangellySwapProvider.ts @@ -12,7 +12,7 @@ import { TransactionInfo, } from "./SwapProvider"; import { toBase } from "@/libs/utils/units"; -import { numberToHex, toBN } from "web3-utils"; +import { toBN } from "web3-utils"; import { BaseNetwork } from "@/types/base-network"; import { EnkryptAccount, NetworkNames } from "@enkryptcom/types"; import { EvmNetwork } from "@/providers/ethereum/types/evm-network"; @@ -32,6 +32,7 @@ import ActivityState from "@/libs/activity-state"; import { Activity, ActivityStatus, ActivityType } from "@/types/activity"; import { ChangellyToken, ChangellyTokenOptions } from "./changelly-token"; import BigNumber from "bignumber.js"; +import broadcastTx from "@/providers/ethereum/libs/tx-broadcaster"; const CHANGELLY_TOKEN_INFO = [ { @@ -700,7 +701,7 @@ export class ChangellySwapProvider extends SwapProvider { to: to as `0x${string}`, data, value, - chainId: numberToHex((network as EvmNetwork).chainID) as `0x{string}`, + chainId: (network as EvmNetwork).chainID, }, web3 ); @@ -728,12 +729,9 @@ export class ChangellySwapProvider extends SwapProvider { account: fromAccount, network: network, payload: finalizedTx, - }).then((signedTx) => - web3 - .sendSignedTransaction( - `0x${signedTx.serialize().toString("hex")}` - ) - .on("transactionHash", (hash: string) => { + }).then((signedTx) => { + return new Promise((resolve) => { + const onHash = (hash: string) => { console.log(hash); activityState.addActivities( [ @@ -744,9 +742,22 @@ export class ChangellySwapProvider extends SwapProvider { ], { address: fromAccount.address, network: network.name } ); - }) - .then((receipt) => [receipt.transactionHash] as `0x${string}`[]) - ) + resolve([hash] as `0x${string}`[]); + }; + broadcastTx( + `0x${signedTx.serialize().toString("hex")}`, + network.name + ) + .then(onHash) + .catch(() => { + web3 + .sendSignedTransaction( + `0x${signedTx.serialize().toString("hex")}` + ) + .on("transactionHash", onHash); + }); + }); + }) ); } } diff --git a/packages/extension/src/providers/swap/types/EvmSwapProvider.ts b/packages/extension/src/providers/swap/types/EvmSwapProvider.ts index 9cee2b9d3..414bab5c6 100644 --- a/packages/extension/src/providers/swap/types/EvmSwapProvider.ts +++ b/packages/extension/src/providers/swap/types/EvmSwapProvider.ts @@ -6,6 +6,7 @@ import API from "@/providers/ethereum/libs/api"; import { NATIVE_TOKEN_ADDRESS } from "@/providers/ethereum/libs/common"; import Transaction from "@/providers/ethereum/libs/transaction"; import { GasPriceTypes } from "@/providers/ethereum/libs/transaction/types"; +import broadcastTx from "@/providers/ethereum/libs/tx-broadcaster"; import { Erc20Token } from "@/providers/ethereum/types/erc20-token"; import { EvmNetwork } from "@/providers/ethereum/types/evm-network"; import { TransactionSigner } from "@/providers/ethereum/ui/libs/signer"; @@ -14,7 +15,7 @@ import { BaseToken } from "@/types/base-token"; import { EnkryptAccount, NetworkNames } from "@enkryptcom/types"; import BigNumber from "bignumber.js"; import Web3Eth from "web3-eth"; -import { isAddress, numberToHex, toBN } from "web3-utils"; +import { isAddress, toBN } from "web3-utils"; import { Quote, QuoteInfo, @@ -388,7 +389,7 @@ export class EvmSwapProvider extends SwapProvider { data, value, gas, - chainId: numberToHex(network.chainID) as `0x{string}`, + chainId: network.chainID, nonce: `0x${toBN(nonce) .addn(index) .toString("hex")}` as `0x${string}`, @@ -408,12 +409,9 @@ export class EvmSwapProvider extends SwapProvider { account: fromAccount, network: network, payload: finalizedTx, - }).then((signedTx) => - web3 - .sendSignedTransaction( - `0x${signedTx.serialize().toString("hex")}` - ) - .on("transactionHash", (hash: string) => { + }).then((signedTx) => { + return new Promise((resolve: (h: `0x${string}`) => void) => { + const onHash = (hash: string) => { if (activity) { activityState.addActivities( [ @@ -425,10 +423,22 @@ export class EvmSwapProvider extends SwapProvider { { address: fromAccount.address, network: network.name } ); } - console.log("hash", hash); - }) - .then((receipt) => receipt.transactionHash as `0x${string}`) - ) + resolve(hash as `0x${string}`); + }; + broadcastTx( + `0x${signedTx.serialize().toString("hex")}`, + network.name + ) + .then(onHash) + .catch(() => { + web3 + .sendSignedTransaction( + `0x${signedTx.serialize().toString("hex")}` + ) + .on("transactionHash", onHash); + }); + }); + }) ) ); diff --git a/packages/extension/src/types/base-network.ts b/packages/extension/src/types/base-network.ts index 0258aa43d..510f8adb2 100644 --- a/packages/extension/src/types/base-network.ts +++ b/packages/extension/src/types/base-network.ts @@ -14,6 +14,7 @@ export interface BaseNetworkOptions { blockExplorerAddr: string; isTestNetwork: boolean; currencyName: string; + currencyNameLong: string; icon: string; decimals: number; signer: SignerType[]; @@ -37,6 +38,7 @@ export abstract class BaseNetwork { public blockExplorerAddr: string; public isTestNetwork: boolean; public currencyName: string; + public currencyNameLong: string; public icon: string; public signer: SignerType[]; public gradient: string; @@ -72,6 +74,7 @@ export abstract class BaseNetwork { this.api = options.api; this.customTokens = options.customTokens ?? false; this.coingeckoPlatform = options.coingeckoPlatform; + this.currencyNameLong = options.currencyNameLong; } public abstract getAllTokens(address: string): Promise; diff --git a/packages/extension/src/ui/action/views/swap-best-offer/index.vue b/packages/extension/src/ui/action/views/swap-best-offer/index.vue index c17d86bd5..9ae7f43ca 100644 --- a/packages/extension/src/ui/action/views/swap-best-offer/index.vue +++ b/packages/extension/src/ui/action/views/swap-best-offer/index.vue @@ -110,7 +110,7 @@ import { BaseToken } from "@/types/base-token"; import { Swap } from "@/providers/swap"; import { BaseNetwork } from "@/types/base-network"; import { AccountsHeaderData } from "../../types/account"; -import { numberToHex, toBN } from "web3-utils"; +import { toBN } from "web3-utils"; import BN from "bn.js"; import Web3Eth from "web3-eth"; import Transaction from "@/providers/ethereum/libs/transaction"; @@ -252,9 +252,7 @@ const Tx = computed(() => { to: txData.to as `0x${string}`, from: txData.from as `0x${string}`, data: txData.data, - chainId: numberToHex( - (props.network as EvmNetwork).chainID - ) as `0x${string}`, + chainId: (props.network as EvmNetwork).chainID, value: txData.value, gas: txData.gas, }, diff --git a/packages/types/src/networks.ts b/packages/types/src/networks.ts index 370de2fc7..2c144ccd5 100644 --- a/packages/types/src/networks.ts +++ b/packages/types/src/networks.ts @@ -20,6 +20,10 @@ export enum NetworkNames { Shiden = "SDN", ShidenEVM = "SDN EVM", AstarEVM = "ASTR EVM", + Optimism = "OP", + Canto = "CANTO", + Bifrost = "BNC", + BifrostKusama = "BNC (Kusama)", } export enum CoingeckoPlatform { @@ -37,4 +41,7 @@ export enum CoingeckoPlatform { Okc = "okc", Astar = "astar", Shiden = "shiden network", + Optimism = "optimistic-ethereum", + Canto = "canto", + Bifrost = "Bifrost Native Coin", } diff --git a/yarn.lock b/yarn.lock index 30908630a..fb8984d2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10517,9 +10517,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001317": - version: 1.0.30001332 - resolution: "caniuse-lite@npm:1.0.30001332" - checksum: e54182ea42ab3d2ff1440f9a6480292f7ab23c00c188df7ad65586312e4da567e8bedd5cb5fb8f0ff4193dc027a54e17e0b3c0b6db5d5a3fb61c7726ff9c45b3 + version: 1.0.30001429 + resolution: "caniuse-lite@npm:1.0.30001429" + checksum: d1658080248ef5ef0f5157423b2766026e6aa45642ce3b2cc74859b6a54e39881dd902397a2368324ed30ed0cd40250f11a4a4f3773453cd57b88db5e5e5c76a languageName: node linkType: hard