aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorbrunobar79 <brunobar79@gmail.com>2018-09-06 04:26:09 +0800
committerbrunobar79 <brunobar79@gmail.com>2018-09-06 04:26:09 +0800
commit8ee01f4e99d59dbe1bfa5703da9b5efda41a7a52 (patch)
tree106d2ab08621f972b4b9140df16e129a84526703 /app
parentb208ce723459a13f9b1fd6837af9d2858ba4cc17 (diff)
parentdc2431fe62bc7e50ebbf864389e9590f29d2136f (diff)
downloadtangerine-wallet-browser-8ee01f4e99d59dbe1bfa5703da9b5efda41a7a52.tar
tangerine-wallet-browser-8ee01f4e99d59dbe1bfa5703da9b5efda41a7a52.tar.gz
tangerine-wallet-browser-8ee01f4e99d59dbe1bfa5703da9b5efda41a7a52.tar.bz2
tangerine-wallet-browser-8ee01f4e99d59dbe1bfa5703da9b5efda41a7a52.tar.lz
tangerine-wallet-browser-8ee01f4e99d59dbe1bfa5703da9b5efda41a7a52.tar.xz
tangerine-wallet-browser-8ee01f4e99d59dbe1bfa5703da9b5efda41a7a52.tar.zst
tangerine-wallet-browser-8ee01f4e99d59dbe1bfa5703da9b5efda41a7a52.zip
Merge branch 'develop' of github.com:MetaMask/metamask-extension into trezor-v5
Diffstat (limited to 'app')
-rw-r--r--app/_locales/cs/messages.json2
-rw-r--r--app/_locales/de/messages.json6
-rw-r--r--app/_locales/en/messages.json34
-rw-r--r--app/_locales/es/messages.json2
-rw-r--r--app/_locales/fr/messages.json2
-rw-r--r--app/_locales/ko/messages.json822
-rw-r--r--app/_locales/ru/messages.json2
-rw-r--r--app/_locales/tml/messages.json2
-rw-r--r--app/_locales/tr/messages.json2
-rw-r--r--app/manifest.json1
-rw-r--r--app/scripts/background.js20
-rw-r--r--app/scripts/controllers/preferences.js120
-rw-r--r--app/scripts/lib/account-tracker.js18
-rw-r--r--app/scripts/lib/ipfsContent.js2
-rw-r--r--app/scripts/metamask-controller.js66
15 files changed, 941 insertions, 160 deletions
diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json
index 6a4ebc8a5..55344f3e1 100644
--- a/app/_locales/cs/messages.json
+++ b/app/_locales/cs/messages.json
@@ -796,7 +796,7 @@
"message": "Testovací faucet"
},
"to": {
- "message": "Komu: "
+ "message": "Komu"
},
"toETHviaShapeShift": {
"message": "$1 na ETH přes ShapeShift",
diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json
index c06a99250..352d5ad7d 100644
--- a/app/_locales/de/messages.json
+++ b/app/_locales/de/messages.json
@@ -384,7 +384,7 @@
"infoHelp": {
"message": "Info & Hilfe"
},
- "insufficientFunds": {
+ "insufficientFunds": {
"message": "Nicht genügend Guthaben."
},
"insufficientTokens": {
@@ -572,7 +572,7 @@
"description": "Wähle diesen Dateityp um damit einen Account zu importieren"
},
"privateKeyWarning": {
- "message": "Warnung: Niemals jemanden deinen Private Key mitteilen. Jeder der im Besitz deines Private Keys ist, kann jegliches Guthaben deines Accounts stehlen."
+ "message": "Warnung: Niemals jemanden deinen Private Key mitteilen. Jeder der im Besitz deines Private Keys ist, kann jegliches Guthaben deines Accounts stehlen."
},
"privateNetwork": {
"message": "Privates Netzwerk"
@@ -775,7 +775,7 @@
"message": "Testfaucet"
},
"to": {
- "message": "An:"
+ "message": "An"
},
"toETHviaShapeShift": {
"message": "$1 an ETH via ShapeShift",
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index a25a2bd59..14e867b33 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -29,6 +29,9 @@
"addTokens": {
"message": "Add Tokens"
},
+ "addSuggestedTokens": {
+ "message": "Add Suggested Tokens"
+ },
"addAcquiredTokens": {
"message": "Add the tokens you've acquired using MetaMask"
},
@@ -451,6 +454,9 @@
"hideTokenPrompt": {
"message": "Hide Token?"
},
+ "history": {
+ "message": "History"
+ },
"howToDeposit": {
"message": "How would you like to deposit Ether?"
},
@@ -651,7 +657,7 @@
"message": "No transaction history."
},
"noTransactions": {
- "message": "No Transactions"
+ "message": "You have no transactions"
},
"notFound": {
"message": "Not Found"
@@ -702,6 +708,9 @@
"pasteSeed": {
"message": "Paste your seed phrase here!"
},
+ "pending": {
+ "message": "pending"
+ },
"personalAddressDetected": {
"message": "Personal address detected. Input the token contract address."
},
@@ -730,6 +739,9 @@
"qrCode": {
"message": "Show QR Code"
},
+ "queue": {
+ "message": "Queue"
+ },
"readdToken": {
"message": "You can add this token back in the future by going go to “Add token” in your accounts options menu."
},
@@ -870,6 +882,12 @@
"secretPhrase": {
"message": "Enter your secret twelve word phrase here to restore your vault."
},
+ "showHexData": {
+ "message": "Show Hex Data"
+ },
+ "showHexDataDescription": {
+ "message": "Select this to show the hex data field on the send screen"
+ },
"newPassword8Chars": {
"message": "New Password (min 8 chars)"
},
@@ -897,6 +915,12 @@
"sendTokens": {
"message": "Send Tokens"
},
+ "sentEther": {
+ "message": "sent ether"
+ },
+ "sentTokens": {
+ "message": "sent tokens"
+ },
"separateEachWord": {
"message": "Separate each word with a single space"
},
@@ -910,6 +934,9 @@
"orderOneHere": {
"message": "Order a Trezor or Ledger and keep your funds in cold storage"
},
+ "outgoing": {
+ "message": "Outgoing"
+ },
"searchTokens": {
"message": "Search Tokens"
},
@@ -973,6 +1000,9 @@
"sign": {
"message": "Sign"
},
+ "signatureRequest": {
+ "message": "Signature Request"
+ },
"signed": {
"message": "Signed"
},
@@ -1025,7 +1055,7 @@
"message": "Test Faucet"
},
"to": {
- "message": "To: "
+ "message": "To"
},
"toETHviaShapeShift": {
"message": "$1 to ETH via ShapeShift",
diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json
index ed7f8f681..3e43a7b43 100644
--- a/app/_locales/es/messages.json
+++ b/app/_locales/es/messages.json
@@ -772,7 +772,7 @@
"message": "Probar Faucet"
},
"to": {
- "message": "Para:"
+ "message": "Para"
},
"toETHviaShapeShift": {
"message": "$1 a ETH via ShapeShift",
diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json
index 1463e2b5f..6f850d89b 100644
--- a/app/_locales/fr/messages.json
+++ b/app/_locales/fr/messages.json
@@ -490,7 +490,7 @@
"message": "Sélectionner un service"
},
"send": {
- "message": "Envoyé"
+ "message": "Envoyer"
},
"sendTokens": {
"message": "Envoyer des jetons"
diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json
index d3801c4f5..30d032357 100644
--- a/app/_locales/ko/messages.json
+++ b/app/_locales/ko/messages.json
@@ -3,86 +3,125 @@
"message": "수락"
},
"account": {
- "message": "계좌"
+ "message": "계정"
},
"accountDetails": {
- "message": "계좌 상세보기"
+ "message": "계정 상세보기"
},
"accountName": {
- "message": "계좌 이름"
+ "message": "계정 이름"
},
"address": {
"message": "주소"
},
+ "addCustomToken": {
+ "message": "사용자 정의 토큰 추가"
+ },
"addToken": {
"message": "토큰 추가"
},
+ "addTokens": {
+ "message": "토큰 추가"
+ },
+ "addAcquiredTokens": {
+ "message": "메타마스크를 통해 획득한 토큰 추가"
+ },
"amount": {
- "message": "금액"
+ "message": "수량"
},
"amountPlusGas": {
- "message": "금액 + 가스"
+ "message": "수량 + 가스"
},
"appDescription": {
"message": "이더리움 브라우저 확장 프로그램",
- "description": "어플리케이션 내용"
+ "description": "어플리케이션 설명"
},
"appName": {
"message": "메타마스크",
"description": "어플리케이션 이름"
},
+ "approved": {
+ "message": "수락"
+ },
"attemptingConnect": {
- "message": "블록체인에 접속 시도 중입니다."
+ "message": "블록체인에 접속을 시도하는 중입니다."
+ },
+ "attributions": {
+ "message": "속성"
},
"available": {
- "message": "사용 가능한"
+ "message": "사용 가능"
},
"back": {
- "message": "뒤로"
+ "message": "돌아가기"
},
"balance": {
- "message": "잔액:"
+ "message": "잔액"
+ },
+ "balances": {
+ "message": "토큰 잔액"
},
"balanceIsInsufficientGas": {
- "message": "가스가 충분하지 않습니다."
+ "message": "현재 가스 총합에 대해 잔액이 부족합니다"
},
"beta": {
- "message": "베타"
+ "message": "BETA"
},
"betweenMinAndMax": {
"message": "$1 이상 $2 이하여야 합니다.",
- "description": "helper for inputting hex as decimal input"
+ "description": "10진수 입력으로 hex값 입력을 도와줍니다"
+ },
+ "blockiesIdenticon": {
+ "message": "Blockies 아이덴티콘 사용"
},
"borrowDharma": {
- "message": "Dharma에서 빌리기(베타)"
+ "message": "Dharma에서 대여하기(Beta)"
+ },
+ "builtInCalifornia": {
+ "message": "메타마스크는 캘리포니아에서 디자인되고 만들어졌습니다."
},
"buy": {
"message": "구매"
},
"buyCoinbase": {
- "message": "코인베이스에서 구매"
+ "message": "코인베이스에서 구매하기"
},
"buyCoinbaseExplainer": {
- "message": "코인베이스에서 비트코인, 이더리움, 라이트코인을 구매하실 수 있습니다."
+ "message": "코인베이스는 비트코인, 이더리움, 라이트코인을 거래할 수 있는 유명한 거래소입니다."
+ },
+ "ok": {
+ "message": "확인"
},
"cancel": {
"message": "취소"
},
+ "classicInterface": {
+ "message": "예전 인터페이스"
+ },
"clickCopy": {
"message": "클릭하여 복사"
},
+ "close": {
+ "message": "닫기"
+ },
"confirm": {
"message": "승인"
},
+ "confirmed": {
+ "message": "승인됨"
+ },
"confirmContract": {
"message": "컨트랙트 승인"
},
"confirmPassword": {
- "message": "패스워드 승인"
+ "message": "비밀번호 확인"
},
"confirmTransaction": {
"message": "트랜잭션 승인"
},
+ "continue": {
+ "message": "계속"
+ },
"continueToCoinbase": {
"message": "코인베이스로 계속하기"
},
@@ -90,72 +129,93 @@
"message": "컨트랙트 배포"
},
"conversionProgress": {
- "message": "변환중.."
+ "message": "변환 진행중"
},
"copiedButton": {
- "message": "복사되었습니다."
+ "message": "복사됨"
},
"copiedClipboard": {
- "message": "클립보드에 복사되었습니다."
+ "message": "클립보드에 복사되었습니다"
},
"copiedExclamation": {
- "message": "복사되었습니다."
+ "message": "복사됨!"
+ },
+ "copiedSafe": {
+ "message": "안전한 곳에 복사하였습니다"
},
"copy": {
- "message": "복사하기"
+ "message": "복사"
+ },
+ "copyContractAddress": {
+ "message": "컨트랙트 주소 복사"
},
"copyToClipboard": {
- "message": "클립보드에 복사"
+ "message": "클립보드로 복사"
},
"copyButton": {
"message": " 복사 "
},
"copyPrivateKey": {
- "message": "비밀 키 (클릭하여 복사)"
+ "message": "비밀 키입니다 (클릭하여 복사)"
},
"create": {
"message": "생성"
},
"createAccount": {
- "message": "계좌 생성"
+ "message": "계정 생성"
},
"createDen": {
"message": "생성"
},
"crypto": {
"message": "암호화폐",
- "description": "Exchange type (cryptocurrencies)"
+ "description": "거래 유형 (암호화폐)"
+ },
+ "currentConversion": {
+ "message": "선택된 단위"
+ },
+ "currentNetwork": {
+ "message": "현재 네트워크"
},
"customGas": {
"message": "가스 설정"
},
+ "customToken": {
+ "message": "사용자 정의 토큰"
+ },
"customize": {
- "message": "커스터마이즈"
+ "message": "맞춤화 하기"
},
"customRPC": {
- "message": "커스텀 RPC"
+ "message": "사용자 정의 RPC"
+ },
+ "decimalsMustZerotoTen": {
+ "message": "소수점은 0 이상이고 36 이하여야 합니다."
+ },
+ "decimal": {
+ "message": "소수점 정확도"
},
"defaultNetwork": {
"message": "이더리움 트랜잭션의 기본 네트워크는 메인넷입니다."
},
"denExplainer": {
- "message": "DEN은 비밀번호가 암호화 된 MetaMask의 스토리지입니다."
+ "message": "DEN은 비밀번호로 암호화 된 메타마스크의 저장소입니다."
},
"deposit": {
"message": "입금"
},
"depositBTC": {
- "message": "아래 주소로 BTC를 입급해주세요."
+ "message": "다음 주소로 BTC를 입급해주세요."
},
"depositCoin": {
- "message": "아래 주소로 $1를 입금해주세요.",
- "description": "Tells the user what coin they have selected to deposit with shapeshift"
+ "message": "다음 주소로 $1 만큼 입금해주세요.",
+ "description": "사용자에게 shapeshift에서 어떤 코인을 선택해 입금했는지 알려줍니다"
},
"depositEth": {
- "message": "이더 입금"
+ "message": "이더 입금하기"
},
"depositEther": {
- "message": "이더 입금"
+ "message": "이더리움 입금하기"
},
"depositFiat": {
"message": "현금으로 입금하기"
@@ -167,10 +227,10 @@
"message": "ShapeShift를 통해 입금하기"
},
"depositShapeShiftExplainer": {
- "message": "다른 암호화폐를 가지고 있으면, 계좌 생성 필요없이, 거래를 하거나 메타마스크 지갑을 통해 이더를 입금할 수 있습니다."
+ "message": "다른 암호화폐를 가지고 있으면, 계정을 생성할 필요없이 메타마스크 지갑에 이더리움을 바로 거래하거나 입금할 수 있습니다."
},
"details": {
- "message": "상세"
+ "message": "세부사항"
},
"directDeposit": {
"message": "즉시 입금"
@@ -179,70 +239,103 @@
"message": "이더 즉시 입금"
},
"directDepositEtherExplainer": {
- "message": "이더를 이미 보유하고 있다면, 직접 입금을 통해 이더를 즉시 입금하실 수 있습니다."
+ "message": "약간의 이더를 이미 보유하고 있다면, 새로 만든 지갑에 직접 입금하여 이더를 보유할 수 있습니다."
},
"done": {
"message": "완료"
},
+ "downloadStateLogs": {
+ "message": "상태 로그 다운로드"
+ },
+ "dropped": {
+ "message": "중단됨"
+ },
"edit": {
"message": "수정"
},
"editAccountName": {
- "message": "계좌명 수정"
+ "message": "계정 이름 수정"
+ },
+ "editingTransaction": {
+ "message": "트랜젝션을 변경합니다"
+ },
+ "emailUs": {
+ "message": "저자에게 메일 보내기!"
},
"encryptNewDen": {
- "message": "새 DEN 암호화"
+ "message": "새로운 DEN을 암호화"
},
"enterPassword": {
- "message": "패스워드를 입력해주세요."
+ "message": "비밀번호를 입력해주세요"
+ },
+ "enterPasswordConfirm": {
+ "message": "비밀번호를 다시 입력해 주세요"
+ },
+ "enterPasswordContinue": {
+ "message": "계속하기 위해 비밀번호 입력"
+ },
+ "passwordNotLongEnough": {
+ "message": "비밀번호가 충분히 길지 않습니다"
+ },
+ "passwordsDontMatch": {
+ "message": "비밀번호가 맞지 않습니다"
},
"etherscanView": {
- "message": "이더스캔에서 계좌보기"
+ "message": "이더스캔에서 계정보기"
},
"exchangeRate": {
"message": "환율"
},
"exportPrivateKey": {
- "message": "비밀키 내보내기"
+ "message": "개인키 내보내기"
},
"exportPrivateKeyWarning": {
- "message": "Export private keys at your own risk."
+ "message": "개인키 내보내기는 위험을 감수해야 합니다."
},
"failed": {
"message": "실패"
},
"fiat": {
"message": "FIAT",
- "description": "Exchange type"
+ "description": "거래 형식"
},
"fileImportFail": {
- "message": "파일을 가져올 수 없나요? 여기를 클릭해주세요!",
- "description": "Helps user import their account from a JSON file"
+ "message": "파일을 가져올 수 없나요? 이곳을 클릭해주세요!",
+ "description": "JSON 파일로부터 계정 가져오기를 도와줍니다"
+ },
+ "followTwitter": {
+ "message": "트위터에서 팔로우하세요"
},
"from": {
- "message": "보내는 사람"
+ "message": "보내는 이"
+ },
+ "fromToSame": {
+ "message": "보내고 받는 주소는 동일할 수 없습니다"
},
"fromShapeShift": {
"message": "ShapeShift로 부터"
},
"gas": {
"message": "가스",
- "description": "Short indication of gas cost"
+ "description": "가스 가격의 줄임"
},
"gasFee": {
"message": "가스 수수료"
},
"gasLimit": {
- "message": "가스 리밋"
+ "message": "가스 한도"
},
"gasLimitCalculation": {
- "message": "네트워크 성공률을 기반으로 적합한 가스 리밋을 계산합니다."
+ "message": "네트워크 성공률을 기반으로 적합한 가스 한도를 계산합니다."
},
"gasLimitRequired": {
- "message": "가스 리밋이 필요합니다."
+ "message": "가스 한도가 필요합니다."
},
"gasLimitTooLow": {
- "message": "가스 리밋은 21000 이상이여야 합니다."
+ "message": "가스 한도는 최소 21000 이상이여야 합니다."
+ },
+ "generatingSeed": {
+ "message": "시드 생성중..."
},
"gasPrice": {
"message": "가스 가격 (GWEI)"
@@ -253,21 +346,27 @@
"gasPriceRequired": {
"message": "가스 가격이 필요합니다."
},
+ "generatingTransaction": {
+ "message": "트랜잭션 생성중"
+ },
"getEther": {
"message": "이더 얻기"
},
"getEtherFromFaucet": {
- "message": "faucet에서 $1에 달하는 이더를 얻으세요.",
- "description": "Displays network name for Ether faucet"
+ "message": "파우셋에서 $1에 달하는 이더를 얻으세요.",
+ "description": "이더 파우셋에 대한 네트워크 이름을 표시합니다"
},
"greaterThanMin": {
"message": "$1 이상이어야 합니다.",
- "description": "helper for inputting hex as decimal input"
+ "description": "10진수 입력으로 hex값 입력을 도와줍니다"
},
"here": {
"message": "여기",
"description": "as in -click here- for more information (goes with troubleTokenBalances)"
},
+ "hereList": {
+ "message": "리스트가 있습니다!!!!"
+ },
"hide": {
"message": "숨기기"
},
@@ -280,51 +379,96 @@
"howToDeposit": {
"message": "어떤 방법으로 이더를 입금하시겠습니까?"
},
+ "holdEther": {
+ "message": "It allows you to hold ether & tokens, and serves as your bridge to decentralized applications."
+ },
"import": {
- "message": "파일에서 가져오기",
- "description": "Button to import an account from a selected file"
+ "message": "가져오기",
+ "description": "선택된 파일로부터 계정 가져오기 버튼"
},
"importAccount": {
- "message": "계좌 가져오기"
+ "message": "계정 가져오기"
+ },
+ "importAccountMsg": {
+ "message": " 가져온 계정은 메타마스크에서 원래 생성된 계정의 시드구문과 연관성이 없습니다. 가져온 계정에 대해 더 배우기 "
},
"importAnAccount": {
- "message": "계좌 가져오기"
+ "message": "계정 가져오기"
},
"importDen": {
- "message": "기존 DEN 가져오기"
+ "message": "기존의 DEN 가져오기"
},
"imported": {
- "message": "가져오기 완료",
- "description": "status showing that an account has been fully loaded into the keyring"
+ "message": "가져온 계정",
+ "description": "이 상태는 해당 계정이 keyring으로 완전히 적재된 상태임을 표시합니다"
+ },
+ "importUsingSeed": {
+ "message": "계정 시드 구문으로 가져오기"
},
"infoHelp": {
"message": "정보 및 도움말"
},
+ "initialTransactionConfirmed": {
+ "message": "초기 트랜잭션이 네트워크를 통해 확정되었습니다. 확인을 누르고 이전으로 돌아갑니다."
+ },
+ "insufficientFunds": {
+ "message": "충분하지 않은 자금."
+ },
+ "insufficientTokens": {
+ "message": "충분하지 않은 토큰."
+ },
"invalidAddress": {
- "message": "유효하지 않은 주소"
+ "message": "올바르지 않은 주소"
+ },
+ "invalidAddressRecipient": {
+ "message": "수신 주소가 올바르지 않습니다"
},
"invalidGasParams": {
- "message": "유효하지 않은 가스 입력값"
+ "message": "올바르지 않은 가스 입력값"
},
"invalidInput": {
- "message": "유효하지 않은 입력값"
+ "message": "올바르지 않은 입력값"
},
"invalidRequest": {
"message": "유효하지 않은 요청"
},
+ "invalidRPC": {
+ "message": "올바르지 않은 RPC URI"
+ },
+ "jsonFail": {
+ "message": "이상이 있습니다. JSON 파일이 올바른 파일인지 확인해주세요."
+ },
"jsonFile": {
"message": "JSON 파일",
- "description": "format for importing an account"
+ "description": "계정을 가져오기 위한 형식"
+ },
+ "keepTrackTokens": {
+ "message": "메타마스크 계정을 통해 구입한 토큰 기록을 추적 및 보관합니다."
},
"kovan": {
"message": "Kovan 테스트넷"
},
+ "knowledgeDataBase": {
+ "message": "지식 베이스 방문"
+ },
+ "max": {
+ "message": "최대"
+ },
+ "learnMore": {
+ "message": "더 배우기."
+ },
"lessThanMax": {
"message": "$1 이하여야합니다.",
- "description": "helper for inputting hex as decimal input"
+ "description": "10진수 입력으로 hex값 입력을 도와줍니다"
+ },
+ "likeToAddTokens": {
+ "message": "토큰을 추가하시겠습니까?"
+ },
+ "links": {
+ "message": "링크"
},
"limit": {
- "message": "리밋"
+ "message": "한도"
},
"loading": {
"message": "로딩중..."
@@ -335,11 +479,17 @@
"localhost": {
"message": "로컬호스트 8545"
},
+ "login": {
+ "message": "로그인"
+ },
"logout": {
"message": "로그아웃"
},
"loose": {
- "message": "외부 비밀키"
+ "message": "느슨함"
+ },
+ "loweCaseWords": {
+ "message": "시드 단어는 소문자만 가능합니다"
},
"mainnet": {
"message": "이더리움 메인넷"
@@ -347,94 +497,127 @@
"message": {
"message": "메시지"
},
+ "metamaskDescription": {
+ "message": "메타마스크는 이더리움을 위한 안전한 신분 저장소입니다."
+ },
+ "metamaskSeedWords": {
+ "message": "메타마스크 시드 단어"
+ },
"min": {
"message": "최소"
},
"myAccounts": {
- "message": "내 계좌"
+ "message": "내 계정"
+ },
+ "mustSelectOne": {
+ "message": "적어도 하나의 토큰을 선택하세요."
},
"needEtherInWallet": {
- "message": "dApp을 이용하기 위해서는 지갑에 이더가 있어야 합니다."
+ "message": "메타마스크를 통한 dApp을 이용하기 위해서는 지갑에 이더가 있어야 합니다."
},
"needImportFile": {
"message": "가져올 파일을 선택해주세요.",
- "description": "User is important an account and needs to add a file to continue"
+ "description": "사용자는 계정을 가져오기 위해서 파일을 추가후 계속 진행해야 합니다"
},
"needImportPassword": {
- "message": "선택 된 파일에 패스워드를 입력해주세요.",
- "description": "Password and file needed to import an account"
+ "message": "선택 된 파일에 대한 비밀번호를 입력해주세요.",
+ "description": "계정을 가져오기 위해서 비밀번호와 파일이 필요합니다."
+ },
+ "negativeETH": {
+ "message": "음수값의 이더를 보낼 수 없습니다."
},
"networks": {
"message": "네트워크"
},
+ "nevermind": {
+ "message": "상관안함"
+ },
"newAccount": {
- "message": "새 계좌"
+ "message": "새 계정"
},
"newAccountNumberName": {
- "message": "새 계좌 $1",
- "description": "Default name of next account to be created on create account screen"
+ "message": "새 계정 $1",
+ "description": "계정 생성시 볼 수 있는 새 계정의 기본 이름"
},
"newContract": {
"message": "새 컨트랙트"
},
"newPassword": {
- "message": "새 패스워드 (최소 8자 이상)"
+ "message": "새 비밀번호 (최소 8자 이상)"
},
"newRecipient": {
"message": "받는 사람"
},
+ "newRPC": {
+ "message": "새로운 RPC URL"
+ },
"next": {
"message": "다음"
},
"noAddressForName": {
- "message": "이 이름에는 주소가 설정되어 있지 않습니다."
+ "message": "이 이름에 대해 주소가 설정되어 있지 않습니다."
},
"noDeposits": {
- "message": "입금이 없습니다."
+ "message": "입금 내역이 없습니다."
},
"noTransactionHistory": {
"message": "트랜잭션 기록이 없습니다."
},
"noTransactions": {
- "message": "트랜잭션이 없습니다."
+ "message": "트랜잭션이 없습니다"
},
"notStarted": {
- "message": "시작되지 않음."
+ "message": "시작 안됨"
},
"oldUI": {
- "message": "구버전의 UI"
+ "message": "구버전 UI"
},
"oldUIMessage": {
- "message": "구버전 UI로 변경하셨습니다. 우 상단 드랍다운 메뉴에서 새 UI로 변경하실 수 있습니다."
+ "message": "구버전 UI로 변경하셨습니다. 우 상단 드롭다운 메뉴에서 새 UI로 변경하실 수 있습니다."
},
"or": {
"message": "또는",
- "description": "choice between creating or importing a new account"
+ "description": "새 계정을 만들거나 가져오기중에 선택하기"
+ },
+ "password": {
+ "message": "비밀번호"
+ },
+ "passwordCorrect": {
+ "message": "비밀번호가 맞는지 확인해주세요."
},
"passwordMismatch": {
- "message": "패스워드가 일치하지 않습니다.",
- "description": "in password creation process, the two new password fields did not match"
+ "message": "비밀번호가 일치하지 않습니다.",
+ "description": "비밀번호를 생성하는 과정에서 두개의 새 비밀번호 입력란이 일치하지 않습니다"
},
"passwordShort": {
- "message": "패스워드가 너무 짧습니다.",
- "description": "in password creation process, the password is not long enough to be secure"
+ "message": "비밀번호가 짧습니다.",
+ "description": "비밀번호를 생성하는 과정에서 비밀번호가 짧으면 안전하지 않습니다"
},
"pastePrivateKey": {
- "message": "비밀키를 입력해주세요.",
- "description": "For importing an account from a private key"
+ "message": "개인키를 입력해주세요:",
+ "description": "개인키로부터 계정을 가져오는 것입니다"
},
"pasteSeed": {
- "message": "시드 문장들을 붙여넣어주세요."
+ "message": "시드 구문을 이곳에 붙여넣어주세요!"
+ },
+ "personalAddressDetected": {
+ "message": "개인 주소가 탐지됨. 토큰 컨트랙트 주소를 입력하세요."
},
"pleaseReviewTransaction": {
"message": "트랜잭션을 검토해주세요."
},
+ "popularTokens": {
+ "message": "인기있는 토큰"
+ },
+ "privacyMsg": {
+ "message": "개인정보 보호 정책"
+ },
"privateKey": {
- "message": "비밀키",
- "description": "select this type of file to use to import an account"
+ "message": "개인키",
+ "description": "이 형식의 파일을 선택하여 계정을 가져올 수 있습니다"
},
"privateKeyWarning": {
- "message": " 절대 이 키를 노출하지 마십시오. 비밀키가 노출되면 누구나 당신의 계좌에서 자산을 빼갈 수 있습니다."
+ "message": " 절대 이 키를 노출하지 마십시오. 개인키가 노출되면 누구나 당신의 계정에서 자산을 빼갈 수 있습니다."
},
"privateNetwork": {
"message": "프라이빗 네트워크"
@@ -446,28 +629,64 @@
"message": "옵션 메뉴에서 “토큰 추가”를 눌러서 추후에 다시 이 토큰을 추가하실 수 있습니다."
},
"readMore": {
- "message": "더 읽기."
+ "message": "여기서 더 보기."
+ },
+ "readMore2": {
+ "message": "더 보기."
},
"receive": {
"message": "받기"
},
"recipientAddress": {
- "message": "받는 사람 주소"
+ "message": "받는 주소"
},
"refundAddress": {
"message": "환불받을 주소"
},
"rejected": {
- "message": "거부되었음."
+ "message": "거부됨"
+ },
+ "reset": {
+ "message": "초기화"
+ },
+ "resetAccount": {
+ "message": "계정 초기화"
+ },
+ "resetAccountDescription": {
+ "message": "계정을 초기화 하는 경우에 트랜잭션 기록이 삭제됩니다."
+ },
+ "restoreFromSeed": {
+ "message": "계정을 복구하시겠습니까?"
+ },
+ "restoreVault": {
+ "message": "저장소 복구"
},
"required": {
- "message": "필요함."
+ "message": "필요함"
},
"retryWithMoreGas": {
- "message": "더 높은 가스 가격으로 다시 시도해주세요."
+ "message": "더 높은 가스 가격으로 다시 시도해주세요"
+ },
+ "walletSeed": {
+ "message": "지갑 시드값"
+ },
+ "revealSeedWords": {
+ "message": "시드 단어 보이기"
+ },
+ "revealSeedWordsTitle": {
+ "message": "시드 단어"
+ },
+ "revealSeedWordsDescription": {
+ "message": "브라우저를 바꾸거나 컴퓨터를 옮기는 경우 이 시드 구문이 필요하며 이를 통해 계정에 접근할 수 있습니다. 시드 구문을 안전한 곳에 보관하세요."
+ },
+ "revealSeedWordsWarningTitle": {
+ "message": "이 구문을 다른사람과 절대로 공유하지 마세요!"
+ },
+ "revealSeedWordsWarning": {
+ "message": "이 단어모음은 당신의 모든 계정을 훔치는데 사용할 수 있습니다."
},
"revert": {
- "message": "취소"
+ "message": "되돌림"
},
"rinkeby": {
"message": "Rinkeby 테스트넷"
@@ -475,46 +694,122 @@
"ropsten": {
"message": "Ropsten 테스트넷"
},
+ "rpc": {
+ "message": "사용자 정의 RPC"
+ },
+ "currentRpc": {
+ "message": "현재 RPC"
+ },
+ "connectingToMainnet": {
+ "message": "이더리움 메인넷 접속중"
+ },
+ "connectingToRopsten": {
+ "message": "Ropsten 테스트넷 접속중"
+ },
+ "connectingToKovan": {
+ "message": "Kovan 테스트넷 접속중"
+ },
+ "connectingToRinkeby": {
+ "message": "Rinkeby 테스트넷 접속중"
+ },
+ "connectingToUnknown": {
+ "message": "알려지지 않은 네트워크 접속중"
+ },
"sampleAccountName": {
- "message": "예) 나의 새 계좌",
- "description": "Help user understand concept of adding a human-readable name to their account"
+ "message": "예) 나의 새 계정",
+ "description": "각 계정에 대해서 구별하기 쉬운 이름을 지정하여 사용자가 쉽게 이해할 수 있게 합니다"
},
"save": {
"message": "저장"
},
+ "speedUpTitle": {
+ "message": "트랜잭션 속도 향상하기"
+ },
+ "speedUpSubtitle": {
+ "message": "트랜잭션 가스 가격을 늘려서 해당 트랙잭션에 덮어쓰기 하여 속도를 빠르게 합니다"
+ },
+ "saveAsCsvFile": {
+ "message": "CSV 파일로 저장"
+ },
"saveAsFile": {
"message": "파일로 저장",
- "description": "Account export process"
+ "description": "계정 내보내기 절차"
+ },
+ "saveSeedAsFile": {
+ "message": "시드 단어를 파일로 저장하기"
+ },
+ "search": {
+ "message": "검색"
+ },
+ "searchResults": {
+ "message": "검색 결과"
+ },
+ "secretPhrase": {
+ "message": "12개 단어로 구성된 비밀 구문을 입력하여 저장소를 복구하세요."
+ },
+ "newPassword8Chars": {
+ "message": "새 비밀번호 (최소 8문자)"
+ },
+ "seedPhraseReq": {
+ "message": "시드 구문은 12개의 단어입니다"
+ },
+ "select": {
+ "message": "선택"
+ },
+ "selectCurrency": {
+ "message": "통화 선택"
},
"selectService": {
"message": "서비스 선택"
},
+ "selectType": {
+ "message": "형식 선택"
+ },
"send": {
"message": "전송"
},
+ "sendETH": {
+ "message": "ETH 보내기"
+ },
"sendTokens": {
"message": "토큰 전송"
},
+ "onlySendToEtherAddress": {
+ "message": "이더리움 주소로 ETH만 송금하세요."
+ },
+ "onlySendTokensToAccountAddress": {
+ "message": "이더리움계정 주소로 $1 만 보내기.",
+ "description": "토큰 심볼 보이기"
+ },
+ "searchTokens": {
+ "message": "토큰 검색"
+ },
"sendTokensAnywhere": {
- "message": "이더 계좌로 토큰 전송"
+ "message": "이더 계정로 토큰 전송"
},
"settings": {
"message": "설정"
},
+ "info": {
+ "message": "정보"
+ },
"shapeshiftBuy": {
"message": "Shapeshift를 통해서 구매하기"
},
"showPrivateKeys": {
- "message": "비밀키 보기"
+ "message": "개인키 보기"
},
"showQRCode": {
- "message": "QR코드 보기"
+ "message": "QR 코드 보기"
},
"sign": {
"message": "서명"
},
+ "signed": {
+ "message": "서명됨"
+ },
"signMessage": {
- "message": "서명 메시지"
+ "message": "메시지 서명"
},
"signNotice": {
"message": "이 메시지에 대한 서명은 위험할 수 있습니다.\n 완전히 신뢰할 수 있는 사이트에서만 서명해주세요.\n 안전을 위해 추후의 버전에서는 삭제될 기능입니다. "
@@ -523,33 +818,81 @@
"message": "서명 요청"
},
"sigRequested": {
- "message": "서명이 요청되었습니다."
+ "message": "서명이 요청됨"
+ },
+ "spaceBetween": {
+ "message": "단어 사이에는 공백만 올 수 있습니다"
},
"status": {
"message": "상태"
},
+ "stateLogs": {
+ "message": "상태 로그"
+ },
+ "stateLogsDescription": {
+ "message": "상태 로그에는 공개 계정 주소와 송신 트랜잭션 정보가 들어있습니다."
+ },
+ "stateLogError": {
+ "message": "상태 로그 받기 실패."
+ },
"submit": {
"message": "제출"
},
+ "submitted": {
+ "message": "제출됨"
+ },
+ "supportCenter": {
+ "message": "지원 센터에 방문하기"
+ },
+ "symbolBetweenZeroTen": {
+ "message": "심볼은 0에서 10개 사이의 문자여야 합니다."
+ },
"takesTooLong": {
"message": "너무 오래걸리나요?"
},
+ "terms": {
+ "message": "사용 지침"
+ },
"testFaucet": {
- "message": "Faucet 테스트"
+ "message": "파우셋 테스트"
},
"to": {
- "message": "대상"
+ "message": "받는이: "
},
"toETHviaShapeShift": {
"message": "ShapeShift를 통해 $1를 ETH로 바꾸기",
- "description": "system will fill in deposit type in start of message"
+ "description": "시스템이 시작할 때에 입금 유형을 입력해줍니다"
+ },
+ "token": {
+ "message": "토큰"
+ },
+ "tokenAddress": {
+ "message": "토큰 주소"
+ },
+ "tokenAlreadyAdded": {
+ "message": "토큰이 이미 추가되어있습니다."
},
"tokenBalance": {
- "message": "현재 토큰 잔액: "
+ "message": "현재 토큰 잔액:"
+ },
+ "tokenSelection": {
+ "message": "토큰을 검색하거나 유명한 토큰 리스트에서 선택하시기 바랍니다."
+ },
+ "tokenSymbol": {
+ "message": "토큰 기호"
+ },
+ "tokenWarning1": {
+ "message": "메타마스크 계좌를 통해 구입한 토큰을 추적합니다. 다른 계정으로 토큰을 구입한 경우 이곳에 나타나지 않습니다."
},
"total": {
"message": "합계"
},
+ "transactions": {
+ "message": "트랜잭션"
+ },
+ "transactionError": {
+ "message": "트랜잭션 오류. 컨트랙트 코드에서 예외 발생(Exception thrown)."
+ },
"transactionMemo": {
"message": "트랜잭션 메모 (선택사항)"
},
@@ -560,23 +903,29 @@
"message": "전송"
},
"troubleTokenBalances": {
- "message": "토큰 잔액을 가져오는데에 문제가 생겼습니다. (여기)서 상세내용을 볼 수 있습니다.",
- "description": "Followed by a link (here) to view token balances"
+ "message": "토큰 잔액을 가져오는데에 문제가 생겼습니다. 링크에서 상세내용을 볼 수 있습니다.",
+ "description": "토큰 잔액을 보려면 (here) 링크를 따라가세요"
+ },
+ "twelveWords": {
+ "message": "12개의 단어는 메타마스크 계정을 복구하기 위한 유일한 방법입니다.\n안전한 장소에 보관하시기 바랍니다."
},
"typePassword": {
- "message": "패스워드를 입력하세요."
+ "message": "비밀번호를 입력하세요"
},
"uiWelcome": {
- "message": "새 UI에 오신 것을 환영합니다. (베타)"
+ "message": "새로운 UI에 오신 것을 환영합니다. (Beta)"
},
"uiWelcomeMessage": {
- "message": "새 메타마스크 UI를 사용하고 계십니다. 토큰 전송과 같은 새 기능들을 사용해보시면서 문제가 있다면 알려주세요."
+ "message": "새로운 메타마스크 UI를 사용하고 계십니다. 토큰 전송과 같은 새 기능들을 사용해보시면서 문제가 있다면 알려주세요."
+ },
+ "unapproved": {
+ "message": "허가안됨"
},
"unavailable": {
- "message": "유효하지 않은"
+ "message": "유효하지 않음"
},
"unknown": {
- "message": "알려지지 않은"
+ "message": "알려지지 않음"
},
"unknownNetwork": {
"message": "알려지지 않은 프라이빗 네트워크"
@@ -584,19 +933,46 @@
"unknownNetworkId": {
"message": "알려지지 않은 네트워크 ID"
},
+ "unlockMessage": {
+ "message": "우리가 기다리던 분권형 웹입니다"
+ },
+ "uriErrorMsg": {
+ "message": "URI는 HTTP/HTTPS로 시작해야 합니다."
+ },
"usaOnly": {
"message": "USA 거주자 한정",
- "description": "Using this exchange is limited to people inside the USA"
+ "description": "해당 거래소는 USA거주자에 한해서만 사용가능합니다"
},
"usedByClients": {
- "message": "다양한 클라이언트에서 사용되고 있습니다."
+ "message": "다양한 클라이언트에서 사용되고 있습니다"
+ },
+ "useOldUI": {
+ "message": "예전 UI 사용"
+ },
+ "validFileImport": {
+ "message": "가져오기 위해 유효한 파일을 선택해야 합니다."
+ },
+ "vaultCreated": {
+ "message": "저장소가 생성됨"
},
"viewAccount": {
- "message": "계좌 보기"
+ "message": "계정 보기"
+ },
+ "viewOnEtherscan": {
+ "message": "이터스캔에서 보기"
+ },
+ "visitWebSite": {
+ "message": "웹사이트 방문"
},
"warning": {
"message": "경고"
},
+ "welcomeBack": {
+ "message": "환영합니다!"
+ },
+ "welcomeBeta": {
+ "message": "메타마스크 Beta에 오신 것을 환영합니다"
+ },
"whatsThis": {
"message": "이것은 무엇인가요?"
},
@@ -604,6 +980,204 @@
"message": "서명이 요청되고 있습니다."
},
"youSign": {
- "message": "서명 중입니다."
+ "message": "서명 중입니다"
+ },
+ "yourPrivateSeedPhrase": {
+ "message": "개인 시드 구문"
+ },
+ "accessingYourCamera": {
+ "message": "카메라 접근중..."
+ },
+ "accountSelectionRequired": {
+ "message": "계정을 선택하셔야 합니다!"
+ },
+ "approve": {
+ "message": "수락"
+ },
+ "browserNotSupported": {
+ "message": "브라우저가 지원하지 않습니다..."
+ },
+ "bytes": {
+ "message": "바이트"
+ },
+ "chromeRequiredForHardwareWallets": {
+ "message": "하드웨어 지갑을 연결하기 위해서는 구글 크롬에서 메타마스크를 사용하셔야 합니다."
+ },
+ "connectHardwareWallet": {
+ "message": "하드웨어 지갑 연결"
+ },
+ "connect": {
+ "message": "연결"
+ },
+ "connecting": {
+ "message": "연결중..."
+ },
+ "connectToLedger": {
+ "message": "Ledger 연결"
+ },
+ "connectToTrezor": {
+ "message": "Trezor 연결"
+ },
+ "copyAddress": {
+ "message": "클립보드로 주소 복사"
+ },
+ "downloadGoogleChrome": {
+ "message": "구글 크롬 다운로드"
+ },
+ "dontHaveAHardwareWallet": {
+ "message": "하드웨어 지갑이 없나요?"
+ },
+ "ensNameNotFound": {
+ "message": "ENS 이름을 찾을 수 없습니다"
+ },
+ "parameters": {
+ "message": "매개변수"
+ },
+ "forgetDevice": {
+ "message": "장치 연결 해제"
+ },
+ "functionType": {
+ "message": "함수 유형"
+ },
+ "getHelp": {
+ "message": "도움말"
+ },
+ "hardware": {
+ "message": "하드웨어"
+ },
+ "hardwareWalletConnected": {
+ "message": "하드웨어 지갑이 연결됨"
+ },
+ "hardwareWallets": {
+ "message": "하드웨어 지갑 연결"
+ },
+ "hardwareWalletsMsg": {
+ "message": "메타마스크에서 사용할 하드웨어 지갑을 선택해주세요"
+ },
+ "havingTroubleConnecting": {
+ "message": "연결에 문제가 있나요?"
+ },
+ "hexData": {
+ "message": "Hex 데이터"
+ },
+ "invalidSeedPhrase": {
+ "message": "잘못된 시드 구문"
+ },
+ "ledgerAccountRestriction": {
+ "message": "새 계정을 추가하려면 최소 마지막 계정을 사용해야 합니다."
+ },
+ "menu": {
+ "message": "메뉴"
+ },
+ "noConversionRateAvailable": {
+ "message": "변환 비율을 찾을 수 없습니다"
+ },
+ "notFound": {
+ "message": "찾을 수 없음"
+ },
+ "noWebcamFoundTitle": {
+ "message": "웹캠이 없습니다"
+ },
+ "noWebcamFound": {
+ "message": "컴퓨터의 웹캠을 찾을 수 없습니다. 다시 시도해보세요."
+ },
+ "openInTab": {
+ "message": "탭으로 열기"
+ },
+ "origin": {
+ "message": "Origin"
+ },
+ "prev": {
+ "message": "이전"
+ },
+ "restoreAccountWithSeed": {
+ "message": "시드 구문으로 계정 복구하기"
+ },
+ "restore": {
+ "message": "복구"
+ },
+ "remove": {
+ "message": "제거"
+ },
+ "removeAccount": {
+ "message": "계정 제거"
+ },
+ "removeAccountDescription": {
+ "message": "이 계정한 지갑에서 삭제될 것입니다. 지우기 전에 이 계정에 대한 개인 키 혹은 시드 구문을 가지고 있는지 확인하세요. 계정 드랍다운 메뉴를 통해서 계정을 가져오거나 생성할 수 있습니다."
+ },
+ "readyToConnect": {
+ "message": "접속 준비되었나요?"
+ },
+ "separateEachWord": {
+ "message": "각 단어는 공백 한칸으로 분리합니다"
+ },
+ "orderOneHere": {
+ "message": "Trezor 혹은 Ledger를 구입하고 자금을 콜드 스토리지에 저장합니다"
+ },
+ "selectAnAddress": {
+ "message": "주소 선택"
+ },
+ "selectAnAccount": {
+ "message": "계정 선택"
+ },
+ "selectAnAccountHelp": {
+ "message": "메타마스크에서 보기위한 계정 선택"
+ },
+ "selectHdPath": {
+ "message": "HD 경로 지정"
+ },
+ "selectPathHelp": {
+ "message": "하단에서 Ledger지갑 계정을 찾지 못하겠으면 \"Legacy (MEW / MyCrypto)\" 경로로 바꿔보세요"
+ },
+ "step1HardwareWallet": {
+ "message": "1. 하드웨어 지갑 연결"
+ },
+ "step1HardwareWalletMsg": {
+ "message": "하드웨어 지갑을 컴퓨터에 연결해주세요."
+ },
+ "step2HardwareWallet": {
+ "message": "2. 계정 선택"
+ },
+ "step2HardwareWalletMsg": {
+ "message": "보고 싶은 계정을 선택합니다. 한번에 하나의 계정만 선택할 수 있습니다."
+ },
+ "step3HardwareWallet": {
+ "message": "3. dApps을 사용하거나 다른 것을 합니다!"
+ },
+ "step3HardwareWalletMsg": {
+ "message": "다른 이더리움 계정을 사용하듯 하드웨어 계정을 사용합니다. dApps을 로그인하거나, 이더를 보내거나, ERC20토큰 혹은 대체가능하지 않은 토큰 (예를 들어 CryptoKitties)을 사거나 저장하거나 합니다."
+ },
+ "scanInstructions": {
+ "message": "QR 코드를 카메라 앞에 가져다 놓아주세요"
+ },
+ "scanQrCode": {
+ "message": "QR 코드 스캔"
+ },
+ "transfer": {
+ "message": "전송"
+ },
+ "trezorHardwareWallet": {
+ "message": "TREZOR 하드웨어 지갑"
+ },
+ "tryAgain": {
+ "message": "다시 시도하세요"
+ },
+ "unknownFunction": {
+ "message": "알 수 없는 함수"
+ },
+ "unknownQrCode": {
+ "message": "오류: QR 코드를 확인할 수 없습니다"
+ },
+ "unknownCameraErrorTitle": {
+ "message": "이런! 뭔가 잘못되었습니다...."
+ },
+ "unknownCameraError": {
+ "message": "카메라를 접근하는 중 오류가 발생했습니다. 다시 시도해 주세요..."
+ },
+ "unlock": {
+ "message": "잠금 해제"
+ },
+ "youNeedToAllowCameraAccess": {
+ "message": "이 기능을 사용하려면 카메라 접근을 허용해야 합니다."
}
}
diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json
index bb722735d..6344e1beb 100644
--- a/app/_locales/ru/messages.json
+++ b/app/_locales/ru/messages.json
@@ -784,7 +784,7 @@
"message": "Тестовый кран"
},
"to": {
- "message": "Получатель: "
+ "message": "Получатель"
},
"toETHviaShapeShift": {
"message": "$1 в ETH через ShapeShift",
diff --git a/app/_locales/tml/messages.json b/app/_locales/tml/messages.json
index fcc418bac..4f733458e 100644
--- a/app/_locales/tml/messages.json
+++ b/app/_locales/tml/messages.json
@@ -796,7 +796,7 @@
"message": "சோதனை குழாய்"
},
"to": {
- "message": "பெறுநர்: "
+ "message": "பெறுநர்"
},
"toETHviaShapeShift": {
"message": "$ 1 முதல் ETH வரை வடிவம்",
diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json
index 08ba6cde8..8be695108 100644
--- a/app/_locales/tr/messages.json
+++ b/app/_locales/tr/messages.json
@@ -796,7 +796,7 @@
"message": "Test Musluğu"
},
"to": {
- "message": "Kime: "
+ "message": "Kime"
},
"toETHviaShapeShift": {
"message": "ShapeShift üstünden $1'dan ETH'e",
diff --git a/app/manifest.json b/app/manifest.json
index 1e12f35b4..7793c6e38 100644
--- a/app/manifest.json
+++ b/app/manifest.json
@@ -71,7 +71,6 @@
"activeTab",
"webRequest",
"*://*.eth/",
- "*://*.test/",
"notifications"
],
"web_accessible_resources": [
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 1599b8f99..e13d2842a 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -256,6 +256,7 @@ function setupController (initState, initLangCode) {
showUnconfirmedMessage: triggerUi,
unlockAccountMessage: triggerUi,
showUnapprovedTx: triggerUi,
+ showWatchAssetUi: showWatchAssetUi,
// initial state
initState,
// initial locale code
@@ -451,9 +452,28 @@ function triggerUi () {
})
}
+/**
+ * Opens the browser popup for user confirmation of watchAsset
+ * then it waits until user interact with the UI
+ */
+function showWatchAssetUi () {
+ triggerUi()
+ return new Promise(
+ (resolve) => {
+ var interval = setInterval(() => {
+ if (!notificationIsOpen) {
+ clearInterval(interval)
+ resolve()
+ }
+ }, 1000)
+ }
+ )
+}
+
// On first install, open a window to MetaMask website to how-it-works.
extension.runtime.onInstalled.addListener(function (details) {
if ((details.reason === 'install') && (!METAMASK_DEBUG)) {
extension.tabs.create({url: 'https://metamask.io/#how-it-works'})
}
})
+
diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js
index 707fd7de9..464a37017 100644
--- a/app/scripts/controllers/preferences.js
+++ b/app/scripts/controllers/preferences.js
@@ -1,5 +1,6 @@
const ObservableStore = require('obs-store')
const normalizeAddress = require('eth-sig-util').normalize
+const { isValidAddress } = require('ethereumjs-util')
const extend = require('xtend')
@@ -14,6 +15,7 @@ class PreferencesController {
* @property {string} store.currentAccountTab Indicates the selected tab in the ui
* @property {array} store.tokens The tokens the user wants display in their token lists
* @property {object} store.accountTokens The tokens stored per account and then per network type
+ * @property {object} store.assetImages Contains assets objects related to assets added
* @property {boolean} store.useBlockie The users preference for blockie identicons within the UI
* @property {object} store.featureFlags A key-boolean map, where keys refer to features and booleans to whether the
* user wishes to see that feature
@@ -26,7 +28,9 @@ class PreferencesController {
frequentRpcList: [],
currentAccountTab: 'history',
accountTokens: {},
+ assetImages: {},
tokens: [],
+ suggestedTokens: {},
useBlockie: false,
featureFlags: {},
currentLocale: opts.initLangCode,
@@ -37,6 +41,7 @@ class PreferencesController {
this.diagnostics = opts.diagnostics
this.network = opts.network
this.store = new ObservableStore(initState)
+ this.showWatchAssetUi = opts.showWatchAssetUi
this._subscribeProviderType()
}
// PUBLIC METHODS
@@ -51,6 +56,53 @@ class PreferencesController {
this.store.updateState({ useBlockie: val })
}
+ getSuggestedTokens () {
+ return this.store.getState().suggestedTokens
+ }
+
+ getAssetImages () {
+ return this.store.getState().assetImages
+ }
+
+ addSuggestedERC20Asset (tokenOpts) {
+ this._validateERC20AssetParams(tokenOpts)
+ const suggested = this.getSuggestedTokens()
+ const { rawAddress, symbol, decimals, image } = tokenOpts
+ const address = normalizeAddress(rawAddress)
+ const newEntry = { address, symbol, decimals, image }
+ suggested[address] = newEntry
+ this.store.updateState({ suggestedTokens: suggested })
+ }
+
+ /**
+ * RPC engine middleware for requesting new asset added
+ *
+ * @param req
+ * @param res
+ * @param {Function} - next
+ * @param {Function} - end
+ */
+ async requestWatchAsset (req, res, next, end) {
+ if (req.method === 'metamask_watchAsset') {
+ const { type, options } = req.params
+ switch (type) {
+ case 'ERC20':
+ const result = await this._handleWatchAssetERC20(options)
+ if (result instanceof Error) {
+ end(result)
+ } else {
+ res.result = result
+ end()
+ }
+ break
+ default:
+ end(new Error(`Asset of type ${type} not supported`))
+ }
+ } else {
+ next()
+ }
+ }
+
/**
* Getter for the `useBlockie` property
*
@@ -186,6 +238,13 @@ class PreferencesController {
return selected
}
+ removeSuggestedTokens () {
+ return new Promise((resolve, reject) => {
+ this.store.updateState({ suggestedTokens: {} })
+ resolve({})
+ })
+ }
+
/**
* Setter for the `selectedAddress` property
*
@@ -232,11 +291,11 @@ class PreferencesController {
* @returns {Promise<array>} Promises the new array of AddedToken objects.
*
*/
- async addToken (rawAddress, symbol, decimals) {
+ async addToken (rawAddress, symbol, decimals, image) {
const address = normalizeAddress(rawAddress)
const newEntry = { address, symbol, decimals }
-
const tokens = this.store.getState().tokens
+ const assetImages = this.getAssetImages()
const previousEntry = tokens.find((token, index) => {
return token.address === address
})
@@ -247,7 +306,8 @@ class PreferencesController {
} else {
tokens.push(newEntry)
}
- this._updateAccountTokens(tokens)
+ assetImages[address] = image
+ this._updateAccountTokens(tokens, assetImages)
return Promise.resolve(tokens)
}
@@ -260,8 +320,10 @@ class PreferencesController {
*/
removeToken (rawAddress) {
const tokens = this.store.getState().tokens
+ const assetImages = this.getAssetImages()
const updatedTokens = tokens.filter(token => token.address !== rawAddress)
- this._updateAccountTokens(updatedTokens)
+ delete assetImages[rawAddress]
+ this._updateAccountTokens(updatedTokens, assetImages)
return Promise.resolve(updatedTokens)
}
@@ -322,7 +384,7 @@ class PreferencesController {
/**
* Returns an updated rpcList based on the passed url and the current list.
- * The returned list will have a max length of 2. If the _url currently exists it the list, it will be moved to the
+ * The returned list will have a max length of 3. If the _url currently exists it the list, it will be moved to the
* end of the list. The current list is modified and returned as a promise.
*
* @param {string} _url The rpc url to add to the frequentRpcList.
@@ -338,7 +400,7 @@ class PreferencesController {
if (_url !== 'http://localhost:8545') {
rpcList.push(_url)
}
- if (rpcList.length > 2) {
+ if (rpcList.length > 3) {
rpcList.shift()
}
return Promise.resolve(rpcList)
@@ -387,6 +449,7 @@ class PreferencesController {
//
// PRIVATE METHODS
//
+
/**
* Subscription to network provider type.
*
@@ -405,10 +468,10 @@ class PreferencesController {
* @param {array} tokens Array of tokens to be updated.
*
*/
- _updateAccountTokens (tokens) {
+ _updateAccountTokens (tokens, assetImages) {
const { accountTokens, providerType, selectedAddress } = this._getTokenRelatedStates()
accountTokens[selectedAddress][providerType] = tokens
- this.store.updateState({ accountTokens, tokens })
+ this.store.updateState({ accountTokens, tokens, assetImages })
}
/**
@@ -438,6 +501,47 @@ class PreferencesController {
const tokens = accountTokens[selectedAddress][providerType]
return { tokens, accountTokens, providerType, selectedAddress }
}
+
+ /**
+ * Handle the suggestion of an ERC20 asset through `watchAsset`
+ * *
+ * @param {Promise} promise Promise according to addition of ERC20 token
+ *
+ */
+ async _handleWatchAssetERC20 (options) {
+ const { address, symbol, decimals, image } = options
+ const rawAddress = address
+ try {
+ this._validateERC20AssetParams({ rawAddress, symbol, decimals })
+ } catch (err) {
+ return err
+ }
+ const tokenOpts = { rawAddress, decimals, symbol, image }
+ this.addSuggestedERC20Asset(tokenOpts)
+ return this.showWatchAssetUi().then(() => {
+ const tokenAddresses = this.getTokens().filter(token => token.address === normalizeAddress(rawAddress))
+ return tokenAddresses.length > 0
+ })
+ }
+
+ /**
+ * Validates that the passed options for suggested token have all required properties.
+ *
+ * @param {Object} opts The options object to validate
+ * @throws {string} Throw a custom error indicating that address, symbol and/or decimals
+ * doesn't fulfill requirements
+ *
+ */
+ _validateERC20AssetParams (opts) {
+ const { rawAddress, symbol, decimals } = opts
+ if (!rawAddress || !symbol || !decimals) throw new Error(`Cannot suggest token without address, symbol, and decimals`)
+ if (!(symbol.length < 6)) throw new Error(`Invalid symbol ${symbol} more than five characters`)
+ const numDecimals = parseInt(decimals, 10)
+ if (isNaN(numDecimals) || numDecimals > 36 || numDecimals < 0) {
+ throw new Error(`Invalid decimals ${decimals} must be at least 0, and not over 36`)
+ }
+ if (!isValidAddress(rawAddress)) throw new Error(`Invalid address ${rawAddress}`)
+ }
}
module.exports = PreferencesController
diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js
index b7e2c7cbe..3a52d5e8d 100644
--- a/app/scripts/lib/account-tracker.js
+++ b/app/scripts/lib/account-tracker.js
@@ -43,10 +43,24 @@ class AccountTracker {
this._provider = opts.provider
this._query = pify(new EthQuery(this._provider))
this._blockTracker = opts.blockTracker
- // subscribe to latest block
- this._blockTracker.on('latest', this._updateForBlock.bind(this))
// blockTracker.currentBlock may be null
this._currentBlockNumber = this._blockTracker.getCurrentBlock()
+ // bind function for easier listener syntax
+ this._updateForBlock = this._updateForBlock.bind(this)
+ }
+
+ start () {
+ // remove first to avoid double add
+ this._blockTracker.removeListener('latest', this._updateForBlock)
+ // add listener
+ this._blockTracker.addListener('latest', this._updateForBlock)
+ // fetch account balances
+ this._updateAccounts()
+ }
+
+ stop () {
+ // remove listener
+ this._blockTracker.removeListener('latest', this._updateForBlock)
}
/**
diff --git a/app/scripts/lib/ipfsContent.js b/app/scripts/lib/ipfsContent.js
index 5db63f47d..38682b916 100644
--- a/app/scripts/lib/ipfsContent.js
+++ b/app/scripts/lib/ipfsContent.js
@@ -34,7 +34,7 @@ module.exports = function (provider) {
return { cancel: true }
}
- extension.webRequest.onErrorOccurred.addListener(ipfsContent, {urls: ['*://*.eth/', '*://*.test/']})
+ extension.webRequest.onErrorOccurred.addListener(ipfsContent, {urls: ['*://*.eth/']})
return {
remove () {
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 29838ad2d..98cb62bfa 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -67,6 +67,10 @@ module.exports = class MetamaskController extends EventEmitter {
const initState = opts.initState || {}
this.recordFirstTimeInfo(initState)
+ // this keeps track of how many "controllerStream" connections are open
+ // the only thing that uses controller connections are open metamask UI instances
+ this.activeControllerConnections = 0
+
// platform-specific api
this.platform = opts.platform
@@ -88,6 +92,7 @@ module.exports = class MetamaskController extends EventEmitter {
this.preferencesController = new PreferencesController({
initState: initState.PreferencesController,
initLangCode: opts.initLangCode,
+ showWatchAssetUi: opts.showWatchAssetUi,
network: this.networkController,
})
@@ -127,6 +132,14 @@ module.exports = class MetamaskController extends EventEmitter {
provider: this.provider,
blockTracker: this.blockTracker,
})
+ // start and stop polling for balances based on activeControllerConnections
+ this.on('controllerConnectionChanged', (activeControllerConnections) => {
+ if (activeControllerConnections > 0) {
+ this.accountTracker.start()
+ } else {
+ this.accountTracker.stop()
+ }
+ })
// key mgmt
const additionalKeyrings = [TrezorKeyring, LedgerBridgeKeyring]
@@ -137,19 +150,7 @@ module.exports = class MetamaskController extends EventEmitter {
encryptor: opts.encryptor || undefined,
})
- // If only one account exists, make sure it is selected.
- this.keyringController.memStore.subscribe((state) => {
- const addresses = state.keyrings.reduce((res, keyring) => {
- return res.concat(keyring.accounts)
- }, [])
- if (addresses.length === 1) {
- const address = addresses[0]
- this.preferencesController.setSelectedAddress(address)
- }
- // ensure preferences + identities controller know about all addresses
- this.preferencesController.addAddresses(addresses)
- this.accountTracker.syncWithAddresses(addresses)
- })
+ this.keyringController.memStore.subscribe((s) => this._onKeyringControllerUpdate(s))
// detect tokens controller
this.detectTokensController = new DetectTokensController({
@@ -386,6 +387,7 @@ module.exports = class MetamaskController extends EventEmitter {
setSelectedAddress: nodeify(preferencesController.setSelectedAddress, preferencesController),
addToken: nodeify(preferencesController.addToken, preferencesController),
removeToken: nodeify(preferencesController.removeToken, preferencesController),
+ removeSuggestedTokens: nodeify(preferencesController.removeSuggestedTokens, preferencesController),
setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab, preferencesController),
setAccountLabel: nodeify(preferencesController.setAccountLabel, preferencesController),
setFeatureFlag: nodeify(preferencesController.setFeatureFlag, preferencesController),
@@ -1209,11 +1211,19 @@ module.exports = class MetamaskController extends EventEmitter {
setupControllerConnection (outStream) {
const api = this.getApi()
const dnode = Dnode(api)
+ // report new active controller connection
+ this.activeControllerConnections++
+ this.emit('controllerConnectionChanged', this.activeControllerConnections)
+ // connect dnode api to remote connection
pump(
outStream,
dnode,
outStream,
(err) => {
+ // report new active controller connection
+ this.activeControllerConnections--
+ this.emit('controllerConnectionChanged', this.activeControllerConnections)
+ // report any error
if (err) log.error(err)
}
)
@@ -1242,6 +1252,7 @@ module.exports = class MetamaskController extends EventEmitter {
engine.push(createOriginMiddleware({ origin }))
engine.push(createLoggerMiddleware({ origin }))
engine.push(filterMiddleware)
+ engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController))
engine.push(createProviderMiddleware({ provider: this.provider }))
// setup connection
@@ -1279,6 +1290,34 @@ module.exports = class MetamaskController extends EventEmitter {
}
/**
+ * Handle a KeyringController update
+ * @param {object} state the KC state
+ * @return {Promise<void>}
+ * @private
+ */
+ async _onKeyringControllerUpdate (state) {
+ const {isUnlocked, keyrings} = state
+ const addresses = keyrings.reduce((acc, {accounts}) => acc.concat(accounts), [])
+
+ if (!addresses.length) {
+ return
+ }
+
+ // Ensure preferences + identities controller know about all addresses
+ this.preferencesController.addAddresses(addresses)
+ this.accountTracker.syncWithAddresses(addresses)
+
+ const wasLocked = !isUnlocked
+ if (wasLocked) {
+ const oldSelectedAddress = this.preferencesController.getSelectedAddress()
+ if (!addresses.includes(oldSelectedAddress)) {
+ const address = addresses[0]
+ await this.preferencesController.setSelectedAddress(address)
+ }
+ }
+ }
+
+ /**
* A method for emitting the full MetaMask state to all registered listeners.
* @private
*/
@@ -1424,6 +1463,7 @@ module.exports = class MetamaskController extends EventEmitter {
}
}
+ // TODO: Replace isClientOpen methods with `controllerConnectionChanged` events.
/**
* A method for recording whether the MetaMask user interface is open or not.
* @private