diff --git a/package-lock.json b/package-lock.json index 4ed0209..940ca77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ecto", - "version": "1.0.2", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 7a346e6..392ff3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ecto", - "version": "1.0.2", + "version": "1.1.0", "private": true, "scripts": { "build": "vue-cli-service build", diff --git a/public/assets/game.png b/public/assets/game.png new file mode 100644 index 0000000..e9cabb8 Binary files /dev/null and b/public/assets/game.png differ diff --git a/public/assets/gfest.png b/public/assets/gfest.png new file mode 100644 index 0000000..ad100bf Binary files /dev/null and b/public/assets/gfest.png differ diff --git a/src/_locales/pt/messages.json b/src/_locales/pt_PT/messages.json similarity index 100% rename from src/_locales/pt/messages.json rename to src/_locales/pt_PT/messages.json diff --git a/src/_locales/vn/messages.json b/src/_locales/vi/messages.json similarity index 100% rename from src/_locales/vn/messages.json rename to src/_locales/vi/messages.json diff --git a/src/_locales/cn/messages.json b/src/_locales/zh_CN/messages.json similarity index 100% rename from src/_locales/cn/messages.json rename to src/_locales/zh_CN/messages.json diff --git a/src/background/index.ts b/src/background/index.ts index 6cb16cb..96fcc86 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -1,9 +1,11 @@ /// import Vue from "vue"; import { PhantasmaAPI } from "@/phan-js"; -import { state } from "@/popup/PopupState"; +import { state, WalletAccount } from "@/popup/PopupState"; import VueI18n from "vue-i18n"; import { messages, defaultLocale } from "@/i18n"; +import { getEthBalances } from "@/ethereum"; +import { getNeoBalances } from "@/neo"; Vue.use(VueI18n); @@ -53,6 +55,14 @@ interface ISignTxResponse extends IWalletLinkResponse { } let authorizations: IAuthorization[] = []; +let accounts: WalletAccount[] = []; +let currentAccountIndex = 0; + +function currentAccount() { + return currentAccountIndex < accounts.length + ? accounts[currentAccountIndex] + : null; +} chrome.tabs.onUpdated.addListener(function(activeInfo) { chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) { @@ -114,6 +124,11 @@ function isValidRequest(args: string[]): boolean { return false; } +function getAddressFromToken(token: string): string | undefined { + const auth = authorizations.find((a) => a.token == token); + return auth?.address; +} + function getRequestAddress( args: string[] ): { address: string; version: string } | undefined { @@ -129,6 +144,12 @@ function getRequestAddress( chrome.storage.local.get((items) => { authorizations = items.authorizations ? items.authorizations : []; + currentAccountIndex = items.currentAccountIndex + ? items.currentAccountIndex + : 0; + accounts = items.accounts + ? items.accounts.filter((a: WalletAccount) => a.type !== "wif") + : []; }); chrome.storage.onChanged.addListener((changes, area) => { @@ -136,6 +157,12 @@ chrome.storage.onChanged.addListener((changes, area) => { if (changes.authorizations) { authorizations = changes.authorizations.newValue; } + if (changes.accounts) { + accounts = changes.accounts.newValue; + } + if (changes.currentAccountIndex) { + currentAccountIndex = changes.currentAccountIndex.newValue; + } } }); @@ -175,12 +202,20 @@ chrome.runtime.onMessage.addListener(async function(msg, sender, sendResponse) { const url = tab.url || "http://unknown"; const favicon = tab.favIconUrl || "unknown"; - const authToken = getAuthorizationToken( + let authToken = getAuthorizationToken( dapp, new URL(url).hostname, version ); + // if authorization doesn't match current address, request new one + if ( + authToken && + getAddressFromToken(authToken) !== currentAccount()?.address + ) { + authToken = undefined; + } + if (authToken) { console.log("Valid authorization token: " + authToken); @@ -194,7 +229,7 @@ chrome.runtime.onMessage.addListener(async function(msg, sender, sendResponse) { token: authToken, // new in v2 nexus: state.nexus, - version: "1", + version: "2", id, success: true, }, @@ -248,7 +283,6 @@ chrome.runtime.onMessage.addListener(async function(msg, sender, sendResponse) { console.log("nexus", state.nexus); console.log("getting account " + address); let account = await state.api.getAccount(address); - if (!account.balances) { account.balances = []; } @@ -261,8 +295,57 @@ chrome.runtime.onMessage.addListener(async function(msg, sender, sendResponse) { decimals: 8, }); + let balances = account.balances.map((x) => { + return { + value: x.amount, + decimals: x.decimals, + symbol: x.symbol, + }; + }); + let external = ""; // external address (neo or eth) if platform is not phantasma + const curAccount = currentAccount(); + if (platform == "ethereum") { + let ethAddress = curAccount?.ethAddress; + if (ethAddress) { + external = ethAddress; + const ethBals = await getEthBalances( + ethAddress, + state.nexus == "mainnet" + ); + balances = ethBals.map((b: any) => { + return { + symbol: b.symbol, + value: b.amount.toString(), + decimals: state.decimals(b.symbol), + }; + }); + } else { + platform = "phantasma"; + } + } + + if (platform == "neo") { + let neoAddress = curAccount?.neoAddress; + if (neoAddress) { + external = neoAddress; + const neoBals = await getNeoBalances( + neoAddress, + state.nexus == "mainnet" + ); + balances = neoBals.map((b: any) => { + return { + symbol: b.symbol, + value: b.amount, + decimals: state.decimals(b.symbol), + }; + }); + } else { + platform = "phantasma"; + } + } + console.log("got account: " + JSON.stringify(account)); let response: IGetAccountResponse = { name: account.name, @@ -270,13 +353,7 @@ chrome.runtime.onMessage.addListener(async function(msg, sender, sendResponse) { avatar: "", platform, external, - balances: account.balances.map((x) => { - return { - value: x.amount, - decimals: x.decimals, - symbol: x.symbol, - }; - }), + balances, id, success: true, }; @@ -297,13 +374,36 @@ chrome.runtime.onMessage.addListener(async function(msg, sender, sendResponse) { const version = req.version; const token = args[args.length - 1]; - const nexus = args[1]; - const chain = args[2]; - const script = args[3]; - let payload = args[4]; + let nexus = ""; + let payload = ""; + let chain = ""; + let script = ""; + let platform = "phantasma"; + let signature = "Ed25519"; + + if (version == "1") { + nexus = args[1]; + chain = args[2]; + script = args[3]; + payload = args[4]; + } else if (version == "2") { + chain = args[1]; + script = args[2]; + payload = args[3]; + signature = args[4]; + platform = args[5]; + } + payload = payload == null || payload == "" ? state.payload : payload; - let txdata = JSON.stringify({ nexus, chain, script, payload }); + let txdata = JSON.stringify({ + nexus, + chain, + script, + payload, + signature, + platform, + }); let b64txdata = btoa(txdata); chrome.tabs.get(msg.tabid, (tab) => { @@ -349,6 +449,10 @@ chrome.runtime.onMessage.addListener(async function(msg, sender, sendResponse) { const hexdata = args[1]; const signKind = args[2]; + let platform = "phantasma"; + + if (version == "2" && args.length > 3) + platform = args[3].toLocaleLowerCase(); chrome.tabs.get(msg.tabid, (tab) => { const url = tab.url || "http://unknown"; diff --git a/src/components/TransactionComponent.vue b/src/components/TransactionComponent.vue index d78150f..a6268cd 100644 --- a/src/components/TransactionComponent.vue +++ b/src/components/TransactionComponent.vue @@ -78,34 +78,7 @@ import { import { state } from "@/popup/PopupState"; function isFungible(symbol: string) { - return symbol !== "TTRS" && symbol !== "GHOST" && symbol !== "CROWN"; -} - -function decimals(symbol: string) { - switch (symbol) { - case "KCAL": - return 10; - case "SOUL": - return 8; - case "NEO": - return 0; - case "GAS": - return 8; - case "GOATI": - return 3; - case "ETH": - return 18; - case "MKNI": - return 0; - case "DYT": - return 18; - case "MUU": - return 18; - case "DANK": - return 18; - default: - return 0; - } + return !state.isNFT(symbol); } function formatNumber(num: any) { @@ -127,7 +100,7 @@ function formatBalance(amount: string, decimals: number): string { } function formatSymbol(amount: string, symbol: string): string { - return formatBalance(amount, decimals(symbol)) + " " + symbol; + return formatBalance(amount, state.decimals(symbol)) + " " + symbol; } function formatAddress(addr: string) { @@ -472,11 +445,7 @@ export default class extends Vue { // if (ev.address == this.address) { { const nftId = data.TokenID; - if ( - data.InfusedSymbol === "TTRS" || - data.InfusedSymbol === "GHOST" || - data.InfusedSymbol === "CROWN" - ) { + if (state.isNFT(data.InfusedSymbol)) { res.push({ icon: "mdi-basket-fill", postIcon: "mdi-eye-outline", diff --git a/src/ethereum/index.ts b/src/ethereum/index.ts index 82a3f98..7774968 100644 --- a/src/ethereum/index.ts +++ b/src/ethereum/index.ts @@ -2,6 +2,7 @@ import WIF from "wif"; import { Transaction as EthereumTx } from "ethereumjs-tx"; import EthWallet from "ethereumjs-wallet"; import { isMainThread } from "worker_threads"; +import { state } from "@/popup/PopupState"; const contractsRopsten: any = { SOUL: "19861B13425d8aCFB70eB91Ac50EC3cF721d0C8a", @@ -20,6 +21,12 @@ const contractsMainnet: any = { }; export function getEthContract(symbol: string, isMainnet: boolean) { + let hash = state.getTokenHash(symbol, "ethereum"); + if (hash) { + return hash; + } + + // to remove soon if (isMainnet) return contractsMainnet[symbol]; else return contractsRopsten[symbol]; } @@ -70,7 +77,13 @@ export function getEthAddressFromWif(wif: string): string { } export async function getEthBalances(ethAddress: string, isMainnet: boolean) { - const balances = []; + const balances: { symbol: string; amount: bigint }[] = []; + + const erc20Tokens = state + .getAllSwapableTokens("ethereum") + .filter((t) => t.symbol != "ETH"); + + console.log("erc20 tokens", erc20Tokens); const rpcUrl = "https://" + @@ -84,71 +97,26 @@ export async function getEthBalances(ethAddress: string, isMainnet: boolean) { const ethVal = BigInt(ethBalance === "0x" ? 0 : ethBalance); console.log("ethBalance", ethVal); + if (ethVal != 0n) balances.push({ symbol: "ETH", amount: ethVal }); const ethDataAddr = "0x70a08231000000000000000000000000" + ethAddress.substring(2); - const soulErcBalance = await JSONRPC(rpcUrl, "eth_call", [ - { - to: "0x" + (isMainnet ? contractsMainnet.SOUL : contractsRopsten.SOUL), - data: ethDataAddr, - }, - "latest", - ]); - - const soulVal = BigInt(soulErcBalance == "0x" ? 0 : soulErcBalance); - console.log("soul balance", soulVal); - - const kcalBalance = await JSONRPC(rpcUrl, "eth_call", [ - { - to: "0x" + (isMainnet ? contractsMainnet.KCAL : contractsRopsten.KCAL), - data: ethDataAddr, - }, - "latest", - ]); - - const kcalVal = BigInt(kcalBalance == "0x" ? 0 : kcalBalance); - console.log("kcal balance", kcalVal); - - const dytBalance = await JSONRPC(rpcUrl, "eth_call", [ - { - to: "0x" + (isMainnet ? contractsMainnet.DYT : contractsRopsten.DYT), - data: ethDataAddr, - }, - "latest", - ]); - - const dytVal = BigInt(dytBalance === "0x" ? 0 : dytBalance); - console.log("dyt balance", dytVal); - - const muuBalance = await JSONRPC(rpcUrl, "eth_call", [ - { - to: "0x" + (isMainnet ? contractsMainnet.MUU : contractsRopsten.MUU), - data: ethDataAddr, - }, - "latest", - ]); - - const muuVal = BigInt(muuBalance === "0x" ? 0 : muuBalance); - console.log("muu balance", muuVal); - - const dankBalance = await JSONRPC(rpcUrl, "eth_call", [ - { - to: "0x" + (isMainnet ? contractsMainnet.DANK : contractsRopsten.DANK), - data: ethDataAddr, - }, - "latest", - ]); - - const dankVal = BigInt(dankBalance === "0x" ? 0 : dankBalance); - console.log("dank balance", dankVal); - - if (ethVal !== 0n) balances.push({ symbol: "ETH", amount: ethVal }); - if (soulVal !== 0n) balances.push({ symbol: "SOUL", amount: soulVal }); - if (kcalVal !== 0n) balances.push({ symbol: "KCAL", amount: kcalVal }); - if (dytVal !== 0n) balances.push({ symbol: "DYT", amount: dytVal }); - if (muuVal !== 0n) balances.push({ symbol: "MUU", amount: muuVal }); - if (dankVal !== 0n) balances.push({ symbol: "DANK", amount: dankVal }); + erc20Tokens.map(async (t) => { + const hash = t.external?.find((e) => e.platform == "ethereum")?.hash; + if (!hash) return; + const ercBalance = await JSONRPC(rpcUrl, "eth_call", [ + { + to: "0x" + hash, + data: ethDataAddr, + }, + "latest", + ]); + + const val = BigInt(ercBalance == "0x" ? 0 : ercBalance); + if (val != 0n) balances.push({ symbol: t.symbol, amount: val }); + console.log(t.symbol, "balance", val); + }); return balances; } diff --git a/src/locales/cn.json b/src/locales/cn.json index 8f57b2a..4cb7064 100644 --- a/src/locales/cn.json +++ b/src/locales/cn.json @@ -66,7 +66,7 @@ "description": "想要连接到Phantasma链接。 每笔交易都会请求您的许可。 您允许吗?", "request": "授权请求", "label": "授权", - "labelAccount": "Account", + "labelAccount": "账户", "refuse": "拒绝", "connect": "连接", "periodCurrent": "当前进程", @@ -79,6 +79,7 @@ "assets": "资产", "activity": "活动", "swaps": "Swaps", + "multiChain": "多个
区块链", "unstake": "解封质押", "unstakeTitle": "解封质押", "stake": "质押", @@ -164,12 +165,20 @@ "or": "或者", "swapAmount": "Swap数额", "needGasToSwap": "您需要 {0} GAS在Phantasma区块链上以能够支付swap费用。", - "needEthToSwap": "您需要大概 {0} ETH在Phantasma区块链上以能够支付swap费用。", + "needEthToSwap": "ETH swap费用大概是{0}ETH.
ERC20 swap费用大概是{1}ETH。", "swapInProgressTitle": "Swap进行中", "swapBeingProcessed": "您的swap正在进行中。", "needsConfirmations": "需要出现12个确认才完成swap。", "checkTransaction": "您可以查看您的交易", - "here": "这里" + "here": "这里", + "assetsIn": "已知资产在", + "sendInProgress": "正在发送中", + "sendBeingProcessed": "您的交易正在进行中。", + "exportPrivateKey": "输出您的HEX密钥", + "andImportInMetamask": "输入到Metamask", + "crossChain": "异链传送", + "sameChain": "同链传送", + "sendOn": "发送到" }, "nfts": { "selected": "已选择", diff --git a/src/locales/de.json b/src/locales/de.json index ab8aa28..dba7782 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -79,6 +79,7 @@ "assets": "Vermögenswerte", "activity": "Aktivität", "swaps": "Tausche", + "multiChain": "multi
chain", "unstake": "Entstaken", "unstakeTitle": "Entstaken", "stake": "Staken", @@ -104,7 +105,7 @@ "sign": "TX signieren", "register": "Name registrieren", "registerDescription": "Ihr Adressname kann als Ihre öffentliche Adresse verwendet werden. Sie müssen 2 SOUL gestaked behalten, oder Sie verlieren den Namen.", - "registerHints": "Note: the name has to be between 3 and 15 characters, lowercase and can not start with a number.", + "registerHints": "Hinweis: Der Name muss aus 3 bis 15 Zeichen besehen. Kleinbuchstaben und darf nicht mit einer Nummer beginnen.", "registerDescription2": "Staken Sie SOUL um einen Namen zu registrieren und erhalten Sie täglich KCAL-Belohnungen. Die Mindest-Stake-Dauer beträgt 24 Stunden.", "registerDescription3": "Gehen Sie los und holen sich ein paar SOUL :)", "registerTitle": "Einen Namen registrieren", @@ -164,12 +165,20 @@ "or": "oder", "swapAmount": "Tauschmenge", "needGasToSwap": "Sie brauchen {0} GAS in Phantasma, um die Tauschgebühren bezahlen zu können.", - "needEthToSwap": "Sie brauchen schätzungsweise {0} ETH in Phantasma, um die Tauschgebühren bezahlen zu können.", + "needEthToSwap": "Ein ETH-Tausch kostet ungefähr {0} ETH an Gebühren.
Ein ERC20-Tausch kostet ungefähr {1} ETH an Gebühren.", "swapInProgressTitle": "Tausch in Bearbeitung", "swapBeingProcessed": "Ihr Tausch wird bearbeitet.", "needsConfirmations": "Es braucht 12 Bestätigungen um zu erscheinen.", "checkTransaction": "Sie können Ihre Transaktion nachprüfen:", - "here": "hier" + "here": "hier", + "assetsIn": "Bekannte Vermögenswerte in", + "sendInProgress": "Versand in Bearbeitung", + "sendBeingProcessed": "Ihr Versand wird bearbeitet.", + "exportPrivateKey": "Exportieren Sie Ihren hex privaten schlüssel", + "andImportInMetamask": "Und importieren Sie diesen in Metamask", + "crossChain": "CROSS CHAIN ÜBERWEISUNGEN", + "sameChain": "ÜBERWEISUNGEN AUF GLEICHER CHAIN", + "sendOn": "Versand auf" }, "nfts": { "selected": "ausgewählt", @@ -234,17 +243,17 @@ "select": "BRIEFTASCHE AUSWÄHLEN", "title": "Konto entfernen", "subtitle": "Entfernt das Konto", - "titleKey": "Export private key", - "subtitleKey": "WIF and HEX format", + "titleKey": "Privaten Schlüssel exportieren", + "subtitleKey": "WIF und HEX Format", "encKey": "Benötigt Passwort", "unverified": "Schreibgeschütztes, nicht verifiziertes Konto", "verified": "Benötigt WIF", - "keyExplanation": "The private key is the only thing required to allow access to your funds. Keep it safe.", - "titlePrivateKey": "Private Key", - "labelWIF": "Private key (WIF format)", - "labelHEX": "Private key (HEX format)", - "enterPassword": "Enter password", - "enterPasswordDecrypt": "Enter your password to decrypt the private key" + "keyExplanation": "Der private Schlüssel ist das einzig Benötigte, um auf Ihre Vermögenswerte zuzugreifen. Bewahren Sie ihn sicher auf.", + "titlePrivateKey": "Privater Schlüssel", + "labelWIF": "Privater Schlüssel (WIF Format)", + "labelHEX": "Privater Schlüssel (HEX Format)", + "enterPassword": "Password eingeben", + "enterPasswordDecrypt": "Geben Sie Ihr Passwort ein, um den privaten Schlüssel zu entschlüsseln" }, "error": { "malformed": "Fehlerhafte Anfrage", diff --git a/src/locales/en.json b/src/locales/en.json index e816e1b..6729c95 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1,257 +1,266 @@ { - "errorDialog": { - "errorDescription": "Error", - "cancelButton": "Cancel" - }, - "transactionComponent": { - "setName": "Set name", - "minted": "Minted", - "sent": "Sent", - "sentTo": "Sent to", - "burned": "Burned", - "claimed": "Claimed", - "paid": "Paid", - "received": "Received", - "listed": "Listed", - "nftSale": "NFT Sale", - "from": "Received from", - "infused": "Infused", - "unshown": "Unshown events", - "swapped": "Swapped", - "staked": "Staked", - "with": "With", - "for": "for", - "bid": "Bid", - "auction": "Auction", - "sale": "Participated in sale with" - }, - "app": { - "currencyDescription": "Currency", - "languageDescription": "Language", - "closeButton": "Close", - "errorMessage": "There has been an error in the transaction:" - }, - "addWallet": { - "add": "ADD WALLET", - "import": "Import", - "importLong": "Import Wallet", - "create": "Create", - "no": "No", - "or": "Or", - "setPassword": "Set Password", - "cancel": "Cancel", - "copy": "Copy to clipboard", - "labelPassword": "Password", - "labelWIF": "WIF or hex private key", - "labelAddress": "Wallet address or name", - "labelAddressShort": "Address", - "hintPassword": "Use at least 6 characters", - "descriptionLong": "Every Phantasma wallet unlocks access to a rich ecosystem of next generation Smart NFTs, powerful dApps, lightning fast transactions and a seamless user experience.

The best part?
It's virtually free to use!", - "description1": "Import a wallet with its address or name (read only), or private key in WIF or HEX format. When using private key you must protect it using a password.", - "description2": "Or if you don't have a wallet, you can", - "description3": "create a new one", - "description4": "Or if you don't like it, you can", - "description5": "generate another one", - "generate": "Generate a new wallet", - "created": "Wallet created with the following address and private key (WIF format)", - "backup": "Backup your WIF", - "recover": "You only need your WIF to recover your wallet. Make sure you always have a secure backup.", - "backupConfirm": "Yes, I did a backup", - "secure": "Insert a password to secure your wallet. You can always use WIF to recover it.", - "errorMessage1": "Error importing WIF wallet", - "errorMessage2": "Error importing HEX wallet", - "errorMessage3": "Error importing wallet" - }, - "authorize": { - "description": "wants to connect to Phantasma Link. Each transaction will request your permission. Do you want to allow it?", - "request": "Authorization request", - "label": "Authorize for", - "labelAccount": "Account", - "refuse": "Refuse", - "connect": "Connect", - "periodCurrent": "Current session", - "period1h": "One hour", - "period1d": "One day", - "period1m": "One month", - "periodAlways": "Always" - }, - "home": { - "assets": "Assets", - "activity": "Activity", - "swaps": "Swaps", - "unstake": "Unstake", - "unstakeTitle": "Unstake", - "stake": "Stake", - "stakeTitle": "Stake", - "claim": "Claim", - "view": "view", - "send": "Send", - "burn": "Burn", - "load": "Load more", - "agree": "Agree", - "disagree": "Disagree", - "addStakes": "Add to Stakes", - "resultStakes": "Result Stakes", - "cancel": "Cancel", - "removeStakes": "Remove from Stakes", - "sendAmount": "Send Amount", - "sendAmount2": "How many do you want to send?", - "remaining": "Remaining", - "next": "Next", - "insertWIF": "Insert your WIF to sign transaction.", - "insertPassword": "Insert your password to sign transaction.", - "authorize": "Authorize TX", - "sign": "Sign TX", - "register": "Register name", - "registerDescription": "Your address name can be used as your public address. Be aware that you need to keep 2 SOUL staked or you will lose your name.", - "registerHints": "Note: the name has to be between 3 and 15 characters, lowercase and can not start with a number.", - "registerDescription2": "Stake SOUL to register a name and get daily KCAL rewards. Minimum stake period is 24 hours.", - "registerDescription3": "Go and get some SOUL :)", - "registerTitle": "register a name", - "registerMain": "You can use your account with a name instead of a public address.", - "destination": "Destination", - "destinationDesc": "Select where do you want to send", - "have": "You have", - "haveStake": "How many do you want to stake?", - "haveUnstake": "staked SOUL. How many do you want to unstake?", - "claimDesc1": "You are going to claim", - "claimDesc2": "KCAL. This claims KCAL in advance, so you won't be able to unstake during 24h.", - "kcalExplanation": "KCAL is used for every transaction on the blockchain. You get 0.002 KCAL per SOUL staked daily. You can claim some now.", - "labelDest": "Dest address or name", - "labelPassword": "Password", - "labelPick": "Pick your name", - "errorMessage1": "", - "secondLine1": "Staked", - "secondLine2": "Unclaimed", - "pendingSwaps": "Pending Swaps", - "pendingSwapFrom": "pending:", - "from": "from", - "to": "to", - "swap": "swap", - "swapUppercase": "Swap", - "swapHowMany": "How many do you want to swap?", - "swapFrom": "Swap from", - "noSwapsNEO": "There are no swappable assets in the NEO side of you wallet.", - "noSwapsETH": "There are no swappable assets in the Ethereum side of you wallet.", - "sendAssetsSwap": "Send the assets you want to swap to", - "swappableAssets": "Swappable assets in", - "importETHWallet": "import your Ethereum wallet", - "withYourKey": "with your hex private key (ie from Metamask)", - "swapTo": "Swap to", - "swapToNeo": "Swap to NEO side of your wallet", - "swapToETH": "Swap to Ethereum side of your wallet", - "swapToAnotherNEO": "Or swap to another NEO wallet", - "swapToAnotherETH": "Or swap to another Ethereum wallet", - "selectAsset": "select asset", - "selectAssetUppercase": "Select Asset", - "selectAssetAndDest": "select asset and destination", - "swapExplanation": "To allow swaps you need to use your WIF or HEX private key once. This will generate the NEO and Ethereum addresses linked to your wallet.", - "continue": "continue", - "labelDestinationAddress": " destination address", - "availableToSwap": "You have the following available assets to swap to", - "fee": "Fee", - "swapNeed": "Swap fee: ", - "swapDestination": "Swap destination", - "write": "Write", - "destinationAddress": "destination address", - "enableSwaps": "Enable swaps", - "insertSwapsWIF": "Insert your WIF to generate swap public addresses.", - "insertSwapsPassword": "Insert your password to generate swap public address.", - "generate": "Generate", - "feeSlow": "Slow", - "feeStandard": "Standard", - "feeFast": "Fast", - "or": "or", - "swapAmount": "Swap Amount", - "needGasToSwap": "A swap to NEO costs {0} GAS in fees.", - "needEthToSwap": "A swap to Ethereum costs approx. {0} ETH in fees.", - "swapInProgressTitle": "Swap in progress", - "swapBeingProcessed": "Your swap is being processed.", - "needsConfirmations": "It needs 12 confirmations to appear.", - "checkTransaction": "You can check your transaction", - "here": "here" - }, - "nfts": { - "selected": "selected", - "send": "send nfts", - "burn": "burn nfts", - "burnTitle": "Burn NFTs", - "confirmBurn": "Confirm that you want to burn", - "confirmBurnSecond": "This is irreversible, destroys these NFTs and claims the infused assets, if any.", - "infused": "Infused assets", - "destination": "Destination", - "select": "Select where do you want to send", - "cancel": "Cancel", - "next": "Next", - "authorize": "Authorize TX", - "sign": "Sign TX", - "insertWIF": "Insert your WIF to sign transaction.", - "insertPassword": "Insert your password to sign transaction.", - "filters": "filters", - "close": "Close", - "sort": "sort", - "labelDest": "Dest address or name", - "labelPassword": "Password", - "labeTypes": "Types", - "labelRarity": "Rarity", - "labelDirection": "Direction", - "labelParameters": "Parameters", - "sortDirOptionsAsc": "Ascending", - "sortDirOptionsDesc": "Descending", - "noWallet": "" - }, - "qr": { - "copy": "Copy to clipboard", - "description": "Here's your public address", - "noWallet": "" - }, - "sign": { - "description": "Do you want to allow to sign tx for", - "request": "Transaction request", - "refuse": "Refuse", - "sign": "Sign tx", - "password": "Password", - "error": "Error", - "cancel": "Cancel", - "retry": "Retry", - "rejected": "user rejected", - "notValid": "WIF is not valid for address" - }, - "signData": { - "description": "Do you want to allow to sign tx for", - "request": "Data sign request", - "signData": "Sign data", - "password": "Password", - "refuse": "Refuse", - "error": "Transaction error", - "cancel": "Cancel", - "retry": "Retry", - "rejected": "user rejected", - "notValid": "WIF is not valid for address" - }, - "wallets": { - "add": "Add Wallet", - "select": "SELECT WALLET", - "title": "Remove account", - "subtitle": "Removes account", - "titleKey": "Export private key", - "subtitleKey": "WIF and HEX format", - "encKey": "Requires password", - "unverified": "Read-only unverified account", - "verified": "Requires WIF", - "keyExplanation": "The private key is the only thing required to allow access to your funds. Keep it safe.", - "titlePrivateKey": "Private Key", - "labelWIF": "Private key (WIF format)", - "labelHEX": "Private key (HEX format)", - "enterPassword": "Enter password", - "enterPasswordDecrypt": "Enter your password to decrypt the private key" - }, - "error": { - "malformed": "Malformed request", - "noAccount": "Cannot find account", - "noEncrypted": "Cannot find encrypted key", - "noPasswordMatch": "Password does not match", - "notValid": "Account not valid", - "noAccountMatch": "Account does not match" - } + "errorDialog": { + "errorDescription": "Error", + "cancelButton": "Cancel" + }, + "transactionComponent": { + "setName": "Set name", + "minted": "Minted", + "sent": "Sent", + "sentTo": "Sent to", + "burned": "Burned", + "claimed": "Claimed", + "paid": "Paid", + "received": "Received", + "listed": "Listed", + "nftSale": "NFT Sale", + "from": "Received from", + "infused": "Infused", + "unshown": "Unshown events", + "swapped": "Swapped", + "staked": "Staked", + "with": "With", + "for": "for", + "bid": "Bid", + "auction": "Auction", + "sale": "Participated in sale with" + }, + "app": { + "currencyDescription": "Currency", + "languageDescription": "Language", + "closeButton": "Close", + "errorMessage": "There has been an error in the transaction:" + }, + "addWallet": { + "add": "ADD WALLET", + "import": "Import", + "importLong": "Import Wallet", + "create": "Create", + "no": "No", + "or": "Or", + "setPassword": "Set Password", + "cancel": "Cancel", + "copy": "Copy to clipboard", + "labelPassword": "Password", + "labelWIF": "WIF or hex private key", + "labelAddress": "Wallet address or name", + "labelAddressShort": "Address", + "hintPassword": "Use at least 6 characters", + "descriptionLong": "Every Phantasma wallet unlocks access to a rich ecosystem of next generation Smart NFTs, powerful dApps, lightning fast transactions and a seamless user experience.

The best part?
It's virtually free to use!", + "description1": "Import a wallet with its address or name (read only), or private key in WIF or HEX format. When using private key you must protect it using a password.", + "description2": "Or if you don't have a wallet, you can", + "description3": "create a new one", + "description4": "Or if you don't like it, you can", + "description5": "generate another one", + "generate": "Generate a new wallet", + "created": "Wallet created with the following address and private key (WIF format)", + "backup": "Backup your WIF", + "recover": "You only need your WIF to recover your wallet. Make sure you always have a secure backup.", + "backupConfirm": "Yes, I did a backup", + "secure": "Insert a password to secure your wallet. You can always use WIF to recover it.", + "errorMessage1": "Error importing WIF wallet", + "errorMessage2": "Error importing HEX wallet", + "errorMessage3": "Error importing wallet" + }, + "authorize": { + "description": "wants to connect to Phantasma Link. Each transaction will request your permission. Do you want to allow it?", + "request": "Authorization request", + "label": "Authorize for", + "labelAccount": "Account", + "refuse": "Refuse", + "connect": "Connect", + "periodCurrent": "Current session", + "period1h": "One hour", + "period1d": "One day", + "period1m": "One month", + "periodAlways": "Always" + }, + "home": { + "assets": "Assets", + "activity": "Activity", + "swaps": "Swaps", + "multiChain": "multi
chain", + "unstake": "Unstake", + "unstakeTitle": "Unstake", + "stake": "Stake", + "stakeTitle": "Stake", + "claim": "Claim", + "view": "view", + "send": "Send", + "burn": "Burn", + "load": "Load more", + "agree": "Agree", + "disagree": "Disagree", + "addStakes": "Add to Stakes", + "resultStakes": "Result Stakes", + "cancel": "Cancel", + "removeStakes": "Remove from Stakes", + "sendAmount": "Send Amount", + "sendAmount2": "How many do you want to send?", + "remaining": "Remaining", + "next": "Next", + "insertWIF": "Insert your WIF to sign transaction.", + "insertPassword": "Insert your password to sign transaction.", + "authorize": "Authorize TX", + "sign": "Sign TX", + "register": "Register name", + "registerDescription": "Your address name can be used as your public address. Be aware that you need to keep 2 SOUL staked or you will lose your name.", + "registerHints": "Note: the name has to be between 3 and 15 characters, lowercase and can not start with a number.", + "registerDescription2": "Stake SOUL to register a name and get daily KCAL rewards. Minimum stake period is 24 hours.", + "registerDescription3": "Go and get some SOUL :)", + "registerTitle": "register a name", + "registerMain": "You can use your account with a name instead of a public address.", + "destination": "Destination", + "destinationDesc": "Select where do you want to send", + "have": "You have", + "haveStake": "How many do you want to stake?", + "haveUnstake": "staked SOUL. How many do you want to unstake?", + "claimDesc1": "You are going to claim", + "claimDesc2": "KCAL. This claims KCAL in advance, so you won't be able to unstake during 24h.", + "kcalExplanation": "KCAL is used for every transaction on the blockchain. You get 0.002 KCAL per SOUL staked daily. You can claim some now.", + "labelDest": "Dest address or name", + "labelPassword": "Password", + "labelPick": "Pick your name", + "errorMessage1": "", + "secondLine1": "Staked", + "secondLine2": "Unclaimed", + "pendingSwaps": "Pending Swaps", + "pendingSwapFrom": "pending:", + "from": "from", + "to": "to", + "swap": "swap", + "swapUppercase": "Swap", + "swapHowMany": "How many do you want to swap?", + "swapFrom": "Transfer from", + "noSwapsNEO": "There are no swappable assets in the NEO side of you wallet.", + "noSwapsETH": "There are no swappable assets in the Ethereum side of you wallet.", + "sendAssetsSwap": "Send the assets you want to swap to", + "swappableAssets": "Swappable assets in", + "importETHWallet": "import your Ethereum wallet", + "withYourKey": "with your hex private key (ie from Metamask)", + "swapTo": "Transfer to", + "swapToNeo": "Send to NEO side of your wallet", + "swapToETH": "Send to Ethereum side of your wallet", + "swapToAnotherNEO": "Or swap to another NEO wallet", + "swapToAnotherETH": "Or swap to another Ethereum wallet", + "selectAsset": "select asset", + "selectAssetUppercase": "Select Asset", + "selectAssetAndDest": "select asset and destination", + "swapExplanation": "To allow swaps you need to use your WIF or HEX private key once. This will generate the NEO and Ethereum addresses linked to your wallet.", + "continue": "continue", + "labelDestinationAddress": " destination address", + "availableToSwap": "You have the following available assets to send to", + "fee": "Fee", + "swapNeed": "Swap fee: ", + "swapDestination": "Swap destination", + "write": "Write", + "destinationAddress": "destination address", + "enableSwaps": "Enable swaps", + "insertSwapsWIF": "Insert your WIF to generate swap public addresses.", + "insertSwapsPassword": "Insert your password to generate swap public address.", + "generate": "Generate", + "feeSlow": "Slow", + "feeStandard": "Standard", + "feeFast": "Fast", + "or": "or", + "swapAmount": "Swap Amount", + "needGasToSwap": "A NEO/NEP5 swap costs {0} GAS in fees.", + "needEthToSwap": "An ETH swap costs approx. {0} ETH in fees.
An ERC20 swap costs approx. {1} ETH in fees.", + "swapInProgressTitle": "Swap in progress", + "swapBeingProcessed": "Your swap is being processed.", + "needsConfirmations": "It needs 12 confirmations to appear.", + "checkTransaction": "You can check your transaction", + "here": "here", + "assetsIn": "Known assets in", + "sendInProgress": "Send in progress", + "sendBeingProcessed": "Your asset transfer is being processed.", + "exportPrivateKey": "export your hex private key", + "andImportInMetamask": "and import in Metamask", + "crossChain": "CROSS CHAIN TRANSFERS", + "sameChain": "SAME CHAIN TRANSFERS", + "sendOn": "Send on" + }, + "nfts": { + "selected": "selected", + "send": "send nfts", + "burn": "burn nfts", + "burnTitle": "Burn NFTs", + "confirmBurn": "Confirm that you want to burn", + "confirmBurnSecond": "This is irreversible, destroys these NFTs and claims the infused assets, if any.", + "infused": "Infused assets", + "destination": "Destination", + "select": "Select where do you want to send", + "cancel": "Cancel", + "next": "Next", + "authorize": "Authorize TX", + "sign": "Sign TX", + "insertWIF": "Insert your WIF to sign transaction.", + "insertPassword": "Insert your password to sign transaction.", + "filters": "filters", + "close": "Close", + "sort": "sort", + "labelDest": "Dest address or name", + "labelPassword": "Password", + "labeTypes": "Types", + "labelRarity": "Rarity", + "labelDirection": "Direction", + "labelParameters": "Parameters", + "sortDirOptionsAsc": "Ascending", + "sortDirOptionsDesc": "Descending", + "noWallet": "" + }, + "qr": { + "copy": "Copy to clipboard", + "description": "Here's your public address", + "noWallet": "" + }, + "sign": { + "description": "Do you want to allow to sign tx for", + "request": "Transaction request", + "refuse": "Refuse", + "sign": "Sign tx", + "password": "Password", + "error": "Error", + "cancel": "Cancel", + "retry": "Retry", + "rejected": "user rejected", + "notValid": "WIF is not valid for address" + }, + "signData": { + "description": "Do you want to allow to sign tx for", + "request": "Data sign request", + "signData": "Sign data", + "password": "Password", + "refuse": "Refuse", + "error": "Transaction error", + "cancel": "Cancel", + "retry": "Retry", + "rejected": "user rejected", + "notValid": "WIF is not valid for address" + }, + "wallets": { + "add": "Add Wallet", + "select": "SELECT WALLET", + "title": "Remove account", + "subtitle": "Removes account", + "titleKey": "Export private key", + "subtitleKey": "WIF and HEX format", + "encKey": "Requires password", + "unverified": "Read-only unverified account", + "verified": "Requires WIF", + "keyExplanation": "The private key is the only thing required to allow access to your funds. Keep it safe.", + "titlePrivateKey": "Private Key", + "labelWIF": "Private key (WIF format)", + "labelHEX": "Private key (HEX format)", + "enterPassword": "Enter password", + "enterPasswordDecrypt": "Enter your password to decrypt the private key" + }, + "error": { + "malformed": "Malformed request", + "noAccount": "Cannot find account", + "noEncrypted": "Cannot find encrypted key", + "noPasswordMatch": "Password does not match", + "notValid": "Account not valid", + "noAccountMatch": "Account does not match" + } } diff --git a/src/locales/es.json b/src/locales/es.json index 33ceee8..3126b81 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -79,6 +79,7 @@ "assets": "Activos", "activity": "Actividad", "swaps": "Cambios", + "multiChain": "multi
chain", "unstake": "Desestacar", "unstakeTitle": "Desestacar", "stake": "Estacar", @@ -130,7 +131,7 @@ "swap": "cambiar", "swapUppercase": "Cambio", "swapHowMany": "¿Cuántas desea cambiar?", - "swapFrom": "Cambiar de", + "swapFrom": "Cambiar desde", "noSwapsNEO": "No hay activos intercambiables en la parte NEO de su wallet.", "noSwapsETH": "No hay activos intercambiables en la parte ETH de su wallet.", "sendAssetsSwap": "Enviar activos que desea cambiar", @@ -164,12 +165,20 @@ "or": "o", "swapAmount": "Cantidad de Cambio", "needGasToSwap": "Necesita {0} GAS en Phantasma para poder pagar las tarifas del cambio.", - "needEthToSwap": "Necesita {0} ETH en Phantasma para poder pagar las tarifas del cambio.", + "needEthToSwap": "El cambio de ETH cuesta unos {0} ETH en fees.
El cambio de ERC20 cuesta unos {1} ETH en fees.", "swapInProgressTitle": "Cambio en progreso", "swapBeingProcessed": "Su cambio esta siendo procesado.", "needsConfirmations": "Necesita 12 confirmaciones para aparecer.", "checkTransaction": "Puede verificar su transacción", - "here": "aquí" + "here": "aquí", + "assetsIn": "Activos conocidos en", + "sendInProgress": "Envio en curso", + "sendBeingProcessed": "Tu envio esta siendo procesado.", + "exportPrivateKey": "exporta tu clave privada en formato HEX", + "andImportInMetamask": "e importala en Metamask", + "crossChain": "TRANSFERENCIA ENTRE CHAINS", + "sameChain": "TRANSFERENCIA NORMAL", + "sendOn": "Enviar en" }, "nfts": { "selected": "seleccionado", diff --git a/src/locales/fr.json b/src/locales/fr.json index f39f0a0..7b431a7 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -79,6 +79,7 @@ "assets": "Actifs", "activity": "Activité", "swaps": "Swaps", + "multiChain": "multi
chain", "unstake": "Unstake", "unstakeTitle": "Unstake", "stake": "Stake", @@ -164,12 +165,20 @@ "or": "ou", "swapAmount": "Montant à swap", "needGasToSwap": "Un swap vers NEO coûte {0} GAS en frais.", - "needEthToSwap": "Un swap vers Ethereum coûte approximativement {0} ETH en frais.", + "needEthToSwap": "Un swap ETH coûte approx. {0} ETH en frais.
Un swap ERC20 coûte approx. {1} ETH en frais.", "swapInProgressTitle": "Swap en cours", "swapBeingProcessed": "Votre swap a été traité.", "needsConfirmations": "12 confirmations de bloc sont requis pour apparaître.", "checkTransaction": "Vous pouvez vérifier votre transaction", - "here": "ici" + "here": "ici", + "assetsIn": "Actifs disponibles dans", + "sendInProgress": "Envoi en cours", + "sendBeingProcessed": "Votre envoi est en cours.", + "exportPrivateKey": "exporter votre clé privée au format hex", + "andImportInMetamask": "et importer dans Metamask", + "crossChain": "TRANSFERTS INTER CHAINES", + "sameChain": "TRANSFERTS INTRA CHAINES", + "sendOn": "Envoi vers" }, "nfts": { "selected": "sélectionné", diff --git a/src/locales/it.json b/src/locales/it.json index 375deb0..4c739d0 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -23,7 +23,7 @@ "for": "per", "bid": "Offri", "auction": "Asta", - "sale": "Participated in sale with" + "sale": "Ha partecipato in una vendita con" }, "app": { "currencyDescription": "Valuta", @@ -79,6 +79,7 @@ "assets": "Risorse", "activity": "Attività", "swaps": "Swaps", + "multiChain": "multi
chain", "unstake": "Unstake", "unstakeTitle": "Unstake", "stake": "Stake", @@ -104,8 +105,8 @@ "sign": "Firma transazione", "register": "Registra nome", "registerDescription": "Il nome del tuo portafoglio può essere usato come indirizzo pubblico. Attenzione, devi lasciare almeno 2 SOUL in stake, o perderai il tuo nome.", - "registerHints": "Note: the name has to be between 3 and 15 characters, lowercase and can not start with a number.", - "registerDescription2": "Stake SOUL per registrare un nome e ricevere ricompense KCAL giornaliere. Il periodo di stake minimo è di 24 ore.", + "registerHints": "Nota: il nome deve essere compreso tra 3 e 15 caratteri, in minuscolo, e il primo carattere non deve essere numerico.", + "registerDescription2": "Aggiungi SOUL al tuo stake per registrare un nome e ricevere ricompense KCAL giornaliere. Il periodo di stake minimo è di 24 ore.", "registerDescription3": "Aggiungi SOUL al tuo portafoglio :)", "registerTitle": "registra un nome", "registerMain": "Puoi usare il tuo account tramite il suo nome, invece dell'indirizzo pubblico.", @@ -164,20 +165,28 @@ "or": "or", "swapAmount": "Scambia Quantità", "needGasToSwap": "Hai bisogno di {0} GAS in Phantasma per poter pagare le tasse di scambio.", - "needEthToSwap": "Hai bisogno di circa {0} ETH in Phantasma per poter pagare le tasse di scambio.", + "needEthToSwap": "Uno scambio di ETH costa circa {0} ETH in commissioni.
Uno scambio di un token ERC20 costa circa {1} ETH in commissioni.", "swapInProgressTitle": "Scambio in corso", "swapBeingProcessed": "Il tuo scambio è in corso.", "needsConfirmations": "Servono 12 conferme sulla blockchain per vedere le tue risorse nella sezione di destinazione.", "checkTransaction": "Puoi controllare la tua transazione", - "here": "qui" + "here": "qui", + "assetsIn": "Asset (supportati) disponibili in", + "sendInProgress": "Trasferimento in corso", + "sendBeingProcessed": "Il tuo trasferimento è in fase di elaborazione.", + "exportPrivateKey": "esporta la tua chiave privata (formato hex)", + "andImportInMetamask": "e importa in Metamask", + "crossChain": "TRASFERIMENTI CROSS-CHAIN", + "sameChain": "TRASFERIMENTI SU CHAIN SINGOLA", + "sendOn": "Manda su" }, "nfts": { "selected": "selezionato", "send": "Trasferisci nfts", - "burn": "burn nfts", - "burnTitle": "Burn NFTs", - "confirmBurn": "Confirm that you want to burn", - "confirmBurnSecond": "This is irreversible, destroys these NFTs and claims the infused assets, if any.", + "burn": "brucia nfts", + "burnTitle": "Brucia NFTs", + "confirmBurn": "Conferma di voler bruciare", + "confirmBurnSecond": "Questa azione è irreversibile, distrugge gli NFTs e reclama gli assets infusi, se ce ne sono.", "infused": "Risorse infuse", "destination": "Destinazione", "select": "Seleziona dove vuoi trasferire", @@ -234,17 +243,17 @@ "select": "SELEZIONA PORTAFOGLIO", "title": "Rimuovi account", "subtitle": "Rimuove un account", - "titleKey": "Export private key", - "subtitleKey": "WIF and HEX format", + "titleKey": "Esporta chiave privata", + "subtitleKey": "Formato WIF e HEX", "encKey": "Password richiesta", "unverified": "Account non verificato in sola lettura", "verified": "Chiave WIF richiesta", - "keyExplanation": "The private key is the only thing required to allow access to your funds. Keep it safe.", - "titlePrivateKey": "Private Key", - "labelWIF": "Private key (WIF format)", - "labelHEX": "Private key (HEX format)", - "enterPassword": "Enter password", - "enterPasswordDecrypt": "Enter your password to decrypt the private key" + "keyExplanation": "La chiave privata è l'unica chiave necessaria per avere accesso ai tuoi fondi. Tienila al sicuro.", + "titlePrivateKey": "Chiave Privata", + "labelWIF": "Chiave privata (formato WIF)", + "labelHEX": "Chiave privata (formato HEX)", + "enterPassword": "Inserisci password", + "enterPasswordDecrypt": "Inserisci la tua password per decriptare la chiave privata" }, "error": { "malformed": "Richiesta non formata correttamente", diff --git a/src/locales/nb.json b/src/locales/nb.json index 2026c78..967bad1 100644 --- a/src/locales/nb.json +++ b/src/locales/nb.json @@ -79,6 +79,7 @@ "assets": "Eiendeler", "activity": "Aktivitet", "swaps": "Overføringer", + "multiChain": "multi
chain", "unstake": "Løs ut", "unstakeTitle": "Løs ut", "stake": "Lås", @@ -164,12 +165,20 @@ "or": "eller", "swapAmount": "Mengde å overføre", "needGasToSwap": "Du trenger {0} GAS på Phantasma for å kunne betale overføringsavgiften.", - "needEthToSwap": "Du trenger ca {0} ETH på Phantasma for å kunne betale overføringsavgiften.", + "needEthToSwap": "Overføring av ETH har en avgift på ca. {0} ETH.
Overføring av en ERC20 har en avgift på ca. {1} ETH.", "swapInProgressTitle": "Overføring pågår", "swapBeingProcessed": "Overføringen din prosesseres.", "needsConfirmations": "Den trenger 12 bekreftelser før den vises.", "checkTransaction": "Du kan sjekke transaksjonen", - "here": "her" + "here": "her", + "assetsIn": "Kjente eiendeler i", + "sendInProgress": "Overføring pågår", + "sendBeingProcessed": "Overføring av eiendeler gjennomføres.", + "exportPrivateKey": "exsporter din private nøkkel i HEX-format", + "andImportInMetamask": "og importer i Metamask", + "crossChain": "OVERFØRING MELLOM ULIKE BLOKKKJEDER", + "sameChain": "SEND PÅ SAMME BLOKKJEDE", + "sendOn": "Send på" }, "nfts": { "selected": "valgte", @@ -234,17 +243,17 @@ "select": "VELG LOMMEBOK", "title": "Fjern lommebok", "subtitle": "Fjerner lommebok", - "titleKey": "Export private key", - "subtitleKey": "WIF and HEX format", + "titleKey": "Eksporter privat nøkkel", + "subtitleKey": "WIF- og HEX-format", "encKey": "Krever passord", "unverified": "Kun lesetilgang, ubekreftet konto", "verified": "Krever WIF", - "keyExplanation": "The private key is the only thing required to allow access to your funds. Keep it safe.", - "titlePrivateKey": "Private Key", - "labelWIF": "Private key (WIF format)", - "labelHEX": "Private key (HEX format)", - "enterPassword": "Enter password", - "enterPasswordDecrypt": "Enter your password to decrypt the private key" + "keyExplanation": "Den private nøkkelen er det eneste man trenger for å få tilgang til eiendelene dine. Oppbevar den på et trygt sted.", + "titlePrivateKey": "Privat nøkkel", + "labelWIF": "Private nøkkel (WIF-format)", + "labelHEX": "Private nøkkel (HEX-format)", + "enterPassword": "Legg inn passord", + "enterPasswordDecrypt": "Legg inn ditt passord for å dekryptere den private nøkkelen" }, "error": { "malformed": "Feil ved forespørsel", diff --git a/src/locales/nl.json b/src/locales/nl.json index cb4eb90..89fff58 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -79,6 +79,7 @@ "assets": "Bezittingen", "activity": "Activiteiten", "swaps": "Swaps", + "multiChain": "multi
chain", "unstake": "Unstake", "unstakeTitle": "Unstake", "stake": "Stake", @@ -164,12 +165,20 @@ "or": "of", "swapAmount": "Swap Aantal", "needGasToSwap": "Je hebt {0} GAS in Phantasma nodig om voor de swapkosten te betalen.", - "needEthToSwap": "Je hebt ongeveer {0} ETH in Phantasma nodig om voor de swapkosten te betalen.", + "needEthToSwap": "An ETH swap costs approx. {0} ETH in fees.
An ERC20 swap costs approx. {1} ETH in fees.", "swapInProgressTitle": "Swap wordt verwerkt", "swapBeingProcessed": "Swap wordt verwerkt.", "needsConfirmations": "Er zijn 12 bevestigingen nodig om te verschijnen.", "checkTransaction": "Controleer de transactie", - "here": "hier" + "here": "hier", + "assetsIn": "Known assets in", + "sendInProgress": "Send in progress", + "sendBeingProcessed": "Your send is being processed.", + "exportPrivateKey": "export your hex private key", + "andImportInMetamask": "and import in Metamask", + "crossChain": "CROSS CHAIN TRANSFERS", + "sameChain": "SAME CHAIN TRANSFERS", + "sendOn": "Send on" }, "nfts": { "selected": "gekozen", diff --git a/src/locales/pt.json b/src/locales/pt.json index 90faaa5..95ed693 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -23,7 +23,7 @@ "for": "para", "bid": "Licitar", "auction": "Leilão", - "sale": "Participated in sale with" + "sale": "Participou na venda com" }, "app": { "currencyDescription": "Moeda", @@ -79,6 +79,7 @@ "assets": "Espólio", "activity": "Atividade", "swaps": "Trocas", + "multiChain": "multi
chain", "unstake": "Recuperar", "unstakeTitle": "Recuperar", "stake": "Depositar", @@ -164,12 +165,20 @@ "or": "ou", "swapAmount": "Quantidade de troca", "needGasToSwap": "Necesitas {0} GAS em Phantasma para puderes pagar as taxas de troca.", - "needEthToSwap": "Necesitas approx. {0} ETH em Phantasma para puderes pagar as taxas de troca.", + "needEthToSwap": "An ETH swap costs approx. {0} ETH in fees.
An ERC20 swap costs approx. {1} ETH in fees.", "swapInProgressTitle": "Troca pendente", "swapBeingProcessed": "A tua troca está a ser processada.", "needsConfirmations": "Necesita 12 confirmações para aparecer.", "checkTransaction": "Podes verificar a tua transação", - "here": "here" + "here": "aqui", + "assetsIn": "Fundos encontrados em", + "sendInProgress": "Envio em progresso", + "sendBeingProcessed": "O teu envio está a ser processado.", + "exportPrivateKey": "exporta a tua chave privada hexadecimal", + "andImportInMetamask": "e importa no Metamask", + "crossChain": "TRANSFERÊNCIAS ENTRE CHAINS", + "sameChain": "TRANSFERÊNCIAS NA MESMA CHAIN", + "sendOn": "Envia em" }, "nfts": { "selected": "selecionado", @@ -239,12 +248,12 @@ "encKey": "Requer password", "unverified": "Conta em modo de leitura", "verified": "Requer WIF", - "keyExplanation": "The private key is the only thing required to allow access to your funds. Keep it safe.", - "titlePrivateKey": "Private Key", - "labelWIF": "Private key (WIF format)", - "labelHEX": "Private key (HEX format)", - "enterPassword": "Enter password", - "enterPasswordDecrypt": "Enter your password to decrypt the private key" + "keyExplanation": "A chave privada é a única coisa necessária para aceder aos teus fundos. Guarda-a num local seguro.", + "titlePrivateKey": "Chave privada", + "labelWIF": "Chave privada (formato WIF)", + "labelHEX": "Chave privada (formato HEX)", + "enterPassword": "Insere a password", + "enterPasswordDecrypt": "Insere o teu password para decifrar a chave privada" }, "error": { "malformed": "Pedido malformado", diff --git a/src/locales/ru.json b/src/locales/ru.json index 8fdc7ae..f27aa70 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -66,7 +66,7 @@ "description": "хочет подключиться к Вашему кошельку, используя технологию Phantasma Link. Операции с кошельком будут совершаться только после получения Ваших подтверждений. Разрешить подключение?", "request": "Запрос на авторизацию", "label": "Авторизовать для", - "labelAccount": "Account", + "labelAccount": "Аккаунт", "refuse": "Отказать", "connect": "Подключиться", "periodCurrent": "Текущая сессия", @@ -79,6 +79,7 @@ "assets": "Активы", "activity": "События", "swaps": "Обмен", + "multiChain": "мульти
чейн", "unstake": "Изъять", "unstakeTitle": "Изъять", "stake": "Вложить", @@ -164,12 +165,20 @@ "or": "или", "swapAmount": "Обмениваемое количество", "needGasToSwap": "Вам нужно {0} GAS в кошельке Phantasma для оплаты комиссии за обмен.", - "needEthToSwap": "Вам нужно примерно {0} ETH в кошельке Phantasma для оплаты комиссии за обмен.", + "needEthToSwap": "Обмен ETH стоит примерно {0} ETH.
Обмен ERC20 стоит примерно {1} ETH.", "swapInProgressTitle": "Обмен в процессе", "swapBeingProcessed": "Ваш обмен обрабатывается.", "needsConfirmations": "Требуется 12 подтверждений прежде чем он появится.", "checkTransaction": "Вы можете проверить Вашу транзакцию", - "here": "здесь" + "here": "здесь", + "assetsIn": "Известные активы в", + "sendInProgress": "Отправка в процессе", + "sendBeingProcessed": "Ваша отправка обрабатывается.", + "exportPrivateKey": "экспортировать Ваш приватный ключ (hex)", + "andImportInMetamask": "и импортировать в Metamask", + "crossChain": "КРОСС-ЧЕЙН ПЕРЕСЫЛКИ", + "sameChain": "ПЕРЕСЫЛКИ В РАМКАХ ОДНОГО БЛОКЧЕЙНА", + "sendOn": "Отправить в" }, "nfts": { "selected": "выбрано", @@ -234,17 +243,17 @@ "select": "ВЫБРАТЬ КОШЕЛЕК", "title": "Удалить кошелек", "subtitle": "Удаляет кошелек", - "titleKey": "Export private key", - "subtitleKey": "WIF and HEX format", + "titleKey": "Экспорт приватного ключа", + "subtitleKey": "WIF и HEX форматы", "encKey": "Требует пароль", "unverified": "Непроверенный кошелек с доступом на просмотр", "verified": "Требует WIF", - "keyExplanation": "The private key is the only thing required to allow access to your funds. Keep it safe.", - "titlePrivateKey": "Private Key", - "labelWIF": "Private key (WIF format)", - "labelHEX": "Private key (HEX format)", - "enterPassword": "Enter password", - "enterPasswordDecrypt": "Enter your password to decrypt the private key" + "keyExplanation": "Приватный ключ - единственное, что Вам нужно для доступа к Вашим средствам. Храните его в безопасности.", + "titlePrivateKey": "Приватный ключ", + "labelWIF": "Приватный ключ (формат WIF)", + "labelHEX": "Приватный ключ (формат HEX)", + "enterPassword": "Введите пароль", + "enterPasswordDecrypt": "Введите Ваш пароль для расшифровки приватного ключа" }, "error": { "malformed": "Некорректный запрос", diff --git a/src/locales/tr.json b/src/locales/tr.json index c539996..b6c1b78 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -79,6 +79,7 @@ "assets": "Varlıklar", "activity": "Hareketler", "swaps": "Değiştir", + "multiChain": "Diğer
Zincirler", "unstake": "Vade iptal", "unstakeTitle": "Vade iptal", "stake": "Vade", @@ -127,17 +128,17 @@ "pendingSwapFrom": "bekliyor:", "from": "buradan", "to": "şuraya", - "swap": "Geçir", - "swapUppercase": "Geçir", - "swapHowMany": "Ne kadar geçirmek istiyorsun?", - "swapFrom": "Zinciri şuradan değiştir", + "swap": "Transfer", + "swapUppercase": "Transfer", + "swapHowMany": "Ne kadarını transfer etmek istiyorsun?", + "swapFrom": "Şuradan değiştir,", "noSwapsNEO": "Cüzdanınızın NEO kısmından Phantasma'ya geçirilebilecek varlık yoktur.", "noSwapsETH": "Cüzdanınızın Ethereum kısmından Phantasma'ya geçirilebilecek varlık yoktur.", "sendAssetsSwap": "Geçirmek istediginiz varlıkları şu adrese gönderin:", "swappableAssets": "Buradaki Phantasma'ya geçirilebilir varlıklar:", "importETHWallet": "Ethereum cüzdanınızı", "withYourKey": "hex özel anahtarınız ile aktarın (Metamask gibi)", - "swapTo": "Zinciri şuraya değiştir", + "swapTo": "Şuraya değiştir,", "swapToNeo": "Cüzdanınızın NEO kısmına geçirin", "swapToETH": "Cüzdanınızın Ethereum kısmına geçirin", "swapToAnotherNEO": "veya başka bir NEO cüzdanına geçirin", @@ -145,13 +146,13 @@ "selectAsset": "varlık seçin", "selectAssetUppercase": "Varlık seç", "selectAssetAndDest": "varlık ve hedef seçin", - "swapExplanation": "Değişimleri aktive etmek için WIF veya özel anahtarınızı bir kereye mahsus girmeniz gereklidir. Bu sayede cüzdanınızla ilintili NEO ve Ethereum adresleri oluşturulur.", + "swapExplanation": "Değişimleri aktive etmek için WIF veya HEX özel anahtarınızı bir kereye mahsus girmeniz gereklidir. Bu sayede cüzdanınızla ilintili NEO ve Ethereum adresleri oluşturulur.", "continue": "devam", "labelDestinationAddress": " hedef adres", "availableToSwap": "Takip eden varlıklar şuraya geçirilebilir,", "fee": "Harç", - "swapNeed": "Değişim harcı:", - "swapDestination": "Geçirme hedefi", + "swapNeed": "Transfer harcı:", + "swapDestination": "Transfer hedefi", "write": "Yaz", "destinationAddress": "Hedef adres", "enableSwaps": "Değişimleri aktive et", @@ -162,14 +163,22 @@ "feeStandard": "Standard", "feeFast": "Hızlı", "or": "veya", - "swapAmount": "Geçirilecek Miktar", - "needGasToSwap": "Değişim harçları için Phantasma tarafında {0} GAS gereklidir.", - "needEthToSwap": "Değişim harçları için Phantasma tarafında yaklaşık {0} ETH gereklidir.", + "swapAmount": "Transfer Edilecek Miktar", + "needGasToSwap": "Transfer harçları için Phantasma tarafında {0} GAS gerekir.", + "needEthToSwap": "Transfer harçları için Phantasma tarafında:
ETH için yaklaşık {0} ETH harç,
ERC20 için yaklaşık {1} ETH harç gerekir.", "swapInProgressTitle": "Değişim işleniyor", "swapBeingProcessed": "Değişiminiz işleme alınacak.", "needsConfirmations": "Görebilmeniz için 12 doğrulama gerekli.", "checkTransaction": "İşleminizi kontrol edebilirsiniz", - "here": "buradan" + "here": "buradan", + "assetsIn": "Buradaki tanınan varlıklar", + "sendInProgress": "Gönderim işleniyor", + "sendBeingProcessed": "Gönderiminiz işleme alınacak", + "exportPrivateKey": "HEX özel anahtarınızı dışarı aktarın", + "andImportInMetamask": "ve Metamask'a aktarın.", + "crossChain": "ZİNCİR DEĞİŞİM İŞLEMLERİ", + "sameChain": "DİĞER ZİNCİRLERDE TRANSFERLER", + "sendOn": "Burada Gönder," }, "nfts": { "selected": "Seçildi", diff --git a/src/locales/vn.json b/src/locales/vn.json index 670d5b3..765a7ae 100644 --- a/src/locales/vn.json +++ b/src/locales/vn.json @@ -79,6 +79,7 @@ "assets": "Tài sản", "activity": "Hoạt động", "swaps": "Swaps", + "multiChain": "multi
chain", "unstake": "Gỡ", "unstakeTitle": "Gỡ", "stake": "Đóng", @@ -164,12 +165,20 @@ "or": "hoặc", "swapAmount": "Số lượng hoán đổi", "needGasToSwap": "Bạn cần {0} GAS trong Phantasma để có thể thanh toán phí hoán đổi.", - "needEthToSwap": "Bạn cần khoảng {0} ETH trong Phantasma để có thể thanh toán phí hoán đổi.", + "needEthToSwap": "Giao dịch hoán đổi ETH tốn khoảng {0} ETH tính phí.
Một giao dịch hoán đổi ERC20 có giá khoảng {1} ETH tính phí.", "swapInProgressTitle": "Hoán đổi đang diễn ra", "swapBeingProcessed": "Hoán đổi của bạn đang được xử lý.", "needsConfirmations": "Nó cần 12 xác nhận để xuất hiện.", "checkTransaction": "Bạn có thể kiểm tra giao dịch của mình", - "here": "đây" + "here": "đây", + "assetIn": "Nội dung đã biết trong", + "sendInProgress": "Đang gửi", + "sendBeingProcessed": "Quá trình chuyển tài sản của bạn đang được xử lý.", + "exportPrivateKey": "xuất khóa cá nhân hex của bạn", + "andImportInMetamask": "và nhập trong Metamask", + "crossChain": "CHUYỂN ĐỔI CHUỖI CHÉO", + "sameChain": "CÙNG CHUYỂN ĐỔI CHUỖI", + "sendOn": "Gửi tiếp" }, "nfts": { "selected": "đã chọn", diff --git a/src/manifest.development.json b/src/manifest.development.json index 04c6d14..e414897 100644 --- a/src/manifest.development.json +++ b/src/manifest.development.json @@ -3,7 +3,7 @@ "name": "__MSG_appName__", "description": "__MSG_appDesc__", "default_locale": "en", - "version": "1.0.2", + "version": "1.1.0", "browser_action": { "default_icon": "icon.png", "default_popup": "popup.html" diff --git a/src/manifest.production.json b/src/manifest.production.json index f3e8e7b..922e187 100644 --- a/src/manifest.production.json +++ b/src/manifest.production.json @@ -3,7 +3,7 @@ "name": "__MSG_appName__", "description": "__MSG_appDesc__", "default_locale": "en", - "version": "1.0.2", + "version": "1.1.0", "browser_action": { "default_icon": "icon.png", "default_popup": "popup.html" diff --git a/src/neo/index.ts b/src/neo/index.ts index 1b9dcfe..7b2f486 100644 --- a/src/neo/index.ts +++ b/src/neo/index.ts @@ -12,6 +12,7 @@ import Neon, { } from "@cityofzion/neon-js"; import { sign } from "crypto"; import { Transaction } from "ethereumjs-tx"; +import { state } from "@/popup/PopupState"; const tokens = { SOUL: "ed07cffad18f1308db51920d99a2af60ac66a7b3", @@ -48,24 +49,32 @@ export function getScriptHashFromAddress(address: string): string { export async function getNeoBalances( neoAddress: string, isMainnet: boolean -): Promise { - const neoRpc = isMainnet ? 'http://seed.neoeconomy.io:10332' : 'http://mankinighost.phantasma.io:30333' - const account = await rpc.Query.getAccountState(neoAddress).execute( - neoRpc - ); +): Promise { + const neoRpc = isMainnet + ? "http://seed.neoeconomy.io:10332" + : "http://mankinighost.phantasma.io:30333"; + const account = await rpc.Query.getAccountState(neoAddress).execute(neoRpc); console.log("neo account", account); - const balances = []; - const soulFixed = await nep5.getTokenBalance( - neoRpc, - tokens.SOUL, - neoAddress - ); - console.log("soulfixed", soulFixed); - const soulAmount = soulFixed.toString(); - console.log("soulamount", soulAmount); - if (soulAmount !== "0") balances.push({ symbol: "SOUL", amount: (parseFloat(soulAmount) * 10 ** 8).toFixed(0)}); + const balances: any[] = []; + + const nep5Tokens = state + .getAllSwapableTokens("neo") + .filter((t) => t.symbol != "GAS" && t.symbol != "NEO"); + + nep5Tokens.map(async (t) => { + const hash = t.external?.find((e) => e.platform == "neo")?.hash; + if (!hash) return; + const valFixed = await nep5.getTokenBalance(neoRpc, hash, neoAddress); + const amount = valFixed.toString(); + console.log(t.symbol, "amount", amount); + if (amount !== "0") + balances.push({ + symbol: t.symbol, + amount: (parseFloat(amount) * 10 ** t.decimals).toFixed(0), + }); + }); if (account.result && account.result.balances) { const bals = account.result.balances; @@ -73,7 +82,10 @@ export async function getNeoBalances( if (el.asset == tokens.NEO && el.value !== 0) balances.push({ symbol: "NEO", amount: el.value }); if (el.asset == tokens.GAS && el.value !== 0) - balances.push({ symbol: "GAS", amount: (parseFloat(el.value) * 10 ** 8).toFixed(0) }); + balances.push({ + symbol: "GAS", + amount: (parseFloat(el.value) * 10 ** 8).toFixed(0), + }); }); } @@ -89,7 +101,7 @@ async function sendNep5( gasFee: number, isMainnet: boolean ) { - const contractScriptHash = "ed07cffad18f1308db51920d99a2af60ac66a7b3"; + const contractScriptHash = state.getNeoContract(symbol).toLowerCase(); // "ed07cffad18f1308db51920d99a2af60ac66a7b3"; const myAccount = new wallet.Account(wif); // We must change the data type of contract parameters @@ -122,14 +134,14 @@ async function sendNep5( ); // add date remark to simulate nonce - const date = new Date() - rawTransaction.addRemark("Sent on " + date) + const date = new Date(); + rawTransaction.addRemark("Sent on " + date); // query neoscan balance - const neoApi = isMainnet ? 'https://api.neoscan.io/api/main_net' : 'http://mankinighost.phantasma.io:4000/api/main_net' - const apiProvider = new api.neoscan.instance( - neoApi - ); + const neoApi = isMainnet + ? "https://api.neoscan.io/api/main_net" + : "http://mankinighost.phantasma.io:4000/api/main_net"; + const apiProvider = new api.neoscan.instance(neoApi); async function queryBalanceNeoScan() { let balance = await apiProvider.getBalance(myAccount.address); return balance; @@ -156,7 +168,9 @@ async function sendNep5( ); // Send raw transaction - const neoRpc = isMainnet ? 'http://seed.neoeconomy.io:10332' : 'http://mankinighost.phantasma.io:30333' + const neoRpc = isMainnet + ? "http://seed.neoeconomy.io:10332" + : "http://mankinighost.phantasma.io:30333"; const client = new rpc.RPCClient(neoRpc); const res = await client.sendRawTransaction(rawTransaction); console.log("sendNep5 Raw Tx", res, rawTransaction); @@ -174,10 +188,10 @@ async function sendNative( ) { const myAccount = new wallet.Account(wif); - const neoApi = isMainnet ? 'https://api.neoscan.io/api/main_net' : 'http://mankinighost.phantasma.io:4000/api/main_net' - const apiProvider = new api.neoscan.instance( - neoApi - ); + const neoApi = isMainnet + ? "https://api.neoscan.io/api/main_net" + : "http://mankinighost.phantasma.io:4000/api/main_net"; + const apiProvider = new api.neoscan.instance(neoApi); // Create contract transaction using Neoscan API async function createTxWithNeoScan() { @@ -193,7 +207,9 @@ async function sendNative( } // Send raw transaction - const neoRpc = isMainnet ? 'http://seed.neoeconomy.io:10332' : 'http://mankinighost.phantasma.io:30333' + const neoRpc = isMainnet + ? "http://seed.neoeconomy.io:10332" + : "http://mankinighost.phantasma.io:30333"; const client = new rpc.RPCClient(neoRpc); const transaction = await createTxWithNeoScan(); @@ -214,7 +230,7 @@ export async function sendNeo( isMainnet: boolean ) { let hash = ""; - if (symbol == "SOUL") { + if (symbol != "NEO" && symbol != "GAS") { hash = await sendNep5(wif, amount, symbol, dest, desc, gasFee, isMainnet); } else { hash = await sendNative(wif, amount, symbol, dest, desc, gasFee, isMainnet); diff --git a/src/phan-js/rpc/phantasma.ts b/src/phan-js/rpc/phantasma.ts index b550c77..0e683c9 100644 --- a/src/phan-js/rpc/phantasma.ts +++ b/src/phan-js/rpc/phantasma.ts @@ -146,6 +146,7 @@ export interface Token { currentSupply: string; //Amount of minted tokens maxSupply: string; //Max amount of tokens that can be minted platform: string; //Platform of token + external?: { hash: string; platform: string }[]; hash: string; //Hash of token flags: string; } @@ -523,9 +524,9 @@ export class PhantasmaAPI { } //Returns an array of tokens deployed in Phantasma. - async getTokens(): Promise { + async getTokens(): Promise { let params: Array = []; - return (await this.JSONRPC("getTokens", params)) as Token; + return (await this.JSONRPC("getTokens", params)) as Token[]; } //Returns info about a specific token deployed in Phantasma. diff --git a/src/popup/PopupState.ts b/src/popup/PopupState.ts index 55e30f4..922586b 100644 --- a/src/popup/PopupState.ts +++ b/src/popup/PopupState.ts @@ -15,6 +15,7 @@ import { Balance, signData, Swap, + Token, } from "@/phan-js"; import { getNeoAddressFromWif, getNeoBalances } from "@/neo"; @@ -64,6 +65,15 @@ export interface TxArgsData { payload: string; } +export interface NexusData { + mainnet: T | undefined; + testnet: T | undefined; + simnet: T | undefined; + mainnetLastUpdate: number; + testnetLastUpdate: number; + simnetLastUpdate: number; +} + export class PopupState { api = new PhantasmaAPI( "https://seed.ghostdevs.com:7077/rpc", @@ -82,6 +92,14 @@ export class PopupState { private _simnetRpc = "http://localhost:7077/rpc"; private _testnetRpc = "http://testnet.phantasma.io:7077/rpc"; private _mainnetRpc = "Auto"; + private _tokens: NexusData = { + mainnet: [], + testnet: [], + simnet: [], + mainnetLastUpdate: 0, + testnetLastUpdate: 0, + simnetLastUpdate: 0, + }; accountNfts: any[] = []; nfts: any = {}; @@ -91,7 +109,7 @@ export class PopupState { allSwaps: Swap[] = []; - payload = "4543542D312E302E32"; + payload = "4543542D312E312E30"; $i18n: any = { t: (s: string) => s, @@ -298,6 +316,8 @@ export class PopupState { return this._currenciesRate["ethereum"][curSym]; case "dyt": return this._currenciesRate["dynamite"][curSym]; + case "dank": + return this._currenciesRate["mu-dank"][curSym]; case "goati": return 0.1; } @@ -310,7 +330,7 @@ export class PopupState { async check($i18n: any): Promise { if ($i18n) this.$i18n = $i18n; // save translate method from Vue i18n return new Promise((resolve, reject) => { - chrome.storage.local.get((items) => { + chrome.storage.local.get(async (items) => { console.log("[PopupState] Get local storage"); this._currentAccountIndex = items.currentAccountIndex ? items.currentAccountIndex @@ -332,6 +352,10 @@ export class PopupState { ? items.accounts.filter((a: WalletAccount) => a.type !== "wif") : []; + if (items.tokens) this._tokens = items.tokens; + + console.log("Current tokens", JSON.stringify(this._tokens, null, 2)); + const numAccounts = items.accounts ? items.accounts.length : 0; if (items.simnetRpc) this._simnetRpc = items.simnetRpc; @@ -344,6 +368,28 @@ export class PopupState { if (this._nexus == "SimNet") this.api.setRpcHost(this._simnetRpc); if (this._nexus == "TestNet") this.api.setRpcHost(this._testnetRpc); + try { + // query tokens info if needed for current nexus + const now = new Date().valueOf(); + const nexus = this.nexus; + var lastUpdate = (this._tokens as any)[nexus + "LastUpdate"]; + const secsSinceLastUpdate = (now - lastUpdate) / 1000; + console.log("Last update was ", secsSinceLastUpdate, "secs ago"); + if (secsSinceLastUpdate > 60 * 60 * 2) { + let tokens = await this.api.getTokens(); + // remove script, we don't need it + tokens.forEach((t: any) => { + if (t.script != undefined) delete t.script; + }); + console.log("tokens for", nexus, tokens); + (this._tokens as any)[nexus] = tokens; + (this._tokens as any)[nexus + "LastUpdate"] = now; + chrome.storage.local.set({ tokens: this._tokens }); + } + } catch (err) { + console.error("Could not get tokens", err); + } + if (this._accounts.length !== numAccounts) chrome.storage.local.set({ accounts: this._accounts }); @@ -406,7 +452,7 @@ export class PopupState { async fetchRates() { const res = await fetch( - "https://api.coingecko.com/api/v3/simple/price?ids=phantasma%2Cphantasma-energy%2Cneo%2Cgas%2Ctether%2Cethereum%2Cdai%2Cdynamite&vs_currencies=usd%2Ceur%2Cgbp%2Cjpy%2Ccad%2Caud%2Ccny%2Crub" + "https://api.coingecko.com/api/v3/simple/price?ids=phantasma%2Cphantasma-energy%2Cneo%2Cgas%2Ctether%2Cethereum%2Cdai%2Cdynamite%2Cmu-dank&vs_currencies=usd%2Ceur%2Cgbp%2Cjpy%2Ccad%2Caud%2Ccny%2Crub" ); const resJson = await res.json(); this._currenciesRate = resJson; @@ -435,7 +481,10 @@ export class PopupState { async addAccount(addressOrName: string): Promise { let address = addressOrName; - if (!address.startsWith("P") || address.length != 47) { + if ( + !(address.startsWith("P") || address.startsWith("S")) || + address.length != 47 + ) { address = await this.api.lookUpName(address); if ((address as any).error) throw new Error("Wallet name not found"); } @@ -468,6 +517,7 @@ export class PopupState { ): boolean { try { return ( + (account && account.address && account.address.startsWith("S")) || (account !== undefined ? account.address : this.currentAccount?.address) === getAddressFromWif(wif) @@ -601,23 +651,23 @@ export class PopupState { account.address ); - await this.fetchNftData( - this._accounts[this._currentAccountIndex].data.balances.find( - (b) => b.symbol == "TTRS" - )! + const allNfts = this.getAllTokens().filter( + (t) => t.flags && !t.flags.includes("Fungible") ); - await this.fetchNftData( - this._accounts[this._currentAccountIndex].data.balances.find( - (b) => b.symbol == "GHOST" - )! - ); - - await this.fetchNftData( - this._accounts[this._currentAccountIndex].data.balances.find( - (b) => b.symbol == "CROWN" - )! - ); + // fetch all nfts data available + for (var i = 0; i < allNfts.length; ++i) { + try { + const symbol = allNfts[i].symbol; + await this.fetchNftData( + this._accounts[this._currentAccountIndex].data.balances.find( + (b) => b.symbol == symbol + )! + ); + } catch (err) { + console.error("Error fetching NFTs", err); + } + } await this.refreshSwapInfo(); @@ -666,18 +716,22 @@ export class PopupState { } } - let phaSwaps = await this.api.getSwapsForAddress( - this.currentAccount!.address - ); - console.log("phaSwaps", phaSwaps); - phaSwaps = phaSwaps.filter( - (s) => - s.destinationHash === "pending" && - this.allSwaps.findIndex( - (p) => p.sourceHash == s.sourceHash && p.symbol == s.symbol - ) < 0 - ); - console.log("allSwaps", this.allSwaps); + try { + let phaSwaps = await this.api.getSwapsForAddress( + this.currentAccount!.address + ); + console.log("phaSwaps", phaSwaps); + phaSwaps = phaSwaps.filter( + (s) => + s.destinationHash === "pending" && + this.allSwaps.findIndex( + (p) => p.sourceHash == s.sourceHash && p.symbol == s.symbol + ) < 0 + ); + console.log("allSwaps", this.allSwaps); + } catch (err) { + console.log("error in getting pending pha swaps", err); + } // check external pending swaps, if there are /* const curTime = new Date().getTime(); @@ -698,7 +752,7 @@ export class PopupState { this._pendingSwaps.filter((p) => !toRemove.includes(p)); chrome.storage.local.set({ pendingSwaps: this._pendingSwaps }, () => {}); } */ - } + } async authorizeDapp( dapp: string, @@ -936,6 +990,12 @@ export class PopupState { return getEthContract(symbol, this.isMainnet); } + getNeoContract(symbol: string) { + const hash = this.getTokenHash(symbol, "neo"); + if (hash) return hash; + return "ed07cffad18f1308db51920d99a2af60ac66a7b3"; // harcoded SOUL NEP5 contract + } + getTranscodeAddress(wif: string) { const pkHex = getPrivateKeyFromWif(wif); const privateKey = Secp256k1.uint256(pkHex, 16); @@ -978,7 +1038,40 @@ export class PopupState { return wif; } - decimals(symbol: string) { + getAllTokens(): Token[] { + return (this._tokens as any)[this.nexus] as Token[]; + } + + getAllSwapableTokens(platform: string) { + return this.getAllTokens().filter( + (t) => + t.external && t.external.findIndex((e) => e.platform == platform) >= 0 + ); + } + + getToken(symbol: string) { + return this.getAllTokens().find((t) => t.symbol == symbol); + } + + getTokenHash(symbol: string, chain: string) { + const ch = chain == "eth" ? "ethereum" : chain; + const token = this.getToken(symbol); + if (token && token.external) { + let ext = token.external.find((e) => e.platform == ch); + if (ext) return ext.hash; + } + return undefined; + } + + isSwappable(symbol: string, swapToChain: string) { + const hash = this.getTokenHash(symbol, swapToChain); + return hash != null; + } + + decimals(symbol: string): number { + const token = this.getToken(symbol); + if (token) return token.decimals; + switch (symbol) { case "KCAL": return 10; @@ -1005,19 +1098,19 @@ export class PopupState { } } + isNFT(symbol: string) { + const token = this.getToken(symbol); + return token && token.flags && !token.flags.includes("Fungible"); + } + + isBurnable(symbol: string) { + const token = this.getToken(symbol); + return token && token.flags && token.flags.includes("Burnable"); + } + formatBalance(symbol: string, amount: string): string { const decimals = this.decimals(symbol); - - switch (symbol) { - case "TTRS": - return symbol + " NFT"; - case "GHOST": - return symbol + " NFT"; - case "CROWN": - return symbol + " NFT"; - default: - break; - } + if (this.isNFT(symbol)) return symbol + " NFT"; if (decimals == 0) return amount + " " + symbol; while (amount.length < decimals + 1) amount = "0" + amount; diff --git a/src/views/Home.vue b/src/views/Home.vue index 8fe5b16..7bed0d9 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -37,15 +37,14 @@ > {{ $t("home.assets") }} {{ $t("home.activity") }} - - {{ $t("home.swaps") }}{{ $t("home.swaps") }} + > mdi-eye {{ $t("home.view") }} - mdi-eye {{ $t("home.view") }} - mdi-eye {{ $t("home.view") }} -
-
- {{ $t("home.pendingSwaps") }} + +
-
-
- *** - {{ formatSymbol(swap.value, swap.symbol) }} - {{ $t("home.from") }} {{ formatChain(swap.sourcePlatform) }} - {{ $t("home.to") }} - {{ formatChain(swap.destinationPlatform) }} - {{ - $t("home.claim") - }} -
- -
-
- +
@@ -386,8 +373,7 @@ ************************************{{ account.neoAddress }}
- ************************************ {{ account.neoAddress }}
{{ $t("home.swap") }}{{ $t("home.send").toLowerCase() }} @@ -472,7 +458,7 @@ >************************************ {{ account.ethAddress }}
************************************ {{ account.ethAddress }}
{{ formatSymbol(bal.amount, bal.symbol) }} - + {{ $t("home.swap") }}{{ $t("home.send").toLowerCase() }} @@ -521,7 +508,16 @@ {{ $t("home.importETHWallet") }} - {{ $t("home.withYourKey") }}
+ {{ $t("home.withYourKey") }}mdi-information-outline
@@ -597,16 +593,173 @@ >-->

- {{ - $t("home.needEthToSwap", [ - ( - Math.round(100000 * ethGasPrices[1] * 1.2) / 1e9 - ).toFixed(4), - ]) - }} +
+
+ {{ $t("home.sameChain") }} +
+ + + + {{ $t("home.sendOn") }} NEO + + + mdi-arrow-right-bold + + + + +
+ {{ $t("home.assetsIn") }} + ************************************ + {{ account.neoAddress }}mdi-content-copy + + + + + *** {{ bal.symbol }}{{ + formatSymbol(bal.amount, bal.symbol) + }} + + + {{ + $t("home.send").toLowerCase() + }} + + + + +
+
+
+ + + + + {{ $t("home.sendOn") }} Ethereum + + + + mdi-arrow-right-bold + + + + +
+ {{ $t("home.assetsIn") }} + ************************************ + {{ account.ethAddress }}mdi-content-copy + + + + + {{ formatSymbol(bal.amount, bal.symbol) }} + + + {{ + $t("home.send").toLowerCase() + }} + + + + +
+ {{ $t("home.or") }} + {{ + $t("home.exportPrivateKey") + }} + {{ $t("home.andImportInMetamask") + }}mdi-information-outline +
+
+
@@ -812,10 +965,16 @@ @@ -1087,7 +1246,7 @@ {{ - $t("home.swap") + $t("home.send").toLowerCase() }} @@ -1098,7 +1257,6 @@ - {{ $t("home.cancel") }} - - @@ -1122,29 +1271,44 @@ {{ - $t("home.swapUppercase") + " " + sendSymbol + swapFromChain == swapToChain + ? $t("home.send") + " " + sendSymbol + : $t("home.send") + " " + sendSymbol }} {{ $t("home.have") }} {{ sendMaxAmount }} {{ sendSymbol }}. - {{ $t("home.swapHowMany") }} + {{ + swapFromChain == swapToChain + ? $t("home.sendAmount2") + : $t("home.sendAmount2") + }} - {{ $t("home.swapAmount") }} + {{ $t("home.sendAmount") }} --> -