1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Merge remote-tracking branch 'origin/develop' into master-sync

This commit is contained in:
ryanml 2021-09-07 14:13:03 -07:00
commit 6836789d2c
179 changed files with 2906 additions and 1141 deletions

View File

@ -304,7 +304,7 @@ jobs:
steps:
- run:
name: Validate changelog
command: yarn auto-changelog validate
command: yarn lint:changelog
- when:
condition:
matches:
@ -313,7 +313,7 @@ jobs:
steps:
- run:
name: Validate release candidate changelog
command: yarn auto-changelog validate --rc
command: yarn lint:changelog:rc
test-deps-audit:

View File

@ -166,6 +166,16 @@ module.exports = {
sourceType: 'script',
},
},
{
files: [
'app/scripts/lockdown-run.js',
'test/unit-global/protect-intrinsics.test.js',
],
globals: {
harden: 'readonly',
Compartment: 'readonly',
},
},
],
settings: {

View File

@ -22,6 +22,6 @@ jobs:
url-to-cladocument: 'https://metamask.io/cla.html'
# This branch can't have protections, commits are made directly to the specified branch.
branch: 'cla-signatures'
allowlist: 'dependabot[bot],metamaskbot,muji'
allowlist: 'dependabot[bot],metamaskbot'
allow-organization-members: true
blockchain-storage-flag: false

BIN
.storybook/images/UNI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

View File

@ -0,0 +1,65 @@
export const suggestedTokens = {
"0x6b175474e89094c44da98b954eedeac495271d0f": {
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"symbol": "META",
"decimals": 18,
"image": "metamark.svg",
"unlisted": false
},
"0xB8c77482e45F1F44dE1745F52C74426C631bDD52": {
"address": "0xB8c77482e45F1F44dE1745F52C74426C631bDD52",
"symbol": "0X",
"decimals": 18,
"image": "0x.svg",
"unlisted": false
},
"0x1f9840a85d5af5bf1d1762f925bdaddc4201f984": {
"address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
"symbol": "AST",
"decimals": 18,
"image": "ast.png",
"unlisted": false
},
"0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2": {
"address": "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2",
"symbol": "BAT",
"decimals": 18,
"image": "BAT_icon.svg",
"unlisted": false
},
"0xe83cccfabd4ed148903bf36d4283ee7c8b3494d1": {
"address": "0xe83cccfabd4ed148903bf36d4283ee7c8b3494d1",
"symbol": "CVL",
"decimals": 18,
"image": "CVL_token.svg",
"unlisted": false
},
"0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e": {
"address": "0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e",
"symbol": "GLA",
"decimals": 18,
"image": "gladius.svg",
"unlisted": false
},
"0x467Bccd9d29f223BcE8043b84E8C8B282827790F": {
"address": "0x467Bccd9d29f223BcE8043b84E8C8B282827790F",
"symbol": "GNO",
"decimals": 18,
"image": "gnosis.svg",
"unlisted": false
},
"0xff20817765cb7f73d4bde2e66e067e58d11095c2": {
"address": "0xff20817765cb7f73d4bde2e66e067e58d11095c2",
"symbol": "OMG",
"decimals": 18,
"image": "omg.jpg",
"unlisted": false
},
"0x8e870d67f660d95d5be530380d0ec0bd388289e1": {
"address": "0x8e870d67f660d95d5be530380d0ec0bd388289e1",
"symbol": "WED",
"decimals": 18,
"image": "wed.png",
"unlisted": false
},
}

View File

@ -0,0 +1,56 @@
export const tokens = {
"0x33f90dee07c6e8b9682dd20f73e6c358b2ed0f03": {
"address": "0x33f90dee07c6e8b9682dd20f73e6c358b2ed0f03",
"symbol": "TRDT",
"decimals": 18,
"unlisted": false
},
"0x39013f961c378f02c2b82a6e1d31e9812786fd9d": {
"address": "0x39013f961c378f02c2b82a6e1d31e9812786fd9d",
"symbol": "SMS",
"decimals": 18,
"unlisted": false
},
"0x78b7fada55a64dd895d8c8c35779dd8b67fa8a05": {
"address": "0x78b7fada55a64dd895d8c8c35779dd8b67fa8a05",
"symbol": "ATL",
"decimals": 18,
"unlisted": false
},
"0xfd8971d5e8e1740ce2d0a84095fca4de729d0c16": {
"address": "0xfd8971d5e8e1740ce2d0a84095fca4de729d0c16",
"symbol": "ZLA",
"decimals": 18,
"unlisted": false
},
"0xe83cccfabd4ed148903bf36d4283ee7c8b3494d1": {
"address": "0xe83cccfabd4ed148903bf36d4283ee7c8b3494d1",
"symbol": "BTT",
"decimals": 18,
"unlisted": false
},
"0x7a07e1a0c2514d51132183ecfea2a880ec3b7648": {
"address": "0x7a07e1a0c2514d51132183ecfea2a880ec3b7648",
"symbol": "IXE",
"decimals": 18,
"unlisted": false
},
"0x467Bccd9d29f223BcE8043b84E8C8B282827790F": {
"address": "0x467Bccd9d29f223BcE8043b84E8C8B282827790F",
"symbol": "TEL",
"decimals": 18,
"unlisted": false
},
"0xff20817765cb7f73d4bde2e66e067e58d11095c2": {
"address": "0xff20817765cb7f73d4bde2e66e067e58d11095c2",
"symbol": "AMP",
"decimals": 18,
"unlisted": false
},
"0x15bda08c3afbf5955d6e9b235fd55a1fd0dbc829": {
"address": "0x15bda08c3afbf5955d6e9b235fd55a1fd0dbc829",
"symbol": "APC",
"decimals": 18,
"unlisted": false
},
}

View File

@ -8,7 +8,13 @@ const state = {
"unconnectedAccount": {
"state": "CLOSED"
},
"activeTab": {},
"activeTab": {
"id": 113,
"title": "E2E Test Dapp",
"origin": "https://metamask.github.io",
"protocol": "https:",
"url": "https://metamask.github.io/test-dapp/"
},
"metamask": {
"networkDetails": {
"EIPS": {
@ -34,8 +40,8 @@ const state = {
}
},
"unapprovedTxs": {
"7786962153682822": {
"id": 7786962153682822,
"3111025347726181": {
"id": 3111025347726181,
"time": 1620710815484,
"status": "unapproved",
"metamaskNetworkId": "3",
@ -43,7 +49,7 @@ const state = {
"loadingDefaults": false,
"txParams": {
"from": "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4",
"to": "0xad6d458402f60fd3bd25163575031acdce07538d",
"to": "0xaD6D458402F60fD3Bd25163575031ACDce07538D",
"value": "0x0",
"data": "0xa9059cbb000000000000000000000000b19ac54efa18cc3a14a5b821bfec73d284bf0c5e0000000000000000000000000000000000000000000000003782dace9d900000",
"gas": "0xcb28",
@ -62,7 +68,7 @@ const state = {
"loadingDefaults": true,
"txParams": {
"from": "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4",
"to": "0xad6d458402f60fd3bd25163575031acdce07538d",
"to": "0xaD6D458402F60fD3Bd25163575031ACDce07538D",
"value": "0x0",
"data": "0xa9059cbb000000000000000000000000b19ac54efa18cc3a14a5b821bfec73d284bf0c5e0000000000000000000000000000000000000000000000003782dace9d900000",
"gas": "0xcb28",
@ -95,11 +101,11 @@ const state = {
}
},
"contractExchangeRates": {
"0xad6d458402f60fd3bd25163575031acdce07538d": 0
"0xaD6D458402F60fD3Bd25163575031ACDce07538D": 0
},
"tokens": [
{
"address": "0xad6d458402f60fd3bd25163575031acdce07538d",
"address": "0xaD6D458402F60fD3Bd25163575031ACDce07538D",
"symbol": "DAI",
"decimals": 18
}
@ -122,7 +128,7 @@ const state = {
"ensResolution": null,
"ensResolutionError": "",
"token": {
"address": "0xad6d458402f60fd3bd25163575031acdce07538d",
"address": "0xaD6D458402F60fD3Bd25163575031ACDce07538D",
"symbol": "DAI",
"decimals": 18
}
@ -259,7 +265,7 @@ const state = {
],
"0x3": [
{
"address": "0xad6d458402f60fd3bd25163575031acdce07538d",
"address": "0xaD6D458402F60fD3Bd25163575031ACDce07538D",
"symbol": "DAI",
"decimals": 18
}
@ -274,7 +280,7 @@ const state = {
}
},
"assetImages": {
"0xad6d458402f60fd3bd25163575031acdce07538d": "./images/logo.png"
"0xaD6D458402F60fD3Bd25163575031ACDce07538D": "./sai.svg"
},
"hiddenTokens": [],
"suggestedTokens": {},
@ -547,7 +553,7 @@ const state = {
}
],
"permissionsHistory": {
"https://app.uniswap.org": {
"https://metamask.github.io": {
"eth_accounts": {
"lastApproved": 1620710693213,
"accounts": {
@ -562,6 +568,12 @@ const state = {
"icon": "https://metamask.github.io/test-dapp/metamask-fox.svg",
"lastUpdated": 1620723443380,
"host": "metamask.github.io"
},
"https://app.uniswap.org": {
"name": "Uniswap",
"icon": "./UNI.png",
"lastUpdated": 1620723443380,
"host": "app.uniswap.org"
}
},
"threeBoxSyncingAllowed": false,
@ -652,14 +664,14 @@ const state = {
"chainId": "0x3",
"loadingDefaults": false,
"txParams": {
"from": "0x983211ce699ea5ab57cc528086154b6db1ad8e55",
"to": "0xad6d458402f60fd3bd25163575031acdce07538d",
"from": "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4",
"to": "0xaD6D458402F60fD3Bd25163575031ACDce07538D",
"value": "0x0",
"data": "0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170",
"gas": "0xea60",
"gasPrice": "0x4a817c800"
},
"type": "standard",
"type": "transfer",
"origin": "https://metamask.github.io",
"transactionCategory": "approve",
"history": [
@ -672,7 +684,7 @@ const state = {
"loadingDefaults": true,
"txParams": {
"from": "0x983211ce699ea5ab57cc528086154b6db1ad8e55",
"to": "0xad6d458402f60fd3bd25163575031acdce07538d",
"to": "0xaD6D458402F60fD3Bd25163575031ACDce07538D",
"value": "0x0",
"data": "0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170",
"gas": "0xea60",

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "አውታረ መረብ አክል"
},
"addRecipient": {
"message": "ተቀባይ አክል"
},
"addSuggestedTokens": {
"message": "የተጠቆሙ ተለዋጭ ስሞችን አክል"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "أضف شبكة"
},
"addRecipient": {
"message": "إضافة مستلم"
},
"addSuggestedTokens": {
"message": "أضف العملات الرمزية المقترحة"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Добавяне на мрежа"
},
"addRecipient": {
"message": "Добавете получател"
},
"addSuggestedTokens": {
"message": "Добавете препоръчани жетони"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "নেটওয়ার্ক যোগ করুন"
},
"addRecipient": {
"message": "প্রাপক যোগ করুন"
},
"addSuggestedTokens": {
"message": "প্রস্তাবিত টোকেনগুলি যোগ করুন"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Afegir Xarxa"
},
"addRecipient": {
"message": "Afegeix un recipient"
},
"addSuggestedTokens": {
"message": "Afegir Fitxes Suggerides"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Tilføj netværk"
},
"addRecipient": {
"message": "Tilføj modtager"
},
"addSuggestedTokens": {
"message": "Tilføj foreslåede tokens"
},

View File

@ -35,9 +35,6 @@
"addNetwork": {
"message": "Netzwerk hinzufügen"
},
"addRecipient": {
"message": "Empfänger hinzufügen"
},
"addSuggestedTokens": {
"message": "Vorgeschlagene Token hinzufügen"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Προσθήκη Δικτύου"
},
"addRecipient": {
"message": "Προσθήκη Παραλήπτη"
},
"addSuggestedTokens": {
"message": "Προσθέστε τα Προτεινόμενα Tokens"
},

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "Add Network"
},
"addRecipient": {
"message": "Add Recipient"
},
"addSuggestedTokens": {
"message": "Add Suggested Tokens"
},
@ -323,10 +320,10 @@
"message": "Confirm password"
},
"confirmSecretBackupPhrase": {
"message": "Confirm your Secret Backup Phrase"
"message": "Confirm your Secret Recovery Phrase"
},
"confirmSeedPhrase": {
"message": "Confirm Seed Phrase"
"message": "Confirm Secret Recovery Phrase"
},
"confirmed": {
"message": "Confirmed"
@ -594,10 +591,10 @@
"message": "Dismiss"
},
"dismissReminderDescriptionField": {
"message": "Turn this on to dismiss the recovery phrase backup reminder message. We highly recommend that you back up your Secret Recovery Phrase to avoid loss of funds"
"message": "Turn this on to dismiss the Secret Recovery Phrase backup reminder message. We highly recommend that you back up your Secret Recovery Phrase to avoid loss of funds"
},
"dismissReminderField": {
"message": "Dismiss recovery phrase backup reminder"
"message": "Dismiss Secret Recovery Phrase backup reminder"
},
"domain": {
"message": "Domain"
@ -612,7 +609,7 @@
"message": "Download Google Chrome"
},
"downloadSecretBackup": {
"message": "Download this Secret Backup Phrase and keep it stored safely on an external encrypted hard drive or storage medium."
"message": "Download this Secret Recovery Phrase and keep it stored safely on an external encrypted hard drive or storage medium."
},
"downloadStateLogs": {
"message": "Download State Logs"
@ -630,16 +627,16 @@
"message": "How should I choose?"
},
"editGasEducationHighExplanation": {
"message": "This is best for swaps or other time sensitive transactions. If a swap takes too long to process it will often fail and you may lose funds."
"message": "This is best for time sensitive transactions (like Swaps) as it increases the likelihood of a successful transaction. If a Swap takes too long to process it may fail and result in losing some of your gas fee."
},
"editGasEducationLowExplanation": {
"message": "A lower gas fee should only be selected for transactions where processing time is less important. With a lower fee, it can be hard to predict when (or if) your transaction will be successful."
"message": "A lower gas fee should only be used when processing time is less important. Lower fees make it hard predict when (or if) your transaction will be successful."
},
"editGasEducationMediumExplanation": {
"message": "A medium gas fee is good for sending, withdrawing or other non-time sensitive but important transactions."
"message": "A medium gas fee is good for sending, withdrawing or other non-time sensitive transactions. This setting will most often result in a successful transaction."
},
"editGasEducationModalIntro": {
"message": "The right gas amount to select depends on the type of transaction and how important it is."
"message": "Selecting the right gas fee depends on the type of transaction and how important it is to you."
},
"editGasEducationModalTitle": {
"message": "How to choose?"
@ -675,7 +672,7 @@
"message": "Max priority fee is higher than necessary. You may pay more than needed."
},
"editGasMaxPriorityFeeLow": {
"message": "Max priority fee extremely low for network conditions"
"message": "Max priority fee is low for current network conditions"
},
"editGasMaxPriorityFeeTooltip": {
"message": "Max priority fee (aka “miner tip”) goes directly to miners and incentivizes them to prioritize your transaction. Youll most often pay your max setting"
@ -714,9 +711,8 @@
"editGasTooLowTooltip": {
"message": "Your max fee or max priority fee may be low for current market conditions. We don't know when (or if) your transaction will be processed. "
},
"editGasTotalBannerSubtitle": {
"message": "Up to $1 ($2)",
"display": "$1 represents a fiat value"
"editGasTooLowWarningTooltip": {
"message": "This lowers your maximum fee but if network traffic increases your transaction may be delayed or fail."
},
"editNonceField": {
"message": "Edit Nonce"
@ -1048,6 +1044,9 @@
"importAccount": {
"message": "Import Account"
},
"importAccountError": {
"message": "Error importing account."
},
"importAccountLinkText": {
"message": "import using Secret Recovery Phrase"
},
@ -1221,7 +1220,7 @@
},
"makeSureNoOneWatching": {
"message": "Make sure no one is watching your screen",
"description": "Warning to users to be care while creating and saving their new seed phrase"
"description": "Warning to users to be care while creating and saving their new Secret Recovery Phrase"
},
"max": {
"message": "Max"
@ -1774,13 +1773,13 @@
"message": "Search Tokens"
},
"secretBackupPhrase": {
"message": "Secret Backup Phrase"
"message": "Secret Recovery Phrase"
},
"secretBackupPhraseDescription": {
"message": "Your secret backup phrase makes it easy to back up and restore your account."
"message": "Your Secret Recovery Phrase makes it easy to back up and restore your account."
},
"secretBackupPhraseWarning": {
"message": "WARNING: Never disclose your backup phrase. Anyone with this phrase can take your Ether forever."
"message": "WARNING: Never disclose your Secret Recovery Phrase. Anyone with this phrase can take your Ether forever."
},
"secretPhrase": {
"message": "Enter your secret phrase here to restore your vault."
@ -1813,28 +1812,28 @@
"message": "Store in a bank vault."
},
"seedPhraseIntroSidebarCopyOne": {
"message": "Your recovery phrase is the “master key” to your wallet and funds."
"message": "Your Secret Recovery Phrase is the “master key” to your wallet and funds."
},
"seedPhraseIntroSidebarCopyThree": {
"message": "If someone asks for your recovery phrase, they are most likely trying to scam you."
"message": "If someone asks for your Secret Recovery Phrase, they are most likely trying to scam you."
},
"seedPhraseIntroSidebarCopyTwo": {
"message": "Never, ever share your recovery phrase, even with MetaMask!"
"message": "Never, ever share your Secret Recovery Phrase, even with MetaMask!"
},
"seedPhraseIntroSidebarTitleOne": {
"message": "What is a recovery phrase?"
"message": "What is a Secret Recovery Phrase?"
},
"seedPhraseIntroSidebarTitleThree": {
"message": "Should I share my recovery phrase?"
"message": "Should I share my Secret Recovery Phrase?"
},
"seedPhraseIntroSidebarTitleTwo": {
"message": "How do I save my recovery phrase?"
"message": "How do I save my Secret Recovery Phrase?"
},
"seedPhraseIntroTitle": {
"message": "Secure your wallet"
},
"seedPhraseIntroTitleCopy": {
"message": "Before getting started, watch this short video to learn about your recovery phrase and how to keep your wallet safe."
"message": "Before getting started, watch this short video to learn about your Secret Recovery Phrase and how to keep your wallet safe."
},
"seedPhrasePlaceholder": {
"message": "Separate each word with a single space"
@ -1898,6 +1897,9 @@
"message": "Send $1",
"description": "Symbol of the specified token"
},
"sendTo": {
"message": "Send to"
},
"sendTokens": {
"message": "Send Tokens"
},
@ -1956,7 +1958,7 @@
"message": "Sign"
},
"signNotice": {
"message": "Signing this message can have \ndangerous side effects. Only sign messages from \nsites you fully trust with your entire account.\n This dangerous method will be removed in a future version. "
"message": "We are unable to predict the result of this signature. This signature could potentially perform any operation on your account's behalf, including granting complete control of your account and all of its assets to the requesting site. Only sign this message if you know what you're doing or completely trust the requesting site."
},
"signatureRequest": {
"message": "Signature Request"
@ -2416,6 +2418,9 @@
"symbolBetweenZeroTwelve": {
"message": "Symbol must be 11 characters or fewer."
},
"syncFailed": {
"message": "Sync failed"
},
"syncInProgress": {
"message": "Sync in progress"
},
@ -2510,9 +2515,8 @@
"transactionCreated": {
"message": "Transaction created with a value of $1 at $2."
},
"transactionDetailDappGasHeading": {
"message": "$1 suggested gas fee",
"description": "$1 represents a dapp origin"
"transactionDetailDappGasMoreInfo": {
"message": "Site suggested"
},
"transactionDetailDappGasTooltip": {
"message": "Edit to use MetaMask's recommended gas fee based on the latest block."
@ -2527,7 +2531,7 @@
"message": "Gas fees are set by the network and fluctuate based on network traffic and transaction complexity."
},
"transactionDetailGasTooltipIntro": {
"message": "Gas fees are paid to crypto miners who process transactions on the Ethereum network. MetaMask does not profit from gas fees."
"message": "Gas fees are paid to crypto miners who process transactions on the $1 network. MetaMask does not profit from gas fees."
},
"transactionDetailGasTotalSubtitle": {
"message": "Amount + gas fee"

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "Agregar red"
},
"addRecipient": {
"message": "Agregar destinatario"
},
"addSuggestedTokens": {
"message": "Agregar tokens sugeridos"
},

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "Agregar red"
},
"addRecipient": {
"message": "Agregar destinatario"
},
"addSuggestedTokens": {
"message": "Agregar tokens sugeridos"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Lisage võrk"
},
"addRecipient": {
"message": "Lisa saaja"
},
"addSuggestedTokens": {
"message": "Lisa soovitatud lube"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "اضافه شبکه"
},
"addRecipient": {
"message": "اضافه کردن دریافت کننده"
},
"addSuggestedTokens": {
"message": "اضافه رمزیاب های پیشنهاد شده"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Lisää verkko"
},
"addRecipient": {
"message": "Lisää vastaanottaja"
},
"addSuggestedTokens": {
"message": "Lisää ehdotetut käyttötunnukset"
},

View File

@ -35,9 +35,6 @@
"addNetwork": {
"message": "Magdagdag ng Network"
},
"addRecipient": {
"message": "Magdagdag ng Recipient"
},
"addSuggestedTokens": {
"message": "Magdagdag ng Mga Iminungkahing Token"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Ajouter un réseau"
},
"addRecipient": {
"message": "Ajouter destinataire"
},
"addSuggestedTokens": {
"message": "Ajouter les jetons suggérés"
},
@ -657,7 +654,7 @@
"message": "de"
},
"off": {
"message": "Déconnecté"
"message": "Désactivé"
},
"on": {
"message": "Activé"

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "הוסף/י רשת"
},
"addRecipient": {
"message": "הוסף נמען"
},
"addSuggestedTokens": {
"message": "הוסף/י אסימונים מוצעים"
},

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "नेटवर्क जोड़ें"
},
"addRecipient": {
"message": "प्राप्तकर्ता को जोड़ें"
},
"addSuggestedTokens": {
"message": "सुझाए गए टोकन जोड़ें"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Dodaj mrežu"
},
"addRecipient": {
"message": "Dodaj primatelja"
},
"addSuggestedTokens": {
"message": "Dodaj predložene tokene"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Hálózat hozzáadása"
},
"addRecipient": {
"message": "Címzett hozzáadása"
},
"addSuggestedTokens": {
"message": "Javasolt tokenek hozzáadása"
},

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "Tambahkan Jaringan"
},
"addRecipient": {
"message": "Tambahkan Penerima"
},
"addSuggestedTokens": {
"message": "Tambahkan Token yang Disarankan"
},

View File

@ -52,9 +52,6 @@
"addNetwork": {
"message": "Aggiungi Rete"
},
"addRecipient": {
"message": "Aggiungi destinatario"
},
"addSuggestedTokens": {
"message": "Aggiungi Token Suggeriti"
},

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "ネットワークの追加"
},
"addRecipient": {
"message": "受信者の追加"
},
"addSuggestedTokens": {
"message": "推奨されたトークンの追加"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "ನೆಟ್‌ವರ್ಕ್ ಸೇರಿಸಿ"
},
"addRecipient": {
"message": "ಸ್ವೀಕೃತಿದಾರರನ್ನು ಸೇರಿಸಿ"
},
"addSuggestedTokens": {
"message": "ಸೂಚಿಸಲಾದ ಟೋಕನ್‌ಗಳನ್ನು ಸೇರಿಸಿ"
},

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "네트워크 추가"
},
"addRecipient": {
"message": "수신인 추가"
},
"addSuggestedTokens": {
"message": "추천 토큰 추가"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Pridėti tinklą"
},
"addRecipient": {
"message": "Pridėti gavėją"
},
"addSuggestedTokens": {
"message": "Pridėti siūlomų žetonų"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Pievienot tīklu"
},
"addRecipient": {
"message": "Pievienot saņēmēju"
},
"addSuggestedTokens": {
"message": "Pievienot ieteiktos marķierus"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Tambah Rangkaian"
},
"addRecipient": {
"message": "Tambah Penerima"
},
"addSuggestedTokens": {
"message": "Tambah Token yang Disyorkan"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Legg til nettverk"
},
"addRecipient": {
"message": "Legg til mottaker "
},
"addSuggestedTokens": {
"message": "Legg til foreslåtte tokener "
},

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "Magdagdag ng Network"
},
"addRecipient": {
"message": "Magdagdag ng Recipient"
},
"addSuggestedTokens": {
"message": "Magdagdag ng Mga Iminumungkahing Token"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Dodaj sieć"
},
"addRecipient": {
"message": "Dodaj odbiorcę"
},
"addSuggestedTokens": {
"message": "Dodaj sugerowane tokeny."
},

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "Adicionar rede"
},
"addRecipient": {
"message": "Adicionar destinatário"
},
"addSuggestedTokens": {
"message": "Adicionar tokens sugeridos"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Adăugați rețea"
},
"addRecipient": {
"message": "Adăugați destinatarul"
},
"addSuggestedTokens": {
"message": "Adăugați indicativele sugerate"
},

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "Добавить сеть"
},
"addRecipient": {
"message": "Добавить получателя"
},
"addSuggestedTokens": {
"message": "Добавить предложенные токены"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Pridať sieť"
},
"addRecipient": {
"message": "Pridať príjemcu"
},
"addSuggestedTokens": {
"message": "Pridať navrhované tokeny"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Dodaj omrežje"
},
"addRecipient": {
"message": "Dodaj prejemnika"
},
"addSuggestedTokens": {
"message": "Dodaj priporočene žetone"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Dodajte mrežu"
},
"addRecipient": {
"message": "Dodaj primaoca"
},
"addSuggestedTokens": {
"message": "Dodajte sugerisane tokene"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Lägg till nätverk"
},
"addRecipient": {
"message": "Lägg till mottagare"
},
"addSuggestedTokens": {
"message": "Lägg till föreslagna tokens"
},

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Ongeza Mtandao"
},
"addRecipient": {
"message": "Ongeza Mpokeaji"
},
"addSuggestedTokens": {
"message": "Ongeza Vianzio Vilivyopendekezwa"
},

View File

@ -52,9 +52,6 @@
"addNetwork": {
"message": "Magdagdag ng Network"
},
"addRecipient": {
"message": "Magdagdag ng Recipient"
},
"addSuggestedTokens": {
"message": "Magdagdag ng Mga Iminumungkahing Token"
},

View File

@ -322,7 +322,7 @@
"message": "Gelecekte Bu jetonu hesap seçenekleri menüsünde “Jeton ekle”'ye giderek geri ekleyebilirsiniz."
},
"reject": {
"message": "Reddetmek"
"message": "Reddet"
},
"rejected": {
"message": "Rededildi"

View File

@ -38,9 +38,6 @@
"addNetwork": {
"message": "Додати мережу"
},
"addRecipient": {
"message": "Додати отримувача"
},
"addSuggestedTokens": {
"message": "Додати рекомендовані токени"
},

View File

@ -79,9 +79,6 @@
"addNetwork": {
"message": "Thêm mạng"
},
"addRecipient": {
"message": "Thêm người nhận"
},
"addSuggestedTokens": {
"message": "Thêm token được đề xuất"
},

View File

@ -52,9 +52,6 @@
"addNetwork": {
"message": "添加网络"
},
"addRecipient": {
"message": "添加接收方"
},
"addSuggestedTokens": {
"message": "添加推荐代币"
},

View File

@ -41,9 +41,6 @@
"addNetwork": {
"message": "新增網路"
},
"addRecipient": {
"message": "新增接收人"
},
"addSuggestedTokens": {
"message": "加入建議的代幣"
},

View File

@ -0,0 +1,115 @@
WEBVTT
1
00:00:00.780 --> 00:00:04.580
MetaMask es una nueva forma de conectarse
a sitios y aplicaciones.
2
00:00:04.580 --> 00:00:08.860
En los sitios web tradicionales, una base de datos
o un banco central es responsable de controlar y
3
00:00:08.860 --> 00:00:10.179
recuperar sus cuentas.
4
00:00:10.179 --> 00:00:15.050
Pero con MetaMask, todo el control lo tiene
el titular de la clave maestra.
5
00:00:15.050 --> 00:00:18.460
La persona que tenga esta clave controlará las cuentas.
6
00:00:18.460 --> 00:00:21.110
La clave maestra
es su frase secreta de recuperación.
7
00:00:21.110 --> 00:00:26.070
Esta frase está compuesta por 12 palabras y se crea
la primera vez que se configura MetaMask; le permite
8
00:00:26.070 --> 00:00:30.120
recuperar su cartera y los fondos en caso de que
alguna vez pierda su clave de acceso.
9
00:00:30.120 --> 00:00:33.451
Es fundamental que proteja
su cartera
10
00:00:33.451 --> 00:00:37.510
guardando la frase secreta de recuperación
en un lugar sumamente seguro y secreto.
11
00:00:37.510 --> 00:00:41.429
Si alguna persona llegara a encontrarla, accederá
a la clave maestra de su cartera y podrá
12
00:00:41.429 --> 00:00:45.190
ingresar a todos sus fondos y tomarlos libremente.
13
00:00:45.190 --> 00:00:50.109
Para proteger su cartera en MetaMask,
guarde en un lugar seguro su frase secreta de recuperación.
14
00:00:50.109 --> 00:00:54.930
Puede anotarla, esconderla en algún lugar,
guardarla en una caja de seguridad
15
00:00:54.930 --> 00:00:57.729
o utilizar un administrador seguro de contraseñas.
16
00:00:57.729 --> 00:01:01.050
Inclusive, algunos usuarios graban
la frase en una placa metálica.
17
00:01:01.050 --> 00:01:04.440
Si llegara a perder su frase secreta de recuperación,
ninguna persona, ni siquiera el equipo de MetaMask, podrá ayudarlo
18
00:01:04.440 --> 00:01:07.820
a recuperar
su cartera.
19
00:01:07.820 --> 00:01:12.072
Si aún no ha anotado ni guardado en un lugar seguro su
frase secreta de recuperación,
20
00:01:12.072 --> 00:01:15.492
hágalo ahora mismo. Lo esperamos.
21
00:01:15.500 --> 00:01:20.780
Y recuerde no compartir nunca su
frase secreta de recuperación con nadie; ni siquiera con nosotros.
22
00:01:20.780 --> 00:01:24.910
Si alguien se la pide alguna vez,
será con intenciones de estafarlo.
23
00:01:24.910 --> 00:01:26.250
¡Eso es todo!
24
00:01:26.250 --> 00:01:31.020
Ahora ya sabe qué es una frase secreta de recuperación
y qué debe hacer para mantener protegida su cartera.

View File

@ -0,0 +1,115 @@
WEBVTT
1
00:00:00.780 --> 00:00:04.580
MetaMask ि
2
00:00:04.580 --> 00:00:08.860
ि , िि
ि
3
00:00:08.860 --> 00:00:10.179
ि
4
00:00:10.179 --> 00:00:15.050
ि MetaMask , ि
5
00:00:15.050 --> 00:00:18.460
, िि
6
00:00:18.460 --> 00:00:21.110
ि
" "
7
00:00:21.110 --> 00:00:26.070
12 ,
MetaMask , ि
8
00:00:26.070 --> 00:00:30.120
9
00:00:30.120 --> 00:00:33.451
ि
ि
10
00:00:33.451 --> 00:00:37.510
ि
ि
11
00:00:37.510 --> 00:00:41.429
ि ि ि ,
" "
12
00:00:41.429 --> 00:00:45.190
13
00:00:45.190 --> 00:00:50.109
MetaMask ि ि
ि ि
14
00:00:50.109 --> 00:00:54.930
ि , ,
िि
15
00:00:54.930 --> 00:00:57.729
ि
16
00:00:57.729 --> 00:01:01.050
!
17
00:01:01.050 --> 00:01:04.440
ि ि ,
, ि MetaMask ,
18
00:01:04.440 --> 00:01:07.820
19
00:01:07.820 --> 00:01:12.072
ि ि
ि ि ि ,
20
00:01:12.072 --> 00:01:15.492
21
00:01:15.500 --> 00:01:20.780
, ि
ि :
22
00:01:20.780 --> 00:01:24.910
ि ,
ि
23
00:01:24.910 --> 00:01:26.250
!
24
00:01:26.250 --> 00:01:31.020
ि ि
ि

View File

@ -0,0 +1,115 @@
WEBVTT
1
00:00:00.780 --> 00:00:04.580
MetaMask adalah cara baru untuk terhubung
ke situs dan aplikasi.
2
00:00:04.580 --> 00:00:08.860
Di situs web tradisional, database sentral
atau bank bertanggung jawab untuk mengontrol dan
3
00:00:08.860 --> 00:00:10.179
memulihkan akun Anda.
4
00:00:10.179 --> 00:00:15.050
Tetapi di MetaMask, semua kuasa milik
pemegang kunci induk.
5
00:00:15.050 --> 00:00:18.460
Siapa pun yang memegang kunci tersebut, akan mengontrol akun.
6
00:00:18.460 --> 00:00:21.110
Frasa pemulihan rahasia
adalah "kunci induk" Anda.
7
00:00:21.110 --> 00:00:26.070
Ini adalah rangkaian 12 kata yang dibuat
saat Anda menyiapkan MetaMask pertama kali, yang memungkinkan
8
00:00:26.070 --> 00:00:30.120
Anda memulihkan dompet dan dana jika Anda
kehilangan akses.
9
00:00:30.120 --> 00:00:33.451
Penting agar Anda mengamankan
dompet Anda dengan menjaga
10
00:00:33.451 --> 00:00:37.510
frasa pemulihan rahasia
Anda dengan sangat aman dan sangat rahasia.
11
00:00:37.510 --> 00:00:41.429
Jika seseorang mendapatkan aksesnya, mereka akan memiliki
"kunci induk" ke dompet Anda dan dapat
12
00:00:41.429 --> 00:00:45.190
mengakses secara bebas dan mengambil semua dana Anda.
13
00:00:45.190 --> 00:00:50.109
Untuk mengamankan dompet MetaMask, Anda pasti ingin
menyimpan frasa pemulihan rahasia Anda secara aman.
14
00:00:50.109 --> 00:00:54.930
Anda dapat menuliskannya, menyembunyikannya di suatu tempat,
menempatkannya di kotak deposit yang aman
15
00:00:54.930 --> 00:00:57.729
atau menggunakan pengelola kata sandi yang aman.
16
00:00:57.729 --> 00:01:01.050
Beberapa pengguna bahkan mengukir frasa
mereka pada pelat logam!
17
00:01:01.050 --> 00:01:04.440
Tidak ada seorang pun, bahkan tidak juga tim
di MetaMask, dapat membantu Anda
18
00:01:04.440 --> 00:01:07.820
memulihkan dompet Anda jika Anda menghilangkan
frasa pemulihan rahasia Anda.
19
00:01:07.820 --> 00:01:12.072
Jika belum menuliskan frasa pemulihan rahasia Anda
dan menyimpannya di suatu tempat yang aman,
20
00:01:12.072 --> 00:01:15.492
lakukan sekarang. Kami akan menunggu.
21
00:01:15.500 --> 00:01:20.780
Dan ingat, jangan membagikan frasa pemulihan rahasia
Anda kepada siapa pun: bahkan tidak kepada kami.
22
00:01:20.780 --> 00:01:24.910
Jika ada yang menanyakannya,
mereka akan mencoba menipu Anda.
23
00:01:24.910 --> 00:01:26.250
Begitulah!
24
00:01:26.250 --> 00:01:31.020
Sekarang, Anda tahu apa itu frasa pemulihan rahasia
dan cara menjaga dompet Anda tetap aman.

View File

@ -0,0 +1,115 @@
WEBVTT
1
00:00:00.780 --> 00:00:04.580
MetaMask
2
00:00:04.580 --> 00:00:08.860
3
00:00:08.860 --> 00:00:10.179
4
00:00:10.179 --> 00:00:15.050
MetaMask
5
00:00:15.050 --> 00:00:18.460
6
00:00:18.460 --> 00:00:21.110
7
00:00:21.110 --> 00:00:26.070
12
MetaMask
8
00:00:26.070 --> 00:00:30.120
9
00:00:30.120 --> 00:00:33.451
10
00:00:33.451 --> 00:00:37.510
11
00:00:37.510 --> 00:00:41.429
12
00:00:41.429 --> 00:00:45.190
13
00:00:45.190 --> 00:00:50.109
MetaMask
14
00:00:50.109 --> 00:00:54.930
15
00:00:54.930 --> 00:00:57.729
使
16
00:00:57.729 --> 00:01:01.050
17
00:01:01.050 --> 00:01:04.440
MetaMask
18
00:01:04.440 --> 00:01:07.820
19
00:01:07.820 --> 00:01:12.072
20
00:01:12.072 --> 00:01:15.492
21
00:01:15.500 --> 00:01:20.780
22
00:01:20.780 --> 00:01:24.910
23
00:01:24.910 --> 00:01:26.250
24
00:01:26.250 --> 00:01:31.020

View File

@ -0,0 +1,115 @@
WEBVTT
1
00:00:00.780 --> 00:00:04.580
MetaMask
.
2
00:00:04.580 --> 00:00:08.860
3
00:00:08.860 --> 00:00:10.179
.
4
00:00:10.179 --> 00:00:15.050
MetaMask
.
5
00:00:15.050 --> 00:00:18.460
.
6
00:00:18.460 --> 00:00:21.110
" ".
7
00:00:21.110 --> 00:00:26.070
MetaMask ,
12 ,
8
00:00:26.070 --> 00:00:30.120
.
9
00:00:30.120 --> 00:00:33.451
10
00:00:33.451 --> 00:00:37.510
.
11
00:00:37.510 --> 00:00:41.429
" "
12
00:00:41.429 --> 00:00:45.190
.
13
00:00:45.190 --> 00:00:50.109
MetaMask ,
.
14
00:00:50.109 --> 00:00:54.930
15
00:00:54.930 --> 00:00:57.729
.
16
00:00:57.729 --> 00:01:01.050
!
17
00:01:01.050 --> 00:01:04.440
,
MetaMask
18
00:01:04.440 --> 00:01:07.820
.
19
00:01:07.820 --> 00:01:12.072
,
20
00:01:12.072 --> 00:01:15.492
. .
21
00:01:15.500 --> 00:01:20.780
. .
22
00:01:20.780 --> 00:01:24.910
.
23
00:01:24.910 --> 00:01:26.250
.
24
00:01:26.250 --> 00:01:31.020
.

View File

@ -0,0 +1,115 @@
WEBVTT
1
00:00:00.780 --> 00:00:04.580
O MetaMask é um novo jeito de se conectar
a sites e aplicativos.
2
00:00:04.580 --> 00:00:08.860
Em websites tradicionais, um banco ou base de dados central
é responsável por controlar e
3
00:00:08.860 --> 00:00:10.179
recuperar as suas contas.
4
00:00:10.179 --> 00:00:15.050
Mas, no MetaMask, todo o poder pertence
ao titular de uma chave-mestra.
5
00:00:15.050 --> 00:00:18.460
Quem quer que detenha a chave controla as contas.
6
00:00:18.460 --> 00:00:21.110
A sua frase de recuperação secreta
é a sua "chave-mestra".
7
00:00:21.110 --> 00:00:26.070
É uma série de 12 palavras que são geradas
quando você configura o MetaMask na primeira vez, o que permite que
8
00:00:26.070 --> 00:00:30.120
você recupere a sua carteira e recursos, caso você
venha a perder o acesso.
9
00:00:30.120 --> 00:00:33.451
É importante que você mantenha protegida
a sua carteira ao manter a sua
10
00:00:33.451 --> 00:00:37.510
frase de recuperação secreta
muito segura e muito secreta.
11
00:00:37.510 --> 00:00:41.429
Caso alguém obtenha acesso a ela, essa pessoa terá
a "chave-mestra" para a sua carteira e poderá
12
00:00:41.429 --> 00:00:45.190
acessá-la livremente e tome todos os seus recursos.
13
00:00:45.190 --> 00:00:50.109
A fim de proteger a sua carteira MetaMask, você desejará
manter em segurança a sua frase de recuperação secreta.
14
00:00:50.109 --> 00:00:54.930
Você pode escrevê-la, escondê-la em algum lugar,
colocá-la em um cofre
15
00:00:54.930 --> 00:00:57.729
ou usar um gerenciador de senhas seguras.
16
00:00:57.729 --> 00:01:01.050
Alguns usuários até mesmo gravam sua
frase em uma placa de metal!
17
00:01:01.050 --> 00:01:04.440
Ninguém, nem mesmo a equipe
na MetaMask, pode lhe ajudar
18
00:01:04.440 --> 00:01:07.820
a recuperar a sua carteira, caso você perca
a sua frase de recuperação secreta.
19
00:01:07.820 --> 00:01:12.072
Caso você não tenha escrito a sua frase de recuperação
secreta e a tenha armazenado em algum lugar seguro,
20
00:01:12.072 --> 00:01:15.492
faça isso agora. Iremos aguardar.
21
00:01:15.500 --> 00:01:20.780
E lembre-se de jamais compartilhar a sua frase de recuperação
secreta com ninguém: nem mesmo conosco.
22
00:01:20.780 --> 00:01:24.910
Caso alguém venha a lhe pedir a sua frase de recuperação secreta,
essa pessoa está tentando dar um golpe em você.
23
00:01:24.910 --> 00:01:26.250
É isso!
24
00:01:26.250 --> 00:01:31.020
Agora, você sabe o que é uma frase de recuperação secreta
e como manter a sua carteira protegida e segura.

View File

@ -0,0 +1,115 @@
WEBVTT
1
00:00:00.780 --> 00:00:04.580
MetaMask это новый способ подключения
к сайтам и приложениям.
2
00:00:04.580 --> 00:00:08.860
На традиционных сайтах центральная база данных
или банк несет ответственность за контроль и
3
00:00:08.860 --> 00:00:10.179
восстановление ваших счетов.
4
00:00:10.179 --> 00:00:15.050
На MetaMask все полномочия находятся
в руках владельца мастер-ключа.
5
00:00:15.050 --> 00:00:18.460
Тот, в чьих руках находится ключ, контролирует счета.
6
00:00:18.460 --> 00:00:21.110
Ваша секретная фраза восстановления
это ваш «мастер-ключ».
7
00:00:21.110 --> 00:00:26.070
Это набор из 12 слов, которые генерируются
при первой настройке MetaMask, он позволяет
8
00:00:26.070 --> 00:00:30.120
вам восстанавливать ваш кошелек и средства, если вы
теряете к ним доступ.
9
00:00:30.120 --> 00:00:33.451
Важно, чтобы вы обезопасили
свой кошелек, храня вашу
10
00:00:33.451 --> 00:00:37.510
секретную фразу восстановления
в очень надежном и тайном месте.
11
00:00:37.510 --> 00:00:41.429
Если кто-то получит доступ к ней, у этого человека окажется в руках
«мастер-ключ» от вашего кошелька, и он сможет
12
00:00:41.429 --> 00:00:45.190
распоряжаться им и завладеть всеми вашими средствами.
13
00:00:45.190 --> 00:00:50.109
Чтобы обезопасить ваш кошелек MetaMask,
сохраните секретную фразу восстановления в безопасном месте.
14
00:00:50.109 --> 00:00:54.930
Вы можете записать ее, спрятать ее где-то,
положить ее в банковский сейф
15
00:00:54.930 --> 00:00:57.729
или воспользоваться безопасным диспетчером паролей.
16
00:00:57.729 --> 00:01:01.050
Некоторые пользователи даже гравируют свою
фразу на металлической пластине!
17
00:01:01.050 --> 00:01:04.440
Никто, даже команда
MetaMask, не сможет помочь вам
18
00:01:04.440 --> 00:01:07.820
восстановить ваш кошелек, если вы потеряете
вашу секретную фразу восстановления.
19
00:01:07.820 --> 00:01:12.072
Если вы еще не записали секретную фразу
восстановления и не поместили ее в надежное место,
20
00:01:12.072 --> 00:01:15.492
сделайте это сейчас. Мы подождем.
21
00:01:15.500 --> 00:01:20.780
И помните, никогда не сообщайте свою секретную фразу
восстановления никому: даже нам.
22
00:01:20.780 --> 00:01:24.910
Если кто-нибудь когда-либо спросит у вас ее,
этот человек пытается вас обмануть.
23
00:01:24.910 --> 00:01:26.250
Вот и все!
24
00:01:26.250 --> 00:01:31.020
Теперь вы знаете, что такое секретная фраза восстановления
и как обезопасить ваш кошелек.

View File

@ -0,0 +1,115 @@
WEBVTT
1
00:00:00.780 --> 00:00:04.580
Ang MetaMask ay isang bagong paraan para kumonekta
sa mga site at application.
2
00:00:04.580 --> 00:00:08.860
Sa mga tradisyonal na website, ang isang central database
o bangko ang magiging responsable sa pagkontrol at
3
00:00:08.860 --> 00:00:10.179
pag-recover ng iyong mga account.
4
00:00:10.179 --> 00:00:15.050
Pero sa MetaMask, ang lahat ng kakayahan ay nasa
may hawak ng master key.
5
00:00:15.050 --> 00:00:18.460
Kung sino man ang may hawak ng key, siya ang magkokontrol sa mga account.
6
00:00:18.460 --> 00:00:21.110
Ang iyong lihim na recovery phrase
ay ang iyong "master key".
7
00:00:21.110 --> 00:00:26.070
Isa itong 12 salita na nagagawa
sa unang pagkakataong i-set up mo ang MetaMask, na magbibigay-daan sa iyo
8
00:00:26.070 --> 00:00:30.120
na maibalik ang iyong wallet at pera kung sakaling
mawalan ka ng access.
9
00:00:30.120 --> 00:00:33.451
Mahalagang i-secure
ang iyong wallet sa pamamagitan ng pagpapanatiling sobrang ligtas at walang nakakaalam ng iyong
10
00:00:33.451 --> 00:00:37.510
lihim na recovery phrase
.
11
00:00:37.510 --> 00:00:41.429
Kung may ibang taong makaka-access nito, makukuha nila
ang "master key" sa iyong wallet at
12
00:00:41.429 --> 00:00:45.190
madali nilang maa-access at makukuha ang lahat ng pera mo.
13
00:00:45.190 --> 00:00:50.109
Para ma-secure ang iyong MetaMask wallet,
ligtas na i-save ang iyong lihim na recovery phrase.
14
00:00:50.109 --> 00:00:54.930
Puwede mo itong isulat, itago,
ilagay sa isang safe deposit box
15
00:00:54.930 --> 00:00:57.729
o kaya ay gumamit ng ligtas na password manager.
16
00:00:57.729 --> 00:01:01.050
Ang ilang user nga ay inuukit pa ang kanilang
phrase sa isang metal plate!
17
00:01:01.050 --> 00:01:04.440
Walang sinuman, maging ang team
sa MetaMask, ang makakatulong sa iyong
18
00:01:04.440 --> 00:01:07.820
maibalik ang wallet mo kung maiwawala mo
iyong lihim na recovery phrase.
19
00:01:07.820 --> 00:01:12.072
Kung hindi mo pa naisusulat ang iyong lihim na recovery
phrase at hindi pa naitatago sa ligtas na lugar,
20
00:01:12.072 --> 00:01:15.492
gawin mo na ngayon. Hihintayin ka namin.
21
00:01:15.500 --> 00:01:20.780
At tandaan, huwag kailanman ipaalam sa iba ang iyong lihim na recovery
phrase: maging sa amin.
22
00:01:20.780 --> 00:01:24.910
Kung may magtatanong man sa iyo,
sinusubukan ka nilang i-scam.
23
00:01:24.910 --> 00:01:26.250
´Yun lang!
24
00:01:26.250 --> 00:01:31.020
Ngayon ay alam mo na kung ano ang lihim na recovery phrase
at kung paano mapapanatiling ligtas ang iyong wallet.

View File

@ -0,0 +1,115 @@
WEBVTT
1
00:00:00.780 --> 00:00:04.580
MetaMask là cách thc mi đ kết ni
vi các trang web và ng dng.
2
00:00:04.580 --> 00:00:08.860
Trên các trang web truyn thng, mt cơ s d liu trung tâm
hay ngân hàng s chu trách nhim kim soát và
3
00:00:08.860 --> 00:00:10.179
khôi phc các tài khon ca bn.
4
00:00:10.179 --> 00:00:15.050
Tuy nhiên, trên MetaMask, toàn b quyn s thuc v
ngưi nm gi khóa chính.
5
00:00:15.050 --> 00:00:18.460
Ngưi có khóa chính s kim soát đưc tài khon.
6
00:00:18.460 --> 00:00:21.110
Cm mt khu khôi phc bí mt
là khóa chính ca bn.
7
00:00:21.110 --> 00:00:26.070
Đây là chui gm 12 t đưc to
vào ln đu tiên bn thiết lp MetaMask, chui này cho phép
8
00:00:26.070 --> 00:00:30.120
bn khôi phc ví và tin ca mình nếu
bn b mt quyn truy cp.
9
00:00:30.120 --> 00:00:33.451
Bn cn phi bo v an toàn cho
ví ca mình bng cách lưu gi
10
00:00:33.451 --> 00:00:37.510
cm mt khu khôi phc bí mt
tht an toàn và bí mt.
11
00:00:37.510 --> 00:00:41.429
Nếu ai đó có đưc cm mt khu khôi phc bí mt ca bn thì ngưi đó s có
khóa chính cho ví ca bn và có th
12
00:00:41.429 --> 00:00:45.190
t do truy cp và ly toàn b tin ca bn.
13
00:00:45.190 --> 00:00:50.109
Đ bo v an toàn cho ví MetaMask, bn cn
lưu gi cm mt khu khôi phc bí mt mt cách an toàn.
14
00:00:50.109 --> 00:00:54.930
Bn có th chép li và giu mt nơi nào đó,
ct trong hp ký gi an toàn
15
00:00:54.930 --> 00:00:57.729
hoc dùng mt trình qun lý mt khu an toàn.
16
00:00:57.729 --> 00:01:01.050
Mt s ngưi dùng thm chí còn khc
cm mt khu ca h lên mt tm kim loi!
17
00:01:01.050 --> 00:01:04.440
Không mt ai, k c đi ngũ
ti MetaMask, có th giúp bn
18
00:01:04.440 --> 00:01:07.820
khôi phc li ví nếu bn đánh mt
cm mt khu khôi phc bí mt ca mình.
19
00:01:07.820 --> 00:01:12.072
Nếu chưa ghi li cm mt khu khôi phc bí mt
ca mình và lưu gi nơi an toàn,
20
00:01:12.072 --> 00:01:15.492
thì bn hãy thc hin ngay bây gi. Chúng tôi s ch bn.
21
00:01:15.500 --> 00:01:20.780
Và đng bao gi chia s cm mt khu khôi phc
bí mt vi bt k ai: k c chúng tôi.
22
00:01:20.780 --> 00:01:24.910
Nếu ai đó hi bn cm mt khu khôi phc bí mt,
thì h đang c gng la đo bn.
23
00:01:24.910 --> 00:01:26.250
Xin hãy ghi nh!
24
00:01:26.250 --> 00:01:31.020
Bây gi bn đã biết cm mt khu khôi phc bí mt
là gì và cách bo v ví ca bn an toàn và bo mt.

View File

@ -3,5 +3,5 @@
"matches": ["https://metamask.io/*"],
"ids": ["*"]
},
"minimum_chrome_version": "63"
"minimum_chrome_version": "66"
}

View File

@ -51,7 +51,7 @@
<a href="https://github.com/metamask/eth-phishing-detect">Ethereum Phishing Detector</a>.
Domains on these warning lists may include outright malicious websites and legitimate websites that have been compromised by a malicious actor.
</p>
<p>To read more about this site <a id="csdbLink">please search for the domain on CryptoScamDB</a>.</p>
<p>To read more about this site <a id="csdbLink" href="https://cryptoscamdb.org/search">please search for the domain on CryptoScamDB</a>.</p>
<p>
Note that this warning list is compiled on a voluntary basis. This list may be inaccurate or incomplete.
Just because a domain does not appear on this list is not an implicit guarantee of that domain's safety.
@ -60,7 +60,7 @@
</p>
<p>
If you think this domain is incorrectly flagged or if a blocked legitimate website has resolved its security issues,
<a href="https://github.com/metamask/eth-phishing-detect/issues/new">please file an issue</a>.
<a id="new-issue-link" href="https://github.com/metamask/eth-phishing-detect/issues/new">please file an issue</a>.
</p>
</div>
</div>

View File

@ -2,9 +2,6 @@
* @file The entry point for the web extension singleton process.
*/
// polyfills
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch';
import endOfStream from 'end-of-stream';
import pump from 'pump';
import debounce from 'debounce-stream';
@ -435,12 +432,16 @@ function setupController(initState, initLangCode) {
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
updateBadge,
);
controller.approvalController.subscribe(updateBadge);
controller.appStateController.on(
METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE,
updateBadge,
);
controller.controllerMessenger.subscribe(
METAMASK_CONTROLLER_EVENTS.APPROVAL_STATE_CHANGE,
updateBadge,
);
/**
* Updates the Web Extension's "badge" number, on the little fox in the toolbar.
* The number reflects the current number of pending transactions or message signatures needing user approval.

View File

@ -40,6 +40,7 @@ export const SAFE_METHODS = [
'eth_coinbase',
'eth_decrypt',
'eth_estimateGas',
'eth_feeHistory',
'eth_gasPrice',
'eth_getBalance',
'eth_getBlockByHash',

View File

@ -249,7 +249,7 @@ export class PermissionsController {
approved.permissions,
accounts,
);
this.approvals.resolve(id, approved.permissions);
this.approvals.accept(id, approved.permissions);
}
} catch (err) {
// if finalization fails, reject the request

View File

@ -816,7 +816,6 @@ export default class PreferencesController {
return await tokenContract
.supportsInterface(ERC721_INTERFACE_ID)
.catch((error) => {
console.log('error', error);
log.debug(error);
return false;
});

View File

@ -1383,6 +1383,10 @@ export default class TransactionController extends EventEmitter {
* @param {Object} extraParams - optional props and values to include in sensitiveProperties
*/
_trackTransactionMetricsEvent(txMeta, event, extraParams = {}) {
if (!txMeta) {
return;
}
const {
type,
time,

View File

@ -136,8 +136,8 @@ export default class PendingTransactionTracker extends EventEmitter {
const retryCount = txMeta.retryCount || 0;
// Exponential backoff to limit retries at publishing
if (txBlockDistance <= Math.pow(2, retryCount) - 1) {
// Exponential backoff to limit retries at publishing (capped at ~15 minutes between retries)
if (txBlockDistance < Math.min(50, Math.pow(2, retryCount))) {
return undefined;
}

View File

@ -1,4 +1,5 @@
import { ObservableStore } from '@metamask/obs-store';
import { getPersistentState } from '@metamask/controllers';
/**
* @typedef {import('@metamask/controllers').ControllerMessenger} ControllerMessenger
@ -27,9 +28,11 @@ export default class ComposableObservableStore extends ObservableStore {
* messenger, used for subscribing to events from BaseControllerV2-based
* controllers.
* @param {Object} [options.state] - The initial store state
* @param {boolean} [options.persist] - Wether or not to apply the persistence for v2 controllers
*/
constructor({ config, controllerMessenger, state }) {
constructor({ config, controllerMessenger, state, persist }) {
super(state);
this.persist = persist;
this.controllerMessenger = controllerMessenger;
if (config) {
this.updateStructure(config);
@ -60,7 +63,11 @@ export default class ComposableObservableStore extends ObservableStore {
this.controllerMessenger.subscribe(
`${store.name}:stateChange`,
(state) => {
this.updateState({ [key]: state });
let updatedState = state;
if (this.persist) {
updatedState = getPersistentState(state, config[key].metadata);
}
this.updateState({ [key]: updatedState });
},
);
}

View File

@ -12,9 +12,103 @@ try {
// If the `lockdown` call throws an exception, it interferes with the
// contentscript injection on some versions of Firefox. The error is
// caught and logged here so that the contentscript still gets injected.
// This affects Firefox v56 and Waterfox Classic
// This affects Firefox v56 and Waterfox Classic.
console.error('Lockdown failed:', error);
if (globalThis.sentry && globalThis.sentry.captureException) {
globalThis.sentry.captureException(error);
globalThis.sentry.captureException(
new Error(`Lockdown failed: ${error.message}`),
);
}
}
// Make all "object" and "function" own properties of globalThis
// non-configurable and non-writable, when possible.
// We call the a property that is non-configurable and non-writable,
// "non-modifiable".
try {
/**
* `lockdown` only hardens the properties enumerated by the
* universalPropertyNames constant specified in 'ses/src/whitelist'. This
* function makes all function and object properties on the start compartment
* global non-configurable and non-writable, unless they are already
* non-configurable.
*
* It is critical that this function runs at the right time during
* initialization, which should always be immediately after `lockdown` has been
* called. At the time of writing, the modifications this function makes to the
* runtime environment appear to be non-breaking, but that could change with
* the addition of dependencies, or the order of our scripts in our HTML files.
* Exercise caution.
*
* See inline comments for implementation details.
*
* We write this function in IIFE format to avoid polluting global scope.
*/
(function protectIntrinsics() {
const namedIntrinsics = Reflect.ownKeys(new Compartment().globalThis);
// These named intrinsics are not automatically hardened by `lockdown`
const shouldHardenManually = new Set(['eval', 'Function']);
const globalProperties = new Set([
// universalPropertyNames is a constant added by lockdown to global scope
// at the time of writing, it is initialized in 'ses/src/whitelist'.
// These properties tend to be non-enumerable.
...namedIntrinsics,
// TODO: Also include the named platform globals
// This grabs every enumerable property on globalThis.
// ...Object.keys(globalThis),
]);
globalProperties.forEach((propertyName) => {
const descriptor = Reflect.getOwnPropertyDescriptor(
globalThis,
propertyName,
);
if (descriptor) {
if (descriptor.configurable) {
// If the property on globalThis is configurable, make it
// non-configurable. If it has no accessor properties, also make it
// non-writable.
if (hasAccessor(descriptor)) {
Object.defineProperty(globalThis, propertyName, {
configurable: false,
});
} else {
Object.defineProperty(globalThis, propertyName, {
configurable: false,
writable: false,
});
}
}
if (shouldHardenManually.has(propertyName)) {
harden(globalThis[propertyName]);
}
}
});
/**
* Checks whether the given propertyName descriptor has any accessors, i.e. the
* properties `get` or `set`.
*
* We want to make globals non-writable, and we can't set the `writable`
* property and accessor properties at the same time.
*
* @param {Object} descriptor - The propertyName descriptor to check.
* @returns {boolean} Whether the propertyName descriptor has any accessors.
*/
function hasAccessor(descriptor) {
return 'set' in descriptor || 'get' in descriptor;
}
})();
} catch (error) {
console.error('Protecting intrinsics failed:', error);
if (globalThis.sentry && globalThis.sentry.captureException) {
globalThis.sentry.captureException(
new Error(`Protecting intrinsics failed: ${error.message}`),
);
}
}

View File

@ -76,6 +76,8 @@ export const METAMASK_CONTROLLER_EVENTS = {
// Fired after state changes that impact the extension badge (unapproved msg count)
// The process of updating the badge happens in app/scripts/background.js.
UPDATE_BADGE: 'updateBadge',
// TODO: Add this and similar enums to @metamask/controllers and export them
APPROVAL_STATE_CHANGE: 'ApprovalController:stateChange',
};
export default class MetamaskController extends EventEmitter {
@ -106,12 +108,13 @@ export default class MetamaskController extends EventEmitter {
this.getRequestAccountTabIds = opts.getRequestAccountTabIds;
this.getOpenMetamaskTabsIds = opts.getOpenMetamaskTabsIds;
const controllerMessenger = new ControllerMessenger();
this.controllerMessenger = new ControllerMessenger();
// observable state store
this.store = new ComposableObservableStore({
state: initState,
controllerMessenger,
controllerMessenger: this.controllerMessenger,
persist: true,
});
// external connections by origin
@ -131,6 +134,9 @@ export default class MetamaskController extends EventEmitter {
// controller initialization order matters
this.approvalController = new ApprovalController({
messenger: this.controllerMessenger.getRestricted({
name: 'ApprovalController',
}),
showApprovalRequest: opts.showUserConfirmation,
});
@ -169,7 +175,7 @@ export default class MetamaskController extends EventEmitter {
initState: initState.MetaMetricsController,
});
const gasFeeMessenger = controllerMessenger.getRestricted({
const gasFeeMessenger = this.controllerMessenger.getRestricted({
name: 'GasFeeController',
});
@ -210,7 +216,7 @@ export default class MetamaskController extends EventEmitter {
preferencesStore: this.preferencesController.store,
});
const currencyRateMessenger = controllerMessenger.getRestricted({
const currencyRateMessenger = this.controllerMessenger.getRestricted({
name: 'CurrencyRateController',
});
this.currencyRateController = new CurrencyRateController({
@ -219,7 +225,7 @@ export default class MetamaskController extends EventEmitter {
state: initState.CurrencyController,
});
const tokenListMessenger = controllerMessenger.getRestricted({
const tokenListMessenger = this.controllerMessenger.getRestricted({
name: 'TokenListController',
});
this.tokenListController = new TokenListController({
@ -569,7 +575,7 @@ export default class MetamaskController extends EventEmitter {
GasFeeController: this.gasFeeController,
TokenListController: this.tokenListController,
},
controllerMessenger,
controllerMessenger: this.controllerMessenger,
});
this.memStore.subscribe(this.sendUpdate.bind(this));
@ -1097,7 +1103,7 @@ export default class MetamaskController extends EventEmitter {
// approval controller
resolvePendingApproval: nodeify(
approvalController.resolve,
approvalController.accept,
approvalController,
),
rejectPendingApproval: nodeify(

View File

@ -23,23 +23,27 @@ function transformState(state) {
state?.IncomingTransactionsController?.incomingTransactions;
if (Array.isArray(transactions)) {
transactions.forEach((transaction) => {
if (
transaction.type !== TRANSACTION_TYPES.RETRY &&
transaction.type !== TRANSACTION_TYPES.CANCEL
) {
transaction.type = transaction.transactionCategory;
if (transaction) {
if (
transaction.type !== TRANSACTION_TYPES.RETRY &&
transaction.type !== TRANSACTION_TYPES.CANCEL
) {
transaction.type = transaction.transactionCategory;
}
delete transaction.transactionCategory;
}
delete transaction.transactionCategory;
});
}
if (incomingTransactions) {
const incomingTransactionsEntries = Object.entries(incomingTransactions);
incomingTransactionsEntries.forEach(([key, transaction]) => {
delete transaction.transactionCategory;
state.IncomingTransactionsController.incomingTransactions[key] = {
...transaction,
type: TRANSACTION_TYPES.INCOMING,
};
if (transaction) {
delete transaction.transactionCategory;
state.IncomingTransactionsController.incomingTransactions[key] = {
...transaction,
type: TRANSACTION_TYPES.INCOMING,
};
}
});
}
return state;

View File

@ -15,14 +15,14 @@ export default {
const { PreferencesController } = versionedData.data;
if (Array.isArray(PreferencesController.tokens)) {
if (Array.isArray(PreferencesController?.tokens)) {
PreferencesController.tokens = PreferencesController.tokens.filter(
({ address }) => address,
);
}
if (
PreferencesController.accountTokens &&
PreferencesController?.accountTokens &&
typeof PreferencesController.accountTokens === 'object'
) {
Object.keys(PreferencesController.accountTokens).forEach((account) => {
@ -40,7 +40,7 @@ export default {
}
if (
PreferencesController.assetImages &&
PreferencesController?.assetImages &&
'undefined' in PreferencesController.assetImages
) {
delete PreferencesController.assetImages.undefined;

View File

@ -12,7 +12,12 @@ function start() {
const hash = window.location.hash.substring(1);
const suspect = querystring.parse(hash);
document.getElementById('csdbLink').href = `https://cryptoscamdb.org/search`;
const newIssueLink = document.getElementById('new-issue-link');
const newIssueUrl = `https://github.com/MetaMask/eth-phishing-detect/issues/new`;
const newIssueParams = `?title=[Legitimate%20Site%20Blocked]%20${encodeURIComponent(
suspect.hostname,
)}&body=${encodeURIComponent(suspect.href)}`;
newIssueLink.href = `${newIssueUrl}${newIssueParams}`;
global.platform = new ExtensionPlatform();

View File

@ -1,5 +1,4 @@
// polyfills
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch';
import '@formatjs/intl-relativetimeformat/polyfill';
// dev only, "react-devtools" import is skipped in prod builds

View File

@ -6,7 +6,7 @@ module.exports = function (api) {
'@babel/preset-env',
{
targets: {
browsers: ['chrome >= 63', 'firefox >= 68'],
browsers: ['chrome >= 66', 'firefox >= 68'],
},
},
],

View File

@ -28,12 +28,17 @@ require('@babel/preset-react');
require('@babel/core');
const browserPlatforms = ['firefox', 'chrome', 'brave', 'opera'];
const shouldIncludeLockdown = !process.argv.includes('--omit-lockdown');
defineAllTasks();
detectAndRunEntryTask();
function defineAllTasks() {
const staticTasks = createStaticAssetTasks({ livereload, browserPlatforms });
const staticTasks = createStaticAssetTasks({
livereload,
browserPlatforms,
shouldIncludeLockdown,
});
const manifestTasks = createManifestTasks({ browserPlatforms });
const styleTasks = createStyleTasks({ livereload });
const scriptTasks = createScriptTasks({ livereload, browserPlatforms });

View File

@ -7,107 +7,17 @@ const locales = require('../../app/_locales/index.json');
const { createTask, composeSeries } = require('./task');
module.exports = createStaticAssetTasks;
const EMPTY_JS_FILE = './development/empty.js';
const copyTargets = [
{
src: `./app/_locales/`,
dest: `_locales`,
},
{
src: `./app/images/`,
dest: `images`,
},
{
src: `./node_modules/@metamask/contract-metadata/images/`,
dest: `images/contract`,
},
{
src: `./app/fonts/`,
dest: `fonts`,
},
{
src: `./app/vendor/`,
dest: `vendor`,
},
{
src: `./node_modules/@fortawesome/fontawesome-free/webfonts/`,
dest: `fonts/fontawesome`,
},
{
src: `./ui/css/output/`,
pattern: `*.css`,
dest: ``,
},
{
src: `./app/loading.html`,
dest: `loading.html`,
},
{
src: `./node_modules/globalthis/dist/browser.js`,
dest: `globalthis.js`,
},
{
src: `./node_modules/ses/dist/lockdown.cjs`,
dest: `lockdown-install.js`,
},
{
src: `./app/scripts/lockdown-run.js`,
dest: `lockdown-run.js`,
},
{
// eslint-disable-next-line node/no-extraneous-require
src: require.resolve('@lavamoat/lavapack/src/runtime-cjs.js'),
dest: `runtime-cjs.js`,
},
{
src: `./app/phishing.html`,
dest: `phishing.html`,
},
];
module.exports = function createStaticAssetTasks({
livereload,
browserPlatforms,
shouldIncludeLockdown = true,
}) {
const [copyTargetsProd, copyTargetsDev] = getCopyTargets(
shouldIncludeLockdown,
);
const languageTags = new Set();
for (const locale of locales) {
const { code } = locale;
const tag = code.split('_')[0];
languageTags.add(tag);
}
for (const tag of languageTags) {
copyTargets.push({
src: `./node_modules/@formatjs/intl-relativetimeformat/dist/locale-data/${tag}.json`,
dest: `intl/${tag}/relative-time-format-data.json`,
});
}
const copyTargetsDev = [
...copyTargets,
{
src: './development',
pattern: '/chromereload.js',
dest: ``,
},
// empty files to suppress missing file errors
{
src: './development/empty.js',
dest: `bg-libs.js`,
},
{
src: './development/empty.js',
dest: `ui-libs.js`,
},
];
const copyTargetsProd = [
...copyTargets,
// empty files to suppress missing file errors
{
src: './development/empty.js',
dest: `chromereload.js`,
},
];
function createStaticAssetTasks({ livereload, browserPlatforms }) {
const prod = createTask(
'static:prod',
composeSeries(
@ -169,4 +79,110 @@ function createStaticAssetTasks({ livereload, browserPlatforms }) {
}),
);
}
};
function getCopyTargets(shouldIncludeLockdown) {
const allCopyTargets = [
{
src: `./app/_locales/`,
dest: `_locales`,
},
{
src: `./app/images/`,
dest: `images`,
},
{
src: `./node_modules/@metamask/contract-metadata/images/`,
dest: `images/contract`,
},
{
src: `./app/fonts/`,
dest: `fonts`,
},
{
src: `./app/vendor/`,
dest: `vendor`,
},
{
src: `./node_modules/@fortawesome/fontawesome-free/webfonts/`,
dest: `fonts/fontawesome`,
},
{
src: `./ui/css/output/`,
pattern: `*.css`,
dest: ``,
},
{
src: `./app/loading.html`,
dest: `loading.html`,
},
{
src: `./node_modules/globalthis/dist/browser.js`,
dest: `globalthis.js`,
},
{
src: shouldIncludeLockdown
? `./node_modules/ses/dist/lockdown.umd.min.js`
: EMPTY_JS_FILE,
dest: `lockdown-install.js`,
},
{
src: shouldIncludeLockdown
? `./app/scripts/lockdown-run.js`
: EMPTY_JS_FILE,
dest: `lockdown-run.js`,
},
{
// eslint-disable-next-line node/no-extraneous-require
src: require.resolve('@lavamoat/lavapack/src/runtime-cjs.js'),
dest: `runtime-cjs.js`,
},
{
src: `./app/phishing.html`,
dest: `phishing.html`,
},
];
const languageTags = new Set();
for (const locale of locales) {
const { code } = locale;
const tag = code.split('_')[0];
languageTags.add(tag);
}
for (const tag of languageTags) {
allCopyTargets.push({
src: `./node_modules/@formatjs/intl-relativetimeformat/dist/locale-data/${tag}.json`,
dest: `intl/${tag}/relative-time-format-data.json`,
});
}
const copyTargetsDev = [
...allCopyTargets,
{
src: './development',
pattern: '/chromereload.js',
dest: ``,
},
// empty files to suppress missing file errors
{
src: EMPTY_JS_FILE,
dest: `bg-libs.js`,
},
{
src: EMPTY_JS_FILE,
dest: `ui-libs.js`,
},
];
const copyTargetsProd = [
...allCopyTargets,
// empty files to suppress missing file errors
{
src: EMPTY_JS_FILE,
dest: `chromereload.js`,
},
];
return [copyTargetsProd, copyTargetsDev];
}

View File

@ -5,4 +5,4 @@ The extension injects the Ethereum web3 API into every website's javascript cont
MetaMask also lets the user create and manage their own identities, so when a Dapp wants to perform a transaction and write to the blockchain, the user gets a secure interface to review the transaction, before approving or rejecting it.
Because it adds functionality to the normal browser context, MetaMask requires the permission to read and write to any webpage. You can always "view the source" of MetaMask the way you do any extension, or view the source code on Github:
https://github.com/MetaMask/metamask-plugin
https://github.com/MetaMask/metamask-extension

View File

@ -48,6 +48,8 @@
"lint:fix": "prettier --write '**/*.json' && eslint . --ext js --cache --fix",
"lint:changed": "{ git ls-files --others --exclude-standard ; git diff-index --name-only --diff-filter=d HEAD ; } | grep --regexp='[.]js$' | tr '\\n' '\\0' | xargs -0 eslint",
"lint:changed:fix": "{ git ls-files --others --exclude-standard ; git diff-index --name-only --diff-filter=d HEAD ; } | grep --regexp='[.]js$' | tr '\\n' '\\0' | xargs -0 eslint --fix",
"lint:changelog": "auto-changelog validate",
"lint:changelog:rc": "auto-changelog validate --rc",
"lint:shellcheck": "./development/shellcheck.sh",
"lint:styles": "stylelint '*/**/*.scss'",
"lint:lockfile": "lockfile-lint --path yarn.lock --allowed-hosts npm yarn github.com codeload.github.com --empty-hostname false --allowed-schemes \"https:\" \"git+https:\"",
@ -60,8 +62,8 @@
"devtools:redux": "remotedev --hostname=localhost --port=8000",
"start:dev": "concurrently -k -n build,react,redux yarn:start yarn:devtools:react yarn:devtools:redux",
"announce": "node development/announcer.js",
"storybook": "start-storybook -p 6006 -c .storybook --static-dir ./app ./storybook/images",
"storybook:build": "build-storybook -c .storybook -o storybook-build --static-dir ./app ./storybook/images",
"storybook": "start-storybook -p 6006 -c .storybook -s ./app,./.storybook/images",
"storybook:build": "build-storybook -c .storybook -o storybook-build -s ./app,./.storybook/images",
"storybook:deploy": "storybook-to-ghpages --existing-output-dir storybook-build --remote storybook --branch master",
"update-changelog": "auto-changelog update",
"generate:migration": "./development/generate-migration.sh",
@ -102,7 +104,7 @@
"@fortawesome/fontawesome-free": "^5.13.0",
"@material-ui/core": "^4.11.0",
"@metamask/contract-metadata": "^1.28.0",
"@metamask/controllers": "^14.0.2",
"@metamask/controllers": "^15.0.2",
"@metamask/eth-ledger-bridge-keyring": "^0.7.0",
"@metamask/eth-token-tracker": "^3.0.1",
"@metamask/etherscan-link": "^2.1.0",
@ -116,7 +118,6 @@
"@sentry/browser": "^5.26.0",
"@sentry/integrations": "^5.26.0",
"@zxing/library": "^0.8.0",
"abortcontroller-polyfill": "^1.4.0",
"analytics-node": "^3.4.0-beta.3",
"await-semaphore": "^0.1.1",
"base32-encode": "^1.2.0",

View File

@ -30,7 +30,9 @@ describe('getFetchWithTimeout', function () {
throw new Error('Request should throw');
};
await expect(fetchWithTimeoutThrowsError()).rejects.toThrow('Aborted');
await expect(fetchWithTimeoutThrowsError()).rejects.toThrow(
'The user aborted a request.',
);
});
it('should abort the request when the custom timeout is hit', async function () {
@ -48,7 +50,9 @@ describe('getFetchWithTimeout', function () {
throw new Error('Request should be aborted');
};
await expect(fetchWithTimeoutThrowsError()).rejects.toThrow('Aborted');
await expect(fetchWithTimeoutThrowsError()).rejects.toThrow(
'The user aborted a request.',
);
});
it('throws on invalid timeout', async function () {

View File

@ -7,7 +7,7 @@ const { hideBin } = require('yargs/helpers');
const ttest = require('ttest');
const { retry } = require('../../development/lib/retry');
const { exitWithError } = require('../../development/lib/exit-with-error');
const { withFixtures } = require('./helpers');
const { withFixtures, tinyDelayMs } = require('./helpers');
const { PAGES } = require('./webdriver/driver');
const DEFAULT_NUM_SAMPLES = 20;
@ -16,6 +16,7 @@ const ALL_PAGES = Object.values(PAGES);
async function measurePage(pageName) {
let metrics;
await withFixtures({ fixtures: 'imported-account' }, async ({ driver }) => {
await driver.delay(tinyDelayMs);
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);

View File

@ -12,6 +12,8 @@ const { ensureXServerIsRunning } = require('./x-server');
const tinyDelayMs = 200;
const regularDelayMs = tinyDelayMs * 2;
const largeDelayMs = regularDelayMs * 2;
const xLargeDelayMs = largeDelayMs * 2;
const xxLargeDelayMs = xLargeDelayMs * 2;
const dappPort = 8080;
@ -148,5 +150,7 @@ module.exports = {
tinyDelayMs,
regularDelayMs,
largeDelayMs,
xLargeDelayMs,
xxLargeDelayMs,
withFixtures,
};

View File

@ -191,25 +191,6 @@ describe('MetaMask', function () {
});
});
describe('Show account information', function () {
it('shows the QR code for the account', async function () {
await driver.clickElement('[data-testid="account-options-menu-button"]');
await driver.clickElement(
'[data-testid="account-options-menu__account-details"]',
);
await driver.findVisibleElement('.qr-code__wrapper');
await driver.delay(regularDelayMs);
// wait for permission modal to be visible.
const permissionModal = await driver.findVisibleElement('span .modal');
await driver.clickElement('.account-modal__close');
// wait for permission modal to be removed from DOM.
await permissionModal.waitForElementState('hidden');
await driver.delay(regularDelayMs);
});
});
describe('Import Secret Recovery Phrase', function () {
it('logs out of the vault', async function () {
await driver.clickElement('.account-menu__icon');

View File

@ -1,6 +1,6 @@
const { strict: assert } = require('assert');
const waitUntilCalled = require('../lib/wait-until-called');
const { withFixtures } = require('./helpers');
const { withFixtures, tinyDelayMs } = require('./helpers');
/**
* WARNING: These tests must be run using a build created with `yarn build:test:metrics`, so that it has
@ -30,6 +30,7 @@ describe('Segment metrics', function () {
const threeSegmentEventsReceived = waitUntilCalled(segmentStub, null, {
callCount: 3,
});
await driver.delay(tinyDelayMs);
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');

View File

@ -0,0 +1,38 @@
const { strict: assert } = require('assert');
const { withFixtures } = require('../helpers');
describe('Show account details', function () {
const ganacheOptions = {
accounts: [
{
secretKey:
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC',
balance: 25000000000000000000,
},
],
};
it('should show the QR code for the account', async function () {
await withFixtures(
{
fixtures: 'imported-account',
ganacheOptions,
title: this.test.title,
},
async ({ driver }) => {
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
await driver.clickElement(
'[data-testid="account-options-menu-button"]',
);
await driver.clickElement(
'[data-testid="account-options-menu__account-details"]',
);
const qrCode = await driver.findElement('.qr-code__wrapper');
assert.equal(await qrCode.isDisplayed(), true);
},
);
});
});

View File

@ -49,7 +49,7 @@ describe('Stores custom RPC history', function () {
await chainIdInput.sendKeys(chainId.toString());
await driver.clickElement('.network-form__footer .btn-secondary');
await driver.findElement({ text: networkName, tag: 'div' });
await driver.findElement({ text: networkName, tag: 'span' });
},
);
});

View File

@ -1,5 +1,5 @@
const { strict: assert } = require('assert');
const { withFixtures } = require('../helpers');
const { withFixtures, xxLargeDelayMs } = require('../helpers');
describe('Permissions', function () {
it('sets permissions and connect to Dapp', async function () {
@ -34,6 +34,7 @@ describe('Permissions', function () {
await driver.waitUntilXWindowHandles(3);
const windowHandles = await driver.getAllWindowHandles();
const extension = windowHandles[0];
await driver.delay(xxLargeDelayMs);
await driver.switchToWindowWithTitle(
'MetaMask Notification',
windowHandles,

View File

@ -1,5 +1,5 @@
const { strict: assert } = require('assert');
const { withFixtures, regularDelayMs } = require('../helpers');
const { withFixtures, regularDelayMs, xxLargeDelayMs } = require('../helpers');
describe('MetaMask', function () {
it('provider should inform dapp when switching networks', async function () {
@ -27,7 +27,7 @@ describe('MetaMask', function () {
await driver.openNewPage('http://127.0.0.1:8080/');
const networkDiv = await driver.findElement('#network');
const chainIdDiv = await driver.findElement('#chainId');
await driver.delay(regularDelayMs);
await driver.delay(xxLargeDelayMs);
assert.equal(await networkDiv.getText(), '1337');
assert.equal(await chainIdDiv.getText(), '0x539');

View File

@ -56,17 +56,12 @@ const popoverContent = window.document.createElement('div');
popoverContent.setAttribute('id', 'popover-content');
window.document.body.appendChild(popoverContent);
// delete AbortController added by jsdom so it can be polyfilled correctly below
delete window.AbortController;
// fetch
const fetch = require('node-fetch');
const { Headers, Request, Response } = fetch;
Object.assign(window, { fetch, Headers, Request, Response });
require('abortcontroller-polyfill/dist/polyfill-patch-fetch');
// localStorage
window.localStorage = {
removeItem: () => null,

View File

@ -1,7 +1,7 @@
import { ethErrors, errorCodes } from 'eth-rpc-errors';
import deepFreeze from 'deep-freeze-strict';
import { ApprovalController } from '@metamask/controllers';
import { ApprovalController, ControllerMessenger } from '@metamask/controllers';
import _getRestrictedMethods from '../../app/scripts/controllers/permissions/restrictedMethods';
@ -70,6 +70,7 @@ const getRestrictedMethods = (permController) => {
export function getPermControllerOpts() {
return {
approvals: new ApprovalController({
messenger: new ControllerMessenger(),
showApprovalRequest: noop,
}),
getKeyringAccounts: async () => [...keyringAccounts],

View File

@ -1,53 +0,0 @@
// Should occur before anything else
import './globalPatch';
import 'ses/lockdown';
import '../../app/scripts/lockdown-run';
import { strict as assert } from 'assert'; /* eslint-disable-line import/first,import/order */
describe('Promise global is immutable', function () {
it('throws when reassinging promise (syntax 1)', function () {
try {
// eslint-disable-next-line no-global-assign,no-native-reassign
Promise = {};
assert.fail('did not throw error');
} catch (err) {
assert.ok(err, 'did throw error');
}
});
it('throws when reassinging promise (syntax 2)', function () {
try {
global.Promise = {};
assert.fail('did not throw error');
} catch (err) {
assert.ok(err, 'did throw error');
}
});
it('throws when mutating existing Promise property', function () {
try {
Promise.all = () => undefined;
assert.fail('did not throw error');
} catch (err) {
assert.ok(err, 'did throw error');
}
});
it('throws when adding new Promise property', function () {
try {
Promise.foo = 'bar';
assert.fail('did not throw error');
} catch (err) {
assert.ok(err, 'did throw error');
}
});
it('throws when deleting Promise from global', function () {
try {
delete global.Promise;
assert.fail('did not throw error');
} catch (err) {
assert.ok(err, 'did throw error');
}
});
});

View File

@ -1,2 +0,0 @@
// eslint-disable-next-line import/unambiguous,node/no-unsupported-features/es-builtins
global.globalThis = global;

View File

@ -0,0 +1,71 @@
import 'ses/lockdown';
import '../../app/scripts/lockdown-run';
import { strict as assert } from 'assert';
// These are Agoric inventions, and we don't care about them.
const ignoreList = new Set([
'Compartment',
'HandledPromise',
'StaticModuleRecord',
]);
describe('non-modifiable intrinsics', function () {
const namedIntrinsics = Reflect.ownKeys(new Compartment().globalThis);
const globalProperties = new Set(
[
// Added to global scope by ses/dist/lockdown.cjs.
...namedIntrinsics,
// TODO: Also include the named platform globals
// This grabs every enumerable property on globalThis.
// ...Object.keys(globalThis),
].filter((propertyName) => !ignoreList.has(propertyName)),
);
globalProperties.forEach((propertyName) => {
it(`intrinsic globalThis["${propertyName}"]`, function () {
const descriptor = Reflect.getOwnPropertyDescriptor(
globalThis,
propertyName,
);
assert.ok(
descriptor,
`globalThis["${propertyName}"] should have a descriptor`,
);
// As long as Object.isFrozen is the true Object.isFrozen, the object
// it is called with cannot lie about being frozen.
const value = globalThis[propertyName];
if (value !== globalThis) {
assert.equal(
Object.isFrozen(value),
true,
`value of universal property globalThis["${propertyName}"] should be frozen`,
);
}
// The writability of properties with accessors cannot be modified.
if ('set' in descriptor || 'get' in descriptor) {
assert.equal(
descriptor.configurable,
false,
`globalThis["${propertyName}"] should be non-configurable`,
);
} else {
assert.equal(
descriptor.configurable,
false,
`globalThis["${propertyName}"] should be non-configurable`,
);
assert.equal(
descriptor.writable,
false,
`globalThis["${propertyName}"] should be non-writable`,
);
}
});
});
});

View File

@ -0,0 +1,10 @@
import React from 'react';
import AccountListItem from './account-list-item';
export default {
title: 'AccountListItem',
};
export const AccountListItemComponent = () => {
return <AccountListItem />;
};

View File

@ -131,5 +131,5 @@ AdvancedGasControls.propTypes = {
maxPriorityFeeFiat: PropTypes.string,
maxFeeFiat: PropTypes.string,
gasErrors: PropTypes.object,
minimumGasLimit: PropTypes.number,
minimumGasLimit: PropTypes.string,
};

View File

@ -15,7 +15,7 @@ import {
getSelectedAddress,
getSelectedIdentity,
} from '../../../../selectors';
import { isExtensionUrl } from '../../../../helpers/utils/util';
import { isExtensionUrl, getURLHost } from '../../../../helpers/utils/util';
import Popover from '../../../ui/popover';
import Button from '../../../ui/button';
import Checkbox from '../../../ui/check-box';
@ -88,7 +88,7 @@ const UnconnectedAccountAlert = () => {
return (
<Popover
title={
isExtensionUrl(origin) ? t('currentExtension') : new URL(origin).host
isExtensionUrl(origin) ? t('currentExtension') : getURLHost(origin)
}
subtitle={t('currentAccountNotConnected')}
onClose={onClose}

View File

@ -1,5 +1,6 @@
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { sortBy } from 'lodash';
import Button from '../../ui/button';
import RecipientGroup from './recipient-group/recipient-group.component';
@ -50,34 +51,36 @@ export default class ContactList extends PureComponent {
}
renderAddressBook() {
const contacts = this.props.searchForContacts();
const unsortedContactsByLetter = this.props
.searchForContacts()
.reduce((obj, contact) => {
const firstLetter = contact.name[0].toUpperCase();
return {
...obj,
[firstLetter]: [...(obj[firstLetter] || []), contact],
};
}, {});
const contactGroups = contacts.reduce((acc, contact) => {
const firstLetter = contact.name.slice(0, 1).toUpperCase();
acc[firstLetter] = acc[firstLetter] || [];
const bucket = acc[firstLetter];
bucket.push(contact);
return acc;
}, {});
const letters = Object.keys(unsortedContactsByLetter).sort();
return Object.entries(contactGroups)
.sort(([letter1], [letter2]) => {
if (letter1 > letter2) {
return 1;
} else if (letter1 === letter2) {
return 0;
}
return -1;
})
.map(([letter, groupItems]) => (
<RecipientGroup
key={`${letter}-contract-group`}
label={letter}
items={groupItems}
onSelect={this.props.selectRecipient}
selectedAddress={this.props.selectedAddress}
/>
));
const sortedContactGroups = letters.map((letter) => {
return [
letter,
sortBy(unsortedContactsByLetter[letter], (contact) => {
return contact.name.toLowerCase();
}),
];
});
return sortedContactGroups.map(([letter, groupItems]) => (
<RecipientGroup
key={`${letter}-contact-group`}
label={letter}
items={groupItems}
onSelect={this.props.selectRecipient}
selectedAddress={this.props.selectedAddress}
/>
));
}
renderMyAccounts() {

Some files were not shown because too many files have changed in this diff Show More