mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Add Snaps via Flask (#13462)
This PR adds `snaps` under Flask build flags to the extension. This branch is mostly equivalent to the current production version of Flask, excepting some bug fixes and tweaks. Closes #11626
This commit is contained in:
parent
2b5b787ca9
commit
35ac762e10
@ -171,7 +171,7 @@ module.exports = {
|
|||||||
'app/scripts/migrations/*.test.js',
|
'app/scripts/migrations/*.test.js',
|
||||||
'app/scripts/platforms/*.test.js',
|
'app/scripts/platforms/*.test.js',
|
||||||
'app/scripts/controllers/network/**/*.test.js',
|
'app/scripts/controllers/network/**/*.test.js',
|
||||||
'app/scripts/controllers/permissions/*.test.js',
|
'app/scripts/controllers/permissions/**/*.test.js',
|
||||||
],
|
],
|
||||||
extends: ['@metamask/eslint-config-mocha'],
|
extends: ['@metamask/eslint-config-mocha'],
|
||||||
rules: {
|
rules: {
|
||||||
@ -198,7 +198,7 @@ module.exports = {
|
|||||||
'app/scripts/migrations/*.test.js',
|
'app/scripts/migrations/*.test.js',
|
||||||
'app/scripts/platforms/*.test.js',
|
'app/scripts/platforms/*.test.js',
|
||||||
'app/scripts/controllers/network/**/*.test.js',
|
'app/scripts/controllers/network/**/*.test.js',
|
||||||
'app/scripts/controllers/permissions/*.test.js',
|
'app/scripts/controllers/permissions/**/*.test.js',
|
||||||
],
|
],
|
||||||
extends: ['@metamask/eslint-config-jest'],
|
extends: ['@metamask/eslint-config-jest'],
|
||||||
rules: {
|
rules: {
|
||||||
|
@ -6,7 +6,7 @@ module.exports = {
|
|||||||
'./app/scripts/migrations/*.test.js',
|
'./app/scripts/migrations/*.test.js',
|
||||||
'./app/scripts/platforms/*.test.js',
|
'./app/scripts/platforms/*.test.js',
|
||||||
'./app/scripts/controllers/network/**/*.test.js',
|
'./app/scripts/controllers/network/**/*.test.js',
|
||||||
'./app/scripts/controllers/permissions/*.test.js',
|
'./app/scripts/controllers/permissions/**/*.test.js',
|
||||||
],
|
],
|
||||||
recursive: true,
|
recursive: true,
|
||||||
require: ['test/env.js', 'test/setup.js'],
|
require: ['test/env.js', 'test/setup.js'],
|
||||||
|
@ -102,6 +102,85 @@ const state = {
|
|||||||
swapsFeatureIsLive: false,
|
swapsFeatureIsLive: false,
|
||||||
swapsQuoteRefreshTime: 60000,
|
swapsQuoteRefreshTime: 60000,
|
||||||
},
|
},
|
||||||
|
"snapStates": {},
|
||||||
|
"snaps": {
|
||||||
|
"local:http://localhost:8080/": {
|
||||||
|
"enabled": true,
|
||||||
|
"id": "local:http://localhost:8080/",
|
||||||
|
"initialPermissions": {
|
||||||
|
"snap_confirm": {}
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"description": "An example MetaMask Snap.",
|
||||||
|
"initialPermissions": {
|
||||||
|
"snap_confirm": {}
|
||||||
|
},
|
||||||
|
"manifestVersion": "0.1",
|
||||||
|
"proposedName": "MetaMask Example Snap",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/MetaMask/snaps-skunkworks.git"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"location": {
|
||||||
|
"npm": {
|
||||||
|
"filePath": "dist/bundle.js",
|
||||||
|
"iconPath": "images/icon.svg",
|
||||||
|
"packageName": "@metamask/example-snap",
|
||||||
|
"registry": "https://registry.npmjs.org/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shasum": "3lEt0yUu080DwV78neROaAAIQWXukSkMnP4OBhOhBnE="
|
||||||
|
},
|
||||||
|
"version": "0.6.0"
|
||||||
|
},
|
||||||
|
"permissionName": "wallet_snap_local:http://localhost:8080/",
|
||||||
|
"sourceCode": "(...)",
|
||||||
|
"status": "stopped",
|
||||||
|
"svgIcon": "<svg>...</svg>",
|
||||||
|
"version": "0.6.0"
|
||||||
|
},
|
||||||
|
"Filecoin Snap": {
|
||||||
|
"enabled": true,
|
||||||
|
"id": "npm:http://localhost:8080/",
|
||||||
|
"initialPermissions": {
|
||||||
|
"snap_confirm": {},
|
||||||
|
"eth_accounts": {},
|
||||||
|
"snap_manageState": {},
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"description": "This swap provides developers everywhere access to an entirely new data storage paradigm, even letting your programs store data autonomously. Learn more.",
|
||||||
|
"initialPermissions": {
|
||||||
|
"snap_confirm": {},
|
||||||
|
"eth_accounts": {},
|
||||||
|
"snap_manageState": {},
|
||||||
|
},
|
||||||
|
"manifestVersion": "0.1",
|
||||||
|
"proposedName": "Filecoin Snap",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/MetaMask/snaps-skunkworks.git"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"location": {
|
||||||
|
"npm": {
|
||||||
|
"filePath": "dist/bundle.js",
|
||||||
|
"iconPath": "images/icon.svg",
|
||||||
|
"packageName": "@metamask/example-snap",
|
||||||
|
"registry": "https://registry.npmjs.org/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shasum": "3lEt0yUu080DwV78neROaAAIQWXukSkMnP4OBhOhBnE="
|
||||||
|
},
|
||||||
|
"version": "0.6.0"
|
||||||
|
},
|
||||||
|
"permissionName": "wallet_snap_npm:http://localhost:8080/",
|
||||||
|
"sourceCode": "(...)",
|
||||||
|
"status": "stopped",
|
||||||
|
"svgIcon": "<svg>...</svg>",
|
||||||
|
"version": "0.6.0"
|
||||||
|
},
|
||||||
|
},
|
||||||
accountArray: [
|
accountArray: [
|
||||||
{
|
{
|
||||||
name: 'This is a Really Long Account Name',
|
name: 'This is a Really Long Account Name',
|
||||||
@ -1030,6 +1109,17 @@ const state = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"local:http://localhost:8080/": {
|
||||||
|
permissions: {
|
||||||
|
'snap_confirm': {
|
||||||
|
invoker: "local:http://localhost:8080/",
|
||||||
|
parentCapability: 'snap_confirm',
|
||||||
|
id: 'a7342F4b-beae-4525-a36c-c0635fd03359',
|
||||||
|
date: 1620710693178,
|
||||||
|
caveats: []
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
permissionActivityLog: [
|
permissionActivityLog: [
|
||||||
{
|
{
|
||||||
@ -1172,20 +1262,6 @@ const state = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
subjectMetadata: {
|
|
||||||
'https://metamask.github.io': {
|
|
||||||
name: 'E2E Test Dapp',
|
|
||||||
origin: 'https://metamask.github.io',
|
|
||||||
iconUrl: 'https://metamask.github.io/test-dapp/metamask-fox.svg',
|
|
||||||
subjectType: 'website',
|
|
||||||
},
|
|
||||||
'https://app.uniswap.org': {
|
|
||||||
name: 'Uniswap',
|
|
||||||
origin: 'https://app.uniswap.org',
|
|
||||||
iconUrl: './UNI.png',
|
|
||||||
subjectType: 'website',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
threeBoxSyncingAllowed: false,
|
threeBoxSyncingAllowed: false,
|
||||||
showRestorePrompt: true,
|
showRestorePrompt: true,
|
||||||
threeBoxLastUpdated: 0,
|
threeBoxLastUpdated: 0,
|
||||||
@ -1212,6 +1288,31 @@ const state = {
|
|||||||
ensResolutionsByAddress: {},
|
ensResolutionsByAddress: {},
|
||||||
pendingApprovals: {},
|
pendingApprovals: {},
|
||||||
pendingApprovalCount: 0,
|
pendingApprovalCount: 0,
|
||||||
|
subjectMetadata: {
|
||||||
|
"http://localhost:8080": {
|
||||||
|
extensionId: null,
|
||||||
|
iconUrl: null,
|
||||||
|
name: "Hello, Snaps!",
|
||||||
|
origin: "http://localhost:8080",
|
||||||
|
subjectType: "website"
|
||||||
|
},
|
||||||
|
"https://metamask.github.io": {
|
||||||
|
extensionId: null,
|
||||||
|
iconUrl: null,
|
||||||
|
name: "Snaps Iframe Execution Environment",
|
||||||
|
origin: "https://metamask.github.io",
|
||||||
|
subjectType: "website"
|
||||||
|
},
|
||||||
|
"local:http://localhost:8080/": {
|
||||||
|
extensionId: null,
|
||||||
|
iconUrl: null,
|
||||||
|
name: "MetaMask Example Snap",
|
||||||
|
origin: "local:http://localhost:8080/",
|
||||||
|
subjectType: "snap",
|
||||||
|
svgIcon: "<svg>...</svg>",
|
||||||
|
version: "0.6.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
appState: {
|
appState: {
|
||||||
shouldClose: false,
|
shouldClose: false,
|
||||||
|
8
app/_locales/de/messages.json
generated
8
app/_locales/de/messages.json
generated
@ -1015,10 +1015,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Der Gaspreis, der sich aus der Gaseinschätzung ergibt, ist derzeit nicht verfügbar."
|
"message": "Der Gaspreis, der sich aus der Gaseinschätzung ergibt, ist derzeit nicht verfügbar."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Siehe Adresse, Kontostand, Aktivität und Einleitung von Transaktionen",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Öffentliche Ethereum-Adresse"
|
"message": "Öffentliche Ethereum-Adresse"
|
||||||
},
|
},
|
||||||
@ -2076,6 +2072,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "Berechtigungsanfrage"
|
"message": "Berechtigungsanfrage"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Siehe Adresse, Kontostand, Aktivität und Einleitung von Transaktionen",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Berechtigungen"
|
"message": "Berechtigungen"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/el/messages.json
generated
8
app/_locales/el/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Το εφεδρικό τέλος συναλλαγής που παρέχεται ως η κύρια υπηρεσία εκτίμησης τελών συναλλαγής, δεν είναι διαθέσιμο αυτή τη στιγμή."
|
"message": "Το εφεδρικό τέλος συναλλαγής που παρέχεται ως η κύρια υπηρεσία εκτίμησης τελών συναλλαγής, δεν είναι διαθέσιμο αυτή τη στιγμή."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Βλέπε διεύθυνση, υπόλοιπο λογαριασμού, δραστηριότητα και έναρξη συναλλαγών",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Δημόσια Διεύθυνση Ethereum"
|
"message": "Δημόσια Διεύθυνση Ethereum"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "Αίτημα άδειας"
|
"message": "Αίτημα άδειας"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Βλέπε διεύθυνση, υπόλοιπο λογαριασμού, δραστηριότητα και έναρξη συναλλαγών",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Άδειες"
|
"message": "Άδειες"
|
||||||
},
|
},
|
||||||
|
99
app/_locales/en/messages.json
generated
99
app/_locales/en/messages.json
generated
@ -248,6 +248,9 @@
|
|||||||
"approve": {
|
"approve": {
|
||||||
"message": "Approve spend limit"
|
"message": "Approve spend limit"
|
||||||
},
|
},
|
||||||
|
"approveAndInstall": {
|
||||||
|
"message": "Approve & Install"
|
||||||
|
},
|
||||||
"approveButtonText": {
|
"approveButtonText": {
|
||||||
"message": "Approve"
|
"message": "Approve"
|
||||||
},
|
},
|
||||||
@ -261,6 +264,12 @@
|
|||||||
"approvedAmountWithColon": {
|
"approvedAmountWithColon": {
|
||||||
"message": "Approved amount:"
|
"message": "Approved amount:"
|
||||||
},
|
},
|
||||||
|
"areYouDeveloper": {
|
||||||
|
"message": "Are you a developer?"
|
||||||
|
},
|
||||||
|
"areYouSure": {
|
||||||
|
"message": "Are you sure?"
|
||||||
|
},
|
||||||
"asset": {
|
"asset": {
|
||||||
"message": "Asset"
|
"message": "Asset"
|
||||||
},
|
},
|
||||||
@ -539,6 +548,10 @@
|
|||||||
"message": "$1 is not connected to any sites.",
|
"message": "$1 is not connected to any sites.",
|
||||||
"description": "$1 is the account name"
|
"description": "$1 is the account name"
|
||||||
},
|
},
|
||||||
|
"connectedSnapSites": {
|
||||||
|
"message": "$1 snap is connected to these sites. They have access to the permissions listed above.",
|
||||||
|
"description": "$1 represents the name of the snap"
|
||||||
|
},
|
||||||
"connecting": {
|
"connecting": {
|
||||||
"message": "Connecting..."
|
"message": "Connecting..."
|
||||||
},
|
},
|
||||||
@ -1077,10 +1090,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Backup gas price is provided as the main gas estimation service is unavailable right now."
|
"message": "Backup gas price is provided as the main gas estimation service is unavailable right now."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "See address, account balance, activity and suggest transactions to approve",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Ethereum Public Address"
|
"message": "Ethereum Public Address"
|
||||||
},
|
},
|
||||||
@ -1093,6 +1102,9 @@
|
|||||||
"etherscanViewOn": {
|
"etherscanViewOn": {
|
||||||
"message": "View on Etherscan"
|
"message": "View on Etherscan"
|
||||||
},
|
},
|
||||||
|
"expandExperience": {
|
||||||
|
"message": "Expand your web3 experience"
|
||||||
|
},
|
||||||
"expandView": {
|
"expandView": {
|
||||||
"message": "Expand view"
|
"message": "Expand view"
|
||||||
},
|
},
|
||||||
@ -1673,6 +1685,9 @@
|
|||||||
"malformedData": {
|
"malformedData": {
|
||||||
"message": "Malformed data"
|
"message": "Malformed data"
|
||||||
},
|
},
|
||||||
|
"manageSnaps": {
|
||||||
|
"message": "Manage your installed Snaps"
|
||||||
|
},
|
||||||
"max": {
|
"max": {
|
||||||
"message": "Max"
|
"message": "Max"
|
||||||
},
|
},
|
||||||
@ -1954,6 +1969,9 @@
|
|||||||
"noNFTs": {
|
"noNFTs": {
|
||||||
"message": "No NFTs yet"
|
"message": "No NFTs yet"
|
||||||
},
|
},
|
||||||
|
"noSnaps": {
|
||||||
|
"message": "No Snaps installed"
|
||||||
|
},
|
||||||
"noThanks": {
|
"noThanks": {
|
||||||
"message": "No Thanks"
|
"message": "No Thanks"
|
||||||
},
|
},
|
||||||
@ -2155,6 +2173,9 @@
|
|||||||
"message": "Open MetaMask in full screen to connect your ledger via WebHID.",
|
"message": "Open MetaMask in full screen to connect your ledger via WebHID.",
|
||||||
"description": "Shown to the user on the confirm screen when they are viewing MetaMask in a popup window but need to connect their ledger via webhid."
|
"description": "Shown to the user on the confirm screen when they are viewing MetaMask in a popup window but need to connect their ledger via webhid."
|
||||||
},
|
},
|
||||||
|
"openSourceCode": {
|
||||||
|
"message": "Check the source code"
|
||||||
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
"message": "Optional"
|
"message": "Optional"
|
||||||
},
|
},
|
||||||
@ -2211,6 +2232,37 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "Permission request"
|
"message": "Permission request"
|
||||||
},
|
},
|
||||||
|
"permissionRequestCapitalized": {
|
||||||
|
"message": "Permission Request"
|
||||||
|
},
|
||||||
|
"permission_accessNetwork": {
|
||||||
|
"message": "Access the Internet.",
|
||||||
|
"description": "The description of the `endowment:network-access` permission."
|
||||||
|
},
|
||||||
|
"permission_accessSnap": {
|
||||||
|
"message": "Connect to the $1 Snap.",
|
||||||
|
"description": "The description for the `wallet_snap_*` permission. $1 is the name of the Snap."
|
||||||
|
},
|
||||||
|
"permission_customConfirmation": {
|
||||||
|
"message": "Display a confirmation in MetaMask.",
|
||||||
|
"description": "The description for the `snap_confirm` permission"
|
||||||
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "See address, account balance, activity and suggest transactions to approve",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
|
"permission_manageBip44Keys": {
|
||||||
|
"message": "Control your \"$1\" accounts and assets.",
|
||||||
|
"description": "The description for the `snap_getBip44Entropy_*` permission. $1 is the name of a protocol, e.g. 'Filecoin'."
|
||||||
|
},
|
||||||
|
"permission_manageState": {
|
||||||
|
"message": "Store and manage its data on your device.",
|
||||||
|
"description": "The description for the `snap_manageState` permission"
|
||||||
|
},
|
||||||
|
"permission_unknown": {
|
||||||
|
"message": "Unknown permission: $1",
|
||||||
|
"description": "$1 is the name of a requested permission that is not recognized."
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Permissions"
|
"message": "Permissions"
|
||||||
},
|
},
|
||||||
@ -2346,6 +2398,12 @@
|
|||||||
"removeNFT": {
|
"removeNFT": {
|
||||||
"message": "Remove NFT"
|
"message": "Remove NFT"
|
||||||
},
|
},
|
||||||
|
"removeSnap": {
|
||||||
|
"message": "Remove Snap"
|
||||||
|
},
|
||||||
|
"removeSnapDescription": {
|
||||||
|
"message": "This action will delete the snap, its data and revoke your given permissions."
|
||||||
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"message": "replace"
|
"message": "replace"
|
||||||
},
|
},
|
||||||
@ -2661,6 +2719,39 @@
|
|||||||
"slow": {
|
"slow": {
|
||||||
"message": "Slow"
|
"message": "Slow"
|
||||||
},
|
},
|
||||||
|
"snapAccess": {
|
||||||
|
"message": "$1 snap has access to:",
|
||||||
|
"description": "$1 represents the name of the snap"
|
||||||
|
},
|
||||||
|
"snapError": {
|
||||||
|
"message": "Snap Error: '$1'. Error Code: '$2'",
|
||||||
|
"description": "This is shown when a snap encounters an error. $1 is the error message from the snap, and $2 is the error code."
|
||||||
|
},
|
||||||
|
"snapInstall": {
|
||||||
|
"message": "Install Snap"
|
||||||
|
},
|
||||||
|
"snapInstallWarningCheck": {
|
||||||
|
"message": "To confirm you understand, check all."
|
||||||
|
},
|
||||||
|
"snapInstallWarningKeyAccess": {
|
||||||
|
"message": "You are granting key access to the snap \"$1\". This is irrevocable and grants \"$1\" control of your accounts and assets. Make sure you trust \"$1\" before proceeding.",
|
||||||
|
"description": "The parameter is the name of the snap"
|
||||||
|
},
|
||||||
|
"snapRequestsPermission": {
|
||||||
|
"message": "This snap is requesting the following permissions:"
|
||||||
|
},
|
||||||
|
"snaps": {
|
||||||
|
"message": "Snaps"
|
||||||
|
},
|
||||||
|
"snapsSettingsDescription": {
|
||||||
|
"message": "Manage your Snaps"
|
||||||
|
},
|
||||||
|
"snapsStatus": {
|
||||||
|
"message": "Snap status is dependent on activity."
|
||||||
|
},
|
||||||
|
"snapsToggle": {
|
||||||
|
"message": "A snap will only run if it is enabled"
|
||||||
|
},
|
||||||
"somethingWentWrong": {
|
"somethingWentWrong": {
|
||||||
"message": "Oops! Something went wrong."
|
"message": "Oops! Something went wrong."
|
||||||
},
|
},
|
||||||
|
8
app/_locales/es/messages.json
generated
8
app/_locales/es/messages.json
generated
@ -665,10 +665,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Se muestra el precio del gas de respaldo, ya que el servicio para calcular el precio del gas principal no se encuentra disponible en este momento."
|
"message": "Se muestra el precio del gas de respaldo, ya que el servicio para calcular el precio del gas principal no se encuentra disponible en este momento."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Ver las direcciones de las cuentas permitidas (requerido)",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Dirección pública de Ethereum"
|
"message": "Dirección pública de Ethereum"
|
||||||
},
|
},
|
||||||
@ -1296,6 +1292,10 @@
|
|||||||
"pending": {
|
"pending": {
|
||||||
"message": "Pendiente"
|
"message": "Pendiente"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Ver las direcciones de las cuentas permitidas (requerido)",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Permisos"
|
"message": "Permisos"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/es_419/messages.json
generated
8
app/_locales/es_419/messages.json
generated
@ -1035,10 +1035,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Se muestra el precio del gas de respaldo, ya que el servicio para calcular el precio del gas principal no se encuentra disponible en este momento."
|
"message": "Se muestra el precio del gas de respaldo, ya que el servicio para calcular el precio del gas principal no se encuentra disponible en este momento."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Ver dirección, saldo de cuenta, actividad e iniciar transacciones",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Dirección pública de Ethereum"
|
"message": "Dirección pública de Ethereum"
|
||||||
},
|
},
|
||||||
@ -2125,6 +2121,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "Solicitud de permiso"
|
"message": "Solicitud de permiso"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Ver dirección, saldo de cuenta, actividad e iniciar transacciones",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Permisos"
|
"message": "Permisos"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/fr/messages.json
generated
8
app/_locales/fr/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Le prix de carburant de sauvegarde est fourni, car le service principal d’estimation du carburant est momentanément indisponible."
|
"message": "Le prix de carburant de sauvegarde est fourni, car le service principal d’estimation du carburant est momentanément indisponible."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Consultez l’adresse, le solde du compte et l’activité, et lancez des transactions",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Adresse publique d’Ethereum"
|
"message": "Adresse publique d’Ethereum"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "Demande d’autorisation"
|
"message": "Demande d’autorisation"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Consultez l’adresse, le solde du compte et l’activité, et lancez des transactions",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Autorisations"
|
"message": "Autorisations"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/hi/messages.json
generated
8
app/_locales/hi/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "बैकअप गैस की कीमत प्रदान की जाती है क्योंकि मुख्य गैस अनुमान सर्विस अभी उपलब्ध नहीं है।"
|
"message": "बैकअप गैस की कीमत प्रदान की जाती है क्योंकि मुख्य गैस अनुमान सर्विस अभी उपलब्ध नहीं है।"
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "पता, खाते की शेषराशि, गतिविधि देखें और लेन-देन शुरू करें",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Ethereum सार्वजनिक पता"
|
"message": "Ethereum सार्वजनिक पता"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "अनुमति अनुरोध"
|
"message": "अनुमति अनुरोध"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "पता, खाते की शेषराशि, गतिविधि देखें और लेन-देन शुरू करें",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "अनुमतियाँ"
|
"message": "अनुमतियाँ"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/id/messages.json
generated
8
app/_locales/id/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Biaya gas cadangan diberikan karena layanan estimasi gas utama saat ini tidak tersedia."
|
"message": "Biaya gas cadangan diberikan karena layanan estimasi gas utama saat ini tidak tersedia."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Lihat alamat, saldo akun, aktivitas, dan mulai transaksi",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Alamat Publik Ethereum"
|
"message": "Alamat Publik Ethereum"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "Permohonan izin"
|
"message": "Permohonan izin"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Lihat alamat, saldo akun, aktivitas, dan mulai transaksi",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Izin"
|
"message": "Izin"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/it/messages.json
generated
8
app/_locales/it/messages.json
generated
@ -565,10 +565,6 @@
|
|||||||
"estimatedProcessingTimes": {
|
"estimatedProcessingTimes": {
|
||||||
"message": "Tempi di Elaborazione Stimati"
|
"message": "Tempi di Elaborazione Stimati"
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Accesso agli indirizzi dei tuoi account autorizzati (richiesto)",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Indirizzo pubblico Ethereum "
|
"message": "Indirizzo pubblico Ethereum "
|
||||||
},
|
},
|
||||||
@ -1054,6 +1050,10 @@
|
|||||||
"pending": {
|
"pending": {
|
||||||
"message": "in corso"
|
"message": "in corso"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Accesso agli indirizzi dei tuoi account autorizzati (richiesto)",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Permessi"
|
"message": "Permessi"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/ja/messages.json
generated
8
app/_locales/ja/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "現在メインのガスの見積もりサービスが利用できないため、バックアップのガス代が提供されています。"
|
"message": "現在メインのガスの見積もりサービスが利用できないため、バックアップのガス代が提供されています。"
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "アドレス、アカウント残高、アクティビティを表示してトランザクションを開始",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "パブリックイーサリアムアドレス"
|
"message": "パブリックイーサリアムアドレス"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "許可のリクエスト"
|
"message": "許可のリクエスト"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "アドレス、アカウント残高、アクティビティを表示してトランザクションを開始",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "許可"
|
"message": "許可"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/ko/messages.json
generated
8
app/_locales/ko/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "현재 주요 가스 견적 서비스를 사용할 수 없으므로 백업 가스 가격을 제공합니다."
|
"message": "현재 주요 가스 견적 서비스를 사용할 수 없으므로 백업 가스 가격을 제공합니다."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "허용되는 계정의 주소 보기(필수)",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "이더리움 공개 주소"
|
"message": "이더리움 공개 주소"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "승인 요청"
|
"message": "승인 요청"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "허용되는 계정의 주소 보기(필수)",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "권한"
|
"message": "권한"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/ph/messages.json
generated
8
app/_locales/ph/messages.json
generated
@ -668,10 +668,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Ibinibigay ang backup na presyo ng gas dahil hindi available ang pangunahing serbisyo sa pagtatantya ng gas sa ngayon."
|
"message": "Ibinibigay ang backup na presyo ng gas dahil hindi available ang pangunahing serbisyo sa pagtatantya ng gas sa ngayon."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Tingnan ang mga address ng iyong mga pinapayagang account (kinakailangan)",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Pampublikong Address ng Ethereum"
|
"message": "Pampublikong Address ng Ethereum"
|
||||||
},
|
},
|
||||||
@ -1321,6 +1317,10 @@
|
|||||||
"pending": {
|
"pending": {
|
||||||
"message": "Nakabinbin"
|
"message": "Nakabinbin"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Tingnan ang mga address ng iyong mga pinapayagang account (kinakailangan)",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Mga Pahintulot"
|
"message": "Mga Pahintulot"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/pt_BR/messages.json
generated
8
app/_locales/pt_BR/messages.json
generated
@ -1019,10 +1019,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "O preço de backup do gás é fornecido porque a estimativa de gás principal está indisponível no momento."
|
"message": "O preço de backup do gás é fornecido porque a estimativa de gás principal está indisponível no momento."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Ver endereço, saldo da conta, atividade e iniciar transações",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Endereço público do Ethereum"
|
"message": "Endereço público do Ethereum"
|
||||||
},
|
},
|
||||||
@ -2109,6 +2105,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "Solicitação de permissão"
|
"message": "Solicitação de permissão"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Ver endereço, saldo da conta, atividade e iniciar transações",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Permissões"
|
"message": "Permissões"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/ru/messages.json
generated
8
app/_locales/ru/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Указана резервная цена газа, поскольку основной сервис определения цены газа сейчас недоступен."
|
"message": "Указана резервная цена газа, поскольку основной сервис определения цены газа сейчас недоступен."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "См. адрес, баланс счета, активность и инициируйте транзакции",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Открытый адрес Ethereum"
|
"message": "Открытый адрес Ethereum"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "Запрос разрешения"
|
"message": "Запрос разрешения"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "См. адрес, баланс счета, активность и инициируйте транзакции",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Разрешения"
|
"message": "Разрешения"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/tl/messages.json
generated
8
app/_locales/tl/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Ang backup gas price ay inilalaan dahil ang pangunahing pagtantiya ng presyo ng gas ay hindi available sa ngayon."
|
"message": "Ang backup gas price ay inilalaan dahil ang pangunahing pagtantiya ng presyo ng gas ay hindi available sa ngayon."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Tingnan ang mga address, balanse ng account, aktibidad at simulan ang iyong mga transaksyon",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Pampublikong Address ng Ethereum"
|
"message": "Pampublikong Address ng Ethereum"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "Kahilingan sa pahintulot"
|
"message": "Kahilingan sa pahintulot"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Tingnan ang mga address, balanse ng account, aktibidad at simulan ang iyong mga transaksyon",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Mga Pahintulot"
|
"message": "Mga Pahintulot"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/tr/messages.json
generated
8
app/_locales/tr/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Ana gaz tahmini hizmeti olarak sunulan yedek gaz fiyatı şu anda kullanılamıyor."
|
"message": "Ana gaz tahmini hizmeti olarak sunulan yedek gaz fiyatı şu anda kullanılamıyor."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Adrese, hesap bakiyesine, aktiviteye bakın ve işlemleri başlatın",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Ethereum Genel Adresi"
|
"message": "Ethereum Genel Adresi"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "İzin talebi"
|
"message": "İzin talebi"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Adrese, hesap bakiyesine, aktiviteye bakın ve işlemleri başlatın",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "İzinler"
|
"message": "İzinler"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/vi/messages.json
generated
8
app/_locales/vi/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "Giá gas dự phòng được cung cấp vì dịch vụ ước tính giá gas chính hiện không hoạt động."
|
"message": "Giá gas dự phòng được cung cấp vì dịch vụ ước tính giá gas chính hiện không hoạt động."
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "Xem địa chỉ, số dư tài khoản, hoạt động và bắt đầu giao dịch",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "Địa chỉ công khai trên Ethereum"
|
"message": "Địa chỉ công khai trên Ethereum"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "Yêu cầu quyền"
|
"message": "Yêu cầu quyền"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "Xem địa chỉ, số dư tài khoản, hoạt động và bắt đầu giao dịch",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "Quyền"
|
"message": "Quyền"
|
||||||
},
|
},
|
||||||
|
8
app/_locales/zh_CN/messages.json
generated
8
app/_locales/zh_CN/messages.json
generated
@ -1005,10 +1005,6 @@
|
|||||||
"ethGasPriceFetchWarning": {
|
"ethGasPriceFetchWarning": {
|
||||||
"message": "由于目前主要的燃料估算服务不可用,因此提供了备用燃料价格。"
|
"message": "由于目前主要的燃料估算服务不可用,因此提供了备用燃料价格。"
|
||||||
},
|
},
|
||||||
"eth_accounts": {
|
|
||||||
"message": "查看您允许的账户的地址(必填)",
|
|
||||||
"description": "The description for the `eth_accounts` permission"
|
|
||||||
},
|
|
||||||
"ethereumPublicAddress": {
|
"ethereumPublicAddress": {
|
||||||
"message": "以太坊 Ethereum 公开地址"
|
"message": "以太坊 Ethereum 公开地址"
|
||||||
},
|
},
|
||||||
@ -2079,6 +2075,10 @@
|
|||||||
"permissionRequest": {
|
"permissionRequest": {
|
||||||
"message": "权限请求"
|
"message": "权限请求"
|
||||||
},
|
},
|
||||||
|
"permission_ethereumAccounts": {
|
||||||
|
"message": "查看您允许的账户的地址(必填)",
|
||||||
|
"description": "The description for the `eth_accounts` permission"
|
||||||
|
},
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"message": "权限"
|
"message": "权限"
|
||||||
},
|
},
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
import {
|
||||||
|
restrictedMethodPermissionBuilders,
|
||||||
|
selectHooks,
|
||||||
|
} from '@metamask/rpc-methods';
|
||||||
|
import { endowmentPermissionBuilders } from '@metamask/snap-controllers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Record<string, Record<string, unknown>>} All endowment permission
|
||||||
|
* specifications.
|
||||||
|
*/
|
||||||
|
export const buildSnapEndowmentSpecifications = () =>
|
||||||
|
Object.values(endowmentPermissionBuilders).reduce(
|
||||||
|
(allSpecifications, { targetKey, specificationBuilder }) => {
|
||||||
|
allSpecifications[targetKey] = specificationBuilder();
|
||||||
|
return allSpecifications;
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Record<string, Function>} hooks - The hooks for the Snap
|
||||||
|
* restricted method implementations.
|
||||||
|
*/
|
||||||
|
export function buildSnapRestrictedMethodSpecifications(hooks) {
|
||||||
|
return Object.values(restrictedMethodPermissionBuilders).reduce(
|
||||||
|
(specifications, { targetKey, specificationBuilder, methodHooks }) => {
|
||||||
|
specifications[targetKey] = specificationBuilder({
|
||||||
|
methodHooks: selectHooks(hooks, methodHooks),
|
||||||
|
});
|
||||||
|
return specifications;
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
import {
|
||||||
|
EndowmentPermissions,
|
||||||
|
RestrictedMethods,
|
||||||
|
} from '../../../../../shared/constants/permissions';
|
||||||
|
import {
|
||||||
|
buildSnapEndowmentSpecifications,
|
||||||
|
buildSnapRestrictedMethodSpecifications,
|
||||||
|
} from './snap-permissions';
|
||||||
|
|
||||||
|
describe('buildSnapRestrictedMethodSpecifications', () => {
|
||||||
|
it('creates valid permission specification objects', () => {
|
||||||
|
const hooks = {
|
||||||
|
addSnap: () => undefined,
|
||||||
|
clearSnapState: () => undefined,
|
||||||
|
getMnemonic: () => undefined,
|
||||||
|
getSnap: () => undefined,
|
||||||
|
getSnapRpcHandler: () => undefined,
|
||||||
|
getSnapState: () => undefined,
|
||||||
|
showConfirmation: () => undefined,
|
||||||
|
updateSnapState: () => undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const specifications = buildSnapRestrictedMethodSpecifications(hooks);
|
||||||
|
|
||||||
|
const allRestrictedMethods = Object.keys(RestrictedMethods);
|
||||||
|
Object.keys(specifications).forEach((permissionKey) =>
|
||||||
|
expect(allRestrictedMethods).toContain(permissionKey),
|
||||||
|
);
|
||||||
|
|
||||||
|
Object.values(specifications).forEach((specification) => {
|
||||||
|
expect(specification).toMatchObject({
|
||||||
|
targetKey: expect.stringMatching(/^(snap_|wallet_)/u),
|
||||||
|
methodImplementation: expect.any(Function),
|
||||||
|
allowedCaveats: null,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('buildSnapEndowmentSpecifications', () => {
|
||||||
|
it('creates valid permission specification objects', () => {
|
||||||
|
expect(
|
||||||
|
Object.keys(buildSnapEndowmentSpecifications()).sort(),
|
||||||
|
).toStrictEqual(Object.keys(EndowmentPermissions).sort());
|
||||||
|
});
|
||||||
|
});
|
@ -4,3 +4,6 @@ export * from './enums';
|
|||||||
export * from './permission-log';
|
export * from './permission-log';
|
||||||
export * from './specifications';
|
export * from './specifications';
|
||||||
export * from './selectors';
|
export * from './selectors';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
export * from './flask/snap-permissions';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import { constructPermission } from '@metamask/snap-controllers';
|
import {
|
||||||
|
constructPermission,
|
||||||
|
PermissionType,
|
||||||
|
} from '@metamask/snap-controllers';
|
||||||
import {
|
import {
|
||||||
CaveatTypes,
|
CaveatTypes,
|
||||||
RestrictedMethods,
|
RestrictedMethods,
|
||||||
@ -90,6 +93,7 @@ export const getPermissionSpecifications = ({
|
|||||||
}) => {
|
}) => {
|
||||||
return {
|
return {
|
||||||
[PermissionKeys.eth_accounts]: {
|
[PermissionKeys.eth_accounts]: {
|
||||||
|
permissionType: PermissionType.RestrictedMethod,
|
||||||
targetKey: PermissionKeys.eth_accounts,
|
targetKey: PermissionKeys.eth_accounts,
|
||||||
allowedCaveats: [CaveatTypes.restrictReturnedAccounts],
|
allowedCaveats: [CaveatTypes.restrictReturnedAccounts],
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
import { handlers as permittedSnapMethods } from '@metamask/rpc-methods/dist/permitted';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
import { flatten } from 'lodash';
|
import { flatten } from 'lodash';
|
||||||
import { permissionRpcMethods } from '@metamask/snap-controllers';
|
import { permissionRpcMethods } from '@metamask/snap-controllers';
|
||||||
import { selectHooks } from '@metamask/rpc-methods';
|
import { selectHooks } from '@metamask/rpc-methods';
|
||||||
@ -30,7 +33,7 @@ const expectedHookNames = Array.from(
|
|||||||
* controllers.
|
* controllers.
|
||||||
* @returns {(req: Object, res: Object, next: Function, end: Function) => void}
|
* @returns {(req: Object, res: Object, next: Function, end: Function) => void}
|
||||||
*/
|
*/
|
||||||
export default function createMethodMiddleware(hooks) {
|
export function createMethodMiddleware(hooks) {
|
||||||
// Fail immediately if we forgot to provide any expected hooks.
|
// Fail immediately if we forgot to provide any expected hooks.
|
||||||
const missingHookNames = expectedHookNames.filter(
|
const missingHookNames = expectedHookNames.filter(
|
||||||
(hookName) => !Object.hasOwnProperty.call(hooks, hookName),
|
(hookName) => !Object.hasOwnProperty.call(hooks, hookName),
|
||||||
@ -60,6 +63,7 @@ export default function createMethodMiddleware(hooks) {
|
|||||||
selectHooks(hooks, hookNames),
|
selectHooks(hooks, hookNames),
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
return end(error);
|
return end(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,3 +71,40 @@ export default function createMethodMiddleware(hooks) {
|
|||||||
return next();
|
return next();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
const snapHandlerMap = permittedSnapMethods.reduce((map, handler) => {
|
||||||
|
for (const methodName of handler.methodNames) {
|
||||||
|
map.set(methodName, handler);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}, new Map());
|
||||||
|
|
||||||
|
export function createSnapMethodMiddleware(isSnap, hooks) {
|
||||||
|
return async function methodMiddleware(req, res, next, end) {
|
||||||
|
const handler = snapHandlerMap.get(req.method);
|
||||||
|
if (handler) {
|
||||||
|
if (/^snap_/iu.test(req.method) && !isSnap) {
|
||||||
|
return end(ethErrors.rpc.methodNotFound());
|
||||||
|
}
|
||||||
|
|
||||||
|
const { implementation, hookNames } = handler;
|
||||||
|
try {
|
||||||
|
// Implementations may or may not be async, so we must await them.
|
||||||
|
return await implementation(
|
||||||
|
req,
|
||||||
|
res,
|
||||||
|
next,
|
||||||
|
end,
|
||||||
|
selectHooks(hooks, hookNames),
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return end(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
@ -1 +1 @@
|
|||||||
export { default } from './createMethodMiddleware';
|
export * from './createMethodMiddleware';
|
||||||
|
@ -38,7 +38,13 @@ import {
|
|||||||
import {
|
import {
|
||||||
PermissionController,
|
PermissionController,
|
||||||
SubjectMetadataController,
|
SubjectMetadataController,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
SnapController,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
} from '@metamask/snap-controllers';
|
} from '@metamask/snap-controllers';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
import { IframeExecutionService } from '@metamask/iframe-execution-environment-service';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
import {
|
import {
|
||||||
TRANSACTION_STATUSES,
|
TRANSACTION_STATUSES,
|
||||||
@ -57,11 +63,17 @@ import {
|
|||||||
import {
|
import {
|
||||||
CaveatTypes,
|
CaveatTypes,
|
||||||
RestrictedMethods,
|
RestrictedMethods,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
EndowmentPermissions,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
} from '../../shared/constants/permissions';
|
} from '../../shared/constants/permissions';
|
||||||
import { UI_NOTIFICATIONS } from '../../shared/notifications';
|
import { UI_NOTIFICATIONS } from '../../shared/notifications';
|
||||||
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
|
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
|
||||||
import { MILLISECOND } from '../../shared/constants/time';
|
import { MILLISECOND } from '../../shared/constants/time';
|
||||||
import {
|
import {
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
MESSAGE_TYPE,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
POLLING_TOKEN_ENVIRONMENT_TYPES,
|
POLLING_TOKEN_ENVIRONMENT_TYPES,
|
||||||
SUBJECT_TYPES,
|
SUBJECT_TYPES,
|
||||||
} from '../../shared/constants/app';
|
} from '../../shared/constants/app';
|
||||||
@ -73,7 +85,12 @@ import { isEqualCaseInsensitive } from '../../ui/helpers/utils/util';
|
|||||||
import ComposableObservableStore from './lib/ComposableObservableStore';
|
import ComposableObservableStore from './lib/ComposableObservableStore';
|
||||||
import AccountTracker from './lib/account-tracker';
|
import AccountTracker from './lib/account-tracker';
|
||||||
import createLoggerMiddleware from './lib/createLoggerMiddleware';
|
import createLoggerMiddleware from './lib/createLoggerMiddleware';
|
||||||
import createMethodMiddleware from './lib/rpc-method-middleware';
|
import {
|
||||||
|
createMethodMiddleware,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
createSnapMethodMiddleware,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
} from './lib/rpc-method-middleware';
|
||||||
import createOriginMiddleware from './lib/createOriginMiddleware';
|
import createOriginMiddleware from './lib/createOriginMiddleware';
|
||||||
import createTabIdMiddleware from './lib/createTabIdMiddleware';
|
import createTabIdMiddleware from './lib/createTabIdMiddleware';
|
||||||
import createOnboardingMiddleware from './lib/createOnboardingMiddleware';
|
import createOnboardingMiddleware from './lib/createOnboardingMiddleware';
|
||||||
@ -107,9 +124,13 @@ import {
|
|||||||
getPermissionBackgroundApiMethods,
|
getPermissionBackgroundApiMethods,
|
||||||
getPermissionSpecifications,
|
getPermissionSpecifications,
|
||||||
getPermittedAccountsByOrigin,
|
getPermittedAccountsByOrigin,
|
||||||
PermissionLogController,
|
|
||||||
NOTIFICATION_NAMES,
|
NOTIFICATION_NAMES,
|
||||||
|
PermissionLogController,
|
||||||
unrestrictedMethods,
|
unrestrictedMethods,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
buildSnapEndowmentSpecifications,
|
||||||
|
buildSnapRestrictedMethodSpecifications,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
} from './controllers/permissions';
|
} from './controllers/permissions';
|
||||||
|
|
||||||
export const METAMASK_CONTROLLER_EVENTS = {
|
export const METAMASK_CONTROLLER_EVENTS = {
|
||||||
@ -500,36 +521,41 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
}),
|
}),
|
||||||
state: initState.PermissionController,
|
state: initState.PermissionController,
|
||||||
caveatSpecifications: getCaveatSpecifications({ getIdentities }),
|
caveatSpecifications: getCaveatSpecifications({ getIdentities }),
|
||||||
permissionSpecifications: getPermissionSpecifications({
|
permissionSpecifications: {
|
||||||
getIdentities,
|
...getPermissionSpecifications({
|
||||||
getAllAccounts: this.keyringController.getAccounts.bind(
|
getIdentities,
|
||||||
this.keyringController,
|
getAllAccounts: this.keyringController.getAccounts.bind(
|
||||||
),
|
this.keyringController,
|
||||||
captureKeyringTypesWithMissingIdentities: (
|
),
|
||||||
identities = {},
|
captureKeyringTypesWithMissingIdentities: (
|
||||||
accounts = [],
|
identities = {},
|
||||||
) => {
|
accounts = [],
|
||||||
const accountsMissingIdentities = accounts.filter(
|
) => {
|
||||||
(address) => !identities[address],
|
const accountsMissingIdentities = accounts.filter(
|
||||||
);
|
(address) => !identities[address],
|
||||||
const keyringTypesWithMissingIdentities = accountsMissingIdentities.map(
|
);
|
||||||
(address) =>
|
const keyringTypesWithMissingIdentities = accountsMissingIdentities.map(
|
||||||
this.keyringController.getKeyringForAccount(address)?.type,
|
(address) =>
|
||||||
);
|
this.keyringController.getKeyringForAccount(address)?.type,
|
||||||
|
);
|
||||||
|
|
||||||
const identitiesCount = Object.keys(identities || {}).length;
|
const identitiesCount = Object.keys(identities || {}).length;
|
||||||
|
|
||||||
const accountTrackerCount = Object.keys(
|
const accountTrackerCount = Object.keys(
|
||||||
this.accountTracker.store.getState().accounts || {},
|
this.accountTracker.store.getState().accounts || {},
|
||||||
).length;
|
).length;
|
||||||
|
|
||||||
captureException(
|
captureException(
|
||||||
new Error(
|
new Error(
|
||||||
`Attempt to get permission specifications failed because their were ${accounts.length} accounts, but ${identitiesCount} identities, and the ${keyringTypesWithMissingIdentities} keyrings included accounts with missing identities. Meanwhile, there are ${accountTrackerCount} accounts in the account tracker.`,
|
`Attempt to get permission specifications failed because their were ${accounts.length} accounts, but ${identitiesCount} identities, and the ${keyringTypesWithMissingIdentities} keyrings included accounts with missing identities. Meanwhile, there are ${accountTrackerCount} accounts in the account tracker.`,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
...this.getSnapPermissionSpecifications(),
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
},
|
||||||
unrestrictedMethods,
|
unrestrictedMethods,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -547,6 +573,53 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
subjectCacheLimit: 100,
|
subjectCacheLimit: 100,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
this.workerController = new IframeExecutionService({
|
||||||
|
onError: this.onExecutionEnvironmentError.bind(this),
|
||||||
|
iframeUrl: new URL(
|
||||||
|
'https://metamask.github.io/iframe-execution-environment/0.3.1',
|
||||||
|
),
|
||||||
|
messenger: this.controllerMessenger.getRestricted({
|
||||||
|
name: 'ExecutionService',
|
||||||
|
}),
|
||||||
|
setupSnapProvider: this.setupSnapProvider.bind(this),
|
||||||
|
});
|
||||||
|
|
||||||
|
const snapControllerMessenger = this.controllerMessenger.getRestricted({
|
||||||
|
name: 'SnapController',
|
||||||
|
allowedEvents: [
|
||||||
|
'ExecutionService:unhandledError',
|
||||||
|
'ExecutionService:unresponsive',
|
||||||
|
],
|
||||||
|
allowedActions: [
|
||||||
|
`${this.permissionController.name}:getEndowments`,
|
||||||
|
`${this.permissionController.name}:getPermissions`,
|
||||||
|
`${this.permissionController.name}:hasPermission`,
|
||||||
|
`${this.permissionController.name}:requestPermissions`,
|
||||||
|
`${this.permissionController.name}:revokeAllPermissions`,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.snapController = new SnapController({
|
||||||
|
endowmentPermissionNames: Object.values(EndowmentPermissions),
|
||||||
|
terminateAllSnaps: this.workerController.terminateAllSnaps.bind(
|
||||||
|
this.workerController,
|
||||||
|
),
|
||||||
|
terminateSnap: this.workerController.terminateSnap.bind(
|
||||||
|
this.workerController,
|
||||||
|
),
|
||||||
|
executeSnap: this.workerController.executeSnap.bind(
|
||||||
|
this.workerController,
|
||||||
|
),
|
||||||
|
getRpcMessageHandler: this.workerController.getRpcMessageHandler.bind(
|
||||||
|
this.workerController,
|
||||||
|
),
|
||||||
|
closeAllConnections: this.removeAllConnections.bind(this),
|
||||||
|
state: initState.SnapController,
|
||||||
|
messenger: snapControllerMessenger,
|
||||||
|
});
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
this.detectTokensController = new DetectTokensController({
|
this.detectTokensController = new DetectTokensController({
|
||||||
preferences: this.preferencesController,
|
preferences: this.preferencesController,
|
||||||
tokensController: this.tokensController,
|
tokensController: this.tokensController,
|
||||||
@ -799,6 +872,9 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
TokenListController: this.tokenListController,
|
TokenListController: this.tokenListController,
|
||||||
TokensController: this.tokensController,
|
TokensController: this.tokensController,
|
||||||
CollectiblesController: this.collectiblesController,
|
CollectiblesController: this.collectiblesController,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
SnapController: this.snapController,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
});
|
});
|
||||||
|
|
||||||
this.memStore = new ComposableObservableStore({
|
this.memStore = new ComposableObservableStore({
|
||||||
@ -835,6 +911,9 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
TokenListController: this.tokenListController,
|
TokenListController: this.tokenListController,
|
||||||
TokensController: this.tokensController,
|
TokensController: this.tokensController,
|
||||||
CollectiblesController: this.collectiblesController,
|
CollectiblesController: this.collectiblesController,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
SnapController: this.snapController,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
},
|
},
|
||||||
controllerMessenger: this.controllerMessenger,
|
controllerMessenger: this.controllerMessenger,
|
||||||
});
|
});
|
||||||
@ -866,6 +945,58 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
this.publicConfigStore = this.createPublicConfigStore();
|
this.publicConfigStore = this.createPublicConfigStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
/**
|
||||||
|
* Constructor helper for getting Snap permission specifications.
|
||||||
|
*/
|
||||||
|
getSnapPermissionSpecifications() {
|
||||||
|
return {
|
||||||
|
...buildSnapEndowmentSpecifications(),
|
||||||
|
...buildSnapRestrictedMethodSpecifications({
|
||||||
|
addSnap: this.controllerMessenger.call.bind(
|
||||||
|
this.controllerMessenger,
|
||||||
|
'SnapController:add',
|
||||||
|
),
|
||||||
|
clearSnapState: (fromSubject) =>
|
||||||
|
this.controllerMessenger(
|
||||||
|
'SnapController:updateSnap',
|
||||||
|
fromSubject,
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
getMnemonic: this.getPrimaryKeyringMnemonic.bind(this),
|
||||||
|
getSnap: this.controllerMessenger.call.bind(
|
||||||
|
this.controllerMessenger,
|
||||||
|
'SnapController:get',
|
||||||
|
),
|
||||||
|
getSnapRpcHandler: this.controllerMessenger.call.bind(
|
||||||
|
this.controllerMessenger,
|
||||||
|
'SnapController:getRpcMessageHandler',
|
||||||
|
),
|
||||||
|
getSnapState: async (...args) => {
|
||||||
|
// TODO:flask Just return the action result directly in the next
|
||||||
|
// @metamask/snap-controllers update.
|
||||||
|
return (
|
||||||
|
(await this.controllerMessenger.call(
|
||||||
|
'SnapController:getSnapState',
|
||||||
|
...args,
|
||||||
|
)) ?? null
|
||||||
|
);
|
||||||
|
},
|
||||||
|
showConfirmation: (origin, confirmationData) =>
|
||||||
|
this.approvalController.addAndShowApprovalRequest({
|
||||||
|
origin,
|
||||||
|
type: MESSAGE_TYPE.SNAP_CONFIRM,
|
||||||
|
requestData: confirmationData,
|
||||||
|
}),
|
||||||
|
updateSnapState: this.controllerMessenger.call.bind(
|
||||||
|
this.controllerMessenger,
|
||||||
|
'SnapController:updateSnapState',
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up BaseController V2 event subscriptions. Currently, this includes
|
* Sets up BaseController V2 event subscriptions. Currently, this includes
|
||||||
* the subscriptions necessary to notify permission subjects of account
|
* the subscriptions necessary to notify permission subjects of account
|
||||||
@ -929,6 +1060,39 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
},
|
},
|
||||||
getPermittedAccountsByOrigin,
|
getPermittedAccountsByOrigin,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
// Record Snap metadata whenever a Snap is added to state.
|
||||||
|
this.controllerMessenger.subscribe(
|
||||||
|
`${this.snapController.name}:snapAdded`,
|
||||||
|
(snapId, snap, svgIcon = null) => {
|
||||||
|
const {
|
||||||
|
manifest: { proposedName },
|
||||||
|
version,
|
||||||
|
} = snap;
|
||||||
|
this.subjectMetadataController.addSubjectMetadata({
|
||||||
|
subjectType: SUBJECT_TYPES.SNAP,
|
||||||
|
name: proposedName,
|
||||||
|
origin: snapId,
|
||||||
|
version,
|
||||||
|
svgIcon,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
this.controllerMessenger.subscribe(
|
||||||
|
`${this.snapController.name}:snapInstalled`,
|
||||||
|
(snapId) => {
|
||||||
|
this.metaMetricsController.trackEvent({
|
||||||
|
event: 'Snap Installed',
|
||||||
|
category: 'Snaps',
|
||||||
|
properties: {
|
||||||
|
snap_id: snapId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1400,6 +1564,16 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
),
|
),
|
||||||
...getPermissionBackgroundApiMethods(permissionController),
|
...getPermissionBackgroundApiMethods(permissionController),
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
// snaps
|
||||||
|
removeSnapError: this.snapController.removeSnapError.bind(
|
||||||
|
this.snapController,
|
||||||
|
),
|
||||||
|
disableSnap: this.snapController.disableSnap.bind(this.snapController),
|
||||||
|
enableSnap: this.snapController.enableSnap.bind(this.snapController),
|
||||||
|
removeSnap: this.removeSnap.bind(this),
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
// swaps
|
// swaps
|
||||||
fetchAndSetQuotes: swapsController.fetchAndSetQuotes.bind(
|
fetchAndSetQuotes: swapsController.fetchAndSetQuotes.bind(
|
||||||
swapsController,
|
swapsController,
|
||||||
@ -1826,6 +2000,17 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
this.preferencesController.setSelectedAddress(address);
|
this.preferencesController.setSelectedAddress(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the mnemonic of the user's primary keyring.
|
||||||
|
*/
|
||||||
|
getPrimaryKeyringMnemonic() {
|
||||||
|
const keyring = this.keyringController.getKeyringsByType('HD Key Tree')[0];
|
||||||
|
if (!keyring.mnemonic) {
|
||||||
|
throw new Error('Primary keyring mnemonic unavailable.');
|
||||||
|
}
|
||||||
|
return keyring.mnemonic;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Hardware
|
// Hardware
|
||||||
//
|
//
|
||||||
@ -2201,6 +2386,32 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
return await promise;
|
return await promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
/**
|
||||||
|
* Gets an "app key" corresponding to an Ethereum address. An app key is more
|
||||||
|
* or less an addrdess hashed together with some string, in this case a
|
||||||
|
* subject identifier / origin.
|
||||||
|
*
|
||||||
|
* @todo Figure out a way to derive app keys that doesn't depend on the user's
|
||||||
|
* Ethereum addresses.
|
||||||
|
* @param {string} subject - The identifier of the subject whose app key to
|
||||||
|
* retrieve.
|
||||||
|
* @param {string} [requestedAccount] - The account whose app key to retrieve.
|
||||||
|
* The first account in the keyring will be used by default.
|
||||||
|
*/
|
||||||
|
async getAppKeyForSubject(subject, requestedAccount) {
|
||||||
|
let account;
|
||||||
|
|
||||||
|
if (requestedAccount) {
|
||||||
|
account = requestedAccount;
|
||||||
|
} else {
|
||||||
|
account = (await this.keyringController.getAccounts())[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.keyringController.exportAppKeyForAddress(account, subject);
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signifies user intent to complete an eth_sign method.
|
* Signifies user intent to complete an eth_sign method.
|
||||||
*
|
*
|
||||||
@ -2671,6 +2882,13 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
* @property {string} - The URL of the page or frame hosting the script that sent the message.
|
* @property {string} - The URL of the page or frame hosting the script that sent the message.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Snap sender object.
|
||||||
|
*
|
||||||
|
* @typedef {Object} SnapSender
|
||||||
|
* @property {string} snapId - The ID of the snap.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to create a multiplexed stream for connecting to an untrusted context
|
* Used to create a multiplexed stream for connecting to an untrusted context
|
||||||
* like a Dapp or other extension.
|
* like a Dapp or other extension.
|
||||||
@ -2682,6 +2900,7 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
setupUntrustedCommunication({ connectionStream, sender, subjectType }) {
|
setupUntrustedCommunication({ connectionStream, sender, subjectType }) {
|
||||||
const { usePhishDetect } = this.preferencesController.store.getState();
|
const { usePhishDetect } = this.preferencesController.store.getState();
|
||||||
|
|
||||||
let _subjectType;
|
let _subjectType;
|
||||||
if (subjectType) {
|
if (subjectType) {
|
||||||
_subjectType = subjectType;
|
_subjectType = subjectType;
|
||||||
@ -2794,14 +3013,20 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
* A method for serving our ethereum provider over a given stream.
|
* A method for serving our ethereum provider over a given stream.
|
||||||
*
|
*
|
||||||
* @param {*} outStream - The stream to provide over.
|
* @param {*} outStream - The stream to provide over.
|
||||||
* @param {MessageSender} sender - The sender of the messages on this stream
|
* @param {MessageSender | SnapSender} sender - The sender of the messages on this stream
|
||||||
* @param {string} subjectType - The type of the sender, i.e. subject.
|
* @param {string} subjectType - The type of the sender, i.e. subject.
|
||||||
*/
|
*/
|
||||||
setupProviderConnection(outStream, sender, subjectType) {
|
setupProviderConnection(outStream, sender, subjectType) {
|
||||||
let origin;
|
let origin;
|
||||||
if (subjectType === SUBJECT_TYPES.INTERNAL) {
|
if (subjectType === SUBJECT_TYPES.INTERNAL) {
|
||||||
origin = 'metamask';
|
origin = 'metamask';
|
||||||
} else {
|
}
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
else if (subjectType === SUBJECT_TYPES.SNAP) {
|
||||||
|
origin = sender.snapId;
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
else {
|
||||||
origin = new URL(sender.url).origin;
|
origin = new URL(sender.url).origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2820,9 +3045,9 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
|
|
||||||
const engine = this.setupProviderEngine({
|
const engine = this.setupProviderEngine({
|
||||||
origin,
|
origin,
|
||||||
tabId,
|
|
||||||
sender,
|
sender,
|
||||||
subjectType,
|
subjectType,
|
||||||
|
tabId,
|
||||||
});
|
});
|
||||||
|
|
||||||
// setup connection
|
// setup connection
|
||||||
@ -2844,6 +3069,33 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
/**
|
||||||
|
* For snaps running in workers.
|
||||||
|
*
|
||||||
|
* @param snapId
|
||||||
|
* @param error
|
||||||
|
*/
|
||||||
|
onExecutionEnvironmentError(snapId, error) {
|
||||||
|
this.snapController.stopPlugin(snapId);
|
||||||
|
this.snapController.addSnapError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For snaps running in workers.
|
||||||
|
*
|
||||||
|
* @param snapId
|
||||||
|
* @param connectionStream
|
||||||
|
*/
|
||||||
|
setupSnapProvider(snapId, connectionStream) {
|
||||||
|
this.setupUntrustedCommunication({
|
||||||
|
connectionStream,
|
||||||
|
sender: { snapId },
|
||||||
|
subjectType: SUBJECT_TYPES.SNAP,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A method for creating a provider that is safely restricted for the requesting subject.
|
* A method for creating a provider that is safely restricted for the requesting subject.
|
||||||
*
|
*
|
||||||
@ -2872,13 +3124,16 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
|
|
||||||
// append origin to each request
|
// append origin to each request
|
||||||
engine.push(createOriginMiddleware({ origin }));
|
engine.push(createOriginMiddleware({ origin }));
|
||||||
|
|
||||||
// append tabId to each request if it exists
|
// append tabId to each request if it exists
|
||||||
if (tabId) {
|
if (tabId) {
|
||||||
engine.push(createTabIdMiddleware({ tabId }));
|
engine.push(createTabIdMiddleware({ tabId }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// logging
|
// logging
|
||||||
engine.push(createLoggerMiddleware({ origin }));
|
engine.push(createLoggerMiddleware({ origin }));
|
||||||
engine.push(this.permissionLogController.createMiddleware());
|
engine.push(this.permissionLogController.createMiddleware());
|
||||||
|
|
||||||
// onboarding
|
// onboarding
|
||||||
if (subjectType === SUBJECT_TYPES.WEBSITE) {
|
if (subjectType === SUBJECT_TYPES.WEBSITE) {
|
||||||
engine.push(
|
engine.push(
|
||||||
@ -2888,6 +3143,8 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unrestricted/permissionless RPC method implementations
|
||||||
engine.push(
|
engine.push(
|
||||||
createMethodMiddleware({
|
createMethodMiddleware({
|
||||||
origin,
|
origin,
|
||||||
@ -2975,6 +3232,34 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
engine.push(
|
||||||
|
createSnapMethodMiddleware(subjectType === SUBJECT_TYPES.SNAP, {
|
||||||
|
getAppKey: this.getAppKeyForSubject.bind(this, origin),
|
||||||
|
getSnaps: this.snapController.getPermittedSnaps.bind(
|
||||||
|
this.snapController,
|
||||||
|
origin,
|
||||||
|
),
|
||||||
|
requestPermissions: async (requestedPermissions) => {
|
||||||
|
const [
|
||||||
|
approvedPermissions,
|
||||||
|
] = await this.permissionController.requestPermissions(
|
||||||
|
{ origin },
|
||||||
|
requestedPermissions,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Object.values(approvedPermissions);
|
||||||
|
},
|
||||||
|
getAccounts: this.getPermittedAccounts.bind(this, origin),
|
||||||
|
installSnaps: this.snapController.installSnaps.bind(
|
||||||
|
this.snapController,
|
||||||
|
origin,
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
// filter and subscription polyfills
|
// filter and subscription polyfills
|
||||||
engine.push(filterMiddleware);
|
engine.push(filterMiddleware);
|
||||||
engine.push(subscriptionManager.middleware);
|
engine.push(subscriptionManager.middleware);
|
||||||
@ -2986,6 +3271,7 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// forward to metamask primary provider
|
// forward to metamask primary provider
|
||||||
engine.push(providerAsMiddleware(provider));
|
engine.push(providerAsMiddleware(provider));
|
||||||
return engine;
|
return engine;
|
||||||
@ -3060,6 +3346,24 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes all connections for the given origin, and removes the references
|
||||||
|
* to them.
|
||||||
|
* Ignores unknown origins.
|
||||||
|
*
|
||||||
|
* @param {string} origin - The origin string.
|
||||||
|
*/
|
||||||
|
removeAllConnections(origin) {
|
||||||
|
const connections = this.connections[origin];
|
||||||
|
if (!connections) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(connections).forEach((id) => {
|
||||||
|
this.removeConnection(origin, id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Causes the RPC engines associated with the connections to the given origin
|
* Causes the RPC engines associated with the connections to the given origin
|
||||||
* to emit a notification event with the given payload.
|
* to emit a notification event with the given payload.
|
||||||
@ -3513,4 +3817,23 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
}
|
}
|
||||||
return this.keyringController.setLocked();
|
return this.keyringController.setLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
// SNAPS
|
||||||
|
/**
|
||||||
|
* Removes the specified snap, and all of its associated permissions.
|
||||||
|
* If we didn't revoke the permission to access the snap from all subjects,
|
||||||
|
* they could just reinstall without any confirmation.
|
||||||
|
*
|
||||||
|
* TODO: This should be implemented in `SnapController.removeSnap` via a controller action.
|
||||||
|
*
|
||||||
|
* @param {{ id: string, permissionName: string }} snap - The wrapper object of the snap to remove.
|
||||||
|
*/
|
||||||
|
removeSnap(snap) {
|
||||||
|
this.snapController.removeSnap(snap.id);
|
||||||
|
this.permissionController.revokePermissionForAllSubjects(
|
||||||
|
snap.permissionName,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@ this.store.updateStructure({
|
|||||||
...,
|
...,
|
||||||
GasFeeController: this.gasFeeController,
|
GasFeeController: this.gasFeeController,
|
||||||
TokenListController: this.tokenListController,
|
TokenListController: this.tokenListController,
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(beta)
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
PluginController: this.pluginController,
|
SnapController: this.snapController,
|
||||||
///: END:ONLY_INCLUDE_IN
|
///: END:ONLY_INCLUDE_IN
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
collectCoverageFrom: [
|
collectCoverageFrom: [
|
||||||
'<rootDir>/app/scripts/controllers/permissions/*.js',
|
'<rootDir>/app/scripts/controllers/permissions/**/*.js',
|
||||||
'<rootDir>/shared/**/*.js',
|
'<rootDir>/shared/**/*.js',
|
||||||
'<rootDir>/ui/**/*.js',
|
'<rootDir>/ui/**/*.js',
|
||||||
],
|
],
|
||||||
@ -14,7 +14,7 @@ module.exports = {
|
|||||||
lines: 43,
|
lines: 43,
|
||||||
statements: 43,
|
statements: 43,
|
||||||
},
|
},
|
||||||
'./app/scripts/controllers/permissions/*.js': {
|
'./app/scripts/controllers/permissions/**/*.js': {
|
||||||
branches: 100,
|
branches: 100,
|
||||||
functions: 100,
|
functions: 100,
|
||||||
lines: 100,
|
lines: 100,
|
||||||
@ -33,7 +33,7 @@ module.exports = {
|
|||||||
'<rootDir>/app/scripts/migrations/*.test.js',
|
'<rootDir>/app/scripts/migrations/*.test.js',
|
||||||
'<rootDir>/app/scripts/platforms/*.test.js',
|
'<rootDir>/app/scripts/platforms/*.test.js',
|
||||||
'<rootDir>app/scripts/controllers/network/**/*.test.js',
|
'<rootDir>app/scripts/controllers/network/**/*.test.js',
|
||||||
'<rootDir>/app/scripts/controllers/permissions/*.test.js',
|
'<rootDir>/app/scripts/controllers/permissions/**/*.test.js',
|
||||||
],
|
],
|
||||||
testTimeout: 2500,
|
testTimeout: 2500,
|
||||||
transform: {
|
transform: {
|
||||||
|
@ -10,6 +10,11 @@
|
|||||||
"@babel/runtime": true
|
"@babel/runtime": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"keccak": {
|
||||||
|
"packages": {
|
||||||
|
"readable-stream": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"node-fetch": {
|
"node-fetch": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"fetch": true
|
"fetch": true
|
||||||
|
@ -700,11 +700,11 @@
|
|||||||
},
|
},
|
||||||
"@metamask/snap-controllers": {
|
"@metamask/snap-controllers": {
|
||||||
"globals": {
|
"globals": {
|
||||||
|
"URL": true,
|
||||||
"Worker": true,
|
"Worker": true,
|
||||||
"clearTimeout": true,
|
"clearTimeout": true,
|
||||||
"console.error": true,
|
"console.error": true,
|
||||||
"console.log": true,
|
"console.log": true,
|
||||||
"console.warn": true,
|
|
||||||
"fetch": true,
|
"fetch": true,
|
||||||
"setTimeout": true
|
"setTimeout": true
|
||||||
},
|
},
|
||||||
@ -715,14 +715,22 @@
|
|||||||
"@metamask/post-message-stream": true,
|
"@metamask/post-message-stream": true,
|
||||||
"@metamask/safe-event-emitter": true,
|
"@metamask/safe-event-emitter": true,
|
||||||
"@metamask/snap-workers": true,
|
"@metamask/snap-workers": true,
|
||||||
|
"ajv": true,
|
||||||
|
"buffer": true,
|
||||||
|
"concat-stream": true,
|
||||||
|
"crypto-browserify": true,
|
||||||
"deep-freeze-strict": true,
|
"deep-freeze-strict": true,
|
||||||
"eth-rpc-errors": true,
|
"eth-rpc-errors": true,
|
||||||
"fast-deep-equal": true,
|
"fast-deep-equal": true,
|
||||||
|
"gunzip-maybe": true,
|
||||||
"immer": true,
|
"immer": true,
|
||||||
"json-rpc-engine": true,
|
"json-rpc-engine": true,
|
||||||
"json-rpc-middleware-stream": true,
|
"json-rpc-middleware-stream": true,
|
||||||
"nanoid": true,
|
"nanoid": true,
|
||||||
"pump": true
|
"pump": true,
|
||||||
|
"readable-web-to-node-stream": true,
|
||||||
|
"semver": true,
|
||||||
|
"tar-stream": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@ngraveio/bc-ur": {
|
"@ngraveio/bc-ur": {
|
||||||
@ -973,6 +981,11 @@
|
|||||||
"define": true
|
"define": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ajv": {
|
||||||
|
"packages": {
|
||||||
|
"fast-deep-equal": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"analytics-node": {
|
"analytics-node": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"clearTimeout": true,
|
"clearTimeout": true,
|
||||||
@ -1158,6 +1171,7 @@
|
|||||||
"bl": {
|
"bl": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"buffer": true,
|
"buffer": true,
|
||||||
|
"inherits": true,
|
||||||
"readable-stream": true,
|
"readable-stream": true,
|
||||||
"util": true
|
"util": true
|
||||||
}
|
}
|
||||||
@ -1270,6 +1284,16 @@
|
|||||||
"btoa": true
|
"btoa": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"browserify-zlib": {
|
||||||
|
"packages": {
|
||||||
|
"assert": true,
|
||||||
|
"buffer": true,
|
||||||
|
"pako": true,
|
||||||
|
"process": true,
|
||||||
|
"readable-stream": true,
|
||||||
|
"util": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"bs58": {
|
"bs58": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"base-x": true
|
"base-x": true
|
||||||
@ -1296,6 +1320,11 @@
|
|||||||
"ieee754": true
|
"ieee754": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"buffer-from": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"buffer-split": {
|
"buffer-split": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"buffer-indexof": true
|
"buffer-indexof": true
|
||||||
@ -1426,6 +1455,13 @@
|
|||||||
"util": true
|
"util": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"concat-stream": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true,
|
||||||
|
"inherits": true,
|
||||||
|
"readable-stream": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"constant-case": {
|
"constant-case": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"snake-case": true,
|
"snake-case": true,
|
||||||
@ -1707,6 +1743,16 @@
|
|||||||
"stream-browserify": true
|
"stream-browserify": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"duplexify": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true,
|
||||||
|
"end-of-stream": true,
|
||||||
|
"inherits": true,
|
||||||
|
"process": true,
|
||||||
|
"readable-stream": true,
|
||||||
|
"stream-shift": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"elliptic": {
|
"elliptic": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"bn.js": true,
|
"bn.js": true,
|
||||||
@ -2212,6 +2258,11 @@
|
|||||||
"postMessage": true
|
"postMessage": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fs-constants": {
|
||||||
|
"packages": {
|
||||||
|
"constants-browserify": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"fsm-event": {
|
"fsm-event": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"assert": true,
|
"assert": true,
|
||||||
@ -2280,6 +2331,16 @@
|
|||||||
"superagent": true
|
"superagent": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"gunzip-maybe": {
|
||||||
|
"packages": {
|
||||||
|
"browserify-zlib": true,
|
||||||
|
"is-deflate": true,
|
||||||
|
"is-gzip": true,
|
||||||
|
"peek-stream": true,
|
||||||
|
"pumpify": true,
|
||||||
|
"through2": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"hamt-sharding": {
|
"hamt-sharding": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"is-buffer": true,
|
"is-buffer": true,
|
||||||
@ -3930,6 +3991,14 @@
|
|||||||
"sha.js": true
|
"sha.js": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"peek-stream": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true,
|
||||||
|
"buffer-from": true,
|
||||||
|
"duplexify": true,
|
||||||
|
"through2": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"peer-book": {
|
"peer-book": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"bs58": true,
|
"bs58": true,
|
||||||
@ -4152,6 +4221,13 @@
|
|||||||
"process": true
|
"process": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pumpify": {
|
||||||
|
"packages": {
|
||||||
|
"duplexify": true,
|
||||||
|
"inherits": true,
|
||||||
|
"pump": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"punycode": {
|
"punycode": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"define": true
|
"define": true
|
||||||
@ -4465,6 +4541,11 @@
|
|||||||
"util-deprecate": true
|
"util-deprecate": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"readable-web-to-node-stream": {
|
||||||
|
"packages": {
|
||||||
|
"readable-stream": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"receptacle": {
|
"receptacle": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"clearTimeout": true,
|
"clearTimeout": true,
|
||||||
@ -4786,6 +4867,19 @@
|
|||||||
"upper-case": true
|
"upper-case": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tar-stream": {
|
||||||
|
"packages": {
|
||||||
|
"bl": true,
|
||||||
|
"buffer": true,
|
||||||
|
"end-of-stream": true,
|
||||||
|
"fs-constants": true,
|
||||||
|
"inherits": true,
|
||||||
|
"process": true,
|
||||||
|
"readable-stream": true,
|
||||||
|
"string_decoder": true,
|
||||||
|
"util": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"textarea-caret": {
|
"textarea-caret": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"document.body.appendChild": true,
|
"document.body.appendChild": true,
|
||||||
|
@ -617,6 +617,25 @@
|
|||||||
"URL": true
|
"URL": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@metamask/iframe-execution-environment-service": {
|
||||||
|
"globals": {
|
||||||
|
"clearTimeout": true,
|
||||||
|
"console.log": true,
|
||||||
|
"document.body.appendChild": true,
|
||||||
|
"document.createElement": true,
|
||||||
|
"document.getElementById": true,
|
||||||
|
"setTimeout": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@metamask/post-message-stream": true,
|
||||||
|
"@metamask/snap-controllers": true,
|
||||||
|
"@metamask/snap-workers": true,
|
||||||
|
"json-rpc-engine": true,
|
||||||
|
"json-rpc-middleware-stream": true,
|
||||||
|
"nanoid": true,
|
||||||
|
"pump": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"@metamask/jazzicon": {
|
"@metamask/jazzicon": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"document.createElement": true,
|
"document.createElement": true,
|
||||||
@ -700,11 +719,11 @@
|
|||||||
},
|
},
|
||||||
"@metamask/snap-controllers": {
|
"@metamask/snap-controllers": {
|
||||||
"globals": {
|
"globals": {
|
||||||
|
"URL": true,
|
||||||
"Worker": true,
|
"Worker": true,
|
||||||
"clearTimeout": true,
|
"clearTimeout": true,
|
||||||
"console.error": true,
|
"console.error": true,
|
||||||
"console.log": true,
|
"console.log": true,
|
||||||
"console.warn": true,
|
|
||||||
"fetch": true,
|
"fetch": true,
|
||||||
"setTimeout": true
|
"setTimeout": true
|
||||||
},
|
},
|
||||||
@ -715,14 +734,22 @@
|
|||||||
"@metamask/post-message-stream": true,
|
"@metamask/post-message-stream": true,
|
||||||
"@metamask/safe-event-emitter": true,
|
"@metamask/safe-event-emitter": true,
|
||||||
"@metamask/snap-workers": true,
|
"@metamask/snap-workers": true,
|
||||||
|
"ajv": true,
|
||||||
|
"buffer": true,
|
||||||
|
"concat-stream": true,
|
||||||
|
"crypto-browserify": true,
|
||||||
"deep-freeze-strict": true,
|
"deep-freeze-strict": true,
|
||||||
"eth-rpc-errors": true,
|
"eth-rpc-errors": true,
|
||||||
"fast-deep-equal": true,
|
"fast-deep-equal": true,
|
||||||
|
"gunzip-maybe": true,
|
||||||
"immer": true,
|
"immer": true,
|
||||||
"json-rpc-engine": true,
|
"json-rpc-engine": true,
|
||||||
"json-rpc-middleware-stream": true,
|
"json-rpc-middleware-stream": true,
|
||||||
"nanoid": true,
|
"nanoid": true,
|
||||||
"pump": true
|
"pump": true,
|
||||||
|
"readable-web-to-node-stream": true,
|
||||||
|
"semver": true,
|
||||||
|
"tar-stream": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@ngraveio/bc-ur": {
|
"@ngraveio/bc-ur": {
|
||||||
@ -973,6 +1000,11 @@
|
|||||||
"define": true
|
"define": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ajv": {
|
||||||
|
"packages": {
|
||||||
|
"fast-deep-equal": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"analytics-node": {
|
"analytics-node": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"clearTimeout": true,
|
"clearTimeout": true,
|
||||||
@ -1158,6 +1190,7 @@
|
|||||||
"bl": {
|
"bl": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"buffer": true,
|
"buffer": true,
|
||||||
|
"inherits": true,
|
||||||
"readable-stream": true,
|
"readable-stream": true,
|
||||||
"util": true
|
"util": true
|
||||||
}
|
}
|
||||||
@ -1270,6 +1303,16 @@
|
|||||||
"btoa": true
|
"btoa": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"browserify-zlib": {
|
||||||
|
"packages": {
|
||||||
|
"assert": true,
|
||||||
|
"buffer": true,
|
||||||
|
"pako": true,
|
||||||
|
"process": true,
|
||||||
|
"readable-stream": true,
|
||||||
|
"util": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"bs58": {
|
"bs58": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"base-x": true
|
"base-x": true
|
||||||
@ -1296,6 +1339,11 @@
|
|||||||
"ieee754": true
|
"ieee754": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"buffer-from": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"buffer-split": {
|
"buffer-split": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"buffer-indexof": true
|
"buffer-indexof": true
|
||||||
@ -1426,6 +1474,13 @@
|
|||||||
"util": true
|
"util": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"concat-stream": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true,
|
||||||
|
"inherits": true,
|
||||||
|
"readable-stream": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"constant-case": {
|
"constant-case": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"snake-case": true,
|
"snake-case": true,
|
||||||
@ -1707,6 +1762,16 @@
|
|||||||
"stream-browserify": true
|
"stream-browserify": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"duplexify": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true,
|
||||||
|
"end-of-stream": true,
|
||||||
|
"inherits": true,
|
||||||
|
"process": true,
|
||||||
|
"readable-stream": true,
|
||||||
|
"stream-shift": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"elliptic": {
|
"elliptic": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"bn.js": true,
|
"bn.js": true,
|
||||||
@ -2212,6 +2277,11 @@
|
|||||||
"postMessage": true
|
"postMessage": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fs-constants": {
|
||||||
|
"packages": {
|
||||||
|
"constants-browserify": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"fsm-event": {
|
"fsm-event": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"assert": true,
|
"assert": true,
|
||||||
@ -2280,6 +2350,16 @@
|
|||||||
"superagent": true
|
"superagent": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"gunzip-maybe": {
|
||||||
|
"packages": {
|
||||||
|
"browserify-zlib": true,
|
||||||
|
"is-deflate": true,
|
||||||
|
"is-gzip": true,
|
||||||
|
"peek-stream": true,
|
||||||
|
"pumpify": true,
|
||||||
|
"through2": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"hamt-sharding": {
|
"hamt-sharding": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"is-buffer": true,
|
"is-buffer": true,
|
||||||
@ -3930,6 +4010,14 @@
|
|||||||
"sha.js": true
|
"sha.js": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"peek-stream": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true,
|
||||||
|
"buffer-from": true,
|
||||||
|
"duplexify": true,
|
||||||
|
"through2": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"peer-book": {
|
"peer-book": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"bs58": true,
|
"bs58": true,
|
||||||
@ -4152,6 +4240,13 @@
|
|||||||
"process": true
|
"process": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pumpify": {
|
||||||
|
"packages": {
|
||||||
|
"duplexify": true,
|
||||||
|
"inherits": true,
|
||||||
|
"pump": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"punycode": {
|
"punycode": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"define": true
|
"define": true
|
||||||
@ -4465,6 +4560,11 @@
|
|||||||
"util-deprecate": true
|
"util-deprecate": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"readable-web-to-node-stream": {
|
||||||
|
"packages": {
|
||||||
|
"readable-stream": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"receptacle": {
|
"receptacle": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"clearTimeout": true,
|
"clearTimeout": true,
|
||||||
@ -4786,6 +4886,19 @@
|
|||||||
"upper-case": true
|
"upper-case": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tar-stream": {
|
||||||
|
"packages": {
|
||||||
|
"bl": true,
|
||||||
|
"buffer": true,
|
||||||
|
"end-of-stream": true,
|
||||||
|
"fs-constants": true,
|
||||||
|
"inherits": true,
|
||||||
|
"process": true,
|
||||||
|
"readable-stream": true,
|
||||||
|
"string_decoder": true,
|
||||||
|
"util": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"textarea-caret": {
|
"textarea-caret": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"document.body.appendChild": true,
|
"document.body.appendChild": true,
|
||||||
|
@ -10,6 +10,11 @@
|
|||||||
"@babel/runtime": true
|
"@babel/runtime": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"keccak": {
|
||||||
|
"packages": {
|
||||||
|
"readable-stream": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"node-fetch": {
|
"node-fetch": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"fetch": true
|
"fetch": true
|
||||||
|
@ -700,11 +700,11 @@
|
|||||||
},
|
},
|
||||||
"@metamask/snap-controllers": {
|
"@metamask/snap-controllers": {
|
||||||
"globals": {
|
"globals": {
|
||||||
|
"URL": true,
|
||||||
"Worker": true,
|
"Worker": true,
|
||||||
"clearTimeout": true,
|
"clearTimeout": true,
|
||||||
"console.error": true,
|
"console.error": true,
|
||||||
"console.log": true,
|
"console.log": true,
|
||||||
"console.warn": true,
|
|
||||||
"fetch": true,
|
"fetch": true,
|
||||||
"setTimeout": true
|
"setTimeout": true
|
||||||
},
|
},
|
||||||
@ -715,14 +715,22 @@
|
|||||||
"@metamask/post-message-stream": true,
|
"@metamask/post-message-stream": true,
|
||||||
"@metamask/safe-event-emitter": true,
|
"@metamask/safe-event-emitter": true,
|
||||||
"@metamask/snap-workers": true,
|
"@metamask/snap-workers": true,
|
||||||
|
"ajv": true,
|
||||||
|
"buffer": true,
|
||||||
|
"concat-stream": true,
|
||||||
|
"crypto-browserify": true,
|
||||||
"deep-freeze-strict": true,
|
"deep-freeze-strict": true,
|
||||||
"eth-rpc-errors": true,
|
"eth-rpc-errors": true,
|
||||||
"fast-deep-equal": true,
|
"fast-deep-equal": true,
|
||||||
|
"gunzip-maybe": true,
|
||||||
"immer": true,
|
"immer": true,
|
||||||
"json-rpc-engine": true,
|
"json-rpc-engine": true,
|
||||||
"json-rpc-middleware-stream": true,
|
"json-rpc-middleware-stream": true,
|
||||||
"nanoid": true,
|
"nanoid": true,
|
||||||
"pump": true
|
"pump": true,
|
||||||
|
"readable-web-to-node-stream": true,
|
||||||
|
"semver": true,
|
||||||
|
"tar-stream": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@ngraveio/bc-ur": {
|
"@ngraveio/bc-ur": {
|
||||||
@ -973,6 +981,11 @@
|
|||||||
"define": true
|
"define": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ajv": {
|
||||||
|
"packages": {
|
||||||
|
"fast-deep-equal": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"analytics-node": {
|
"analytics-node": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"clearTimeout": true,
|
"clearTimeout": true,
|
||||||
@ -1158,6 +1171,7 @@
|
|||||||
"bl": {
|
"bl": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"buffer": true,
|
"buffer": true,
|
||||||
|
"inherits": true,
|
||||||
"readable-stream": true,
|
"readable-stream": true,
|
||||||
"util": true
|
"util": true
|
||||||
}
|
}
|
||||||
@ -1270,6 +1284,16 @@
|
|||||||
"btoa": true
|
"btoa": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"browserify-zlib": {
|
||||||
|
"packages": {
|
||||||
|
"assert": true,
|
||||||
|
"buffer": true,
|
||||||
|
"pako": true,
|
||||||
|
"process": true,
|
||||||
|
"readable-stream": true,
|
||||||
|
"util": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"bs58": {
|
"bs58": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"base-x": true
|
"base-x": true
|
||||||
@ -1296,6 +1320,11 @@
|
|||||||
"ieee754": true
|
"ieee754": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"buffer-from": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"buffer-split": {
|
"buffer-split": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"buffer-indexof": true
|
"buffer-indexof": true
|
||||||
@ -1426,6 +1455,13 @@
|
|||||||
"util": true
|
"util": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"concat-stream": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true,
|
||||||
|
"inherits": true,
|
||||||
|
"readable-stream": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"constant-case": {
|
"constant-case": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"snake-case": true,
|
"snake-case": true,
|
||||||
@ -1707,6 +1743,16 @@
|
|||||||
"stream-browserify": true
|
"stream-browserify": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"duplexify": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true,
|
||||||
|
"end-of-stream": true,
|
||||||
|
"inherits": true,
|
||||||
|
"process": true,
|
||||||
|
"readable-stream": true,
|
||||||
|
"stream-shift": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"elliptic": {
|
"elliptic": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"bn.js": true,
|
"bn.js": true,
|
||||||
@ -2212,6 +2258,11 @@
|
|||||||
"postMessage": true
|
"postMessage": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fs-constants": {
|
||||||
|
"packages": {
|
||||||
|
"constants-browserify": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"fsm-event": {
|
"fsm-event": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"assert": true,
|
"assert": true,
|
||||||
@ -2280,6 +2331,16 @@
|
|||||||
"superagent": true
|
"superagent": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"gunzip-maybe": {
|
||||||
|
"packages": {
|
||||||
|
"browserify-zlib": true,
|
||||||
|
"is-deflate": true,
|
||||||
|
"is-gzip": true,
|
||||||
|
"peek-stream": true,
|
||||||
|
"pumpify": true,
|
||||||
|
"through2": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"hamt-sharding": {
|
"hamt-sharding": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"is-buffer": true,
|
"is-buffer": true,
|
||||||
@ -3930,6 +3991,14 @@
|
|||||||
"sha.js": true
|
"sha.js": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"peek-stream": {
|
||||||
|
"packages": {
|
||||||
|
"buffer": true,
|
||||||
|
"buffer-from": true,
|
||||||
|
"duplexify": true,
|
||||||
|
"through2": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"peer-book": {
|
"peer-book": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"bs58": true,
|
"bs58": true,
|
||||||
@ -4152,6 +4221,13 @@
|
|||||||
"process": true
|
"process": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pumpify": {
|
||||||
|
"packages": {
|
||||||
|
"duplexify": true,
|
||||||
|
"inherits": true,
|
||||||
|
"pump": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"punycode": {
|
"punycode": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"define": true
|
"define": true
|
||||||
@ -4465,6 +4541,11 @@
|
|||||||
"util-deprecate": true
|
"util-deprecate": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"readable-web-to-node-stream": {
|
||||||
|
"packages": {
|
||||||
|
"readable-stream": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"receptacle": {
|
"receptacle": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"clearTimeout": true,
|
"clearTimeout": true,
|
||||||
@ -4786,6 +4867,19 @@
|
|||||||
"upper-case": true
|
"upper-case": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tar-stream": {
|
||||||
|
"packages": {
|
||||||
|
"bl": true,
|
||||||
|
"buffer": true,
|
||||||
|
"end-of-stream": true,
|
||||||
|
"fs-constants": true,
|
||||||
|
"inherits": true,
|
||||||
|
"process": true,
|
||||||
|
"readable-stream": true,
|
||||||
|
"string_decoder": true,
|
||||||
|
"util": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"textarea-caret": {
|
"textarea-caret": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"document.body.appendChild": true,
|
"document.body.appendChild": true,
|
||||||
|
@ -113,13 +113,15 @@
|
|||||||
"@metamask/eth-ledger-bridge-keyring": "^0.10.0",
|
"@metamask/eth-ledger-bridge-keyring": "^0.10.0",
|
||||||
"@metamask/eth-token-tracker": "^4.0.0",
|
"@metamask/eth-token-tracker": "^4.0.0",
|
||||||
"@metamask/etherscan-link": "^2.1.0",
|
"@metamask/etherscan-link": "^2.1.0",
|
||||||
|
"@metamask/iframe-execution-environment-service": "^0.9.0",
|
||||||
"@metamask/jazzicon": "^2.0.0",
|
"@metamask/jazzicon": "^2.0.0",
|
||||||
"@metamask/logo": "^3.1.1",
|
"@metamask/logo": "^3.1.1",
|
||||||
"@metamask/obs-store": "^5.0.0",
|
"@metamask/obs-store": "^5.0.0",
|
||||||
"@metamask/post-message-stream": "^4.0.0",
|
"@metamask/post-message-stream": "^4.0.0",
|
||||||
"@metamask/providers": "^8.1.1",
|
"@metamask/providers": "^8.1.1",
|
||||||
"@metamask/rpc-methods": "^0.5.0",
|
"@metamask/rpc-methods": "^0.9.0",
|
||||||
"@metamask/snap-controllers": "^0.4.0",
|
"@metamask/slip44": "^2.0.0",
|
||||||
|
"@metamask/snap-controllers": "^0.9.0",
|
||||||
"@ngraveio/bc-ur": "^1.1.6",
|
"@ngraveio/bc-ur": "^1.1.6",
|
||||||
"@popperjs/core": "^2.4.0",
|
"@popperjs/core": "^2.4.0",
|
||||||
"@reduxjs/toolkit": "^1.6.2",
|
"@reduxjs/toolkit": "^1.6.2",
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { RestrictedMethods } from './permissions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A string representing the type of environment the application is currently running in
|
* A string representing the type of environment the application is currently running in
|
||||||
* popup - When the user click's the icon in their browser's extension bar; the default view
|
* popup - When the user click's the icon in their browser's extension bar; the default view
|
||||||
@ -31,7 +33,7 @@ export const PLATFORM_OPERA = 'Opera';
|
|||||||
|
|
||||||
export const MESSAGE_TYPE = {
|
export const MESSAGE_TYPE = {
|
||||||
ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain',
|
ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain',
|
||||||
ETH_ACCOUNTS: 'eth_accounts',
|
ETH_ACCOUNTS: RestrictedMethods.eth_accounts,
|
||||||
ETH_DECRYPT: 'eth_decrypt',
|
ETH_DECRYPT: 'eth_decrypt',
|
||||||
ETH_GET_ENCRYPTION_PUBLIC_KEY: 'eth_getEncryptionPublicKey',
|
ETH_GET_ENCRYPTION_PUBLIC_KEY: 'eth_getEncryptionPublicKey',
|
||||||
ETH_REQUEST_ACCOUNTS: 'eth_requestAccounts',
|
ETH_REQUEST_ACCOUNTS: 'eth_requestAccounts',
|
||||||
@ -44,6 +46,9 @@ export const MESSAGE_TYPE = {
|
|||||||
SWITCH_ETHEREUM_CHAIN: 'wallet_switchEthereumChain',
|
SWITCH_ETHEREUM_CHAIN: 'wallet_switchEthereumChain',
|
||||||
WATCH_ASSET: 'wallet_watchAsset',
|
WATCH_ASSET: 'wallet_watchAsset',
|
||||||
WATCH_ASSET_LEGACY: 'metamask_watchAsset',
|
WATCH_ASSET_LEGACY: 'metamask_watchAsset',
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
SNAP_CONFIRM: RestrictedMethods.snap_confirm,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,6 +60,9 @@ export const SUBJECT_TYPES = {
|
|||||||
INTERNAL: 'internal',
|
INTERNAL: 'internal',
|
||||||
UNKNOWN: 'unknown',
|
UNKNOWN: 'unknown',
|
||||||
WEBSITE: 'website',
|
WEBSITE: 'website',
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
SNAP: 'snap',
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
};
|
};
|
||||||
|
|
||||||
export const POLLING_TOKEN_ENVIRONMENT_TYPES = {
|
export const POLLING_TOKEN_ENVIRONMENT_TYPES = {
|
||||||
|
@ -4,4 +4,21 @@ export const CaveatTypes = Object.freeze({
|
|||||||
|
|
||||||
export const RestrictedMethods = Object.freeze({
|
export const RestrictedMethods = Object.freeze({
|
||||||
eth_accounts: 'eth_accounts',
|
eth_accounts: 'eth_accounts',
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
snap_confirm: 'snap_confirm',
|
||||||
|
snap_manageState: 'snap_manageState',
|
||||||
|
'snap_getBip44Entropy_*': 'snap_getBip44Entropy_*',
|
||||||
|
'wallet_snap_*': 'wallet_snap_*',
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
});
|
});
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
export const PermissionNamespaces = Object.freeze({
|
||||||
|
snap_getBip44Entropy_: 'snap_getBip44Entropy_*',
|
||||||
|
wallet_snap_: 'wallet_snap_*',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const EndowmentPermissions = Object.freeze({
|
||||||
|
'endowment:network-access': 'endowment:network-access',
|
||||||
|
});
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
22
shared/constants/permissions.test.js
Normal file
22
shared/constants/permissions.test.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { endowmentPermissionBuilders } from '@metamask/snap-controllers';
|
||||||
|
import { restrictedMethodPermissionBuilders } from '@metamask/rpc-methods';
|
||||||
|
import { EndowmentPermissions, RestrictedMethods } from './permissions';
|
||||||
|
|
||||||
|
describe('EndowmentPermissions', () => {
|
||||||
|
it('has the expected permission keys', () => {
|
||||||
|
expect(Object.keys(EndowmentPermissions).sort()).toStrictEqual(
|
||||||
|
Object.keys(endowmentPermissionBuilders).sort(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('RestrictedMethods', () => {
|
||||||
|
it('has the expected permission keys', () => {
|
||||||
|
expect(Object.keys(RestrictedMethods).sort()).toStrictEqual(
|
||||||
|
[
|
||||||
|
'eth_accounts',
|
||||||
|
...Object.keys(restrictedMethodPermissionBuilders),
|
||||||
|
].sort(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -27,8 +27,11 @@
|
|||||||
@import 'edit-gas-fee-popover/edit-gas-item/index';
|
@import 'edit-gas-fee-popover/edit-gas-item/index';
|
||||||
@import 'edit-gas-fee-popover/network-statistics/index';
|
@import 'edit-gas-fee-popover/network-statistics/index';
|
||||||
@import 'edit-gas-fee-popover/network-statistics/status-slider/index';
|
@import 'edit-gas-fee-popover/network-statistics/status-slider/index';
|
||||||
@import 'flask/snaps-authorship-pill/index';
|
|
||||||
@import 'edit-gas-fee-popover/edit-gas-tooltip/index';
|
@import 'edit-gas-fee-popover/edit-gas-tooltip/index';
|
||||||
|
@import 'flask/experimental-area/index';
|
||||||
|
@import 'flask/snap-install-warning/index';
|
||||||
|
@import 'flask/snap-settings-card/index';
|
||||||
|
@import 'flask/snaps-authorship-pill/index';
|
||||||
@import 'gas-customization/gas-modal-page-container/index';
|
@import 'gas-customization/gas-modal-page-container/index';
|
||||||
@import 'gas-customization/gas-price-button-group/index';
|
@import 'gas-customization/gas-price-button-group/index';
|
||||||
@import 'gas-customization/index';
|
@import 'gas-customization/index';
|
||||||
@ -51,7 +54,6 @@
|
|||||||
@import 'selected-account/index';
|
@import 'selected-account/index';
|
||||||
@import 'signature-request/index';
|
@import 'signature-request/index';
|
||||||
@import 'signature-request-original/index';
|
@import 'signature-request-original/index';
|
||||||
@import 'flask/snap-settings-card/index';
|
|
||||||
@import 'tab-bar/index';
|
@import 'tab-bar/index';
|
||||||
@import 'token-cell/token-cell';
|
@import 'token-cell/token-cell';
|
||||||
@import 'token-list-display/token-list-display';
|
@import 'token-list-display/token-list-display';
|
||||||
@ -68,7 +70,6 @@
|
|||||||
@import 'wallet-overview/index';
|
@import 'wallet-overview/index';
|
||||||
@import 'whats-new-popup/index';
|
@import 'whats-new-popup/index';
|
||||||
@import 'loading-network-screen/index';
|
@import 'loading-network-screen/index';
|
||||||
@import 'flask/experimental-area/index';
|
|
||||||
@import 'transaction-decoding/index';
|
@import 'transaction-decoding/index';
|
||||||
@import 'advanced-gas-fee-popover/index';
|
@import 'advanced-gas-fee-popover/index';
|
||||||
@import 'advanced-gas-fee-popover/advanced-gas-fee-gas-limit/index';
|
@import 'advanced-gas-fee-popover/advanced-gas-fee-gas-limit/index';
|
||||||
|
1
ui/components/app/flask/snap-install-warning/index.js
Normal file
1
ui/components/app/flask/snap-install-warning/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './snap-install-warning';
|
30
ui/components/app/flask/snap-install-warning/index.scss
Normal file
30
ui/components/app/flask/snap-install-warning/index.scss
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
.snap-install-warning {
|
||||||
|
.checkbox-label {
|
||||||
|
@include H7;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
padding: 0 16px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer-button {
|
||||||
|
margin-right: 16px;
|
||||||
|
|
||||||
|
&:last-of-type {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
import React, { useCallback, useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
||||||
|
import CheckBox from '../../../ui/check-box/check-box.component';
|
||||||
|
import Typography from '../../../ui/typography/typography';
|
||||||
|
import { TYPOGRAPHY } from '../../../../helpers/constants/design-system';
|
||||||
|
import Popover from '../../../ui/popover';
|
||||||
|
import Button from '../../../ui/button';
|
||||||
|
|
||||||
|
export default function SnapInstallWarning({ onCancel, onSubmit, snapName }) {
|
||||||
|
const t = useI18nContext();
|
||||||
|
const [isConfirmed, setIsConfirmed] = useState(false);
|
||||||
|
|
||||||
|
const onCheckboxClicked = useCallback(
|
||||||
|
() => setIsConfirmed((confirmedState) => !confirmedState),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const SnapInstallWarningFooter = () => {
|
||||||
|
return (
|
||||||
|
<div className="snap-install-warning__footer">
|
||||||
|
<Button
|
||||||
|
className="snap-install-warning__footer-button"
|
||||||
|
type="default"
|
||||||
|
onClick={onCancel}
|
||||||
|
>
|
||||||
|
{t('cancel')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className="snap-install-warning__footer-button"
|
||||||
|
type="primary"
|
||||||
|
disabled={!isConfirmed}
|
||||||
|
onClick={onSubmit}
|
||||||
|
>
|
||||||
|
{t('confirm')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
className="snap-install-warning"
|
||||||
|
title={t('areYouSure')}
|
||||||
|
footer={<SnapInstallWarningFooter />}
|
||||||
|
>
|
||||||
|
<div className="snap-install-warning__content">
|
||||||
|
<Typography variant={TYPOGRAPHY.H6} boxProps={{ paddingBottom: 4 }}>
|
||||||
|
{t('snapInstallWarningCheck')}
|
||||||
|
</Typography>
|
||||||
|
<div className="checkbox-label">
|
||||||
|
<CheckBox
|
||||||
|
checked={isConfirmed}
|
||||||
|
id="warning-accept"
|
||||||
|
onClick={onCheckboxClicked}
|
||||||
|
/>
|
||||||
|
<label htmlFor="warning-accept">
|
||||||
|
{t('snapInstallWarningKeyAccess', [snapName])}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SnapInstallWarning.propTypes = {
|
||||||
|
/**
|
||||||
|
* onCancel handler
|
||||||
|
*/
|
||||||
|
onCancel: PropTypes.func,
|
||||||
|
/**
|
||||||
|
* onSubmit handler
|
||||||
|
*/
|
||||||
|
onSubmit: PropTypes.func,
|
||||||
|
/**
|
||||||
|
* Name of snap
|
||||||
|
*/
|
||||||
|
snapName: PropTypes.string,
|
||||||
|
};
|
@ -13,12 +13,14 @@ import ToggleButton from '../../../ui/toggle-button';
|
|||||||
import Chip from '../../../ui/chip';
|
import Chip from '../../../ui/chip';
|
||||||
import ColorIndicator from '../../../ui/color-indicator';
|
import ColorIndicator from '../../../ui/color-indicator';
|
||||||
import Button from '../../../ui/button';
|
import Button from '../../../ui/button';
|
||||||
|
import Tooltip from '../../../ui/tooltip';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
COLORS,
|
COLORS,
|
||||||
TYPOGRAPHY,
|
TYPOGRAPHY,
|
||||||
FONT_WEIGHT,
|
FONT_WEIGHT,
|
||||||
ALIGN_ITEMS,
|
ALIGN_ITEMS,
|
||||||
|
JUSTIFY_CONTENT,
|
||||||
DISPLAY,
|
DISPLAY,
|
||||||
TEXT_ALIGN,
|
TEXT_ALIGN,
|
||||||
} from '../../../../helpers/constants/design-system';
|
} from '../../../../helpers/constants/design-system';
|
||||||
@ -41,7 +43,7 @@ const SnapSettingsCard = ({
|
|||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
icon,
|
icon,
|
||||||
dateAdded,
|
dateAdded = '',
|
||||||
version,
|
version,
|
||||||
url,
|
url,
|
||||||
onToggle,
|
onToggle,
|
||||||
@ -87,12 +89,14 @@ const SnapSettingsCard = ({
|
|||||||
{name}
|
{name}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box paddingLeft={4} className="snap-settings-card__toggle-container">
|
<Box paddingLeft={4} className="snap-settings-card__toggle-container">
|
||||||
<ToggleButton
|
<Tooltip interactive position="bottom" html={t('snapsToggle')}>
|
||||||
value={isEnabled}
|
<ToggleButton
|
||||||
onToggle={onToggle}
|
value={isEnabled}
|
||||||
className="snap-settings-card__toggle-container__toggle-button"
|
onToggle={onToggle}
|
||||||
{...toggleButtonProps}
|
className="snap-settings-card__toggle-container__toggle-button"
|
||||||
/>
|
{...toggleButtonProps}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Typography
|
<Typography
|
||||||
@ -113,6 +117,7 @@ const SnapSettingsCard = ({
|
|||||||
<Box
|
<Box
|
||||||
display={DISPLAY.FLEX}
|
display={DISPLAY.FLEX}
|
||||||
alignItems={ALIGN_ITEMS.CENTER}
|
alignItems={ALIGN_ITEMS.CENTER}
|
||||||
|
justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN}
|
||||||
marginBottom={4}
|
marginBottom={4}
|
||||||
>
|
>
|
||||||
<Box>
|
<Box>
|
||||||
@ -124,24 +129,26 @@ const SnapSettingsCard = ({
|
|||||||
{t('flaskSnapSettingsCardButtonCta')}
|
{t('flaskSnapSettingsCardButtonCta')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
<Chip
|
<Tooltip interactive position="bottom" html={t('snapsStatus')}>
|
||||||
leftIcon={
|
<Chip
|
||||||
<Box paddingLeft={1}>
|
leftIcon={
|
||||||
<ColorIndicator
|
<Box paddingLeft={1}>
|
||||||
color={STATUS_COLORS[status]}
|
<ColorIndicator
|
||||||
type={ColorIndicator.TYPES.FILLED}
|
color={STATUS_COLORS[status]}
|
||||||
/>
|
type={ColorIndicator.TYPES.FILLED}
|
||||||
</Box>
|
/>
|
||||||
}
|
</Box>
|
||||||
label={status}
|
}
|
||||||
labelProps={{
|
label={status}
|
||||||
color: COLORS.UI4,
|
labelProps={{
|
||||||
margin: [0, 1],
|
color: COLORS.UI4,
|
||||||
}}
|
margin: [0, 1],
|
||||||
backgroundColor={COLORS.UI1}
|
}}
|
||||||
className="snap-settings-card__chip"
|
backgroundColor={COLORS.UI1}
|
||||||
{...chipProps}
|
className="snap-settings-card__chip"
|
||||||
/>
|
{...chipProps}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Box display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
<Box display={DISPLAY.FLEX} alignItems={ALIGN_ITEMS.CENTER}>
|
||||||
|
@ -44,4 +44,3 @@
|
|||||||
outline: none !important;
|
outline: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,11 +71,14 @@ export default class PermissionPageContainerContent extends PureComponent {
|
|||||||
subjectMetadata,
|
subjectMetadata,
|
||||||
selectedIdentities,
|
selectedIdentities,
|
||||||
allIdentitiesSelected,
|
allIdentitiesSelected,
|
||||||
|
selectedPermissions,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { t } = this.context;
|
const { t } = this.context;
|
||||||
|
|
||||||
if (subjectMetadata.extensionId) {
|
if (subjectMetadata.extensionId) {
|
||||||
return t('externalExtension', [subjectMetadata.extensionId]);
|
return t('externalExtension', [subjectMetadata.extensionId]);
|
||||||
|
} else if (!selectedPermissions.eth_accounts) {
|
||||||
|
return t('permissionRequestCapitalized');
|
||||||
} else if (allIdentitiesSelected) {
|
} else if (allIdentitiesSelected) {
|
||||||
return t('connectToAll', [
|
return t('connectToAll', [
|
||||||
this.renderAccountTooltip(t('connectToAllAccounts')),
|
this.renderAccountTooltip(t('connectToAllAccounts')),
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
.permissions-connect-header {
|
.permissions-connect-header {
|
||||||
display: flex;
|
|
||||||
flex: 0;
|
flex: 0;
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
width: 92%;
|
width: 92%;
|
||||||
|
|
||||||
&__icon {
|
&__icon {
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import SiteOrigin from '../../ui/site-origin/site-origin';
|
import SiteOrigin from '../../ui/site-origin';
|
||||||
|
import Box from '../../ui/box';
|
||||||
|
import {
|
||||||
|
FLEX_DIRECTION,
|
||||||
|
JUSTIFY_CONTENT,
|
||||||
|
} from '../../../helpers/constants/design-system';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
import SnapsAuthorshipPill from '../flask/snaps-authorship-pill';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
export default class PermissionsConnectHeader extends Component {
|
export default class PermissionsConnectHeader extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -8,13 +16,18 @@ export default class PermissionsConnectHeader extends Component {
|
|||||||
iconName: PropTypes.string.isRequired,
|
iconName: PropTypes.string.isRequired,
|
||||||
siteOrigin: PropTypes.string.isRequired,
|
siteOrigin: PropTypes.string.isRequired,
|
||||||
headerTitle: PropTypes.node,
|
headerTitle: PropTypes.node,
|
||||||
|
boxProps: PropTypes.shape({ ...Box.propTypes }),
|
||||||
headerText: PropTypes.string,
|
headerText: PropTypes.string,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
npmPackageName: PropTypes.string,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
iconUrl: null,
|
iconUrl: null,
|
||||||
headerTitle: '',
|
headerTitle: '',
|
||||||
headerText: '',
|
headerText: '',
|
||||||
|
boxProps: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
renderHeaderIcon() {
|
renderHeaderIcon() {
|
||||||
@ -28,13 +41,38 @@ export default class PermissionsConnectHeader extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { headerTitle, headerText } = this.props;
|
const {
|
||||||
|
boxProps,
|
||||||
|
headerTitle,
|
||||||
|
headerText,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
npmPackageName,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
} = this.props;
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
const npmPackageUrl = `https://www.npmjs.com/package/${npmPackageName}`;
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
return (
|
return (
|
||||||
<div className="permissions-connect-header">
|
<Box
|
||||||
|
className="permissions-connect-header"
|
||||||
|
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||||
|
justifyContent={JUSTIFY_CONTENT.CENTER}
|
||||||
|
{...boxProps}
|
||||||
|
>
|
||||||
{this.renderHeaderIcon()}
|
{this.renderHeaderIcon()}
|
||||||
<div className="permissions-connect-header__title">{headerTitle}</div>
|
<div className="permissions-connect-header__title">{headerTitle}</div>
|
||||||
|
{
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
npmPackageName ? (
|
||||||
|
<SnapsAuthorshipPill
|
||||||
|
packageName={npmPackageName}
|
||||||
|
url={npmPackageUrl}
|
||||||
|
/>
|
||||||
|
) : null
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
}
|
||||||
<div className="permissions-connect-header__subtitle">{headerText}</div>
|
<div className="permissions-connect-header__subtitle">{headerText}</div>
|
||||||
</div>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
.permission {
|
.permission {
|
||||||
@include H6;
|
@include H6;
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
border-bottom: 1px solid var(--Grey-100);
|
border-bottom: 1px solid var(--Grey-100);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,33 +1,129 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
RestrictedMethods,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
EndowmentPermissions,
|
||||||
|
PermissionNamespaces,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
} from '../../../../shared/constants/permissions';
|
||||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
import { coinTypeToProtocolName } from '../../../helpers/utils/util';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
|
const UNKNOWN_PERMISSION = Symbol('unknown');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} PermissionLabelObject
|
||||||
|
* @property {string} label - The text label.
|
||||||
|
* @property {string} leftIcon - The left icon.
|
||||||
|
* @property {string} rightIcon - The right icon.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the permission list label dictionary key for the specified permission
|
||||||
|
* name.
|
||||||
|
*
|
||||||
|
* @param {string} permissionName - The name of the permission whose key to
|
||||||
|
* retrieve.
|
||||||
|
* @param {Record<string, PermissionLabelObject>} permissionDictionary - The
|
||||||
|
* dictionary object mapping permission keys to label objects.
|
||||||
|
*/
|
||||||
|
function getPermissionKey(permissionName, permissionDictionary) {
|
||||||
|
if (Object.hasOwnProperty.call(permissionDictionary, permissionName)) {
|
||||||
|
return permissionName;
|
||||||
|
}
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
for (const namespace of Object.keys(PermissionNamespaces)) {
|
||||||
|
if (permissionName.startsWith(namespace)) {
|
||||||
|
return PermissionNamespaces[namespace];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
|
return UNKNOWN_PERMISSION;
|
||||||
|
}
|
||||||
|
|
||||||
export default function PermissionsConnectPermissionList({ permissions }) {
|
export default function PermissionsConnectPermissionList({ permissions }) {
|
||||||
const t = useI18nContext();
|
const t = useI18nContext();
|
||||||
|
|
||||||
const PERMISSION_TYPES = useMemo(() => {
|
const PERMISSION_LIST_VALUES = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
eth_accounts: {
|
[RestrictedMethods.eth_accounts]: {
|
||||||
leftIcon: 'fas fa-eye',
|
leftIcon: 'fas fa-eye',
|
||||||
label: t('eth_accounts'),
|
label: t('permission_ethereumAccounts'),
|
||||||
rightIcon: null,
|
rightIcon: null,
|
||||||
},
|
},
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
[RestrictedMethods.snap_confirm]: {
|
||||||
|
leftIcon: 'fas fa-user-check',
|
||||||
|
label: t('permission_customConfirmation'),
|
||||||
|
rightIcon: null,
|
||||||
|
},
|
||||||
|
[RestrictedMethods['snap_getBip44Entropy_*']]: (permissionName) => {
|
||||||
|
const coinType = permissionName.split('_').slice(-1);
|
||||||
|
return {
|
||||||
|
leftIcon: 'fas fa-door-open',
|
||||||
|
label: t('permission_manageBip44Keys', [
|
||||||
|
coinTypeToProtocolName(coinType) ||
|
||||||
|
`${coinType} (Unrecognized protocol)`,
|
||||||
|
]),
|
||||||
|
rightIcon: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[RestrictedMethods.snap_manageState]: {
|
||||||
|
leftIcon: 'fas fa-download',
|
||||||
|
label: t('permission_manageState'),
|
||||||
|
rightIcon: null,
|
||||||
|
},
|
||||||
|
[RestrictedMethods['wallet_snap_*']]: (permissionName) => {
|
||||||
|
const snapId = permissionName.split('_').slice(-1);
|
||||||
|
return {
|
||||||
|
leftIcon: 'fas fa-bolt',
|
||||||
|
label: t('permission_accessSnap', [snapId]),
|
||||||
|
rightIcon: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[EndowmentPermissions['endowment:network-access']]: {
|
||||||
|
leftIcon: 'fas fa-wifi',
|
||||||
|
label: t('permission_accessNetwork'),
|
||||||
|
rightIcon: null,
|
||||||
|
},
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
[UNKNOWN_PERMISSION]: (permissionName) => {
|
||||||
|
return {
|
||||||
|
leftIcon: 'fas fa-times-circle',
|
||||||
|
label: t('permission_unknown', [permissionName ?? 'undefined']),
|
||||||
|
rightIcon: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}, [t]);
|
}, [t]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="permissions-connect-permission-list">
|
<div className="permissions-connect-permission-list">
|
||||||
{Object.keys(permissions).map((permission) => (
|
{Object.keys(permissions).map((permission) => {
|
||||||
<div className="permission" key={PERMISSION_TYPES[permission].label}>
|
const listValue =
|
||||||
<i className={PERMISSION_TYPES[permission].leftIcon} />
|
PERMISSION_LIST_VALUES[
|
||||||
{PERMISSION_TYPES[permission].label}
|
getPermissionKey(permission, PERMISSION_LIST_VALUES)
|
||||||
<i className={PERMISSION_TYPES[permission].rightIcon} />
|
];
|
||||||
</div>
|
|
||||||
))}
|
const { label, leftIcon, rightIcon } =
|
||||||
|
typeof listValue === 'function' ? listValue(permission) : listValue;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="permission" key={permission}>
|
||||||
|
<i className={leftIcon} />
|
||||||
|
{label}
|
||||||
|
{rightIcon && <i className={rightIcon} />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
PermissionsConnectPermissionList.propTypes = {
|
PermissionsConnectPermissionList.propTypes = {
|
||||||
permissions: PropTypes.objectOf(PropTypes.bool).isRequired,
|
permissions: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
@ -113,7 +113,7 @@ export const DISPLAY = {
|
|||||||
LIST_ITEM: 'list-item',
|
LIST_ITEM: 'list-item',
|
||||||
};
|
};
|
||||||
|
|
||||||
const FRACTIONS = {
|
export const FRACTIONS = {
|
||||||
HALF: '1/2',
|
HALF: '1/2',
|
||||||
ONE_THIRD: '1/3',
|
ONE_THIRD: '1/3',
|
||||||
TWO_THIRDS: '2/3',
|
TWO_THIRDS: '2/3',
|
||||||
|
@ -12,6 +12,8 @@ const ALERTS_ROUTE = '/settings/alerts';
|
|||||||
const NETWORKS_ROUTE = '/settings/networks';
|
const NETWORKS_ROUTE = '/settings/networks';
|
||||||
const NETWORKS_FORM_ROUTE = '/settings/networks/form';
|
const NETWORKS_FORM_ROUTE = '/settings/networks/form';
|
||||||
const ADD_NETWORK_ROUTE = '/settings/networks/add-network';
|
const ADD_NETWORK_ROUTE = '/settings/networks/add-network';
|
||||||
|
const SNAPS_LIST_ROUTE = '/settings/snaps-list';
|
||||||
|
const SNAPS_VIEW_ROUTE = '/settings/snaps-view';
|
||||||
const CONTACT_LIST_ROUTE = '/settings/contact-list';
|
const CONTACT_LIST_ROUTE = '/settings/contact-list';
|
||||||
const CONTACT_EDIT_ROUTE = '/settings/contact-list/edit-contact';
|
const CONTACT_EDIT_ROUTE = '/settings/contact-list/edit-contact';
|
||||||
const CONTACT_ADD_ROUTE = '/settings/contact-list/add-contact';
|
const CONTACT_ADD_ROUTE = '/settings/contact-list/add-contact';
|
||||||
@ -28,6 +30,9 @@ const CONNECT_HARDWARE_ROUTE = '/new-account/connect';
|
|||||||
const SEND_ROUTE = '/send';
|
const SEND_ROUTE = '/send';
|
||||||
const CONNECT_ROUTE = '/connect';
|
const CONNECT_ROUTE = '/connect';
|
||||||
const CONNECT_CONFIRM_PERMISSIONS_ROUTE = '/confirm-permissions';
|
const CONNECT_CONFIRM_PERMISSIONS_ROUTE = '/confirm-permissions';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
const CONNECT_SNAP_INSTALL_ROUTE = '/snap-install';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
const CONNECTED_ROUTE = '/connected';
|
const CONNECTED_ROUTE = '/connected';
|
||||||
const CONNECTED_ACCOUNTS_ROUTE = '/connected/accounts';
|
const CONNECTED_ACCOUNTS_ROUTE = '/connected/accounts';
|
||||||
const SWAPS_ROUTE = '/swaps';
|
const SWAPS_ROUTE = '/swaps';
|
||||||
@ -202,6 +207,8 @@ export {
|
|||||||
SECURITY_ROUTE,
|
SECURITY_ROUTE,
|
||||||
GENERAL_ROUTE,
|
GENERAL_ROUTE,
|
||||||
ABOUT_US_ROUTE,
|
ABOUT_US_ROUTE,
|
||||||
|
SNAPS_LIST_ROUTE,
|
||||||
|
SNAPS_VIEW_ROUTE,
|
||||||
CONTACT_LIST_ROUTE,
|
CONTACT_LIST_ROUTE,
|
||||||
CONTACT_EDIT_ROUTE,
|
CONTACT_EDIT_ROUTE,
|
||||||
CONTACT_ADD_ROUTE,
|
CONTACT_ADD_ROUTE,
|
||||||
@ -213,6 +220,9 @@ export {
|
|||||||
INITIALIZE_SEED_PHRASE_INTRO_ROUTE,
|
INITIALIZE_SEED_PHRASE_INTRO_ROUTE,
|
||||||
CONNECT_ROUTE,
|
CONNECT_ROUTE,
|
||||||
CONNECT_CONFIRM_PERMISSIONS_ROUTE,
|
CONNECT_CONFIRM_PERMISSIONS_ROUTE,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
CONNECT_SNAP_INSTALL_ROUTE,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
CONNECTED_ROUTE,
|
CONNECTED_ROUTE,
|
||||||
CONNECTED_ACCOUNTS_ROUTE,
|
CONNECTED_ACCOUNTS_ROUTE,
|
||||||
PATH_NAME_MAP,
|
PATH_NAME_MAP,
|
||||||
|
@ -4,6 +4,7 @@ import BigNumber from 'bignumber.js';
|
|||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { util } from '@metamask/controllers';
|
import { util } from '@metamask/controllers';
|
||||||
|
import slip44 from '@metamask/slip44';
|
||||||
import { addHexPrefix } from '../../../app/scripts/lib/util';
|
import { addHexPrefix } from '../../../app/scripts/lib/util';
|
||||||
import {
|
import {
|
||||||
GOERLI_CHAIN_ID,
|
GOERLI_CHAIN_ID,
|
||||||
@ -580,3 +581,18 @@ export function roundToDecimalPlacesRemovingExtraZeroes(
|
|||||||
.dec(toBigNumber.dec(numberish).toFixed(numberOfDecimalPlaces))
|
.dec(toBigNumber.dec(numberish).toFixed(numberOfDecimalPlaces))
|
||||||
.toNumber();
|
.toNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the SLIP-44 protocol corresponding to the specified
|
||||||
|
* `coin_type`.
|
||||||
|
*
|
||||||
|
* @param {string | number} coinType - The SLIP-44 `coin_type` value whose name
|
||||||
|
* to retrieve.
|
||||||
|
* @returns {string | undefined} The name of the protocol if found.
|
||||||
|
*/
|
||||||
|
export function coinTypeToProtocolName(coinType) {
|
||||||
|
if (String(coinType) === '1') {
|
||||||
|
return 'Test Networks';
|
||||||
|
}
|
||||||
|
return slip44[coinType]?.name || undefined;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { getSubjectMetadata } from '../selectors';
|
import { getTargetSubjectMetadata } from '../selectors';
|
||||||
import { SUBJECT_TYPES } from '../../shared/constants/app';
|
import { SUBJECT_TYPES } from '../../shared/constants/app';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,24 +19,35 @@ import { SUBJECT_TYPES } from '../../shared/constants/app';
|
|||||||
* current origin
|
* current origin
|
||||||
*/
|
*/
|
||||||
export function useOriginMetadata(origin) {
|
export function useOriginMetadata(origin) {
|
||||||
const subjectMetadata = useSelector(getSubjectMetadata);
|
const targetSubjectMetadata = useSelector((state) =>
|
||||||
|
getTargetSubjectMetadata(state, origin),
|
||||||
|
);
|
||||||
|
|
||||||
if (!origin) {
|
if (!origin) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = new URL(origin);
|
let minimumOriginMetadata = null;
|
||||||
const minimumOriginMetadata = {
|
try {
|
||||||
host: url.host,
|
const url = new URL(origin);
|
||||||
hostname: url.hostname,
|
minimumOriginMetadata = {
|
||||||
origin,
|
host: url.host,
|
||||||
subjectType: SUBJECT_TYPES.UNKNOWN,
|
hostname: url.hostname,
|
||||||
};
|
origin,
|
||||||
|
subjectType: SUBJECT_TYPES.UNKNOWN,
|
||||||
|
};
|
||||||
|
} catch (_) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
if (subjectMetadata?.[origin]) {
|
if (targetSubjectMetadata && minimumOriginMetadata) {
|
||||||
return {
|
return {
|
||||||
...minimumOriginMetadata,
|
...minimumOriginMetadata,
|
||||||
...subjectMetadata[origin],
|
...targetSubjectMetadata,
|
||||||
};
|
};
|
||||||
|
} else if (targetSubjectMetadata) {
|
||||||
|
return targetSubjectMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
return minimumOriginMetadata;
|
return minimumOriginMetadata;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
@import 'components/confirmation-footer/confirmation-footer';
|
@import 'components/confirmation-footer/confirmation-footer';
|
||||||
|
@import 'templates/flask/snap-confirm/index';
|
||||||
|
|
||||||
.confirmation-page {
|
.confirmation-page {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -20,7 +21,6 @@
|
|||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
grid-area: content;
|
grid-area: content;
|
||||||
padding: 16px 16px 0;
|
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
& > :last-child {
|
& > :last-child {
|
||||||
|
@ -206,6 +206,7 @@ function getValues(pendingApproval, t, actions) {
|
|||||||
pendingApproval.id,
|
pendingApproval.id,
|
||||||
ethErrors.provider.userRejectedRequest(),
|
ethErrors.provider.userRejectedRequest(),
|
||||||
),
|
),
|
||||||
|
networkDisplay: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
.snap-confirm {
|
||||||
|
padding: 16px 32px;
|
||||||
|
border-top: 1px solid var(--Grey-100);
|
||||||
|
border-bottom: 1px solid var(--Grey-100);
|
||||||
|
margin: 24px 0 16px 0;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
import {
|
||||||
|
RESIZE,
|
||||||
|
TYPOGRAPHY,
|
||||||
|
} from '../../../../../helpers/constants/design-system';
|
||||||
|
|
||||||
|
function getValues(pendingApproval, t, actions) {
|
||||||
|
const { prompt, description, textAreaContent } = pendingApproval.requestData;
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
element: 'Typography',
|
||||||
|
key: 'title',
|
||||||
|
children: prompt,
|
||||||
|
props: {
|
||||||
|
variant: TYPOGRAPHY.H3,
|
||||||
|
align: 'center',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
boxProps: {
|
||||||
|
margin: [0, 0, 4],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...(description
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
element: 'Typography',
|
||||||
|
key: 'subtitle',
|
||||||
|
children: description,
|
||||||
|
props: {
|
||||||
|
variant: TYPOGRAPHY.H6,
|
||||||
|
align: 'center',
|
||||||
|
boxProps: {
|
||||||
|
margin: [0, 0, 4],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(textAreaContent
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
element: 'div',
|
||||||
|
key: 'text-area',
|
||||||
|
children: {
|
||||||
|
element: 'TextArea',
|
||||||
|
props: {
|
||||||
|
// TODO(ritave): Terrible hard-coded height hack. Fixing this to adjust automatically to current window height would
|
||||||
|
// mean allowing template compoments to change global css, and since the intended use of the template
|
||||||
|
// renderer was to allow users to build their own UIs, this would be a big no-no.
|
||||||
|
height: '238px',
|
||||||
|
value: textAreaContent,
|
||||||
|
readOnly: true,
|
||||||
|
resize: RESIZE.VERTICAL,
|
||||||
|
scrollable: true,
|
||||||
|
className: 'text',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
className: 'snap-confirm',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
{
|
||||||
|
element: 'Typography',
|
||||||
|
key: 'only-interact-with-entities-you-trust',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
element: 'span',
|
||||||
|
key: 'only-connect-trust',
|
||||||
|
children: `${t('onlyConnectTrust')} `,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
element: 'a',
|
||||||
|
children: t('learnMore'),
|
||||||
|
key: 'learnMore-a-href',
|
||||||
|
props: {
|
||||||
|
href:
|
||||||
|
'https://metamask.zendesk.com/hc/en-us/articles/4405506066331-User-guide-Dapps',
|
||||||
|
target: '__blank',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
variant: TYPOGRAPHY.H7,
|
||||||
|
align: 'center',
|
||||||
|
boxProps: {
|
||||||
|
margin: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
approvalText: t('approveButtonText'),
|
||||||
|
cancelText: t('reject'),
|
||||||
|
onApprove: () => actions.resolvePendingApproval(pendingApproval.id, true),
|
||||||
|
onCancel: () => actions.resolvePendingApproval(pendingApproval.id, false),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const snapConfirm = {
|
||||||
|
getValues,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default snapConfirm;
|
@ -6,10 +6,16 @@ import {
|
|||||||
} from '../../../store/actions';
|
} from '../../../store/actions';
|
||||||
import addEthereumChain from './add-ethereum-chain';
|
import addEthereumChain from './add-ethereum-chain';
|
||||||
import switchEthereumChain from './switch-ethereum-chain';
|
import switchEthereumChain from './switch-ethereum-chain';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
import snapConfirm from './flask/snap-confirm/snap-confirm';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
const APPROVAL_TEMPLATES = {
|
const APPROVAL_TEMPLATES = {
|
||||||
[MESSAGE_TYPE.ADD_ETHEREUM_CHAIN]: addEthereumChain,
|
[MESSAGE_TYPE.ADD_ETHEREUM_CHAIN]: addEthereumChain,
|
||||||
[MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN]: switchEthereumChain,
|
[MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN]: switchEthereumChain,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
[MESSAGE_TYPE.SNAP_CONFIRM]: snapConfirm,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TEMPLATED_CONFIRMATION_MESSAGE_TYPES = Object.keys(
|
export const TEMPLATED_CONFIRMATION_MESSAGE_TYPES = Object.keys(
|
||||||
|
@ -85,6 +85,7 @@ function getValues(pendingApproval, t, actions) {
|
|||||||
pendingApproval.id,
|
pendingApproval.id,
|
||||||
ethErrors.provider.userRejectedRequest(),
|
ethErrors.provider.userRejectedRequest(),
|
||||||
),
|
),
|
||||||
|
networkDisplay: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,13 @@ import WhatsNewPopup from '../../components/app/whats-new-popup';
|
|||||||
import RecoveryPhraseReminder from '../../components/app/recovery-phrase-reminder';
|
import RecoveryPhraseReminder from '../../components/app/recovery-phrase-reminder';
|
||||||
import ActionableMessage from '../../components/ui/actionable-message/actionable-message';
|
import ActionableMessage from '../../components/ui/actionable-message/actionable-message';
|
||||||
import Typography from '../../components/ui/typography/typography';
|
import Typography from '../../components/ui/typography/typography';
|
||||||
import { TYPOGRAPHY, FONT_WEIGHT } from '../../helpers/constants/design-system';
|
import {
|
||||||
|
TYPOGRAPHY,
|
||||||
|
FONT_WEIGHT,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
COLORS,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
} from '../../helpers/constants/design-system';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ASSET_ROUTE,
|
ASSET_ROUTE,
|
||||||
@ -105,6 +111,11 @@ export default class Home extends PureComponent {
|
|||||||
showWhatsNewPopup: PropTypes.bool.isRequired,
|
showWhatsNewPopup: PropTypes.bool.isRequired,
|
||||||
hideWhatsNewPopup: PropTypes.func.isRequired,
|
hideWhatsNewPopup: PropTypes.func.isRequired,
|
||||||
notificationsToShow: PropTypes.bool.isRequired,
|
notificationsToShow: PropTypes.bool.isRequired,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
errorsToShow: PropTypes.object.isRequired,
|
||||||
|
shouldShowErrors: PropTypes.bool.isRequired,
|
||||||
|
removeSnapError: PropTypes.func.isRequired,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
showRecoveryPhraseReminder: PropTypes.bool.isRequired,
|
showRecoveryPhraseReminder: PropTypes.bool.isRequired,
|
||||||
setRecoveryPhraseReminderHasBeenShown: PropTypes.func.isRequired,
|
setRecoveryPhraseReminderHasBeenShown: PropTypes.func.isRequired,
|
||||||
setRecoveryPhraseReminderLastShown: PropTypes.func.isRequired,
|
setRecoveryPhraseReminderLastShown: PropTypes.func.isRequired,
|
||||||
@ -242,6 +253,11 @@ export default class Home extends PureComponent {
|
|||||||
setWeb3ShimUsageAlertDismissed,
|
setWeb3ShimUsageAlertDismissed,
|
||||||
originOfCurrentTab,
|
originOfCurrentTab,
|
||||||
disableWeb3ShimUsageAlert,
|
disableWeb3ShimUsageAlert,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
removeSnapError,
|
||||||
|
errorsToShow,
|
||||||
|
shouldShowErrors,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
infuraBlocked,
|
infuraBlocked,
|
||||||
newNetworkAdded,
|
newNetworkAdded,
|
||||||
setNewNetworkAdded,
|
setNewNetworkAdded,
|
||||||
@ -250,6 +266,43 @@ export default class Home extends PureComponent {
|
|||||||
} = this.props;
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<MultipleNotifications>
|
<MultipleNotifications>
|
||||||
|
{
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
shouldShowErrors
|
||||||
|
? Object.entries(errorsToShow).map(([errorId, error]) => {
|
||||||
|
return (
|
||||||
|
<HomeNotification
|
||||||
|
classNames={['home__error-message']}
|
||||||
|
infoText={error.data.snapId}
|
||||||
|
descriptionText={
|
||||||
|
<>
|
||||||
|
<Typography
|
||||||
|
color={COLORS.UI1}
|
||||||
|
variant={TYPOGRAPHY.H5}
|
||||||
|
fontWeight={FONT_WEIGHT.NORMAL}
|
||||||
|
>
|
||||||
|
{t('somethingWentWrong')}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
color={COLORS.UI1}
|
||||||
|
variant={TYPOGRAPHY.H7}
|
||||||
|
fontWeight={FONT_WEIGHT.NORMAL}
|
||||||
|
>
|
||||||
|
{t('snapError', [error.message, error.code])}
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
onIgnore={async () => {
|
||||||
|
await removeSnapError(errorId);
|
||||||
|
}}
|
||||||
|
ignoreText="Dismiss"
|
||||||
|
key="home-error-message"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
: null
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
}
|
||||||
{newCollectibleAddedMessage ? (
|
{newCollectibleAddedMessage ? (
|
||||||
<ActionableMessage
|
<ActionableMessage
|
||||||
type={newCollectibleAddedMessage === 'success' ? 'info' : 'warning'}
|
type={newCollectibleAddedMessage === 'success' ? 'info' : 'warning'}
|
||||||
|
@ -35,6 +35,9 @@ import {
|
|||||||
setRecoveryPhraseReminderLastShown,
|
setRecoveryPhraseReminderLastShown,
|
||||||
setNewNetworkAdded,
|
setNewNetworkAdded,
|
||||||
setNewCollectibleAddedMessage,
|
setNewCollectibleAddedMessage,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
removeSnapError,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
} from '../../store/actions';
|
} from '../../store/actions';
|
||||||
import { setThreeBoxLastUpdated, hideWhatsNewPopup } from '../../ducks/app/app';
|
import { setThreeBoxLastUpdated, hideWhatsNewPopup } from '../../ducks/app/app';
|
||||||
import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask';
|
import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask';
|
||||||
@ -118,6 +121,10 @@ const mapStateToProps = (state) => {
|
|||||||
pendingConfirmations,
|
pendingConfirmations,
|
||||||
infuraBlocked: getInfuraBlocked(state),
|
infuraBlocked: getInfuraBlocked(state),
|
||||||
notificationsToShow: getSortedNotificationsToShow(state).length > 0,
|
notificationsToShow: getSortedNotificationsToShow(state).length > 0,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
errorsToShow: metamask.snapErrors,
|
||||||
|
shouldShowErrors: Object.entries(metamask.snapErrors || []).length > 0,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
showWhatsNewPopup: getShowWhatsNewPopup(state),
|
showWhatsNewPopup: getShowWhatsNewPopup(state),
|
||||||
showRecoveryPhraseReminder: getShowRecoveryPhraseReminder(state),
|
showRecoveryPhraseReminder: getShowRecoveryPhraseReminder(state),
|
||||||
seedPhraseBackedUp,
|
seedPhraseBackedUp,
|
||||||
@ -140,6 +147,9 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
removeSnapError: async (id) => await removeSnapError(id),
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
restoreFromThreeBox: (address) => dispatch(restoreFromThreeBox(address)),
|
restoreFromThreeBox: (address) => dispatch(restoreFromThreeBox(address)),
|
||||||
setShowRestorePromptToFalse: () => dispatch(setShowRestorePromptToFalse()),
|
setShowRestorePromptToFalse: () => dispatch(setShowRestorePromptToFalse()),
|
||||||
setConnectedStatusPopoverHasBeenShown: () =>
|
setConnectedStatusPopoverHasBeenShown: () =>
|
||||||
|
@ -152,4 +152,8 @@
|
|||||||
background: none;
|
background: none;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__error-message {
|
||||||
|
left: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
1
ui/pages/permissions-connect/flask/snap-install/index.js
Normal file
1
ui/pages/permissions-connect/flask/snap-install/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './snap-install';
|
28
ui/pages/permissions-connect/flask/snap-install/index.scss
Normal file
28
ui/pages/permissions-connect/flask/snap-install/index.scss
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
.snap-install {
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
.permissions-connect-permission-list {
|
||||||
|
padding: 0 24px;
|
||||||
|
|
||||||
|
.permission {
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-code {
|
||||||
|
@include H7;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
color: var(--ui-4);
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: var(--primary-blue);
|
||||||
|
margin-inline-start: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-container__footer {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
153
ui/pages/permissions-connect/flask/snap-install/snap-install.js
Normal file
153
ui/pages/permissions-connect/flask/snap-install/snap-install.js
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
|
import { PageContainerFooter } from '../../../../components/ui/page-container';
|
||||||
|
import PermissionsConnectPermissionList from '../../../../components/app/permissions-connect-permission-list';
|
||||||
|
import PermissionsConnectFooter from '../../../../components/app/permissions-connect-footer';
|
||||||
|
import PermissionConnectHeader from '../../../../components/app/permissions-connect-header';
|
||||||
|
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
||||||
|
import SnapInstallWarning from '../../../../components/app/flask/snap-install-warning';
|
||||||
|
import Box from '../../../../components/ui/box/box';
|
||||||
|
import {
|
||||||
|
ALIGN_ITEMS,
|
||||||
|
BLOCK_SIZES,
|
||||||
|
BORDER_STYLE,
|
||||||
|
FLEX_DIRECTION,
|
||||||
|
JUSTIFY_CONTENT,
|
||||||
|
TYPOGRAPHY,
|
||||||
|
} from '../../../../helpers/constants/design-system';
|
||||||
|
import Typography from '../../../../components/ui/typography';
|
||||||
|
|
||||||
|
export default function SnapInstall({
|
||||||
|
request,
|
||||||
|
approveSnapInstall,
|
||||||
|
rejectSnapInstall,
|
||||||
|
targetSubjectMetadata,
|
||||||
|
}) {
|
||||||
|
const t = useI18nContext();
|
||||||
|
|
||||||
|
const [isShowingWarning, setIsShowingWarning] = useState(false);
|
||||||
|
|
||||||
|
const onCancel = useCallback(() => rejectSnapInstall(request.metadata.id), [
|
||||||
|
request,
|
||||||
|
rejectSnapInstall,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const onSubmit = useCallback(() => approveSnapInstall(request), [
|
||||||
|
request,
|
||||||
|
approveSnapInstall,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const npmId = useMemo(() => {
|
||||||
|
if (!targetSubjectMetadata.origin.startsWith('npm:')) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return targetSubjectMetadata.origin.substring(4);
|
||||||
|
}, [targetSubjectMetadata]);
|
||||||
|
|
||||||
|
const shouldShowWarning = useMemo(
|
||||||
|
() =>
|
||||||
|
Boolean(
|
||||||
|
request.permissions &&
|
||||||
|
Object.keys(request.permissions).find((v) =>
|
||||||
|
v.startsWith('snap_getBip44Entropy_'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[request.permissions],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
className="page-container snap-install"
|
||||||
|
justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN}
|
||||||
|
height={BLOCK_SIZES.FULL}
|
||||||
|
borderStyle={BORDER_STYLE.NONE}
|
||||||
|
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
className="headers"
|
||||||
|
alignItems={ALIGN_ITEMS.CENTER}
|
||||||
|
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||||
|
>
|
||||||
|
<PermissionConnectHeader
|
||||||
|
icon={targetSubjectMetadata.iconUrl}
|
||||||
|
iconName={targetSubjectMetadata.name}
|
||||||
|
headerTitle={t('snapInstall')}
|
||||||
|
headerText={null} // TODO(ritave): Add header text when snaps support description
|
||||||
|
siteOrigin={targetSubjectMetadata.origin}
|
||||||
|
npmPackageName={npmId}
|
||||||
|
boxProps={{ alignItems: ALIGN_ITEMS.CENTER }}
|
||||||
|
/>
|
||||||
|
<Typography></Typography>
|
||||||
|
<Box
|
||||||
|
className="snap-requests-permission"
|
||||||
|
padding={4}
|
||||||
|
tag={TYPOGRAPHY.H7}
|
||||||
|
>
|
||||||
|
<span>{t('snapRequestsPermission')}</span>
|
||||||
|
</Box>
|
||||||
|
<PermissionsConnectPermissionList
|
||||||
|
permissions={request.permissions || {}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
className="footers"
|
||||||
|
alignItems={ALIGN_ITEMS.CENTER}
|
||||||
|
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||||
|
>
|
||||||
|
{targetSubjectMetadata.sourceCode ? (
|
||||||
|
<>
|
||||||
|
<div className="source-code">
|
||||||
|
<div className="text">{t('areYouDeveloper')}</div>
|
||||||
|
<div
|
||||||
|
className="link"
|
||||||
|
onClick={() =>
|
||||||
|
global.platform.openTab({
|
||||||
|
url: targetSubjectMetadata.sourceCode,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t('openSourceCode')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Box paddingBottom={4}>
|
||||||
|
<PermissionsConnectFooter />
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Box className="snap-install__footer--no-source-code" paddingTop={4}>
|
||||||
|
<PermissionsConnectFooter />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<PageContainerFooter
|
||||||
|
cancelButtonType="default"
|
||||||
|
onCancel={onCancel}
|
||||||
|
cancelText={t('cancel')}
|
||||||
|
onSubmit={
|
||||||
|
shouldShowWarning ? () => setIsShowingWarning(true) : onSubmit
|
||||||
|
}
|
||||||
|
submitText={t('approveAndInstall')}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
{isShowingWarning && (
|
||||||
|
<SnapInstallWarning
|
||||||
|
onCancel={() => setIsShowingWarning(false)}
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
snapName={targetSubjectMetadata.name}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SnapInstall.propTypes = {
|
||||||
|
request: PropTypes.object.isRequired,
|
||||||
|
approveSnapInstall: PropTypes.func.isRequired,
|
||||||
|
rejectSnapInstall: PropTypes.func.isRequired,
|
||||||
|
targetSubjectMetadata: PropTypes.shape({
|
||||||
|
iconUrl: PropTypes.string,
|
||||||
|
name: PropTypes.string,
|
||||||
|
origin: PropTypes.string.isRequired,
|
||||||
|
sourceCode: PropTypes.string,
|
||||||
|
}).isRequired,
|
||||||
|
};
|
@ -1,4 +1,5 @@
|
|||||||
@import 'choose-account/index';
|
@import 'choose-account/index';
|
||||||
|
@import 'flask/snap-install/index';
|
||||||
@import 'redirect/index';
|
@import 'redirect/index';
|
||||||
|
|
||||||
.permissions-connect {
|
.permissions-connect {
|
||||||
|
@ -8,6 +8,9 @@ import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
|
|||||||
import PermissionPageContainer from '../../components/app/permission-page-container';
|
import PermissionPageContainer from '../../components/app/permission-page-container';
|
||||||
import ChooseAccount from './choose-account';
|
import ChooseAccount from './choose-account';
|
||||||
import PermissionsRedirect from './redirect';
|
import PermissionsRedirect from './redirect';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
import SnapInstall from './flask/snap-install';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
const APPROVE_TIMEOUT = MILLISECOND * 1200;
|
const APPROVE_TIMEOUT = MILLISECOND * 1200;
|
||||||
|
|
||||||
@ -30,6 +33,11 @@ export default class PermissionConnect extends Component {
|
|||||||
history: PropTypes.object.isRequired,
|
history: PropTypes.object.isRequired,
|
||||||
connectPath: PropTypes.string.isRequired,
|
connectPath: PropTypes.string.isRequired,
|
||||||
confirmPermissionPath: PropTypes.string.isRequired,
|
confirmPermissionPath: PropTypes.string.isRequired,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
snapInstallPath: PropTypes.string.isRequired,
|
||||||
|
isSnap: PropTypes.bool.isRequired,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
totalPages: PropTypes.string.isRequired,
|
||||||
page: PropTypes.string.isRequired,
|
page: PropTypes.string.isRequired,
|
||||||
targetSubjectMetadata: PropTypes.shape({
|
targetSubjectMetadata: PropTypes.shape({
|
||||||
extensionId: PropTypes.string,
|
extensionId: PropTypes.string,
|
||||||
@ -38,6 +46,7 @@ export default class PermissionConnect extends Component {
|
|||||||
origin: PropTypes.string.isRequired,
|
origin: PropTypes.string.isRequired,
|
||||||
subjectType: PropTypes.string,
|
subjectType: PropTypes.string,
|
||||||
}),
|
}),
|
||||||
|
isRequestingAccounts: PropTypes.bool.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@ -77,10 +86,17 @@ export default class PermissionConnect extends Component {
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const {
|
const {
|
||||||
|
connectPath,
|
||||||
|
confirmPermissionPath,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
snapInstallPath,
|
||||||
|
isSnap,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
getCurrentWindowTab,
|
getCurrentWindowTab,
|
||||||
getRequestAccountTabIds,
|
getRequestAccountTabIds,
|
||||||
permissionsRequest,
|
permissionsRequest,
|
||||||
history,
|
history,
|
||||||
|
isRequestingAccounts,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
getCurrentWindowTab();
|
getCurrentWindowTab();
|
||||||
getRequestAccountTabIds();
|
getRequestAccountTabIds();
|
||||||
@ -94,6 +110,18 @@ export default class PermissionConnect extends Component {
|
|||||||
if (environmentType === ENVIRONMENT_TYPE_NOTIFICATION) {
|
if (environmentType === ENVIRONMENT_TYPE_NOTIFICATION) {
|
||||||
window.addEventListener('beforeunload', this.beforeUnload);
|
window.addEventListener('beforeunload', this.beforeUnload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (history.location.pathname === connectPath && !isRequestingAccounts) {
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
if (isSnap) {
|
||||||
|
history.push(snapInstallPath);
|
||||||
|
} else {
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
history.push(confirmPermissionPath);
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDerivedStateFromProps(props, state) {
|
static getDerivedStateFromProps(props, state) {
|
||||||
@ -165,11 +193,11 @@ export default class PermissionConnect extends Component {
|
|||||||
|
|
||||||
renderTopBar() {
|
renderTopBar() {
|
||||||
const { redirecting } = this.state;
|
const { redirecting } = this.state;
|
||||||
const { page } = this.props;
|
const { page, isRequestingAccounts, totalPages } = this.props;
|
||||||
const { t } = this.context;
|
const { t } = this.context;
|
||||||
return redirecting ? null : (
|
return redirecting ? null : (
|
||||||
<div className="permissions-connect__top-bar">
|
<div className="permissions-connect__top-bar">
|
||||||
{page === '2' ? (
|
{page === '2' && isRequestingAccounts ? (
|
||||||
<div
|
<div
|
||||||
className="permissions-connect__back"
|
className="permissions-connect__back"
|
||||||
onClick={() => this.goBack()}
|
onClick={() => this.goBack()}
|
||||||
@ -178,9 +206,11 @@ export default class PermissionConnect extends Component {
|
|||||||
{t('back')}
|
{t('back')}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="permissions-connect__page-count">
|
{isRequestingAccounts ? (
|
||||||
{t('xOfY', [page, '2'])}
|
<div className="permissions-connect__page-count">
|
||||||
</div>
|
{t('xOfY', [page, totalPages])}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -197,6 +227,9 @@ export default class PermissionConnect extends Component {
|
|||||||
permissionsRequestId,
|
permissionsRequestId,
|
||||||
connectPath,
|
connectPath,
|
||||||
confirmPermissionPath,
|
confirmPermissionPath,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
snapInstallPath,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {
|
const {
|
||||||
selectedAccountAddresses,
|
selectedAccountAddresses,
|
||||||
@ -257,6 +290,29 @@ export default class PermissionConnect extends Component {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
{
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
}
|
||||||
|
<Route
|
||||||
|
path={snapInstallPath}
|
||||||
|
exact
|
||||||
|
render={() => (
|
||||||
|
<SnapInstall
|
||||||
|
request={permissionsRequest || {}}
|
||||||
|
approveSnapInstall={(...args) => {
|
||||||
|
approvePermissionsRequest(...args);
|
||||||
|
this.redirect(true);
|
||||||
|
}}
|
||||||
|
rejectSnapInstall={(requestId) =>
|
||||||
|
this.cancelPermissionsRequest(requestId)
|
||||||
|
}
|
||||||
|
targetSubjectMetadata={targetSubjectMetadata}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
}
|
||||||
</Switch>
|
</Switch>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {
|
import {
|
||||||
getPermissionsRequests,
|
|
||||||
getAccountsWithLabels,
|
getAccountsWithLabels,
|
||||||
getLastConnectedInfo,
|
getLastConnectedInfo,
|
||||||
getSubjectMetadata,
|
getPermissionsRequests,
|
||||||
getSelectedAddress,
|
getSelectedAddress,
|
||||||
|
getTargetSubjectMetadata,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
import { getNativeCurrency } from '../../ducks/metamask/metamask';
|
import { getNativeCurrency } from '../../ducks/metamask/metamask';
|
||||||
|
|
||||||
import { formatDate } from '../../helpers/utils/util';
|
import { formatDate, getURLHostName } from '../../helpers/utils/util';
|
||||||
import {
|
import {
|
||||||
approvePermissionsRequest,
|
approvePermissionsRequest,
|
||||||
rejectPermissionsRequest,
|
rejectPermissionsRequest,
|
||||||
@ -20,6 +20,9 @@ import {
|
|||||||
import {
|
import {
|
||||||
CONNECT_ROUTE,
|
CONNECT_ROUTE,
|
||||||
CONNECT_CONFIRM_PERMISSIONS_ROUTE,
|
CONNECT_CONFIRM_PERMISSIONS_ROUTE,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
CONNECT_SNAP_INSTALL_ROUTE,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
} from '../../helpers/constants/routes';
|
} from '../../helpers/constants/routes';
|
||||||
import { SUBJECT_TYPES } from '../../../shared/constants/app';
|
import { SUBJECT_TYPES } from '../../../shared/constants/app';
|
||||||
import PermissionApproval from './permissions-connect.component';
|
import PermissionApproval from './permissions-connect.component';
|
||||||
@ -38,27 +41,25 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
(req) => req.metadata.id === permissionsRequestId,
|
(req) => req.metadata.id === permissionsRequestId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isRequestingAccounts = Boolean(
|
||||||
|
permissionsRequest?.permissions.eth_accounts,
|
||||||
|
);
|
||||||
|
|
||||||
const { metadata = {} } = permissionsRequest || {};
|
const { metadata = {} } = permissionsRequest || {};
|
||||||
const { origin } = metadata;
|
const { origin } = metadata;
|
||||||
const nativeCurrency = getNativeCurrency(state);
|
const nativeCurrency = getNativeCurrency(state);
|
||||||
|
|
||||||
const subjectMetadata = getSubjectMetadata(state);
|
const targetSubjectMetadata = getTargetSubjectMetadata(state, origin) ?? {
|
||||||
|
name: getURLHostName(origin) || origin,
|
||||||
|
origin,
|
||||||
|
iconUrl: null,
|
||||||
|
extensionId: null,
|
||||||
|
subjectType: SUBJECT_TYPES.UNKNOWN,
|
||||||
|
};
|
||||||
|
|
||||||
let targetSubjectMetadata = null;
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
if (origin) {
|
const isSnap = targetSubjectMetadata.subjectType === SUBJECT_TYPES.SNAP;
|
||||||
if (subjectMetadata[origin]) {
|
///: END:ONLY_INCLUDE_IN
|
||||||
targetSubjectMetadata = subjectMetadata[origin];
|
|
||||||
} else {
|
|
||||||
const targetUrl = new URL(origin);
|
|
||||||
targetSubjectMetadata = {
|
|
||||||
name: targetUrl.hostname,
|
|
||||||
origin,
|
|
||||||
iconUrl: null,
|
|
||||||
extensionId: null,
|
|
||||||
subjectType: SUBJECT_TYPES.UNKNOWN,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const accountsWithLabels = getAccountsWithLabels(state);
|
const accountsWithLabels = getAccountsWithLabels(state);
|
||||||
|
|
||||||
@ -74,17 +75,35 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
|
|
||||||
const connectPath = `${CONNECT_ROUTE}/${permissionsRequestId}`;
|
const connectPath = `${CONNECT_ROUTE}/${permissionsRequestId}`;
|
||||||
const confirmPermissionPath = `${CONNECT_ROUTE}/${permissionsRequestId}${CONNECT_CONFIRM_PERMISSIONS_ROUTE}`;
|
const confirmPermissionPath = `${CONNECT_ROUTE}/${permissionsRequestId}${CONNECT_CONFIRM_PERMISSIONS_ROUTE}`;
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
const snapInstallPath = `${CONNECT_ROUTE}/${permissionsRequestId}${CONNECT_SNAP_INSTALL_ROUTE}`;
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
|
let totalPages = 1 + isRequestingAccounts;
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
totalPages += isSnap;
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
totalPages = totalPages.toString();
|
||||||
|
|
||||||
let page = '';
|
let page = '';
|
||||||
if (pathname === connectPath) {
|
if (pathname === connectPath) {
|
||||||
page = '1';
|
page = '1';
|
||||||
} else if (pathname === confirmPermissionPath) {
|
} else if (pathname === confirmPermissionPath) {
|
||||||
page = '2';
|
page = isRequestingAccounts ? '2' : '1';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
} else if (pathname === snapInstallPath) {
|
||||||
|
page = isRequestingAccounts ? '3' : '2';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Incorrect path for permissions-connect component');
|
throw new Error('Incorrect path for permissions-connect component');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
isRequestingAccounts,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
isSnap,
|
||||||
|
snapInstallPath,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
permissionsRequest,
|
permissionsRequest,
|
||||||
permissionsRequestId,
|
permissionsRequestId,
|
||||||
accounts: accountsWithLabels,
|
accounts: accountsWithLabels,
|
||||||
@ -96,6 +115,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
lastConnectedInfo,
|
lastConnectedInfo,
|
||||||
connectPath,
|
connectPath,
|
||||||
confirmPermissionPath,
|
confirmPermissionPath,
|
||||||
|
totalPages,
|
||||||
page,
|
page,
|
||||||
targetSubjectMetadata,
|
targetSubjectMetadata,
|
||||||
};
|
};
|
||||||
|
1
ui/pages/settings/flask/snaps-list-tab/index.js
Normal file
1
ui/pages/settings/flask/snaps-list-tab/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './snap-list-tab';
|
21
ui/pages/settings/flask/snaps-list-tab/index.scss
Normal file
21
ui/pages/settings/flask/snaps-list-tab/index.scss
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
.snap-list-tab {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
&__wrapper {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
padding: 12px 18px;
|
||||||
|
|
||||||
|
@media screen and (min-width: $break-large) {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.snap-settings-card {
|
||||||
|
margin: 8px 0;
|
||||||
|
max-width: 344px;
|
||||||
|
}
|
||||||
|
}
|
94
ui/pages/settings/flask/snaps-list-tab/snap-list-tab.js
Normal file
94
ui/pages/settings/flask/snaps-list-tab/snap-list-tab.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import SnapSettingsCard from '../../../../components/app/flask/snap-settings-card';
|
||||||
|
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
||||||
|
import Typography from '../../../../components/ui/typography/typography';
|
||||||
|
import {
|
||||||
|
TYPOGRAPHY,
|
||||||
|
COLORS,
|
||||||
|
FLEX_DIRECTION,
|
||||||
|
JUSTIFY_CONTENT,
|
||||||
|
ALIGN_ITEMS,
|
||||||
|
} from '../../../../helpers/constants/design-system';
|
||||||
|
import Box from '../../../../components/ui/box';
|
||||||
|
import { SNAPS_VIEW_ROUTE } from '../../../../helpers/constants/routes';
|
||||||
|
import { disableSnap, enableSnap } from '../../../../store/actions';
|
||||||
|
import { getSnaps } from '../../../../selectors';
|
||||||
|
|
||||||
|
const SnapListTab = () => {
|
||||||
|
const t = useI18nContext();
|
||||||
|
const history = useHistory();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const snaps = useSelector(getSnaps);
|
||||||
|
const onClick = (snap) => {
|
||||||
|
const route = `${SNAPS_VIEW_ROUTE}/${window.btoa(
|
||||||
|
unescape(encodeURIComponent(snap.id)),
|
||||||
|
)}`;
|
||||||
|
history.push(route);
|
||||||
|
};
|
||||||
|
const onToggle = (snap) => {
|
||||||
|
if (snap.enabled) {
|
||||||
|
dispatch(disableSnap(snap.id));
|
||||||
|
} else {
|
||||||
|
dispatch(enableSnap(snap.id));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="snap-list-tab">
|
||||||
|
{Object.entries(snaps).length ? (
|
||||||
|
<div className="snap-list-tab__body">
|
||||||
|
<Box display="flex" flexDirection={FLEX_DIRECTION.COLUMN}>
|
||||||
|
<Typography variant={TYPOGRAPHY.H5} marginBottom={2}>
|
||||||
|
{t('expandExperience')}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
variant={TYPOGRAPHY.H6}
|
||||||
|
color={COLORS.UI4}
|
||||||
|
marginBottom={2}
|
||||||
|
>
|
||||||
|
{t('manageSnaps')}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<div className="snap-list-tab__wrapper">
|
||||||
|
{Object.entries(snaps).map(([key, snap]) => {
|
||||||
|
return (
|
||||||
|
<SnapSettingsCard
|
||||||
|
className="snap-settings-card"
|
||||||
|
isEnabled={snap.enabled}
|
||||||
|
key={key}
|
||||||
|
onToggle={() => {
|
||||||
|
onToggle(snap);
|
||||||
|
}}
|
||||||
|
description={snap.manifest.description}
|
||||||
|
url={snap.id}
|
||||||
|
name={snap.manifest.proposedName}
|
||||||
|
status={snap.status}
|
||||||
|
version={snap.version}
|
||||||
|
onClick={() => {
|
||||||
|
onClick(snap);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Box
|
||||||
|
className="snap-list-tab__container--no-snaps"
|
||||||
|
width="full"
|
||||||
|
height="full"
|
||||||
|
justifyContent={JUSTIFY_CONTENT.CENTER}
|
||||||
|
alignItems={ALIGN_ITEMS.CENTER}
|
||||||
|
>
|
||||||
|
<Typography variant={TYPOGRAPHY.H4} color={COLORS.UI4}>
|
||||||
|
<span>{t('noSnaps')}</span>
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SnapListTab;
|
@ -0,0 +1,50 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import configureStore from '../../../../store/store';
|
||||||
|
import testData from '../../../../../.storybook/test-data';
|
||||||
|
import SnapListTab from './snap-list-tab';
|
||||||
|
|
||||||
|
// Using Test Data For Redux
|
||||||
|
const store = configureStore(testData);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Pages/Settings/SnapListTab',
|
||||||
|
id: __filename,
|
||||||
|
decorators: [(story) => <Provider store={store}>{story()}</Provider>],
|
||||||
|
argTypes: {
|
||||||
|
onToggle: {
|
||||||
|
action: 'onToggle',
|
||||||
|
},
|
||||||
|
onRemove: {
|
||||||
|
action: 'onRemove',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export const DefaultStory = (args) => {
|
||||||
|
const state = store.getState();
|
||||||
|
const [viewingSnap, setViewingSnap] = useState();
|
||||||
|
const [snap, setSnap] = useState();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SnapListTab
|
||||||
|
{...args}
|
||||||
|
snaps={state.metamask.snaps}
|
||||||
|
viewingSnap={viewingSnap}
|
||||||
|
currentSnap={snap}
|
||||||
|
onToggle={args.onToggle}
|
||||||
|
onRemove={args.onRemove}
|
||||||
|
onClick={(_, s) => {
|
||||||
|
setSnap(s);
|
||||||
|
setViewingSnap(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const state = store.getState();
|
||||||
|
DefaultStory.args = {
|
||||||
|
snaps: state.metamask.snaps,
|
||||||
|
viewingSnap: false,
|
||||||
|
};
|
||||||
|
DefaultStory.storyName = 'Default';
|
1
ui/pages/settings/flask/view-snap/index.js
Normal file
1
ui/pages/settings/flask/view-snap/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './view-snap';
|
114
ui/pages/settings/flask/view-snap/index.scss
Normal file
114
ui/pages/settings/flask/view-snap/index.scss
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
.view-snap {
|
||||||
|
padding: 12px 18px;
|
||||||
|
|
||||||
|
@media screen and (min-width: $break-large) {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__subheader {
|
||||||
|
@include H4;
|
||||||
|
|
||||||
|
padding: 16px 4px;
|
||||||
|
border-bottom: 1px solid var(--alto);
|
||||||
|
margin-right: 24px;
|
||||||
|
height: 72px;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
|
||||||
|
@media screen and (max-width: $break-small) {
|
||||||
|
margin-right: 0;
|
||||||
|
padding: 0 0 16px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
height: max-content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
@media screen and (max-width: $break-small) {
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__pill-toggle-container {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
@media screen and (max-width: $break-small) {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__pill-container {
|
||||||
|
@media screen and (max-width: $break-small) {
|
||||||
|
padding-left: 0;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__toggle-container {
|
||||||
|
@media screen and (max-width: $break-small) {
|
||||||
|
padding-left: 0;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content-container {
|
||||||
|
@media screen and (max-width: $break-small) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__section {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-bottom: 1px solid var(--Grey-100);
|
||||||
|
padding-bottom: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
@media screen and (max-width: $break-small) {
|
||||||
|
height: initial;
|
||||||
|
padding: 5px 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.connected-sites-list__content-row {
|
||||||
|
border-top: none;
|
||||||
|
border-bottom: 1px solid var(--ui-2);
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__permission-list {
|
||||||
|
padding-bottom: 0;
|
||||||
|
|
||||||
|
.permission {
|
||||||
|
padding-top: 16px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__remove-button {
|
||||||
|
max-width: 175px;
|
||||||
|
|
||||||
|
@media screen and (max-width: $break-small) {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
171
ui/pages/settings/flask/view-snap/view-snap.js
Normal file
171
ui/pages/settings/flask/view-snap/view-snap.js
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { useHistory, useLocation } from 'react-router-dom';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import Button from '../../../../components/ui/button';
|
||||||
|
import Typography from '../../../../components/ui/typography';
|
||||||
|
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
||||||
|
import {
|
||||||
|
TYPOGRAPHY,
|
||||||
|
COLORS,
|
||||||
|
TEXT_ALIGN,
|
||||||
|
FRACTIONS,
|
||||||
|
} from '../../../../helpers/constants/design-system';
|
||||||
|
import SnapsAuthorshipPill from '../../../../components/app/flask/snaps-authorship-pill';
|
||||||
|
import Box from '../../../../components/ui/box';
|
||||||
|
import ToggleButton from '../../../../components/ui/toggle-button';
|
||||||
|
import PermissionsConnectPermissionList from '../../../../components/app/permissions-connect-permission-list/permissions-connect-permission-list';
|
||||||
|
import ConnectedSitesList from '../../../../components/app/connected-sites-list';
|
||||||
|
import Tooltip from '../../../../components/ui/tooltip';
|
||||||
|
import { SNAPS_LIST_ROUTE } from '../../../../helpers/constants/routes';
|
||||||
|
import {
|
||||||
|
disableSnap,
|
||||||
|
enableSnap,
|
||||||
|
removeSnap,
|
||||||
|
removePermissionsFor,
|
||||||
|
} from '../../../../store/actions';
|
||||||
|
import { getSnaps, getSubjectsWithPermission } from '../../../../selectors';
|
||||||
|
|
||||||
|
function ViewSnap() {
|
||||||
|
const t = useI18nContext();
|
||||||
|
const history = useHistory();
|
||||||
|
const location = useLocation();
|
||||||
|
const { pathname } = location;
|
||||||
|
const pathNameTail = pathname.match(/[^/]+$/u)[0];
|
||||||
|
const snaps = useSelector(getSnaps);
|
||||||
|
const snap = Object.entries(snaps)
|
||||||
|
.map(([_, snapState]) => snapState)
|
||||||
|
.find((snapState) => {
|
||||||
|
const decoded = decodeURIComponent(escape(window.atob(pathNameTail)));
|
||||||
|
return snapState.id === decoded;
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!snap) {
|
||||||
|
history.push(SNAPS_LIST_ROUTE);
|
||||||
|
}
|
||||||
|
}, [history, snap]);
|
||||||
|
|
||||||
|
const authorshipPillUrl = `https://npmjs.com/package/${snap?.manifest.source.location.npm.packageName}`;
|
||||||
|
const connectedSubjects = useSelector((state) =>
|
||||||
|
getSubjectsWithPermission(state, snap?.permissionName),
|
||||||
|
);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const onDisconnect = (connectedOrigin, snapPermissionName) => {
|
||||||
|
dispatch(
|
||||||
|
removePermissionsFor({
|
||||||
|
[connectedOrigin]: [snapPermissionName],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const onToggle = () => {
|
||||||
|
if (snap.enabled) {
|
||||||
|
dispatch(disableSnap(snap.id));
|
||||||
|
} else {
|
||||||
|
dispatch(enableSnap(snap.id));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!snap) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="view-snap">
|
||||||
|
<div className="settings-page__content-row">
|
||||||
|
<div className="view-snap__subheader">
|
||||||
|
<Typography
|
||||||
|
className="view-snap__title"
|
||||||
|
variant={TYPOGRAPHY.H3}
|
||||||
|
boxProps={{ textAlign: TEXT_ALIGN.CENTER }}
|
||||||
|
>
|
||||||
|
{snap.manifest.proposedName}
|
||||||
|
</Typography>
|
||||||
|
<Box className="view-snap__pill-toggle-container">
|
||||||
|
<Box className="view-snap__pill-container" paddingLeft={2}>
|
||||||
|
<SnapsAuthorshipPill
|
||||||
|
packageName={snap.id}
|
||||||
|
url={authorshipPillUrl}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
paddingLeft={4}
|
||||||
|
className="snap-settings-card__toggle-container view-snap__toggle-container"
|
||||||
|
>
|
||||||
|
<Tooltip interactive position="bottom" html={t('snapsToggle')}>
|
||||||
|
<ToggleButton
|
||||||
|
value={snap.enabled}
|
||||||
|
onToggle={onToggle}
|
||||||
|
className="snap-settings-card__toggle-container__toggle-button"
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</div>
|
||||||
|
<Box
|
||||||
|
className="view-snap__content-container"
|
||||||
|
width={FRACTIONS.SEVEN_TWELFTHS}
|
||||||
|
>
|
||||||
|
<div className="view-snap__section">
|
||||||
|
<Typography
|
||||||
|
variant={TYPOGRAPHY.H6}
|
||||||
|
color={COLORS.UI4}
|
||||||
|
boxProps={{ marginTop: 5 }}
|
||||||
|
>
|
||||||
|
{snap.manifest.description}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<div className="view-snap__section view-snap__permission-list">
|
||||||
|
<Typography variant={TYPOGRAPHY.H4}>{t('permissions')}</Typography>
|
||||||
|
<Typography variant={TYPOGRAPHY.H6} color={COLORS.UI4}>
|
||||||
|
{t('snapAccess', [snap.manifest.proposedName])}
|
||||||
|
</Typography>
|
||||||
|
<Box width={FRACTIONS.TEN_TWELFTHS}>
|
||||||
|
<PermissionsConnectPermissionList
|
||||||
|
permissions={snap.manifest.initialPermissions}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</div>
|
||||||
|
<div className="view-snap__section">
|
||||||
|
<Box width="11/12">
|
||||||
|
<Typography variant={TYPOGRAPHY.H4}>
|
||||||
|
{t('connectedSites')}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant={TYPOGRAPHY.H6} color={COLORS.UI4}>
|
||||||
|
{t('connectedSnapSites', [snap.manifest.proposedName])}
|
||||||
|
</Typography>
|
||||||
|
<ConnectedSitesList
|
||||||
|
connectedSubjects={connectedSubjects}
|
||||||
|
onDisconnect={(origin) => {
|
||||||
|
onDisconnect(origin, snap.permissionName);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</div>
|
||||||
|
<div className="view-snap__section">
|
||||||
|
<Typography variant={TYPOGRAPHY.H4}>{t('removeSnap')}</Typography>
|
||||||
|
<Typography
|
||||||
|
variant={TYPOGRAPHY.H6}
|
||||||
|
color={COLORS.UI4}
|
||||||
|
boxProps={{ paddingBottom: 3 }}
|
||||||
|
>
|
||||||
|
{t('removeSnapDescription')}
|
||||||
|
</Typography>
|
||||||
|
<Button
|
||||||
|
className="view-snap__remove-button"
|
||||||
|
type="danger"
|
||||||
|
css={{
|
||||||
|
maxWidth: '175px',
|
||||||
|
}}
|
||||||
|
onClick={async () => {
|
||||||
|
await dispatch(removeSnap(snap));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('removeSnap')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(ViewSnap);
|
@ -3,6 +3,8 @@
|
|||||||
@import 'networks-tab/index';
|
@import 'networks-tab/index';
|
||||||
@import 'settings-tab/index';
|
@import 'settings-tab/index';
|
||||||
@import 'contact-list-tab/index';
|
@import 'contact-list-tab/index';
|
||||||
|
@import 'flask/snaps-list-tab/index';
|
||||||
|
@import 'flask/view-snap/index';
|
||||||
|
|
||||||
.settings-page {
|
.settings-page {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -11,6 +11,10 @@ import {
|
|||||||
ABOUT_US_ROUTE,
|
ABOUT_US_ROUTE,
|
||||||
SETTINGS_ROUTE,
|
SETTINGS_ROUTE,
|
||||||
NETWORKS_ROUTE,
|
NETWORKS_ROUTE,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
SNAPS_VIEW_ROUTE,
|
||||||
|
SNAPS_LIST_ROUTE,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
CONTACT_LIST_ROUTE,
|
CONTACT_LIST_ROUTE,
|
||||||
CONTACT_ADD_ROUTE,
|
CONTACT_ADD_ROUTE,
|
||||||
CONTACT_EDIT_ROUTE,
|
CONTACT_EDIT_ROUTE,
|
||||||
@ -26,6 +30,10 @@ import InfoTab from './info-tab';
|
|||||||
import SecurityTab from './security-tab';
|
import SecurityTab from './security-tab';
|
||||||
import ContactListTab from './contact-list-tab';
|
import ContactListTab from './contact-list-tab';
|
||||||
import ExperimentalTab from './experimental-tab';
|
import ExperimentalTab from './experimental-tab';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
import SnapListTab from './flask/snaps-list-tab';
|
||||||
|
import ViewSnap from './flask/view-snap';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
class SettingsPage extends PureComponent {
|
class SettingsPage extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -35,6 +43,7 @@ class SettingsPage extends PureComponent {
|
|||||||
history: PropTypes.object,
|
history: PropTypes.object,
|
||||||
isAddressEntryPage: PropTypes.bool,
|
isAddressEntryPage: PropTypes.bool,
|
||||||
isPopup: PropTypes.bool,
|
isPopup: PropTypes.bool,
|
||||||
|
isSnapViewPage: PropTypes.bool,
|
||||||
pathnameI18nKey: PropTypes.string,
|
pathnameI18nKey: PropTypes.string,
|
||||||
initialBreadCrumbRoute: PropTypes.string,
|
initialBreadCrumbRoute: PropTypes.string,
|
||||||
breadCrumbTextKey: PropTypes.string,
|
breadCrumbTextKey: PropTypes.string,
|
||||||
@ -74,8 +83,8 @@ class SettingsPage extends PureComponent {
|
|||||||
currentPath,
|
currentPath,
|
||||||
mostRecentOverviewPage,
|
mostRecentOverviewPage,
|
||||||
addNewNetwork,
|
addNewNetwork,
|
||||||
|
isSnapViewPage,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classnames('main-container settings-page', {
|
className={classnames('main-container settings-page', {
|
||||||
@ -106,7 +115,7 @@ class SettingsPage extends PureComponent {
|
|||||||
{this.renderTabs()}
|
{this.renderTabs()}
|
||||||
</div>
|
</div>
|
||||||
<div className="settings-page__content__modules">
|
<div className="settings-page__content__modules">
|
||||||
{this.renderSubHeader()}
|
{isSnapViewPage ? null : this.renderSubHeader()}
|
||||||
{this.renderContent()}
|
{this.renderContent()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -116,11 +125,16 @@ class SettingsPage extends PureComponent {
|
|||||||
|
|
||||||
renderTitle() {
|
renderTitle() {
|
||||||
const { t } = this.context;
|
const { t } = this.context;
|
||||||
const { isPopup, pathnameI18nKey, addressName } = this.props;
|
const {
|
||||||
|
isPopup,
|
||||||
|
pathnameI18nKey,
|
||||||
|
addressName,
|
||||||
|
isSnapViewPage,
|
||||||
|
} = this.props;
|
||||||
let titleText;
|
let titleText;
|
||||||
|
if (isSnapViewPage) {
|
||||||
if (isPopup && addressName) {
|
titleText = t('snaps');
|
||||||
|
} else if (isPopup && addressName) {
|
||||||
titleText = t('details');
|
titleText = t('details');
|
||||||
} else if (pathnameI18nKey && isPopup) {
|
} else if (pathnameI18nKey && isPopup) {
|
||||||
titleText = t(pathnameI18nKey);
|
titleText = t(pathnameI18nKey);
|
||||||
@ -152,7 +166,7 @@ class SettingsPage extends PureComponent {
|
|||||||
} else if (initialBreadCrumbKey) {
|
} else if (initialBreadCrumbKey) {
|
||||||
subheaderText = t(initialBreadCrumbKey);
|
subheaderText = t(initialBreadCrumbKey);
|
||||||
} else {
|
} else {
|
||||||
subheaderText = t(pathnameI18nKey || 'contacts');
|
subheaderText = t(pathnameI18nKey || 'general');
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -207,6 +221,18 @@ class SettingsPage extends PureComponent {
|
|||||||
content: t('contacts'),
|
content: t('contacts'),
|
||||||
key: CONTACT_LIST_ROUTE,
|
key: CONTACT_LIST_ROUTE,
|
||||||
},
|
},
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<img
|
||||||
|
src="images/experimental-icon.svg"
|
||||||
|
alt={t('snapsSettingsDescription')}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
content: t('snaps'),
|
||||||
|
key: SNAPS_LIST_ROUTE,
|
||||||
|
},
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
{
|
{
|
||||||
icon: <img src="images/security-icon.svg" alt="" />,
|
icon: <img src="images/security-icon.svg" alt="" />,
|
||||||
content: t('securityAndPrivacy'),
|
content: t('securityAndPrivacy'),
|
||||||
@ -280,6 +306,16 @@ class SettingsPage extends PureComponent {
|
|||||||
path={`${CONTACT_VIEW_ROUTE}/:id`}
|
path={`${CONTACT_VIEW_ROUTE}/:id`}
|
||||||
component={ContactListTab}
|
component={ContactListTab}
|
||||||
/>
|
/>
|
||||||
|
{
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
<Route exact path={SNAPS_LIST_ROUTE} component={SnapListTab} />
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
}
|
||||||
|
{
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
<Route exact path={`${SNAPS_VIEW_ROUTE}/:id`} component={ViewSnap} />
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
}
|
||||||
<Route
|
<Route
|
||||||
render={(routeProps) => (
|
render={(routeProps) => (
|
||||||
<SettingsTab
|
<SettingsTab
|
||||||
|
@ -25,6 +25,8 @@ import {
|
|||||||
SETTINGS_ROUTE,
|
SETTINGS_ROUTE,
|
||||||
EXPERIMENTAL_ROUTE,
|
EXPERIMENTAL_ROUTE,
|
||||||
ADD_NETWORK_ROUTE,
|
ADD_NETWORK_ROUTE,
|
||||||
|
SNAPS_LIST_ROUTE,
|
||||||
|
SNAPS_VIEW_ROUTE,
|
||||||
} from '../../helpers/constants/routes';
|
} from '../../helpers/constants/routes';
|
||||||
import Settings from './settings.component';
|
import Settings from './settings.component';
|
||||||
|
|
||||||
@ -36,6 +38,8 @@ const ROUTES_TO_I18N_KEYS = {
|
|||||||
[CONTACT_ADD_ROUTE]: 'newContact',
|
[CONTACT_ADD_ROUTE]: 'newContact',
|
||||||
[CONTACT_EDIT_ROUTE]: 'editContact',
|
[CONTACT_EDIT_ROUTE]: 'editContact',
|
||||||
[CONTACT_LIST_ROUTE]: 'contacts',
|
[CONTACT_LIST_ROUTE]: 'contacts',
|
||||||
|
[SNAPS_LIST_ROUTE]: 'snaps',
|
||||||
|
[SNAPS_VIEW_ROUTE]: 'snaps',
|
||||||
[CONTACT_VIEW_ROUTE]: 'viewContact',
|
[CONTACT_VIEW_ROUTE]: 'viewContact',
|
||||||
[NETWORKS_ROUTE]: 'networks',
|
[NETWORKS_ROUTE]: 'networks',
|
||||||
[NETWORKS_FORM_ROUTE]: 'networks',
|
[NETWORKS_FORM_ROUTE]: 'networks',
|
||||||
@ -52,8 +56,8 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
const pathNameTail = pathname.match(/[^/]+$/u)[0];
|
const pathNameTail = pathname.match(/[^/]+$/u)[0];
|
||||||
|
|
||||||
const isAddressEntryPage = pathNameTail.includes('0x');
|
const isAddressEntryPage = pathNameTail.includes('0x');
|
||||||
|
const isSnapViewPage = Boolean(pathname.match(SNAPS_VIEW_ROUTE));
|
||||||
const isAddContactPage = Boolean(pathname.match(CONTACT_ADD_ROUTE));
|
const isAddContactPage = Boolean(pathname.match(CONTACT_ADD_ROUTE));
|
||||||
const isEditContactPage = Boolean(pathname.match(CONTACT_EDIT_ROUTE));
|
const isEditContactPage = Boolean(pathname.match(CONTACT_EDIT_ROUTE));
|
||||||
const isNetworksFormPage =
|
const isNetworksFormPage =
|
||||||
@ -71,6 +75,8 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
backRoute = CONTACT_LIST_ROUTE;
|
backRoute = CONTACT_LIST_ROUTE;
|
||||||
} else if (isNetworksFormPage) {
|
} else if (isNetworksFormPage) {
|
||||||
backRoute = NETWORKS_ROUTE;
|
backRoute = NETWORKS_ROUTE;
|
||||||
|
} else if (isSnapViewPage) {
|
||||||
|
backRoute = SNAPS_LIST_ROUTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
let initialBreadCrumbRoute;
|
let initialBreadCrumbRoute;
|
||||||
@ -96,6 +102,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
mostRecentOverviewPage: getMostRecentOverviewPage(state),
|
mostRecentOverviewPage: getMostRecentOverviewPage(state),
|
||||||
addNewNetwork,
|
addNewNetwork,
|
||||||
conversionDate,
|
conversionDate,
|
||||||
|
isSnapViewPage,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ import {
|
|||||||
NETWORKS_ROUTE,
|
NETWORKS_ROUTE,
|
||||||
SECURITY_ROUTE,
|
SECURITY_ROUTE,
|
||||||
SETTINGS_ROUTE,
|
SETTINGS_ROUTE,
|
||||||
|
SNAPS_LIST_ROUTE,
|
||||||
|
SNAPS_VIEW_ROUTE,
|
||||||
} from '../../helpers/constants/routes';
|
} from '../../helpers/constants/routes';
|
||||||
import SettingsPage from './settings.component';
|
import SettingsPage from './settings.component';
|
||||||
|
|
||||||
@ -38,6 +40,8 @@ const ROUTES_TO_I18N_KEYS = {
|
|||||||
[CONTACT_ADD_ROUTE]: 'newContact',
|
[CONTACT_ADD_ROUTE]: 'newContact',
|
||||||
[CONTACT_EDIT_ROUTE]: 'editContact',
|
[CONTACT_EDIT_ROUTE]: 'editContact',
|
||||||
[CONTACT_LIST_ROUTE]: 'contacts',
|
[CONTACT_LIST_ROUTE]: 'contacts',
|
||||||
|
[SNAPS_LIST_ROUTE]: 'snaps',
|
||||||
|
[SNAPS_VIEW_ROUTE]: 'snaps',
|
||||||
[CONTACT_VIEW_ROUTE]: 'viewContact',
|
[CONTACT_VIEW_ROUTE]: 'viewContact',
|
||||||
[NETWORKS_ROUTE]: 'networks',
|
[NETWORKS_ROUTE]: 'networks',
|
||||||
[NETWORKS_FORM_ROUTE]: 'networks',
|
[NETWORKS_FORM_ROUTE]: 'networks',
|
||||||
@ -54,9 +58,9 @@ const Settings = ({ history }) => {
|
|||||||
location.pathname === '/iframe.html'
|
location.pathname === '/iframe.html'
|
||||||
? '/settings/general'
|
? '/settings/general'
|
||||||
: location.pathname;
|
: location.pathname;
|
||||||
|
|
||||||
const pathnameI18nKey = ROUTES_TO_I18N_KEYS[pathname];
|
const pathnameI18nKey = ROUTES_TO_I18N_KEYS[pathname];
|
||||||
const backRoute = SETTINGS_ROUTE;
|
const isSnapViewPage = Boolean(pathname.match(SNAPS_VIEW_ROUTE));
|
||||||
|
const backRoute = isSnapViewPage ? SNAPS_LIST_ROUTE : SETTINGS_ROUTE;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ height: 500 }}>
|
<div style={{ height: 500 }}>
|
||||||
@ -66,6 +70,7 @@ const Settings = ({ history }) => {
|
|||||||
history={history}
|
history={history}
|
||||||
pathnameI18nKey={pathnameI18nKey}
|
pathnameI18nKey={pathnameI18nKey}
|
||||||
backRoute={backRoute}
|
backRoute={backRoute}
|
||||||
|
isSnapViewPage={isSnapViewPage}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
getOriginOfCurrentTab,
|
getOriginOfCurrentTab,
|
||||||
getSelectedAddress,
|
getSelectedAddress,
|
||||||
getSubjectMetadata,
|
getSubjectMetadata,
|
||||||
|
getTargetSubjectMetadata,
|
||||||
} from '.';
|
} from '.';
|
||||||
|
|
||||||
// selectors
|
// selectors
|
||||||
@ -96,6 +97,27 @@ export function getConnectedSubjectsForSelectedAddress(state) {
|
|||||||
return connectedSubjects;
|
return connectedSubjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSubjectsWithPermission(state, permissionName) {
|
||||||
|
const subjects = getPermissionSubjects(state);
|
||||||
|
|
||||||
|
const connectedSubjects = [];
|
||||||
|
|
||||||
|
Object.entries(subjects).forEach(([origin, { permissions }]) => {
|
||||||
|
if (permissions[permissionName]) {
|
||||||
|
const { extensionId, name, iconUrl } =
|
||||||
|
getTargetSubjectMetadata(state, origin) || {};
|
||||||
|
|
||||||
|
connectedSubjects.push({
|
||||||
|
extensionId,
|
||||||
|
origin,
|
||||||
|
name,
|
||||||
|
iconUrl,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return connectedSubjects;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an object mapping addresses to objects mapping origins to connected
|
* Returns an object mapping addresses to objects mapping origins to connected
|
||||||
* subject info. Subject info objects have the following properties:
|
* subject info. Subject info objects have the following properties:
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
import { memoize } from 'lodash';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
import { addHexPrefix } from '../../app/scripts/lib/util';
|
import { addHexPrefix } from '../../app/scripts/lib/util';
|
||||||
import {
|
import {
|
||||||
MAINNET_CHAIN_ID,
|
MAINNET_CHAIN_ID,
|
||||||
@ -16,13 +19,20 @@ import {
|
|||||||
TRANSPORT_STATES,
|
TRANSPORT_STATES,
|
||||||
} from '../../shared/constants/hardware-wallets';
|
} from '../../shared/constants/hardware-wallets';
|
||||||
|
|
||||||
|
import {
|
||||||
|
MESSAGE_TYPE,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
SUBJECT_TYPES,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
} from '../../shared/constants/app';
|
||||||
|
|
||||||
|
import { TRUNCATED_NAME_CHAR_LIMIT } from '../../shared/constants/labels';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
||||||
ALLOWED_SWAPS_CHAIN_IDS,
|
ALLOWED_SWAPS_CHAIN_IDS,
|
||||||
} from '../../shared/constants/swaps';
|
} from '../../shared/constants/swaps';
|
||||||
|
|
||||||
import { TRUNCATED_NAME_CHAR_LIMIT } from '../../shared/constants/labels';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
shortenAddress,
|
shortenAddress,
|
||||||
getAccountByAddress,
|
getAccountByAddress,
|
||||||
@ -50,7 +60,6 @@ import {
|
|||||||
getLedgerWebHidConnectedStatus,
|
getLedgerWebHidConnectedStatus,
|
||||||
getLedgerTransportStatus,
|
getLedgerTransportStatus,
|
||||||
} from '../ducks/app/app';
|
} from '../ducks/app/app';
|
||||||
import { MESSAGE_TYPE } from '../../shared/constants/app';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One of the only remaining valid uses of selecting the network subkey of the
|
* One of the only remaining valid uses of selecting the network subkey of the
|
||||||
@ -526,6 +535,31 @@ export function getSubjectMetadata(state) {
|
|||||||
return state.metamask.subjectMetadata;
|
return state.metamask.subjectMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
/**
|
||||||
|
* @param {string} svgString - The raw SVG string to make embeddable.
|
||||||
|
* @returns {string} The embeddable SVG string.
|
||||||
|
*/
|
||||||
|
const getEmbeddableSvg = memoize(
|
||||||
|
(svgString) => `data:image/svg+xml;utf8,${encodeURIComponent(svgString)}`,
|
||||||
|
);
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
|
export function getTargetSubjectMetadata(state, origin) {
|
||||||
|
const metadata = getSubjectMetadata(state)[origin];
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
if (metadata?.subjectType === SUBJECT_TYPES.SNAP) {
|
||||||
|
const { svgIcon, ...remainingMetadata } = metadata;
|
||||||
|
return {
|
||||||
|
...remainingMetadata,
|
||||||
|
iconUrl: svgIcon ? getEmbeddableSvg(svgIcon) : null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
export function getRpcPrefsForCurrentProvider(state) {
|
export function getRpcPrefsForCurrentProvider(state) {
|
||||||
const { frequentRpcListDetail, provider } = state.metamask;
|
const { frequentRpcListDetail, provider } = state.metamask;
|
||||||
const selectRpcInfo = frequentRpcListDetail.find(
|
const selectRpcInfo = frequentRpcListDetail.find(
|
||||||
@ -650,6 +684,12 @@ export function getShowWhatsNewPopup(state) {
|
|||||||
return state.appState.showWhatsNewPopup;
|
return state.appState.showWhatsNewPopup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
export function getSnaps(state) {
|
||||||
|
return state.metamask.snaps;
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an object of notification IDs and if they are allowed or not.
|
* Get an object of notification IDs and if they are allowed or not.
|
||||||
*
|
*
|
||||||
|
@ -807,6 +807,33 @@ export function txError(err) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
export function disableSnap(snapId) {
|
||||||
|
return async (dispatch) => {
|
||||||
|
await promisifiedBackground.disableSnap(snapId);
|
||||||
|
await forceUpdateMetamaskState(dispatch);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function enableSnap(snapId) {
|
||||||
|
return async (dispatch) => {
|
||||||
|
await promisifiedBackground.enableSnap(snapId);
|
||||||
|
await forceUpdateMetamaskState(dispatch);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeSnap(snap) {
|
||||||
|
return async (dispatch) => {
|
||||||
|
await promisifiedBackground.removeSnap(snap);
|
||||||
|
await forceUpdateMetamaskState(dispatch);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function removeSnapError(msgData) {
|
||||||
|
return promisifiedBackground.removeSnapError(msgData);
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
export function cancelMsg(msgData) {
|
export function cancelMsg(msgData) {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
dispatch(showLoadingIndication());
|
dispatch(showLoadingIndication());
|
||||||
|
241
yarn.lock
241
yarn.lock
@ -2586,49 +2586,12 @@
|
|||||||
semver "^7.3.5"
|
semver "^7.3.5"
|
||||||
yargs "^17.0.1"
|
yargs "^17.0.1"
|
||||||
|
|
||||||
"@metamask/contract-metadata@^1.29.0", "@metamask/contract-metadata@^1.31.0":
|
"@metamask/contract-metadata@^1.31.0":
|
||||||
version "1.31.0"
|
version "1.31.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.31.0.tgz#9e3e46de7a955ea1ca61f7db20d9a17b5e91d3d0"
|
resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.31.0.tgz#9e3e46de7a955ea1ca61f7db20d9a17b5e91d3d0"
|
||||||
integrity sha512-4FBJkg/vDiYp/thIiZknxrJ0lfsj2eWIPenwlNZmoqOhoL4VqhK5eKWxi+EuGMvv9taP+QBRk6Key7wC1uL78A==
|
integrity sha512-4FBJkg/vDiYp/thIiZknxrJ0lfsj2eWIPenwlNZmoqOhoL4VqhK5eKWxi+EuGMvv9taP+QBRk6Key7wC1uL78A==
|
||||||
|
|
||||||
"@metamask/controllers@^17.0.0":
|
"@metamask/controllers@^25.0.0", "@metamask/controllers@^25.1.0":
|
||||||
version "17.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-17.0.0.tgz#7ef00b4f7583d8075115e8a2f074d7b66646bbe8"
|
|
||||||
integrity sha512-myPlAk8SpNm5SwHHKGgm2XDLP4bxNR2UsKoQlYtV7bJq3l8FV1agSFwHBwDhg61/52Xvqdqy+1YDVdV3kOwPgg==
|
|
||||||
dependencies:
|
|
||||||
"@ethereumjs/common" "^2.3.1"
|
|
||||||
"@ethereumjs/tx" "^3.2.1"
|
|
||||||
"@metamask/contract-metadata" "^1.29.0"
|
|
||||||
"@types/uuid" "^8.3.0"
|
|
||||||
abort-controller "^3.0.0"
|
|
||||||
async-mutex "^0.2.6"
|
|
||||||
babel-runtime "^6.26.0"
|
|
||||||
eth-ens-namehash "^2.0.8"
|
|
||||||
eth-json-rpc-infura "^5.1.0"
|
|
||||||
eth-keyring-controller "^6.2.1"
|
|
||||||
eth-method-registry "1.1.0"
|
|
||||||
eth-phishing-detect "^1.1.14"
|
|
||||||
eth-query "^2.1.2"
|
|
||||||
eth-rpc-errors "^4.0.0"
|
|
||||||
eth-sig-util "^3.0.0"
|
|
||||||
ethereumjs-util "^7.0.10"
|
|
||||||
ethereumjs-wallet "^1.0.1"
|
|
||||||
ethers "^5.4.1"
|
|
||||||
ethjs-unit "^0.1.6"
|
|
||||||
ethjs-util "^0.1.6"
|
|
||||||
human-standard-collectible-abi "^1.0.2"
|
|
||||||
human-standard-token-abi "^2.0.0"
|
|
||||||
immer "^9.0.6"
|
|
||||||
isomorphic-fetch "^3.0.0"
|
|
||||||
jsonschema "^1.2.4"
|
|
||||||
nanoid "^3.1.12"
|
|
||||||
punycode "^2.1.1"
|
|
||||||
single-call-balance-checker-abi "^1.0.0"
|
|
||||||
uuid "^8.3.2"
|
|
||||||
web3 "^0.20.7"
|
|
||||||
web3-provider-engine "^16.0.3"
|
|
||||||
|
|
||||||
"@metamask/controllers@^25.0.0":
|
|
||||||
version "25.1.0"
|
version "25.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-25.1.0.tgz#2efee24a9a2b03ab2a2b0422c8f250931c269560"
|
resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-25.1.0.tgz#2efee24a9a2b03ab2a2b0422c8f250931c269560"
|
||||||
integrity sha512-syndn2lIhtlACzaqjDrw23dJzw8pZ6en4Cr35C7B9RRS87EhahUqkPP73moAzLtvbyqtBlAUO1HHrqV3lw4E5g==
|
integrity sha512-syndn2lIhtlACzaqjDrw23dJzw8pZ6en4Cr35C7B9RRS87EhahUqkPP73moAzLtvbyqtBlAUO1HHrqV3lw4E5g==
|
||||||
@ -2717,6 +2680,24 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@metamask/forwarder/-/forwarder-1.1.0.tgz#13829d8244bbf19ea658c0b20d21a77b67de0bdd"
|
resolved "https://registry.yarnpkg.com/@metamask/forwarder/-/forwarder-1.1.0.tgz#13829d8244bbf19ea658c0b20d21a77b67de0bdd"
|
||||||
integrity sha512-Hggj4y0QIjDzKGTXzarhEPIQyFSB2bi2y6YLJNwaT4JmP30UB5Cj6gqoY0M4pj3QT57fzp0BUuGp7F/AUe28tw==
|
integrity sha512-Hggj4y0QIjDzKGTXzarhEPIQyFSB2bi2y6YLJNwaT4JmP30UB5Cj6gqoY0M4pj3QT57fzp0BUuGp7F/AUe28tw==
|
||||||
|
|
||||||
|
"@metamask/iframe-execution-environment-service@^0.9.0":
|
||||||
|
version "0.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@metamask/iframe-execution-environment-service/-/iframe-execution-environment-service-0.9.0.tgz#721e15ee4651741a599940dbcfa524cc55eaaa47"
|
||||||
|
integrity sha512-a240sg83sX1dxfBDdRd0uoujaN4V9VtHKELMcTMgpYCI0uE83//Q01a7L8MiBtLhzr8o4D/xXRUIDR0Y9NKc3Q==
|
||||||
|
dependencies:
|
||||||
|
"@metamask/controllers" "^25.1.0"
|
||||||
|
"@metamask/object-multiplex" "^1.2.0"
|
||||||
|
"@metamask/post-message-stream" "^4.0.0"
|
||||||
|
"@metamask/snap-controllers" "^0.9.0"
|
||||||
|
"@metamask/snap-types" "^0.9.0"
|
||||||
|
"@metamask/snap-workers" "^0.9.0"
|
||||||
|
eth-rpc-errors "^4.0.3"
|
||||||
|
json-rpc-engine "^6.1.0"
|
||||||
|
json-rpc-middleware-stream "^3.0.0"
|
||||||
|
nanoid "^3.1.31"
|
||||||
|
pump "^3.0.0"
|
||||||
|
stream "^0.0.2"
|
||||||
|
|
||||||
"@metamask/jazzicon@^2.0.0":
|
"@metamask/jazzicon@^2.0.0":
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/jazzicon/-/jazzicon-2.0.0.tgz#5615528e91c0fc5c9d79202d1f0954a7922525a0"
|
resolved "https://registry.yarnpkg.com/@metamask/jazzicon/-/jazzicon-2.0.0.tgz#5615528e91c0fc5c9d79202d1f0954a7922525a0"
|
||||||
@ -2747,10 +2728,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@metamask/metamask-eth-abis/-/metamask-eth-abis-2.1.0.tgz#316c2e72373506f1a0120b76e432760a27eb6806"
|
resolved "https://registry.yarnpkg.com/@metamask/metamask-eth-abis/-/metamask-eth-abis-2.1.0.tgz#316c2e72373506f1a0120b76e432760a27eb6806"
|
||||||
integrity sha512-T8LBEB0PQo0N1tZQKZ2K8BGmv+IDLcXkzt8Pn7x0YnwZD6YpCIvKqYM3iy2fJ6wFXeCvRKqpn4K6EqwnkSJAbQ==
|
integrity sha512-T8LBEB0PQo0N1tZQKZ2K8BGmv+IDLcXkzt8Pn7x0YnwZD6YpCIvKqYM3iy2fJ6wFXeCvRKqpn4K6EqwnkSJAbQ==
|
||||||
|
|
||||||
"@metamask/object-multiplex@^1.1.0":
|
"@metamask/object-multiplex@^1.1.0", "@metamask/object-multiplex@^1.2.0":
|
||||||
version "1.1.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/object-multiplex/-/object-multiplex-1.1.0.tgz#6b1507c4d10caafd2ea82dd2a5360b91631e036e"
|
resolved "https://registry.yarnpkg.com/@metamask/object-multiplex/-/object-multiplex-1.2.0.tgz#38fc15c142f61939391e1b9a8eed679696c7e4f4"
|
||||||
integrity sha512-ImDw5+NdO5qnzmK/rpSlPmQMQm6HIC6wAHdR9nBaDK8TpeuRik5H8DCUcoNrxSeUAk1iHwchZ03lpZu6mZfrdw==
|
integrity sha512-hksV602d3NWE2Q30Mf2Np1WfVKaGqfJRy9vpHAmelbaD0OkDt06/0KQkRR6UVYdMbTbkuEu8xN5JDUU80inGwQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
end-of-stream "^1.4.4"
|
end-of-stream "^1.4.4"
|
||||||
once "^1.4.0"
|
once "^1.4.0"
|
||||||
@ -2765,15 +2746,6 @@
|
|||||||
readable-stream "^2.2.2"
|
readable-stream "^2.2.2"
|
||||||
through2 "^2.0.3"
|
through2 "^2.0.3"
|
||||||
|
|
||||||
"@metamask/obs-store@^6.0.2":
|
|
||||||
version "6.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/obs-store/-/obs-store-6.0.2.tgz#1fbc458cc617557a4557f9ab58e6676c474df2b1"
|
|
||||||
integrity sha512-MjnP+xNZGBx46YZrR8ZYPb+ScPfxJUbs09MTByuQKxMsf7Lxz17oBTI5ZMkOZOTSBBxhknKdjJg+nAM8mMopwg==
|
|
||||||
dependencies:
|
|
||||||
"@metamask/safe-event-emitter" "^2.0.0"
|
|
||||||
readable-stream "^2.2.2"
|
|
||||||
through2 "^2.0.3"
|
|
||||||
|
|
||||||
"@metamask/obs-store@^7.0.0":
|
"@metamask/obs-store@^7.0.0":
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/obs-store/-/obs-store-7.0.0.tgz#6cae5f28306bb3e83a381bc9ae22682316095bd3"
|
resolved "https://registry.yarnpkg.com/@metamask/obs-store/-/obs-store-7.0.0.tgz#6cae5f28306bb3e83a381bc9ae22682316095bd3"
|
||||||
@ -2807,13 +2779,13 @@
|
|||||||
pump "^3.0.0"
|
pump "^3.0.0"
|
||||||
webextension-polyfill-ts "^0.25.0"
|
webextension-polyfill-ts "^0.25.0"
|
||||||
|
|
||||||
"@metamask/rpc-methods@^0.5.0":
|
"@metamask/rpc-methods@^0.9.0":
|
||||||
version "0.5.0"
|
version "0.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/rpc-methods/-/rpc-methods-0.5.0.tgz#3c0073d80e68eceb8b9fa19bea0b2daef8638a42"
|
resolved "https://registry.yarnpkg.com/@metamask/rpc-methods/-/rpc-methods-0.9.0.tgz#eb55cc39d2ea9a663211e8d805bdf566af70c764"
|
||||||
integrity sha512-OFGd4T20dYTYxdB8WK0xa6FXRaNmJR5mAS7Wp7+6n8rqKljKJ0jDyfpGia1YKI6gKsB7Xdn5efnWxviuF/XQXQ==
|
integrity sha512-wii0TMuRscet8+x3tqfAcEmY0TrMFzOnD3QFpFVUy3fznv4b/EzDD/XLQToafd2yUaDjUrrS9FHwU9omqzPxcg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@metamask/key-tree" "^3.0.1"
|
"@metamask/key-tree" "^3.0.1"
|
||||||
"@metamask/snap-controllers" "^0.5.0"
|
"@metamask/snap-controllers" "^0.9.0"
|
||||||
eth-rpc-errors "^4.0.2"
|
eth-rpc-errors "^4.0.2"
|
||||||
|
|
||||||
"@metamask/safe-event-emitter@^2.0.0":
|
"@metamask/safe-event-emitter@^2.0.0":
|
||||||
@ -2821,57 +2793,49 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c"
|
resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c"
|
||||||
integrity sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==
|
integrity sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==
|
||||||
|
|
||||||
"@metamask/snap-controllers@^0.4.0":
|
"@metamask/slip44@^2.0.0":
|
||||||
version "0.4.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/snap-controllers/-/snap-controllers-0.4.0.tgz#20647f061e20263f462347c2bf0d59f7aedd6898"
|
resolved "https://registry.yarnpkg.com/@metamask/slip44/-/slip44-2.0.0.tgz#1b646a1418af341d5ea979c28015a817ff23af33"
|
||||||
integrity sha512-pZ9S72Y9u2KBrMdzFauz6t4LIxJBqcT6uzxstxdY8y0qroeeTJum6Z0L9HFkVSsTLP3JMyVSDD6FwRsHIwXewg==
|
integrity sha512-eRomm783ti/1b/TlNnlTCUkYRuTaMYkeTAG0z2rt/WyT8UzxY+8+v/kbl9vk5qhDHeclzBrd9gbqLnLU1kh+Ow==
|
||||||
dependencies:
|
|
||||||
"@metamask/controllers" "^17.0.0"
|
|
||||||
"@metamask/object-multiplex" "^1.1.0"
|
|
||||||
"@metamask/obs-store" "^6.0.2"
|
|
||||||
"@metamask/post-message-stream" "4.0.0"
|
|
||||||
"@metamask/safe-event-emitter" "^2.0.0"
|
|
||||||
"@metamask/snap-workers" "^0.4.0"
|
|
||||||
"@types/deep-freeze-strict" "^1.1.0"
|
|
||||||
deep-freeze-strict "^1.1.1"
|
|
||||||
eth-rpc-errors "^4.0.2"
|
|
||||||
fast-deep-equal "^3.1.3"
|
|
||||||
immer "^9.0.6"
|
|
||||||
json-rpc-engine "^6.1.0"
|
|
||||||
json-rpc-middleware-stream "^3.0.0"
|
|
||||||
nanoid "^3.1.28"
|
|
||||||
pump "^3.0.0"
|
|
||||||
|
|
||||||
"@metamask/snap-controllers@^0.5.0":
|
"@metamask/snap-controllers@^0.9.0":
|
||||||
version "0.5.0"
|
version "0.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/snap-controllers/-/snap-controllers-0.5.0.tgz#a77563ea7bea0ba7c6fd73059f9ecbf86be16fd4"
|
resolved "https://registry.yarnpkg.com/@metamask/snap-controllers/-/snap-controllers-0.9.0.tgz#e0006fc9991e995dd86dff792106990aae2aeda0"
|
||||||
integrity sha512-eKuKQh17LrHfkpk8T5J87jg4TTmnoG65JpPHgpV+GLyohF4CMEtyK6uJYoPcm5c3z7IArcYbuucc1bqLbz9JoA==
|
integrity sha512-os3fEai0w4ctpyy6ExlthY8tnww98Vm+RVwOZgrCKDY5dAXqlSXpyWc1uOfkQyiPhUEJtdznJTWzaWzNIO9MfQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@metamask/controllers" "^17.0.0"
|
"@metamask/controllers" "^25.1.0"
|
||||||
"@metamask/object-multiplex" "^1.1.0"
|
"@metamask/object-multiplex" "^1.1.0"
|
||||||
"@metamask/obs-store" "^7.0.0"
|
"@metamask/obs-store" "^7.0.0"
|
||||||
"@metamask/post-message-stream" "4.0.0"
|
"@metamask/post-message-stream" "4.0.0"
|
||||||
"@metamask/safe-event-emitter" "^2.0.0"
|
"@metamask/safe-event-emitter" "^2.0.0"
|
||||||
"@metamask/snap-workers" "^0.5.0"
|
"@metamask/snap-workers" "^0.9.0"
|
||||||
"@types/deep-freeze-strict" "^1.1.0"
|
"@types/deep-freeze-strict" "^1.1.0"
|
||||||
|
ajv "^8.8.2"
|
||||||
|
concat-stream "^2.0.0"
|
||||||
deep-freeze-strict "^1.1.1"
|
deep-freeze-strict "^1.1.1"
|
||||||
eth-rpc-errors "^4.0.2"
|
eth-rpc-errors "^4.0.2"
|
||||||
fast-deep-equal "^3.1.3"
|
fast-deep-equal "^3.1.3"
|
||||||
|
gunzip-maybe "^1.4.2"
|
||||||
immer "^9.0.6"
|
immer "^9.0.6"
|
||||||
json-rpc-engine "^6.1.0"
|
json-rpc-engine "^6.1.0"
|
||||||
json-rpc-middleware-stream "^3.0.0"
|
json-rpc-middleware-stream "^3.0.0"
|
||||||
nanoid "^3.1.28"
|
nanoid "^3.1.31"
|
||||||
pump "^3.0.0"
|
pump "^3.0.0"
|
||||||
|
readable-web-to-node-stream "^3.0.2"
|
||||||
|
semver "^7.3.5"
|
||||||
|
tar-stream "^2.2.0"
|
||||||
|
|
||||||
"@metamask/snap-workers@^0.4.0":
|
"@metamask/snap-types@^0.9.0":
|
||||||
version "0.4.0"
|
version "0.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/snap-workers/-/snap-workers-0.4.0.tgz#ba561eb15a7b7e7b353738ad5635a68c03cf64b0"
|
resolved "https://registry.yarnpkg.com/@metamask/snap-types/-/snap-types-0.9.0.tgz#aa164111be1b5c53fbaaf03c1bccbdbd0741daa4"
|
||||||
integrity sha512-usPEnwRXIwaDc06f8Jis4/CxXzmZJpPOLucOMqkxGAAz3hepA/T5fbfus12sibo5h6QsG0VTqBQ5AqKFlTr0zQ==
|
integrity sha512-pK4tvurUhcKMEkTD0XvQze5HCbtrgmpFWDztBekNIMJTXDrnYIEw4Dxn+LwCX7WJ0DN/03brQSEzmIrYbcBw7Q==
|
||||||
|
dependencies:
|
||||||
|
"@metamask/controllers" "^25.1.0"
|
||||||
|
|
||||||
"@metamask/snap-workers@^0.5.0":
|
"@metamask/snap-workers@^0.9.0":
|
||||||
version "0.5.0"
|
version "0.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/@metamask/snap-workers/-/snap-workers-0.5.0.tgz#9f1b8243f64819e40d66e659d580b6da59cb8015"
|
resolved "https://registry.yarnpkg.com/@metamask/snap-workers/-/snap-workers-0.9.0.tgz#215407b632fef4723dd75af7accf1f02a6a46916"
|
||||||
integrity sha512-sR30/nmkndPeLox282BdTNnU3g6Mo5Gt8rdr6PUSyfosbwrYtrbZcXFqR+ozK/gNhJ3de7hpjLXKNkVSF8OjOQ==
|
integrity sha512-+4YY5CQ7OPFPWh4QF5e4COgc0aWL6Df7Oc8/y//Sabp1rmXWI429OzCOlBi+NGJfQ1K7ORBMlRtOwYB9ZmWyLA==
|
||||||
|
|
||||||
"@metamask/test-dapp@^5.0.0":
|
"@metamask/test-dapp@^5.0.0":
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
@ -5303,10 +5267,10 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv
|
|||||||
json-schema-traverse "^0.4.1"
|
json-schema-traverse "^0.4.1"
|
||||||
uri-js "^4.2.2"
|
uri-js "^4.2.2"
|
||||||
|
|
||||||
ajv@^8.0.1:
|
ajv@^8.0.1, ajv@^8.8.2:
|
||||||
version "8.0.2"
|
version "8.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.0.2.tgz#1396e27f208ed56dd5638ab5a251edeb1c91d402"
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb"
|
||||||
integrity sha512-V0HGxJd0PiDF0ecHYIesTOqfd1gJguwQUOYfMfAWnRsWQEXfc5ifbUFhD3Wjc+O+y7VAqL+g07prq9gHQ/JOZQ==
|
integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==
|
||||||
dependencies:
|
dependencies:
|
||||||
fast-deep-equal "^3.1.1"
|
fast-deep-equal "^3.1.1"
|
||||||
json-schema-traverse "^1.0.0"
|
json-schema-traverse "^1.0.0"
|
||||||
@ -6914,6 +6878,13 @@ browserify-unibabel@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/browserify-unibabel/-/browserify-unibabel-3.0.0.tgz#5a6b8f0f704ce388d3927df47337e25830f71dda"
|
resolved "https://registry.yarnpkg.com/browserify-unibabel/-/browserify-unibabel-3.0.0.tgz#5a6b8f0f704ce388d3927df47337e25830f71dda"
|
||||||
integrity sha1-WmuPD3BM44jTkn30czfiWDD3Hdo=
|
integrity sha1-WmuPD3BM44jTkn30czfiWDD3Hdo=
|
||||||
|
|
||||||
|
browserify-zlib@^0.1.4:
|
||||||
|
version "0.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d"
|
||||||
|
integrity sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=
|
||||||
|
dependencies:
|
||||||
|
pako "~0.2.0"
|
||||||
|
|
||||||
browserify-zlib@^0.2.0, browserify-zlib@~0.2.0:
|
browserify-zlib@^0.2.0, browserify-zlib@~0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
|
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
|
||||||
@ -9839,10 +9810,10 @@ duplexer@^0.1.1, duplexer@~0.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
|
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
|
||||||
integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=
|
integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=
|
||||||
|
|
||||||
duplexify@^3.1.2, duplexify@^3.4.2:
|
duplexify@^3.1.2, duplexify@^3.4.2, duplexify@^3.5.0:
|
||||||
version "3.5.1"
|
version "3.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd"
|
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
|
||||||
integrity sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==
|
integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
|
||||||
dependencies:
|
dependencies:
|
||||||
end-of-stream "^1.0.0"
|
end-of-stream "^1.0.0"
|
||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
@ -9921,6 +9892,11 @@ elliptic@6.5.3, elliptic@6.5.4, elliptic@=3.0.3, elliptic@^6.0.0, elliptic@^6.4.
|
|||||||
minimalistic-assert "^1.0.1"
|
minimalistic-assert "^1.0.1"
|
||||||
minimalistic-crypto-utils "^1.0.1"
|
minimalistic-crypto-utils "^1.0.1"
|
||||||
|
|
||||||
|
emitter-component@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/emitter-component/-/emitter-component-1.1.1.tgz#065e2dbed6959bf470679edabeaf7981d1003ab6"
|
||||||
|
integrity sha1-Bl4tvtaVm/RwZ57avq95gdEAOrY=
|
||||||
|
|
||||||
emittery@0.10.0:
|
emittery@0.10.0:
|
||||||
version "0.10.0"
|
version "0.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.0.tgz#bb373c660a9d421bb44706ec4967ed50c02a8026"
|
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.0.tgz#bb373c660a9d421bb44706ec4967ed50c02a8026"
|
||||||
@ -11417,7 +11393,7 @@ ethjs-util@0.1.3:
|
|||||||
is-hex-prefixed "1.0.0"
|
is-hex-prefixed "1.0.0"
|
||||||
strip-hex-prefix "1.0.0"
|
strip-hex-prefix "1.0.0"
|
||||||
|
|
||||||
ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6:
|
ethjs-util@0.1.6, ethjs-util@^0.1.3:
|
||||||
version "0.1.6"
|
version "0.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536"
|
resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536"
|
||||||
integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==
|
integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==
|
||||||
@ -13433,6 +13409,18 @@ gulplog@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glogg "^1.0.0"
|
glogg "^1.0.0"
|
||||||
|
|
||||||
|
gunzip-maybe@^1.4.2:
|
||||||
|
version "1.4.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz#b913564ae3be0eda6f3de36464837a9cd94b98ac"
|
||||||
|
integrity sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==
|
||||||
|
dependencies:
|
||||||
|
browserify-zlib "^0.1.4"
|
||||||
|
is-deflate "^1.0.0"
|
||||||
|
is-gzip "^1.0.0"
|
||||||
|
peek-stream "^1.1.0"
|
||||||
|
pumpify "^1.3.3"
|
||||||
|
through2 "^2.0.3"
|
||||||
|
|
||||||
gzip-size@5.1.1, gzip-size@^5.1.1:
|
gzip-size@5.1.1, gzip-size@^5.1.1:
|
||||||
version "5.1.1"
|
version "5.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274"
|
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274"
|
||||||
@ -15019,6 +15007,11 @@ is-decimal@^1.0.0, is-decimal@^1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5"
|
resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5"
|
||||||
integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==
|
integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==
|
||||||
|
|
||||||
|
is-deflate@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-deflate/-/is-deflate-1.0.0.tgz#c862901c3c161fb09dac7cdc7e784f80e98f2f14"
|
||||||
|
integrity sha1-yGKQHDwWH7CdrHzcfnhPgOmPLxQ=
|
||||||
|
|
||||||
is-descriptor@^0.1.0:
|
is-descriptor@^0.1.0:
|
||||||
version "0.1.6"
|
version "0.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
|
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
|
||||||
@ -15147,6 +15140,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-extglob "^2.1.1"
|
is-extglob "^2.1.1"
|
||||||
|
|
||||||
|
is-gzip@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-gzip/-/is-gzip-1.0.0.tgz#6ca8b07b99c77998025900e555ced8ed80879a83"
|
||||||
|
integrity sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=
|
||||||
|
|
||||||
is-hex-prefixed@1.0.0:
|
is-hex-prefixed@1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554"
|
resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554"
|
||||||
@ -19105,7 +19103,7 @@ nanoid@^2.0.0, nanoid@^2.1.6:
|
|||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280"
|
||||||
integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==
|
integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==
|
||||||
|
|
||||||
nanoid@^3.1.12, nanoid@^3.1.23, nanoid@^3.1.28, nanoid@^3.1.31:
|
nanoid@^3.1.23, nanoid@^3.1.31:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
|
||||||
integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==
|
integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==
|
||||||
@ -20444,6 +20442,11 @@ package-json@^6.3.0:
|
|||||||
registry-url "^5.0.0"
|
registry-url "^5.0.0"
|
||||||
semver "^6.2.0"
|
semver "^6.2.0"
|
||||||
|
|
||||||
|
pako@~0.2.0:
|
||||||
|
version "0.2.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
|
||||||
|
integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=
|
||||||
|
|
||||||
pako@~1.0.2, pako@~1.0.5:
|
pako@~1.0.2, pako@~1.0.5:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
|
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
|
||||||
@ -20816,6 +20819,15 @@ pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9:
|
|||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
sha.js "^2.4.8"
|
sha.js "^2.4.8"
|
||||||
|
|
||||||
|
peek-stream@^1.1.0:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/peek-stream/-/peek-stream-1.1.3.tgz#3b35d84b7ccbbd262fff31dc10da56856ead6d67"
|
||||||
|
integrity sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==
|
||||||
|
dependencies:
|
||||||
|
buffer-from "^1.0.0"
|
||||||
|
duplexify "^3.5.0"
|
||||||
|
through2 "^2.0.3"
|
||||||
|
|
||||||
peer-book@^0.9.1, peer-book@~0.9.0:
|
peer-book@^0.9.1, peer-book@~0.9.0:
|
||||||
version "0.9.1"
|
version "0.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/peer-book/-/peer-book-0.9.1.tgz#42dffd7b1faf263bd6abe2907a26f7411f4dbf34"
|
resolved "https://registry.yarnpkg.com/peer-book/-/peer-book-0.9.1.tgz#42dffd7b1faf263bd6abe2907a26f7411f4dbf34"
|
||||||
@ -22811,6 +22823,13 @@ readable-stream@~1.0.15:
|
|||||||
isarray "0.0.1"
|
isarray "0.0.1"
|
||||||
string_decoder "~0.10.x"
|
string_decoder "~0.10.x"
|
||||||
|
|
||||||
|
readable-web-to-node-stream@^3.0.2:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb"
|
||||||
|
integrity sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==
|
||||||
|
dependencies:
|
||||||
|
readable-stream "^3.6.0"
|
||||||
|
|
||||||
readdir-scoped-modules@^1.0.0:
|
readdir-scoped-modules@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309"
|
resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309"
|
||||||
@ -24937,6 +24956,13 @@ stream-to-pull-stream@^1.7.2, stream-to-pull-stream@^1.7.3:
|
|||||||
looper "^3.0.0"
|
looper "^3.0.0"
|
||||||
pull-stream "^3.2.3"
|
pull-stream "^3.2.3"
|
||||||
|
|
||||||
|
stream@^0.0.2:
|
||||||
|
version "0.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/stream/-/stream-0.0.2.tgz#7f5363f057f6592c5595f00bc80a27f5cec1f0ef"
|
||||||
|
integrity sha1-f1Nj8Ff2WSxVlfALyAon9c7B8O8=
|
||||||
|
dependencies:
|
||||||
|
emitter-component "^1.1.1"
|
||||||
|
|
||||||
streamsearch@0.1.2:
|
streamsearch@0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
||||||
@ -25522,7 +25548,7 @@ tar-fs@^2.0.0:
|
|||||||
pump "^3.0.0"
|
pump "^3.0.0"
|
||||||
tar-stream "^2.1.4"
|
tar-stream "^2.1.4"
|
||||||
|
|
||||||
tar-stream@^2.0.0, tar-stream@^2.0.1, tar-stream@^2.1.4:
|
tar-stream@^2.0.0, tar-stream@^2.0.1, tar-stream@^2.1.4, tar-stream@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
|
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
|
||||||
integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
|
integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
|
||||||
@ -26751,7 +26777,7 @@ util.promisify@1.0.0:
|
|||||||
define-properties "^1.1.2"
|
define-properties "^1.1.2"
|
||||||
object.getownpropertydescriptors "^2.0.3"
|
object.getownpropertydescriptors "^2.0.3"
|
||||||
|
|
||||||
util@0.10.3, util@~0.10.1:
|
util@0.10.3:
|
||||||
version "0.10.3"
|
version "0.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
|
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
|
||||||
integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk=
|
integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk=
|
||||||
@ -26777,6 +26803,13 @@ util@^0.12.0, util@^0.12.3, util@~0.12.0:
|
|||||||
safe-buffer "^5.1.2"
|
safe-buffer "^5.1.2"
|
||||||
which-typed-array "^1.1.2"
|
which-typed-array "^1.1.2"
|
||||||
|
|
||||||
|
util@~0.10.1:
|
||||||
|
version "0.10.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901"
|
||||||
|
integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==
|
||||||
|
dependencies:
|
||||||
|
inherits "2.0.3"
|
||||||
|
|
||||||
utila@^0.4.0, utila@~0.4:
|
utila@^0.4.0, utila@~0.4:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
|
resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
|
||||||
|
Loading…
Reference in New Issue
Block a user