mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 17:33:23 +01:00
Merge pull request #20075 from MetaMask/Version-v10.35.0
Version v10.35.0 RC
This commit is contained in:
commit
391294d0d4
@ -353,18 +353,15 @@ jobs:
|
||||
echo "Not a PR; skipping"
|
||||
fi
|
||||
- run:
|
||||
name: Setup registry config for using package previews on draft PRs
|
||||
name: Install dependencies
|
||||
command: |
|
||||
if [[ $IS_DRAFT == 'true' ]]
|
||||
then
|
||||
printf '%s\n\n%s' '@metamask:registry=https://npm.pkg.github.com' "//npm.pkg.github.com/:_authToken=${GITHUB_PACKAGE_READ_TOKEN}" > .npmrc
|
||||
# Use GitHub registry on draft PRs, allowing the use of preview builds
|
||||
METAMASK_NPM_REGISTRY=https://npm.pkg.github.com yarn --immutable
|
||||
else
|
||||
echo "Not draft; skipping GitHub registry setup"
|
||||
yarn --immutable
|
||||
fi
|
||||
- run:
|
||||
name: Install deps
|
||||
command: |
|
||||
.circleci/scripts/deps-install.sh
|
||||
- save_cache:
|
||||
key: dependency-cache-v1-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
|
@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Print commands and their arguments as they are executed.
|
||||
set -x
|
||||
# Exit immediately if a command exits with a non-zero status.
|
||||
set -e
|
||||
|
||||
yarn install --frozen-lockfile
|
||||
|
28
.github/workflows/stale-issues-pr.yml
vendored
Normal file
28
.github/workflows/stale-issues-pr.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: 'Close stale issues and PRs'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 12 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@72afbce2b0dbd1d903bb142cebe2d15dc307ae57
|
||||
with:
|
||||
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity in the last 90 days. It will be closed in 45 days. Thank you for your contributions.'
|
||||
stale-issue-label: 'stale'
|
||||
only-issue-labels: 'type-bug'
|
||||
exempt-issue-labels: 'type-security, type-pinned, feature-request, awaiting-metamask'
|
||||
stale-pr-message: 'This PR has been automatically marked as stale because it has not had recent activity in the last 60 days. It will be closed in 14 days. Thank you for your contributions.'
|
||||
stale-pr-label: 'stale'
|
||||
exempt-pr-labels: 'work-in-progress'
|
||||
close-issue-message: 'This issue was closed because there has been no follow up activity in the last 7 days. If you feel this was closed in error, please reopen and provide evidence on the latest release of the extension. Thank you for your contributions.'
|
||||
close-pr-message: 'This PR was closed because there has been no follow up activity in the last 7 days. Thank you for your contributions.'
|
||||
days-before-issue-stale: 90
|
||||
days-before-pr-stale: 60
|
||||
days-before-issue-close: 45
|
||||
days-before-pr-close: 14
|
||||
operations-per-run: 1
|
59
.github/workflows/update-lavamoat-policies.yml
vendored
59
.github/workflows/update-lavamoat-policies.yml
vendored
@ -48,6 +48,8 @@ jobs:
|
||||
needs: is-fork-pull-request
|
||||
# Early exit if this is a fork, since later steps are skipped for forks
|
||||
if: ${{ needs.is-fork-pull-request.outputs.IS_FORK == 'false' }}
|
||||
outputs:
|
||||
COMMIT_SHA: ${{ steps.commit-sha.outputs.COMMIT_SHA }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
@ -63,6 +65,9 @@ jobs:
|
||||
cache: 'yarn'
|
||||
- name: Install Yarn dependencies
|
||||
run: yarn --immutable
|
||||
- name: Get commit SHA
|
||||
id: commit-sha
|
||||
run: echo "COMMIT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
update-lavamoat-build-policy:
|
||||
name: Update LavaMoat build policy
|
||||
@ -90,7 +95,7 @@ jobs:
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
path: lavamoat/build-system
|
||||
key: cache-build-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
key: cache-build-${{ needs.prepare.outputs.COMMIT_SHA }}
|
||||
|
||||
update-lavamoat-webapp-policy:
|
||||
strategy:
|
||||
@ -125,12 +130,13 @@ jobs:
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
path: lavamoat/browserify/${{ matrix.build-type }}
|
||||
key: cache-${{ matrix.build-type }}-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
key: cache-${{ matrix.build-type }}-${{ needs.prepare.outputs.COMMIT_SHA }}
|
||||
|
||||
commit-updated-policies:
|
||||
name: Commit the updated LavaMoat policies
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prepare
|
||||
- is-fork-pull-request
|
||||
- update-lavamoat-build-policy
|
||||
- update-lavamoat-webapp-policy
|
||||
@ -147,11 +153,14 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.LAVAMOAT_UPDATE_TOKEN }}
|
||||
PR_NUMBER: ${{ github.event.issue.number }}
|
||||
- name: Get commit SHA
|
||||
id: commit-sha
|
||||
run: echo "COMMIT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
|
||||
- name: Restore build policy
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: lavamoat/build-system
|
||||
key: cache-build-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
key: cache-build-${{ needs.prepare.outputs.COMMIT_SHA }}
|
||||
fail-on-cache-miss: true
|
||||
# One restore step per build type: [main, beta, flask, mmi, desktop]
|
||||
# Ensure this is synchronized with the list above in the "update-lavamoat-webapp-policy" job
|
||||
@ -160,31 +169,31 @@ jobs:
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: lavamoat/browserify/main
|
||||
key: cache-main-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
key: cache-main-${{ needs.prepare.outputs.COMMIT_SHA }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore beta application policy
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: lavamoat/browserify/beta
|
||||
key: cache-beta-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
key: cache-beta-${{ needs.prepare.outputs.COMMIT_SHA }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore flask application policy
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: lavamoat/browserify/flask
|
||||
key: cache-flask-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
key: cache-flask-${{ needs.prepare.outputs.COMMIT_SHA }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore mmi application policy
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: lavamoat/browserify/mmi
|
||||
key: cache-mmi-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
key: cache-mmi-${{ needs.prepare.outputs.COMMIT_SHA }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore desktop application policy
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: lavamoat/browserify/desktop
|
||||
key: cache-desktop-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
key: cache-desktop-${{ needs.prepare.outputs.COMMIT_SHA }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Check whether there are policy changes
|
||||
id: policy-changes
|
||||
@ -214,3 +223,37 @@ jobs:
|
||||
HAS_CHANGES: ${{ steps.policy-changes.outputs.HAS_CHANGES }}
|
||||
GITHUB_TOKEN: ${{ secrets.LAVAMOAT_UPDATE_TOKEN }}
|
||||
PR_NUMBER: ${{ github.event.issue.number }}
|
||||
|
||||
check-status:
|
||||
name: Check whether the policy update succeeded
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- commit-updated-policies
|
||||
outputs:
|
||||
PASSED: ${{ steps.set-output.outputs.PASSED }}
|
||||
steps:
|
||||
- name: Set PASSED output
|
||||
id: set-output
|
||||
run: echo "PASSED=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
failure-comment:
|
||||
name: Comment about the policy update failure
|
||||
if: ${{ always() && needs.is-fork-pull-request.outputs.IS_FORK == 'false' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- is-fork-pull-request
|
||||
- check-status
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.LAVAMOAT_UPDATE_TOKEN }}
|
||||
- name: Post comment if the update failed
|
||||
run: |
|
||||
passed="${{ needs.check-status.outputs.PASSED }}"
|
||||
if [[ $passed != "true" ]]; then
|
||||
gh pr comment "${PR_NUMBER}" --body "Policy update failed. You can [review the logs or retry the policy update here](${ACTION_RUN_URL})"
|
||||
fi
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.LAVAMOAT_UPDATE_TOKEN }}
|
||||
PR_NUMBER: ${{ github.event.issue.number }}
|
||||
ACTION_RUN_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
|
4
.iyarc
4
.iyarc
@ -4,3 +4,7 @@ GHSA-257v-vj4p-3w2h
|
||||
# request library is subject to SSRF.
|
||||
# addressed by temporary patch in .yarn/patches/request-npm-2.88.2-f4a57c72c4.patch
|
||||
GHSA-p8p7-x288-28g6
|
||||
|
||||
# tough-cookie
|
||||
# this will go away soon when we get rid of web3-provider-engine
|
||||
GHSA-72xf-g2v4-qvf3
|
||||
|
@ -50,7 +50,13 @@ Theme colors are color agnostic, semantically neutral and theme compatible desig
|
||||
```css
|
||||
/** Backgrounds */
|
||||
var(--color-background-default)
|
||||
var(--color-background-default-hover)
|
||||
var(--color-background-default-pressed)
|
||||
var(--color-background-alternative)
|
||||
var(--color-background-alternative-hover)
|
||||
var(--color-background-alternative-pressed)
|
||||
var(--color-background-hover)
|
||||
var(--color-background-pressed)
|
||||
|
||||
/** Text */
|
||||
var(--color-text-default)
|
||||
|
80
.yarn/patches/jsdom-npm-16.7.0-216c5c4bf9.patch
Normal file
80
.yarn/patches/jsdom-npm-16.7.0-216c5c4bf9.patch
Normal file
@ -0,0 +1,80 @@
|
||||
diff --git a/lib/jsdom/browser/Window.js b/lib/jsdom/browser/Window.js
|
||||
index 9b2d75f55050f865382e2f0e8a88f066e0bff2da..d4a635da8eae02eaf0543693356f1252f8b6bac0 100644
|
||||
--- a/lib/jsdom/browser/Window.js
|
||||
+++ b/lib/jsdom/browser/Window.js
|
||||
@@ -24,7 +24,6 @@ const External = require("../living/generated/External");
|
||||
const Navigator = require("../living/generated/Navigator");
|
||||
const Performance = require("../living/generated/Performance");
|
||||
const Screen = require("../living/generated/Screen");
|
||||
-const Storage = require("../living/generated/Storage");
|
||||
const Selection = require("../living/generated/Selection");
|
||||
const reportException = require("../living/helpers/runtime-script-errors");
|
||||
const { getCurrentEventHandlerValue } = require("../living/helpers/create-event-accessor.js");
|
||||
@@ -285,40 +284,6 @@ function Window(options) {
|
||||
this._pretendToBeVisual = options.pretendToBeVisual;
|
||||
this._storageQuota = options.storageQuota;
|
||||
|
||||
- // Some properties (such as localStorage and sessionStorage) share data
|
||||
- // between windows in the same origin. This object is intended
|
||||
- // to contain such data.
|
||||
- if (options.commonForOrigin && options.commonForOrigin[documentOrigin]) {
|
||||
- this._commonForOrigin = options.commonForOrigin;
|
||||
- } else {
|
||||
- this._commonForOrigin = {
|
||||
- [documentOrigin]: {
|
||||
- localStorageArea: new Map(),
|
||||
- sessionStorageArea: new Map(),
|
||||
- windowsInSameOrigin: [this]
|
||||
- }
|
||||
- };
|
||||
- }
|
||||
-
|
||||
- this._currentOriginData = this._commonForOrigin[documentOrigin];
|
||||
-
|
||||
- // ### WEB STORAGE
|
||||
-
|
||||
- this._localStorage = Storage.create(window, [], {
|
||||
- associatedWindow: this,
|
||||
- storageArea: this._currentOriginData.localStorageArea,
|
||||
- type: "localStorage",
|
||||
- url: this._document.documentURI,
|
||||
- storageQuota: this._storageQuota
|
||||
- });
|
||||
- this._sessionStorage = Storage.create(window, [], {
|
||||
- associatedWindow: this,
|
||||
- storageArea: this._currentOriginData.sessionStorageArea,
|
||||
- type: "sessionStorage",
|
||||
- url: this._document.documentURI,
|
||||
- storageQuota: this._storageQuota
|
||||
- });
|
||||
-
|
||||
// ### SELECTION
|
||||
|
||||
// https://w3c.github.io/selection-api/#dfn-selection
|
||||
@@ -416,26 +381,6 @@ function Window(options) {
|
||||
configurable: true
|
||||
});
|
||||
},
|
||||
- get localStorage() {
|
||||
- if (idlUtils.implForWrapper(this._document)._origin === "null") {
|
||||
- throw DOMException.create(window, [
|
||||
- "localStorage is not available for opaque origins",
|
||||
- "SecurityError"
|
||||
- ]);
|
||||
- }
|
||||
-
|
||||
- return this._localStorage;
|
||||
- },
|
||||
- get sessionStorage() {
|
||||
- if (idlUtils.implForWrapper(this._document)._origin === "null") {
|
||||
- throw DOMException.create(window, [
|
||||
- "sessionStorage is not available for opaque origins",
|
||||
- "SecurityError"
|
||||
- ]);
|
||||
- }
|
||||
-
|
||||
- return this._sessionStorage;
|
||||
- },
|
||||
get customElements() {
|
||||
return customElementRegistry;
|
||||
},
|
18
.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch
Normal file
18
.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch
Normal file
@ -0,0 +1,18 @@
|
||||
diff --git a/src/loadPolicy.js b/src/loadPolicy.js
|
||||
index ef71923f9282d6a5e9f74e6ec6fa0516f28f508b..0118fda7e1b0fa461ec01ceff8d7112d072f3dfb 100644
|
||||
--- a/src/loadPolicy.js
|
||||
+++ b/src/loadPolicy.js
|
||||
@@ -33,10 +33,9 @@ async function loadPolicyAndApplyOverrides({ debugMode, policyPath, policyOverri
|
||||
}
|
||||
const policyOverride = await readPolicyFile({ debugMode, policyPath: policyOverridePath })
|
||||
lavamoatPolicy = mergePolicy(policy, policyOverride)
|
||||
- // TODO: Only write if merge results in changes.
|
||||
- // Would have to make a deep equal check on whole policy, which is a waste of time.
|
||||
- // mergePolicy() should be able to do it in one pass.
|
||||
- fs.writeFileSync(policyPath, jsonStringify(lavamoatPolicy, { space: 2 }))
|
||||
+ // Skip policy write step to prevent intermittent build failures
|
||||
+ // The extension validates the policy in a separate step, we don't need it
|
||||
+ // to be written to disk here.
|
||||
}
|
||||
return lavamoatPolicy
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
diff --git a/dist/index.d.ts b/dist/index.d.ts
|
||||
index 81253d38280bb25de1e36443d919f0e95b3e023c..d2333bf6796ff3ec94f5857d23ef34cc39c9729a 100644
|
||||
index 66eb3236059f88f73355d4fddef9e06a0169b407..04f067d2bda8af760c0a95ca6b5d85bcdfb2421a 100644
|
||||
--- a/dist/index.d.ts
|
||||
+++ b/dist/index.d.ts
|
||||
@@ -1,10 +1,10 @@
|
||||
@@ -1,11 +1,12 @@
|
||||
-import { type ParserOptions } from './parser/index.js';
|
||||
+import { ParserOptions } from './parser/index.js';
|
||||
import type { DefaultTreeAdapterMap } from './tree-adapters/default.js';
|
||||
@ -12,12 +12,15 @@ index 81253d38280bb25de1e36443d919f0e95b3e023c..d2333bf6796ff3ec94f5857d23ef34cc
|
||||
export type { TreeAdapter, TreeAdapterTypeMap } from './tree-adapters/interface.js';
|
||||
-export { type ParserOptions, /** @internal */ Parser } from './parser/index.js';
|
||||
-export { serialize, serializeOuter, type SerializerOptions } from './serializer/index.js';
|
||||
-export { ERR as ErrorCodes, type ParserError } from './common/error-codes.js';
|
||||
+export { ParserOptions, /** @internal */ Parser } from './parser/index.js';
|
||||
+export { serialize, serializeOuter, SerializerOptions } from './serializer/index.js';
|
||||
export type { ParserError } from './common/error-codes.js';
|
||||
+export type { ParserError } from './common/error-codes.js';
|
||||
+export { ERR as ErrorCodes } from './common/error-codes.js';
|
||||
/** @internal */
|
||||
export * as foreignContent from './common/foreign-content.js';
|
||||
@@ -13,7 +13,7 @@ export * as html from './common/html.js';
|
||||
/** @internal */
|
||||
@@ -13,7 +14,7 @@ export * as html from './common/html.js';
|
||||
/** @internal */
|
||||
export * as Token from './common/token.js';
|
||||
/** @internal */
|
||||
@ -27,7 +30,7 @@ index 81253d38280bb25de1e36443d919f0e95b3e023c..d2333bf6796ff3ec94f5857d23ef34cc
|
||||
* Parses an HTML string.
|
||||
*
|
||||
diff --git a/dist/parser/index.d.ts b/dist/parser/index.d.ts
|
||||
index 50a9bd0c73649e4a78edd0d18b4ee44ae9cdf3b7..df1863e335e64269298dea42a7481b26b9e77581 100644
|
||||
index 50a9bd0c73649e4a78edd0d18b4ee44ae9cdf3b7..85cc630db81d7a4ebd01691223d81187cdd8adcb 100644
|
||||
--- a/dist/parser/index.d.ts
|
||||
+++ b/dist/parser/index.d.ts
|
||||
@@ -1,10 +1,10 @@
|
||||
@ -46,18 +49,18 @@ index 50a9bd0c73649e4a78edd0d18b4ee44ae9cdf3b7..df1863e335e64269298dea42a7481b26
|
||||
INITIAL = 0,
|
||||
BEFORE_HTML = 1,
|
||||
diff --git a/dist/serializer/index.d.ts b/dist/serializer/index.d.ts
|
||||
index d944fae103a245cb84623fd733c91cc7e79f72f1..432464c9e05ecfd93c66526bcf4f0c81f09bf00d 100644
|
||||
index bf759e63ba1be31a2ab14884fcfd6bd3e8ecd2d7..839e21e45dc13e678c9874c51524a8ed1a463591 100644
|
||||
--- a/dist/serializer/index.d.ts
|
||||
+++ b/dist/serializer/index.d.ts
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { TreeAdapter, TreeAdapterTypeMap } from '../tree-adapters/interface';
|
||||
import type { TreeAdapter, TreeAdapterTypeMap } from '../tree-adapters/interface.js';
|
||||
-import { type DefaultTreeAdapterMap } from '../tree-adapters/default.js';
|
||||
+import { DefaultTreeAdapterMap } from '../tree-adapters/default.js';
|
||||
export interface SerializerOptions<T extends TreeAdapterTypeMap> {
|
||||
/**
|
||||
* Specifies input tree format.
|
||||
diff --git a/dist/tokenizer/index.d.ts b/dist/tokenizer/index.d.ts
|
||||
index de6e234cfb36bb3a4b928c47ab0d0fdf0b4311e1..89e2484b43f3487f3f157435a283ba932a879210 100644
|
||||
index 5afab96d6499bb0bba706aee7d2f153647db8713..3680d732d8a3570b6a1d9336c0ebdf8fe4f392db 100644
|
||||
--- a/dist/tokenizer/index.d.ts
|
||||
+++ b/dist/tokenizer/index.d.ts
|
||||
@@ -1,6 +1,6 @@
|
||||
@ -69,8 +72,18 @@ index de6e234cfb36bb3a4b928c47ab0d0fdf0b4311e1..89e2484b43f3487f3f157435a283ba93
|
||||
declare const enum State {
|
||||
DATA = 0,
|
||||
RCDATA = 1,
|
||||
diff --git a/dist/tree-adapters/default.d.ts b/dist/tree-adapters/default.d.ts
|
||||
index 547d714bdc5a664ba1414c16bdfc9247c71ab4de..d96a23d6ce3e80d78da21d958c059de194bb5146 100644
|
||||
--- a/dist/tree-adapters/default.d.ts
|
||||
+++ b/dist/tree-adapters/default.d.ts
|
||||
@@ -1,4 +1,4 @@
|
||||
-import { DOCUMENT_MODE, type NS } from '../common/html.js';
|
||||
+import { DOCUMENT_MODE, NS } from '../common/html.js';
|
||||
import type { Attribute, Location, ElementLocation } from '../common/token.js';
|
||||
import type { TreeAdapter, TreeAdapterTypeMap } from './interface.js';
|
||||
export interface Document {
|
||||
diff --git a/dist/tokenizer/preprocessor.d.ts b/dist/tokenizer/preprocessor.d.ts
|
||||
index e74a590783b4688fb6498b019c1a75cfd9ac23e7..d145dcce97b104830e5b3d7f57f3a63377bbf89c 100644
|
||||
index e74a590783b4688fb6498b019c1a75cfd9ac23e7..7350e44b4ed952bcb8f167e30a94958e9fcf743a 100644
|
||||
--- a/dist/tokenizer/preprocessor.d.ts
|
||||
+++ b/dist/tokenizer/preprocessor.d.ts
|
||||
@@ -1,4 +1,4 @@
|
||||
@ -79,13 +92,3 @@ index e74a590783b4688fb6498b019c1a75cfd9ac23e7..d145dcce97b104830e5b3d7f57f3a633
|
||||
export declare class Preprocessor {
|
||||
private handler;
|
||||
html: string;
|
||||
diff --git a/dist/tree-adapters/default.d.ts b/dist/tree-adapters/default.d.ts
|
||||
index cccdf8f86d2295b3059c42943d896e81691c8419..d70b8fa2562f4dc6415d7ebaaba6cb322f66e9cb 100644
|
||||
--- a/dist/tree-adapters/default.d.ts
|
||||
+++ b/dist/tree-adapters/default.d.ts
|
||||
@@ -1,4 +1,4 @@
|
||||
-import { DOCUMENT_MODE, type NS } from '../common/html.js';
|
||||
+import { DOCUMENT_MODE, NS } from '../common/html.js';
|
||||
import type { Attribute, Location, ElementLocation } from '../common/token.js';
|
||||
import type { TreeAdapter, TreeAdapterTypeMap } from './interface.js';
|
||||
export declare enum NodeType {
|
@ -8,6 +8,15 @@ logFilters:
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
npmRegistries:
|
||||
"https://npm.pkg.github.com":
|
||||
npmAlwaysAuth: true
|
||||
npmAuthToken: "${GITHUB_PACKAGE_READ_TOKEN-}"
|
||||
|
||||
npmScopes:
|
||||
metamask:
|
||||
npmRegistryServer: "${METAMASK_NPM_REGISTRY:-https://registry.yarnpkg.com}"
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs
|
||||
spec: "https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js"
|
||||
|
53
CHANGELOG.md
53
CHANGELOG.md
@ -6,6 +6,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [10.35.0]
|
||||
### Added
|
||||
- Add the ability to customize tx nonce on ERC20 approval screens ([#17945](https://github.com/MetaMask/metamask-extension/pull/17945))
|
||||
- Improved gas estimates on Base network ([#20097](https://github.com/MetaMask/metamask-extension/pull/20097))
|
||||
|
||||
### Changed
|
||||
- Update the "Spending Cap Request" screen (also known as the "ERC 20 approval" or "token allowance" screen) ([#19666](https://github.com/MetaMask/metamask-extension/pull/19666))
|
||||
- Populate the "Custom Spending Cap" input with the dapp suggesed value
|
||||
- Show "Use Site Suggestion" button when user changes input
|
||||
- Update copy
|
||||
- Add a "Learn more" link
|
||||
- Update icons and text of Activity Screen, and categorize transactions by dates ([#19557](https://github.com/MetaMask/metamask-extension/pull/19557))
|
||||
- Change the "Import NFTs" UI from a full screen page to a modal ([#19806](https://github.com/MetaMask/metamask-extension/pull/19806))
|
||||
- Add loading indicator when clicking Refresh list on tokens screen ([#19952](https://github.com/MetaMask/metamask-extension/pull/19952))
|
||||
- Bolden "Done" text for priv key export button ([#20059](https://github.com/MetaMask/metamask-extension/pull/20059))
|
||||
- Added background color of test network icons in the network menu ([#20032](https://github.com/MetaMask/metamask-extension/pull/20032))
|
||||
- Ensure "Show test networks" is toggled on if current network is a test network ([#20048](https://github.com/MetaMask/metamask-extension/pull/20048))
|
||||
- Disable the "Show test networks" toggle when the currently selected network is a test network ([#19951](https://github.com/MetaMask/metamask-extension/pull/19951))
|
||||
- Increase size of nft detection text ([#20053](https://github.com/MetaMask/metamask-extension/pull/20053))
|
||||
- Add underline to most link texts on hover ([#19992](https://github.com/MetaMask/metamask-extension/pull/19992))
|
||||
- Move MetaMask fee and quote list to new line for swap review quote ([#20030](https://github.com/MetaMask/metamask-extension/pull/20030))
|
||||
- Change the "Import NFTs" UI from a full screen page to a modal ([#19806](https://github.com/MetaMask/metamask-extension/pull/19806))
|
||||
- Change "Hardware wallet" link text to "Add Hardware wallet" ([#20026](https://github.com/MetaMask/metamask-extension/pull/20026))
|
||||
- Remove the portfolio icon from the screen (because it is now it the three dot menu) ([#19988](https://github.com/MetaMask/metamask-extension/pull/19988))
|
||||
- Use System Theme colors for tooltip ([#19954](https://github.com/MetaMask/metamask-extension/pull/19954))
|
||||
- Separate the test networks from other networks in the "Select a network" popup ([#19812](https://github.com/MetaMask/metamask-extension/pull/19812))
|
||||
- Update "three dot" menu on token screen ([#19765](https://github.com/MetaMask/metamask-extension/pull/19765))
|
||||
- Make the token's three-dot menu smaller
|
||||
- Move it next to the breadcrumbs
|
||||
- Remove the "Account Details" option from the token detail menu
|
||||
- Update BNB Chain name from "BNB Smart Chain" to "BNB Chain" ([#19836](https://github.com/MetaMask/metamask-extension/pull/19836))
|
||||
- [FLASK] Allow Snaps to use `eth_accounts` as a revokable permission ([#19306](https://github.com/MetaMask/metamask-extension/pull/19306))
|
||||
|
||||
|
||||
### Fixed
|
||||
- Fix "Hold to reveal SRP" button on mobile browsers ([#19847](https://github.com/MetaMask/metamask-extension/pull/19847))
|
||||
- Correctly show network name and selection when chainIds collide ([#19947](https://github.com/MetaMask/metamask-extension/pull/19947))
|
||||
- Fix misaligned icons in 'Connected sites' modal ([#19944](https://github.com/MetaMask/metamask-extension/pull/19944))
|
||||
- Show the icon of the correct network in the "badge" associated with token icon's in the assets list ([#19964](https://github.com/MetaMask/metamask-extension/pull/19964))
|
||||
- Stop showing "product tour" steps when on the Swaps screen ([#19938](https://github.com/MetaMask/metamask-extension/pull/19938))
|
||||
- Fixing auto scrolling to settings when searching within Advanced and Security settings ([#19771](https://github.com/MetaMask/metamask-extension/pull/19771))
|
||||
- Fixed connected sites icon's background color ([#19891](https://github.com/MetaMask/metamask-extension/pull/19891))
|
||||
- Fix to ensure "Account Details" is displayed when that option is selected from each accounts three-dot menu within the Account Menu ([#19857](https://github.com/MetaMask/metamask-extension/pull/19857))
|
||||
- Render correct image in the asset dropdown while sending an NFT ([#19787](https://github.com/MetaMask/metamask-extension/pull/19787))
|
||||
- Removed grey line from connected sites modal if there are no connected sites ([#20036](https://github.com/MetaMask/metamask-extension/pull/20036))
|
||||
- [FLASK] Fix overflow on snaps connect screen ([#19995](https://github.com/MetaMask/metamask-extension/pull/19995))
|
||||
- [FLASK] Fix Snaps UI divider ([#19919](https://github.com/MetaMask/metamask-extension/pull/19919))
|
||||
- [FLASK] Fix fetch for snap registry ([#19866](https://github.com/MetaMask/metamask-extension/pull/19866))
|
||||
- [FLASK] Fix Snaps UI divider ([#19919](https://github.com/MetaMask/metamask-extension/pull/19919))
|
||||
|
||||
## [10.34.5]
|
||||
### Changed
|
||||
- Improve error diagnostic information
|
||||
@ -3896,7 +3946,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Uncategorized
|
||||
- Added the ability to restore accounts from seed words.
|
||||
|
||||
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.34.5...HEAD
|
||||
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.35.0...HEAD
|
||||
[10.35.0]: https://github.com/MetaMask/metamask-extension/compare/v10.34.5...v10.35.0
|
||||
[10.34.5]: https://github.com/MetaMask/metamask-extension/compare/v10.34.4...v10.34.5
|
||||
[10.34.4]: https://github.com/MetaMask/metamask-extension/compare/v10.34.3...v10.34.4
|
||||
[10.34.3]: https://github.com/MetaMask/metamask-extension/compare/v10.34.2...v10.34.3
|
||||
|
3
app/_locales/am/messages.json
generated
3
app/_locales/am/messages.json
generated
@ -545,9 +545,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "የግል አውታረ መረብ"
|
||||
},
|
||||
"queue": {
|
||||
"message": "ወረፋ"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "በመለያ አማራጮችዎ ምናሌ ውስጥ ወደ “ተለዋጭ ስም አክል” በመግባት ለወደፊቱ ይህን ተለዋጭ ስም መልሰው ማከል ይችላሉ።"
|
||||
},
|
||||
|
3
app/_locales/ar/messages.json
generated
3
app/_locales/ar/messages.json
generated
@ -557,9 +557,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "شبكة خاصة"
|
||||
},
|
||||
"queue": {
|
||||
"message": "اللائحة"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "يمكنك إضافة هذه العملة الرمزية مرة أخرى في المستقبل من خلال الانتقال إلى \"إضافة عملة رمزية\" في قائمة خيارات الحسابات الخاصة بك."
|
||||
},
|
||||
|
3
app/_locales/bg/messages.json
generated
3
app/_locales/bg/messages.json
generated
@ -556,9 +556,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Частна мрежа"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Опашка"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Можете да добавите този жетон в бъдеще, като отидете на „Добавяне на жетон“ в менюто с опции на акаунти."
|
||||
},
|
||||
|
3
app/_locales/bn/messages.json
generated
3
app/_locales/bn/messages.json
generated
@ -554,9 +554,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "ব্যক্তিগত নেটওয়ার্ক"
|
||||
},
|
||||
"queue": {
|
||||
"message": "অপেক্ষমাণ"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "আপনি আপনার অ্যাকাউন্টস বিকল্পের মেনুতে \"টোকেনগুলি যোগ করুন\" এ গিয়ে ভবিষ্যতে আবার এই টোকেনটি যোগ করতে পারবেন। "
|
||||
},
|
||||
|
3
app/_locales/ca/messages.json
generated
3
app/_locales/ca/messages.json
generated
@ -541,9 +541,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Xarxa privada"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Cua"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Pots tornar a afegir aquesta fitxa en el futur anant a \"Afegir fitxa\" al menu d'opcions dels teus comptes."
|
||||
},
|
||||
|
3
app/_locales/da/messages.json
generated
3
app/_locales/da/messages.json
generated
@ -541,9 +541,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Privat netværk"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Kø"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Du kan tilføje denne token i fremtiden, ved at gå til \"Tilføj token\" under dine valgmenuen for dine konti."
|
||||
},
|
||||
|
13
app/_locales/de/messages.json
generated
13
app/_locales/de/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Öffentliche Adresse"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Warteschlange"
|
||||
},
|
||||
"queued": {
|
||||
"message": "In Warteschlange"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Seed-Phrase anzeigen"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Überprüfen SIe Ihre Ausgabegrenze"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Erlaubnis zum Zugriff auf alle Ihre $1 sowie deren Übertragung entziehen?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "$1 ohne Ausgabenlimit genehmigen",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Eine Ausgabegrenze für Ihr $1 einrichten",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Einstellungen"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Diese URL wird derzeit vom $1-Netzwerk verwendet."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Standardeinstellungen verwenden"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Kontoguthaben-Anfragen sammeln"
|
||||
},
|
||||
|
13
app/_locales/el/messages.json
generated
13
app/_locales/el/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Δημόσια Διεύθυνση"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Ουρά"
|
||||
},
|
||||
"queued": {
|
||||
"message": "Σε Αναμονή"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Αποκάλυψη φράσης ανάκτησης"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Επανεξετάστε το όριο δαπανών σας"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Ανάκληση άδειας πρόσβασης σε όλα σας τα $1;",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3137,10 +3131,6 @@
|
||||
"message": "Έγκριση $1 χωρίς όριο δαπανών",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Ορίστε ένα ανώτατο όριο δαπανών για το $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Ρυθμίσεις"
|
||||
},
|
||||
@ -4164,9 +4154,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Αυτό το URL χρησιμοποιείται επί του παρόντος από το δίκτυο $1."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Χρήση προκαθορισμένου"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Μαζικά αιτήματα υπολοίπου λογαριασμού"
|
||||
},
|
||||
|
78
app/_locales/en/messages.json
generated
78
app/_locales/en/messages.json
generated
@ -249,6 +249,9 @@
|
||||
"addFromAListOfPopularNetworks": {
|
||||
"message": "Add from a list of popular networks or add a network manually. Only interact with the entities you trust."
|
||||
},
|
||||
"addHardwareWallet": {
|
||||
"message": "Add hardware wallet"
|
||||
},
|
||||
"addMemo": {
|
||||
"message": "Add memo"
|
||||
},
|
||||
@ -366,6 +369,9 @@
|
||||
"allowThisSiteTo": {
|
||||
"message": "Allow this site to:"
|
||||
},
|
||||
"allowThisSnapTo": {
|
||||
"message": "Allow this snap to:"
|
||||
},
|
||||
"allowWithdrawAndSpend": {
|
||||
"message": "Allow $1 to withdraw and spend up to the following amount:",
|
||||
"description": "The url of the site that requested permission to 'withdraw and spend'"
|
||||
@ -525,6 +531,9 @@
|
||||
"message": "This is a beta version. Please report bugs $1",
|
||||
"description": "$1 represents the word 'here' in a hyperlink"
|
||||
},
|
||||
"betaMetamaskInstitutionalVersion": {
|
||||
"message": "MetaMask Institutional Beta Version"
|
||||
},
|
||||
"betaMetamaskVersion": {
|
||||
"message": "MetaMask Beta Version"
|
||||
},
|
||||
@ -979,6 +988,12 @@
|
||||
"custodianAccount": {
|
||||
"message": "Custodian account"
|
||||
},
|
||||
"custodianAccountAddedDesc": {
|
||||
"message": "You can now use your custodian accounts in MetaMask Institutional."
|
||||
},
|
||||
"custodianAccountAddedTitle": {
|
||||
"message": "Selected custodian accounts have been added."
|
||||
},
|
||||
"custodianReplaceRefreshTokenChangedFailed": {
|
||||
"message": "Please go to $1 and click the 'Connect to MMI' button within their user interface to connect your accounts to MMI again."
|
||||
},
|
||||
@ -1052,6 +1067,9 @@
|
||||
"customerSupport": {
|
||||
"message": "customer support"
|
||||
},
|
||||
"dappRequestedSpendingCap": {
|
||||
"message": "Site requested spending cap"
|
||||
},
|
||||
"dappSuggested": {
|
||||
"message": "Site suggested"
|
||||
},
|
||||
@ -1743,9 +1761,6 @@
|
||||
"hardware": {
|
||||
"message": "Hardware"
|
||||
},
|
||||
"hardwareWallet": {
|
||||
"message": "Hardware wallet"
|
||||
},
|
||||
"hardwareWalletConnected": {
|
||||
"message": "Hardware wallet connected"
|
||||
},
|
||||
@ -2256,6 +2271,9 @@
|
||||
"metaMaskConnectStatusParagraphTwo": {
|
||||
"message": "The connection status button shows if the website you’re visiting is connected to your currently selected account."
|
||||
},
|
||||
"metamaskInstitutionalVersion": {
|
||||
"message": "MetaMask Institutional Version"
|
||||
},
|
||||
"metamaskSwapsOfflineDescription": {
|
||||
"message": "MetaMask Swaps is undergoing maintenance. Please check back later."
|
||||
},
|
||||
@ -2300,6 +2318,9 @@
|
||||
"mmiAuthenticate": {
|
||||
"message": "The page at $1 would like to authorise the following project’s compliance settings in MetaMask Institutional"
|
||||
},
|
||||
"mmiBuiltAroundTheWorld": {
|
||||
"message": "MetaMask Institutional is designed and built around the world."
|
||||
},
|
||||
"more": {
|
||||
"message": "more"
|
||||
},
|
||||
@ -3074,9 +3095,6 @@
|
||||
"message": "You have (1) pending transaction.",
|
||||
"description": "$1 is count of pending transactions"
|
||||
},
|
||||
"percentage": {
|
||||
"message": "$1%"
|
||||
},
|
||||
"permissionRequest": {
|
||||
"message": "Permission request"
|
||||
},
|
||||
@ -3332,9 +3350,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Public address"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Queue"
|
||||
},
|
||||
"queued": {
|
||||
"message": "Queued"
|
||||
},
|
||||
@ -3507,6 +3522,18 @@
|
||||
"restoreUserDataDescription": {
|
||||
"message": "You can restore user settings containing preferences and account addresses from a previously backed up JSON file."
|
||||
},
|
||||
"resultPageError": {
|
||||
"message": "Error"
|
||||
},
|
||||
"resultPageErrorDefaultMessage": {
|
||||
"message": "The operation failed."
|
||||
},
|
||||
"resultPageSuccess": {
|
||||
"message": "Success"
|
||||
},
|
||||
"resultPageSuccessDefaultMessage": {
|
||||
"message": "The operation completed successfully."
|
||||
},
|
||||
"retryTransaction": {
|
||||
"message": "Retry transaction"
|
||||
},
|
||||
@ -3550,9 +3577,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Reveal seed phrase"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Review the spending cap for your"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Revoke permission to access and transfer all of your $1?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3569,6 +3593,9 @@
|
||||
"message": "This revokes the permission for a third party to access and transfer all of your NFTs from $1 without further notice.",
|
||||
"description": "$1 is a link to contract on the block explorer when we're not able to retrieve a erc721 or erc1155 name"
|
||||
},
|
||||
"revokePermission": {
|
||||
"message": "Revoke permission"
|
||||
},
|
||||
"revokeSpendingCap": {
|
||||
"message": "Revoke spending cap for your $1",
|
||||
"description": "$1 is a token symbol"
|
||||
@ -3690,6 +3717,9 @@
|
||||
"selectAccounts": {
|
||||
"message": "Select the account(s) to use on this site"
|
||||
},
|
||||
"selectAccountsForSnap": {
|
||||
"message": "Select the account(s) to use with this snap"
|
||||
},
|
||||
"selectAll": {
|
||||
"message": "Select all"
|
||||
},
|
||||
@ -3766,10 +3796,6 @@
|
||||
"message": "Approve $1 with no spend limit",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Set a spending cap for your $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settingAddSnapAccount": {
|
||||
"message": "Add snap account"
|
||||
},
|
||||
@ -3779,10 +3805,6 @@
|
||||
"settingsSearchMatchingNotFound": {
|
||||
"message": "No matching results found."
|
||||
},
|
||||
"shortVersion": {
|
||||
"message": "v$1",
|
||||
"description": "$1 is the version number to show"
|
||||
},
|
||||
"show": {
|
||||
"message": "Show"
|
||||
},
|
||||
@ -4096,6 +4118,9 @@
|
||||
"message": "Only enter a number that you're comfortable with $1 accessing now or in the future. You can always increase the token limit later.",
|
||||
"description": "$1 is origin of the site requesting the token limit"
|
||||
},
|
||||
"spendingCapRequest": {
|
||||
"message": "Spending cap request for your $1"
|
||||
},
|
||||
"srpInputNumberOfWords": {
|
||||
"message": "I have a $1-word phrase",
|
||||
"description": "This is the text for each option in the dropdown where a user selects how many words their secret recovery phrase has during import. The $1 is the number of words (either 12, 15, 18, 21, or 24)."
|
||||
@ -4447,6 +4472,10 @@
|
||||
"message": "Includes a $1% MetaMask fee.",
|
||||
"description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number."
|
||||
},
|
||||
"swapIncludesMetaMaskFeeViewAllQuotes": {
|
||||
"message": "Includes a $1% MetaMask fee – $2",
|
||||
"description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number and $2 is a link to view all quotes."
|
||||
},
|
||||
"swapLearnMore": {
|
||||
"message": "Learn more about Swaps"
|
||||
},
|
||||
@ -5145,9 +5174,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "This URL is currently used by the $1 network."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Use default"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Batch account balance requests"
|
||||
},
|
||||
@ -5178,6 +5204,9 @@
|
||||
"usePhishingDetectionDescription": {
|
||||
"message": "Display a warning for phishing domains targeting Ethereum users"
|
||||
},
|
||||
"useSiteSuggestion": {
|
||||
"message": "Use site suggestion"
|
||||
},
|
||||
"useTokenDetectionPrivacyDesc": {
|
||||
"message": "Automatically displaying tokens sent to your account involves communication with third party servers to fetch token’s images. Those serves will have access to your IP address."
|
||||
},
|
||||
@ -5211,6 +5240,9 @@
|
||||
"viewAllDetails": {
|
||||
"message": "View all details"
|
||||
},
|
||||
"viewAllQuotes": {
|
||||
"message": "view all quotes"
|
||||
},
|
||||
"viewContact": {
|
||||
"message": "View contact"
|
||||
},
|
||||
|
13
app/_locales/es/messages.json
generated
13
app/_locales/es/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Dirección pública"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Cola"
|
||||
},
|
||||
"queued": {
|
||||
"message": "En cola"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Revelar frase semilla"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Revise su límite de gasto"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "¿Revocar el permiso para acceder y transferir todos sus $1?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "Aprobar $1 sin límite preestablecido",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Establecer un límite de gasto para su $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Configuración"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "En este momento, la red $1 está utilizando esta dirección URL."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Uso por defecto"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Solicitudes de saldo de cuenta por lotes"
|
||||
},
|
||||
|
3
app/_locales/es_419/messages.json
generated
3
app/_locales/es_419/messages.json
generated
@ -1767,9 +1767,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Dirección pública"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Cola"
|
||||
},
|
||||
"queued": {
|
||||
"message": "En cola"
|
||||
},
|
||||
|
3
app/_locales/et/messages.json
generated
3
app/_locales/et/messages.json
generated
@ -550,9 +550,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Privaatvõrk"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Järjekord"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Saate selle loa tulevikus tagasi lisada, kui lähete oma kontovalikute menüüs vahelehele „Lisa luba“."
|
||||
},
|
||||
|
3
app/_locales/fa/messages.json
generated
3
app/_locales/fa/messages.json
generated
@ -560,9 +560,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "شبکه شخصی"
|
||||
},
|
||||
"queue": {
|
||||
"message": "صف"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "شما میتوانید این رمزیاب را دوباره برای آینده با رفتن به گزینه \"Add token\" در مینوی تنظیمات حساب ها، اضافه نمایید."
|
||||
},
|
||||
|
3
app/_locales/fi/messages.json
generated
3
app/_locales/fi/messages.json
generated
@ -557,9 +557,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Yksityinen verkko"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Jono"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Voit lisätä tämän tietueen myöhemmin takaisin siirtymällä tilisi vaihtoehtovalikon kohtaan ”Lisää tietue”."
|
||||
},
|
||||
|
3
app/_locales/fil/messages.json
generated
3
app/_locales/fil/messages.json
generated
@ -484,9 +484,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Pribadong Network"
|
||||
},
|
||||
"queue": {
|
||||
"message": "I-queue"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Puwede mong idagdag ulit ang token na ito sa hinaharap sa pamamagitan ng pagpunta sa “Magdagdag ng token” sa menu ng mga opsyon ng iyong mga accounts."
|
||||
},
|
||||
|
13
app/_locales/fr/messages.json
generated
13
app/_locales/fr/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Adresse publique"
|
||||
},
|
||||
"queue": {
|
||||
"message": "File d’attente"
|
||||
},
|
||||
"queued": {
|
||||
"message": "En attente"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Révéler la phrase mnémonique"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Modifiez votre plafond de dépenses"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Révoquer l’autorisation d’accès et de transfert de tous vos $1 ?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "Approuver $1 sans limite de dépenses",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Fixez un plafond de dépenses pour vos $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Paramètres"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Cette URL est actuellement utilisée par le réseau $1."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Utiliser par défaut"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Demandes d’informations concernant le solde de plusieurs comptes"
|
||||
},
|
||||
|
3
app/_locales/gu/messages.json
generated
3
app/_locales/gu/messages.json
generated
@ -103,9 +103,6 @@
|
||||
"password": {
|
||||
"message": "પાસવર્ડ"
|
||||
},
|
||||
"queue": {
|
||||
"message": "કતારમાં"
|
||||
},
|
||||
"reject": {
|
||||
"message": "નકારો"
|
||||
},
|
||||
|
3
app/_locales/he/messages.json
generated
3
app/_locales/he/messages.json
generated
@ -557,9 +557,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "רשת פרטית"
|
||||
},
|
||||
"queue": {
|
||||
"message": "תור"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "באפשרותך להוסיף טוקן זה בחזרה בעתיד על ידי מעבר אל \"הוסף טוקן\" בתפריט אפשרויות החשבונות שלך."
|
||||
},
|
||||
|
13
app/_locales/hi/messages.json
generated
13
app/_locales/hi/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "सार्वजनिक पता"
|
||||
},
|
||||
"queue": {
|
||||
"message": "कतार"
|
||||
},
|
||||
"queued": {
|
||||
"message": "कतारबद्ध"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "सीड फ़्रेज़ दिखाएं"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "अपनी खर्च के सीमा की समीक्षा करें"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "आपके सभी $1 को एक्सेस और स्थानांतरित करने की अनुमति निरस्त करें?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "बिना किसी खर्च सीमा के $1 स्वीकृत करें",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "अपने $1 के लिए खर्च की सीमा को निर्धारित करें",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "सेटिंग"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "यह URL वर्तमान में $1 नेटवर्क द्वारा उपयोग किया जाता है।"
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "डिफॉल्ट का उपयोग करें"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "खाता के शेष राशि के अनुरोधों को बैच करें"
|
||||
},
|
||||
|
3
app/_locales/hr/messages.json
generated
3
app/_locales/hr/messages.json
generated
@ -553,9 +553,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Privatna mreža"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Red čekanja"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Ovaj token možete dodati kasnije odlaskom pod stavku „Dodaj token” u izborniku mogućnosti računa. "
|
||||
},
|
||||
|
3
app/_locales/hu/messages.json
generated
3
app/_locales/hu/messages.json
generated
@ -553,9 +553,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Magánhálózat"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Nyomtatólista"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Ezt a tokent a jövőben is hozzáadhatja, ha a fiókbeállítások menü „Token hozzáadása” elemére lép."
|
||||
},
|
||||
|
13
app/_locales/id/messages.json
generated
13
app/_locales/id/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Alamat publik"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Antrean"
|
||||
},
|
||||
"queued": {
|
||||
"message": "Antrean"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Ungkap frasa seed"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Tinjau batas pengeluaran Anda"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Cabut izin untuk mengakses dan mentransfer seluruh $1 Anda?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "Setujui $1 tanpa batas penggunaan",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Tetapkan batas pengeluaran untuk $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Pengaturan"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "URL ini saat ini digunakan oleh jaringan $1."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Gunakan default"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Kelompokkan permintaan saldo akun"
|
||||
},
|
||||
|
3
app/_locales/it/messages.json
generated
3
app/_locales/it/messages.json
generated
@ -1301,9 +1301,6 @@
|
||||
"provide": {
|
||||
"message": "Fornisci"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Coda"
|
||||
},
|
||||
"queued": {
|
||||
"message": "In coda"
|
||||
},
|
||||
|
13
app/_locales/ja/messages.json
generated
13
app/_locales/ja/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "パブリックアドレス"
|
||||
},
|
||||
"queue": {
|
||||
"message": "キュー"
|
||||
},
|
||||
"queued": {
|
||||
"message": "キュー待ち"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "シードフレーズを表示"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "使用上限を確認してください"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "すべての $1 へのアクセスおよび転送許可を取り消しますか?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "使用限度額なしで $1 を承認",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "$1 の使用上限を設定",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "設定"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "このURLは現在$1ネットワークで使用されています。"
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "既定値を使用"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "アカウント残高の一括リクエスト"
|
||||
},
|
||||
|
3
app/_locales/kn/messages.json
generated
3
app/_locales/kn/messages.json
generated
@ -560,9 +560,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "ಖಾಸಗಿ ನೆಟ್ವರ್ಕ್"
|
||||
},
|
||||
"queue": {
|
||||
"message": "ಸರತಿ"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "ನಿಮ್ಮ ಖಾತೆಗಳ ಆಯ್ಕೆಗಳ ಮೆನುವಿನಲ್ಲಿ \"ಟೋಕನ್ ಸೇರಿಸು\" ಗೆ ಹೋಗುವ ಮೂಲಕ ನೀವು ಈ ಟೋಕನ್ ಅನ್ನು ಭವಿಷ್ಯದಲ್ಲಿ ಮರಳಿ ಸೇರಿಸಬಹುದು."
|
||||
},
|
||||
|
13
app/_locales/ko/messages.json
generated
13
app/_locales/ko/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "공개 주소"
|
||||
},
|
||||
"queue": {
|
||||
"message": "대기열"
|
||||
},
|
||||
"queued": {
|
||||
"message": "대기열에 지정됨"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "시드 구문 보기"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "지출 한도 검토"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "모든 $1에 액세스할 수 있는 권한을 철회할까요?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "$1 무제한 지출 승인",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "$1에 대한 지출 한도 설정",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "설정"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "이 URL은 현재 $1 네트워크에서 사용됩니다."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "기본값 사용"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "일괄 계정 잔액 요청"
|
||||
},
|
||||
|
3
app/_locales/lt/messages.json
generated
3
app/_locales/lt/messages.json
generated
@ -560,9 +560,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Privatus tinklas"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Eilė"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Šį žetoną galite bet kada galite įtraukti ir vėl, tiesiog savo paskyros parinkčių meniu nueikite į „Įtraukti žetoną“."
|
||||
},
|
||||
|
3
app/_locales/lv/messages.json
generated
3
app/_locales/lv/messages.json
generated
@ -556,9 +556,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Privātais tīkls"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Rinda"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Jūs varat šo marķieri iestatīt atpakaļ nākotnē, konta opciju izvēlnē atverot \"Pievienot marķieri\"."
|
||||
},
|
||||
|
3
app/_locales/ml/messages.json
generated
3
app/_locales/ml/messages.json
generated
@ -103,9 +103,6 @@
|
||||
"password": {
|
||||
"message": "പാസ്വേഡ്"
|
||||
},
|
||||
"queue": {
|
||||
"message": "ക്യൂവിൽ"
|
||||
},
|
||||
"reject": {
|
||||
"message": "നിരസിക്കുക"
|
||||
},
|
||||
|
3
app/_locales/mr/messages.json
generated
3
app/_locales/mr/messages.json
generated
@ -103,9 +103,6 @@
|
||||
"password": {
|
||||
"message": "पासवर्ड"
|
||||
},
|
||||
"queue": {
|
||||
"message": "रांग"
|
||||
},
|
||||
"reject": {
|
||||
"message": "नाकारा"
|
||||
},
|
||||
|
3
app/_locales/ms/messages.json
generated
3
app/_locales/ms/messages.json
generated
@ -540,9 +540,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Rangkaian Persendirian"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Baris Gilir"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Anda boleh tambah token ini kembali pada masa depan dengan pergi ke \"Tambah token\" di dalam menu pilihan akaun anda."
|
||||
},
|
||||
|
3
app/_locales/no/messages.json
generated
3
app/_locales/no/messages.json
generated
@ -544,9 +544,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Privat nettverk "
|
||||
},
|
||||
"queue": {
|
||||
"message": "Kø"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Du kan legge til dette tokenet igjen i fremtiden ved å gå til \"Legg til token\" i menyen for kontoalternativer."
|
||||
},
|
||||
|
3
app/_locales/ph/messages.json
generated
3
app/_locales/ph/messages.json
generated
@ -1105,9 +1105,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Pampublikong Address"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Queue"
|
||||
},
|
||||
"queued": {
|
||||
"message": "Naka-queue"
|
||||
},
|
||||
|
3
app/_locales/pl/messages.json
generated
3
app/_locales/pl/messages.json
generated
@ -554,9 +554,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Sieć prywatna"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Kolejka"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Możesz później ponownie dodać ten token poprzez \"Dodaj token\" w opcjach menu swojego konta."
|
||||
},
|
||||
|
13
app/_locales/pt/messages.json
generated
13
app/_locales/pt/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Endereço público"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Fila"
|
||||
},
|
||||
"queued": {
|
||||
"message": "Na fila"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Revelar a frase de recuperação"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Revise seu limite de gastos"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Revogar permissão de acesso e transferência de todos os seus $1?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "Aprovar $1 sem limite de gastos",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Definir um limite de gastos para seu $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Definições"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "O ID da cadeia está sendo usado pela rede $1."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Usar padrão"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Agrupar solicitações de saldo de contas"
|
||||
},
|
||||
|
3
app/_locales/pt_BR/messages.json
generated
3
app/_locales/pt_BR/messages.json
generated
@ -1767,9 +1767,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Endereço público"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Fila"
|
||||
},
|
||||
"queued": {
|
||||
"message": "Na fila"
|
||||
},
|
||||
|
3
app/_locales/pt_PT/messages.json
generated
3
app/_locales/pt_PT/messages.json
generated
@ -113,9 +113,6 @@
|
||||
"privacyMsg": {
|
||||
"message": "Política de Privacidade"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Fila"
|
||||
},
|
||||
"reject": {
|
||||
"message": "Rejeitar"
|
||||
},
|
||||
|
3
app/_locales/ro/messages.json
generated
3
app/_locales/ro/messages.json
generated
@ -547,9 +547,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Rețea privată"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Coadă"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Puteți adăuga din nou acest indicativ în viitor accesând „Adăugați indicativ” din meniul de opțiuni al contului dvs."
|
||||
},
|
||||
|
13
app/_locales/ru/messages.json
generated
13
app/_locales/ru/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Открытый адрес"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Очередь"
|
||||
},
|
||||
"queued": {
|
||||
"message": "В очереди"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Показать сид-фразу"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Проверьте свой лимит расходов"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Отозвать разрешение на доступ ко всем вашим $1 и их перевод?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "Одобрить $1 без ограничений по расходам",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Установить верхний лимит расходов для вашего $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Настройки"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Это URL-адрес в настоящее время используется сетью $1."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Использовать значения по умолчанию"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Пакетные запросы баланса счета"
|
||||
},
|
||||
|
3
app/_locales/sk/messages.json
generated
3
app/_locales/sk/messages.json
generated
@ -532,9 +532,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Soukromá síť"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Poradie"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Tento token můžete v budoucnu přidat zpět s „Přidat token“ v nastavení účtu."
|
||||
},
|
||||
|
3
app/_locales/sl/messages.json
generated
3
app/_locales/sl/messages.json
generated
@ -548,9 +548,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Zasebno omrežje"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Čakalna vrsta"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Ta žeton lahko dodate tudi kasneje z uporabo gumba “Dodaj žeton” v možnostih vašega računa."
|
||||
},
|
||||
|
3
app/_locales/sr/messages.json
generated
3
app/_locales/sr/messages.json
generated
@ -551,9 +551,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Privatna mreža"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Ред"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "U budućnosti možete vratiti ovaj token tako što ćete otvoriti „Dodaj token“ u meniju opcija vašeg naloga."
|
||||
},
|
||||
|
3
app/_locales/sv/messages.json
generated
3
app/_locales/sv/messages.json
generated
@ -544,9 +544,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Privat nätverk"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Utskriftskö"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Du kan lägga till denna token i framtiden genom att välja \"Lägg till token\" i kontots alternativmeny."
|
||||
},
|
||||
|
3
app/_locales/sw/messages.json
generated
3
app/_locales/sw/messages.json
generated
@ -538,9 +538,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Mtandao Binafsi"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Foleni"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Unaweza kuongeza tena kianzio hiki hapo baadaye kwa kwenda kwenye \"Ongeza kianzio\" kwenye machaguo yako ya menyu ya akaunti."
|
||||
},
|
||||
|
3
app/_locales/ta/messages.json
generated
3
app/_locales/ta/messages.json
generated
@ -322,9 +322,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "தனியார் நெட்வொர்க்"
|
||||
},
|
||||
"queue": {
|
||||
"message": "வரிசை"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "உங்கள் கணக்கு விருப்பங்கள் மெனுவில் \"டோக்கனைச் சேர்\" என்பதன் மூலம் நீங்கள் எதிர்காலத்தில் இந்த டோக்கனை மீண்டும் சேர்க்கலாம்."
|
||||
},
|
||||
|
3
app/_locales/te/messages.json
generated
3
app/_locales/te/messages.json
generated
@ -103,9 +103,6 @@
|
||||
"password": {
|
||||
"message": "పాస్వర్డ్"
|
||||
},
|
||||
"queue": {
|
||||
"message": "క్రమ వరుస"
|
||||
},
|
||||
"reject": {
|
||||
"message": "తిరస్కరించు"
|
||||
},
|
||||
|
13
app/_locales/tl/messages.json
generated
13
app/_locales/tl/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Pampublikong Address"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Pila"
|
||||
},
|
||||
"queued": {
|
||||
"message": "Naka-queue"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Ipakita ang seed phrase"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "I-review ang iyong limitasyon sa paggastos"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Bawiin ang pahintulot na i-access at ilipat ang lahat ng iyong $1?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "Aprubahan ang $1 nang walang limitasyon sa paggastos",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Magtakda ng limitasyon sa paggastos para sa iyong $1",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Mga Setting"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Nasa kasalukuyang listahan ng mga network na ang URL."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Gamitin ang default"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Mga kahilingan sa balanse ng batch account"
|
||||
},
|
||||
|
13
app/_locales/tr/messages.json
generated
13
app/_locales/tr/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Genel adres"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Kuyruğa al"
|
||||
},
|
||||
"queued": {
|
||||
"message": "Kuyruğa alındı"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Tohum ifadesini ortaya çıkar"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Harcama üst limitinize göz atın"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Tüm $1 için izin erişim ve transfer izni geri çekilsin mi?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "$1 için harcama limiti olmadan onay ver",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "$1 için harcama üst limiti belirle",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Ayarlar"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Bu URL şu anda $1 ağı tarafından kullanılıyor."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Varsayılanı kullan"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Toplu hesap bakiyesi talepleri"
|
||||
},
|
||||
|
3
app/_locales/uk/messages.json
generated
3
app/_locales/uk/messages.json
generated
@ -560,9 +560,6 @@
|
||||
"privateNetwork": {
|
||||
"message": "Приватна мережа"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Черга"
|
||||
},
|
||||
"readdToken": {
|
||||
"message": "Ви можете знову додати цей токен у меню облікового запису у розділі “Додати токен”. "
|
||||
},
|
||||
|
13
app/_locales/vi/messages.json
generated
13
app/_locales/vi/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "Địa chỉ công khai"
|
||||
},
|
||||
"queue": {
|
||||
"message": "Hàng đợi"
|
||||
},
|
||||
"queued": {
|
||||
"message": "Đã đưa vào hàng đợi"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "Hiện cụm từ khôi phục bí mật"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "Xem lại hạn mức chi tiêu của bạn"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "Thu hồi quyền truy cập và chuyển tất cả $1 của bạn?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "Phê duyệt $1 không có giới hạn chi tiêu",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "Đặt hạn mức chi tiêu cho $1 của bạn",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "Cài đặt"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "Mạng $1 hiện đang sử dụng URL này."
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "Sử dụng mặc định"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "Xử lý hàng loạt yêu cầu số dư tài khoản"
|
||||
},
|
||||
|
13
app/_locales/zh_CN/messages.json
generated
13
app/_locales/zh_CN/messages.json
generated
@ -2753,9 +2753,6 @@
|
||||
"publicAddress": {
|
||||
"message": "公共地址"
|
||||
},
|
||||
"queue": {
|
||||
"message": "队列"
|
||||
},
|
||||
"queued": {
|
||||
"message": "队列中"
|
||||
},
|
||||
@ -2956,9 +2953,6 @@
|
||||
"revealTheSeedPhrase": {
|
||||
"message": "显示助记词"
|
||||
},
|
||||
"reviewSpendingCap": {
|
||||
"message": "检查您的支出上限"
|
||||
},
|
||||
"revokeAllTokensTitle": {
|
||||
"message": "撤销访问和转移您的所有 $1 的权限?",
|
||||
"description": "$1 is the symbol of the token for which the user is revoking approval"
|
||||
@ -3140,10 +3134,6 @@
|
||||
"message": "批准$1,且无消费限制",
|
||||
"description": "The token symbol that is being approved"
|
||||
},
|
||||
"setSpendingCap": {
|
||||
"message": "为 $1 设置支出上限",
|
||||
"description": "$1 is a token symbol"
|
||||
},
|
||||
"settings": {
|
||||
"message": "设置"
|
||||
},
|
||||
@ -4167,9 +4157,6 @@
|
||||
"urlExistsErrorMsg": {
|
||||
"message": "此 URL 目前已被 $1 网络使用。"
|
||||
},
|
||||
"useDefault": {
|
||||
"message": "使用默认值"
|
||||
},
|
||||
"useMultiAccountBalanceChecker": {
|
||||
"message": "账户余额分批请求"
|
||||
},
|
||||
|
3
app/_locales/zh_TW/messages.json
generated
3
app/_locales/zh_TW/messages.json
generated
@ -1051,9 +1051,6 @@
|
||||
"publicAddress": {
|
||||
"message": "公開位址"
|
||||
},
|
||||
"queue": {
|
||||
"message": "佇列"
|
||||
},
|
||||
"queued": {
|
||||
"message": "已排入佇列"
|
||||
},
|
||||
|
1
app/images/icons/check-bold.svg
Normal file
1
app/images/icons/check-bold.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="m412 145c12 12 12 32 0 45l-185 183c-12 12-32 12-45 0l-81-80c-13-13-13-33 0-46 12-12 32-12 45 0l59 58 161-161c13-12 33-12 46 1z"/></svg>
|
After Width: | Height: | Size: 207 B |
1
app/images/icons/minus-bold.svg
Normal file
1
app/images/icons/minus-bold.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="m93 224l320 0c18 0 32 14 32 32 0 18-14 32-32 32l-320 0c-18 0-32-14-32-32 0-18 14-32 32-32z"/></svg>
|
After Width: | Height: | Size: 171 B |
@ -1,5 +1,5 @@
|
||||
{
|
||||
"content_security_policy": "frame-ancestors 'none'; script-src 'self'; object-src 'self'",
|
||||
"content_security_policy": "frame-ancestors 'none'; script-src 'self' 'wasm-unsafe-eval'; object-src 'self'",
|
||||
"externally_connectable": {
|
||||
"matches": ["https://metamask.io/*"],
|
||||
"ids": ["*"]
|
||||
|
@ -615,6 +615,12 @@ function redirectToPhishingWarning() {
|
||||
|
||||
const querystring = new URLSearchParams({ hostname, href });
|
||||
window.location.href = `${baseUrl}#${querystring}`;
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (1) {
|
||||
console.log(
|
||||
'MetaMask: Locking js execution, redirection will complete shortly',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const start = () => {
|
||||
|
@ -442,25 +442,8 @@ export default class MMIController extends EventEmitter {
|
||||
return keyring.getTransactionDeepLink(from, custodyTxId);
|
||||
}
|
||||
|
||||
async getCustodianToken(custodianType) {
|
||||
let currentCustodyType;
|
||||
|
||||
const address = this.preferencesController.getSelectedAddress();
|
||||
|
||||
if (!custodianType) {
|
||||
const resultCustody = this.custodyController.getCustodyTypeByAddress(
|
||||
toChecksumHexAddress(address),
|
||||
);
|
||||
currentCustodyType = resultCustody;
|
||||
}
|
||||
let keyring = await this.keyringController.getKeyringsByType(
|
||||
currentCustodyType || `Custody - ${custodianType}`,
|
||||
)[0];
|
||||
if (!keyring) {
|
||||
keyring = await this.keyringController.addNewKeyring(
|
||||
currentCustodyType || `Custody - ${custodianType}`,
|
||||
);
|
||||
}
|
||||
async getCustodianToken(address) {
|
||||
const keyring = await this.keyringController.getKeyringForAccount(address);
|
||||
const { authDetails } = keyring.getAccountDetails(address);
|
||||
return keyring ? authDetails.jwt || authDetails.refreshToken : '';
|
||||
}
|
||||
|
@ -1305,6 +1305,8 @@ export default class TransactionController extends EventEmitter {
|
||||
txMeta.custodyId,
|
||||
fromAddress,
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
|
93
app/scripts/lib/indexed-db-backend.test.ts
Normal file
93
app/scripts/lib/indexed-db-backend.test.ts
Normal file
@ -0,0 +1,93 @@
|
||||
import 'fake-indexeddb/auto';
|
||||
|
||||
import { IndexedDBPPOMStorage } from './indexed-db-backend';
|
||||
|
||||
Object.defineProperty(globalThis, 'crypto', {
|
||||
value: {
|
||||
subtle: {
|
||||
digest: () => new ArrayBuffer(12),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const enc = new TextEncoder();
|
||||
const dec = new TextDecoder('utf-8');
|
||||
|
||||
describe('IndexedDBPPOMStorage', () => {
|
||||
it('should be able to initialise correctly', () => {
|
||||
const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1);
|
||||
expect(indexDBBackend).toBeDefined();
|
||||
});
|
||||
|
||||
it('should be able to write and read file data if checksum matches', async () => {
|
||||
const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1);
|
||||
await indexDBBackend.write(
|
||||
{ name: 'fake_name', chainId: '5' },
|
||||
enc.encode('fake_data'),
|
||||
'000000000000000000000000',
|
||||
);
|
||||
const file = await indexDBBackend.read(
|
||||
{ name: 'fake_name', chainId: '5' },
|
||||
'000000000000000000000000',
|
||||
);
|
||||
expect(dec.decode(file)).toStrictEqual('fake_data');
|
||||
});
|
||||
|
||||
it('should fail to write if checksum does not match', async () => {
|
||||
const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1);
|
||||
await expect(async () => {
|
||||
await indexDBBackend.write(
|
||||
{ name: 'fake_name', chainId: '5' },
|
||||
enc.encode('fake_data'),
|
||||
'XXX',
|
||||
);
|
||||
}).rejects.toThrow('Checksum mismatch');
|
||||
});
|
||||
|
||||
it('should fail to read if checksum does not match', async () => {
|
||||
const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1);
|
||||
await expect(async () => {
|
||||
await indexDBBackend.write(
|
||||
{ name: 'fake_name', chainId: '5' },
|
||||
enc.encode('fake_data'),
|
||||
'000000000000000000000000',
|
||||
);
|
||||
await indexDBBackend.read({ name: 'fake_name', chainId: '5' }, 'XXX');
|
||||
}).rejects.toThrow('Checksum mismatch');
|
||||
});
|
||||
|
||||
it('should delete a file when delete method is called', async () => {
|
||||
const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1);
|
||||
await indexDBBackend.write(
|
||||
{ name: 'fake_name', chainId: '5' },
|
||||
enc.encode('fake_data'),
|
||||
'000000000000000000000000',
|
||||
);
|
||||
await indexDBBackend.delete({ name: 'fake_name', chainId: '5' });
|
||||
const result = await indexDBBackend.read(
|
||||
{ name: 'fake_name', chainId: '5' },
|
||||
'000000000000000000000000',
|
||||
);
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should list all keys when dir is called', async () => {
|
||||
const keys = [
|
||||
{ chainId: '5', name: 'fake_name_1' },
|
||||
{ chainId: '1', name: 'fake_name_2' },
|
||||
];
|
||||
const indexDBBackend = new IndexedDBPPOMStorage('PPOMDB', 1);
|
||||
await indexDBBackend.write(
|
||||
keys[0],
|
||||
enc.encode('fake_data_1'),
|
||||
'000000000000000000000000',
|
||||
);
|
||||
await indexDBBackend.write(
|
||||
keys[1],
|
||||
enc.encode('fake_data_2'),
|
||||
'000000000000000000000000',
|
||||
);
|
||||
const result = await indexDBBackend.dir();
|
||||
expect(result).toStrictEqual(keys);
|
||||
});
|
||||
});
|
127
app/scripts/lib/indexed-db-backend.ts
Normal file
127
app/scripts/lib/indexed-db-backend.ts
Normal file
@ -0,0 +1,127 @@
|
||||
import { StorageBackend } from '@metamask/ppom-validator';
|
||||
|
||||
type StorageKey = {
|
||||
name: string;
|
||||
chainId: string;
|
||||
};
|
||||
|
||||
const validateChecksum = async (
|
||||
key: StorageKey,
|
||||
data: ArrayBuffer,
|
||||
checksum: string,
|
||||
) => {
|
||||
const hash = await crypto.subtle.digest('SHA-256', data);
|
||||
const hashString = Array.from(new Uint8Array(hash))
|
||||
.map((b) => b.toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
|
||||
if (hashString !== checksum) {
|
||||
throw new Error(`Checksum mismatch for key ${key}`);
|
||||
}
|
||||
};
|
||||
|
||||
export class IndexedDBPPOMStorage implements StorageBackend {
|
||||
private storeName: string;
|
||||
|
||||
private dbVersion: number;
|
||||
|
||||
constructor(storeName: string, dbVersion: number) {
|
||||
this.storeName = storeName;
|
||||
this.dbVersion = dbVersion;
|
||||
}
|
||||
|
||||
#getObjectStore(mode: IDBTransactionMode): Promise<IDBObjectStore> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = indexedDB.open(this.storeName, this.dbVersion);
|
||||
|
||||
request.onerror = (event: Event) => {
|
||||
reject(
|
||||
new Error(
|
||||
`Failed to open database ${this.storeName}: ${
|
||||
(event.target as any)?.error
|
||||
}`,
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
request.onupgradeneeded = (event) => {
|
||||
const db = (event.target as IDBOpenDBRequest).result;
|
||||
|
||||
if (!db.objectStoreNames.contains(this.storeName)) {
|
||||
db.createObjectStore(this.storeName, {
|
||||
keyPath: ['name', 'chainId'],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
request.onsuccess = (event) => {
|
||||
const db = (event.target as IDBOpenDBRequest).result;
|
||||
const transaction = db.transaction([this.storeName], mode);
|
||||
const objectStore = transaction.objectStore(this.storeName);
|
||||
resolve(objectStore);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private async objectStoreAction(
|
||||
method: 'get' | 'delete' | 'put' | 'getAllKeys',
|
||||
args?: any,
|
||||
mode: IDBTransactionMode = 'readonly',
|
||||
): Promise<any> {
|
||||
return new Promise<Event>((resolve, reject) => {
|
||||
this.#getObjectStore(mode)
|
||||
.then((objectStore) => {
|
||||
const request = objectStore[method](args);
|
||||
|
||||
request.onsuccess = async (event) => {
|
||||
resolve(event);
|
||||
};
|
||||
|
||||
request.onerror = (event) => {
|
||||
reject(
|
||||
new Error(
|
||||
`Error in indexDB operation ${method}: ${
|
||||
(event.target as any)?.error
|
||||
}`,
|
||||
),
|
||||
);
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async read(key: StorageKey, checksum: string): Promise<ArrayBuffer> {
|
||||
const event = await this.objectStoreAction('get', [key.name, key.chainId]);
|
||||
const data = (event.target as any)?.result?.data;
|
||||
await validateChecksum(key, data, checksum);
|
||||
return data;
|
||||
}
|
||||
|
||||
async write(
|
||||
key: StorageKey,
|
||||
data: ArrayBuffer,
|
||||
checksum: string,
|
||||
): Promise<void> {
|
||||
await validateChecksum(key, data, checksum);
|
||||
await this.objectStoreAction('put', { ...key, data }, 'readwrite');
|
||||
}
|
||||
|
||||
async delete(key: StorageKey): Promise<void> {
|
||||
await this.objectStoreAction(
|
||||
'delete',
|
||||
[key.name, key.chainId],
|
||||
'readwrite',
|
||||
);
|
||||
}
|
||||
|
||||
async dir(): Promise<StorageKey[]> {
|
||||
const event = await this.objectStoreAction('getAllKeys');
|
||||
return (event.target as any)?.result.map(([name, chainId]: string[]) => ({
|
||||
name,
|
||||
chainId,
|
||||
}));
|
||||
}
|
||||
}
|
@ -76,6 +76,9 @@ import { CustodyController } from '@metamask-institutional/custody-controller';
|
||||
import { TransactionUpdateController } from '@metamask-institutional/transaction-update';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import { SignatureController } from '@metamask/signature-controller';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(blockaid)
|
||||
import { PPOMController, createPPOMMiddleware } from '@metamask/ppom-validator';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(desktop)
|
||||
// eslint-disable-next-line import/order
|
||||
@ -211,6 +214,9 @@ import {
|
||||
} from './controllers/permissions';
|
||||
import createRPCMethodTrackingMiddleware from './lib/createRPCMethodTrackingMiddleware';
|
||||
import { securityProviderCheck } from './lib/security-provider-helpers';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(blockaid)
|
||||
import { IndexedDBPPOMStorage } from './lib/indexed-db-backend';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import { updateCurrentLocale } from './translate';
|
||||
|
||||
export const METAMASK_CONTROLLER_EVENTS = {
|
||||
@ -324,31 +330,42 @@ export default class MetamaskController extends EventEmitter {
|
||||
],
|
||||
});
|
||||
|
||||
let initialProviderConfig;
|
||||
if (process.env.IN_TEST) {
|
||||
initialProviderConfig = {
|
||||
type: NETWORK_TYPES.RPC,
|
||||
rpcUrl: 'http://localhost:8545',
|
||||
chainId: '0x539',
|
||||
nickname: 'Localhost 8545',
|
||||
ticker: 'ETH',
|
||||
let initialNetworkControllerState = {};
|
||||
if (initState.NetworkController) {
|
||||
initialNetworkControllerState = initState.NetworkController;
|
||||
} else if (process.env.IN_TEST) {
|
||||
initialNetworkControllerState = {
|
||||
providerConfig: {
|
||||
chainId: CHAIN_IDS.LOCALHOST,
|
||||
nickname: 'Localhost 8545',
|
||||
rpcPrefs: {},
|
||||
rpcUrl: 'http://localhost:8545',
|
||||
ticker: 'ETH',
|
||||
type: 'rpc',
|
||||
},
|
||||
networkConfigurations: {
|
||||
networkConfigurationId: {
|
||||
chainId: CHAIN_IDS.LOCALHOST,
|
||||
nickname: 'Localhost 8545',
|
||||
rpcPrefs: {},
|
||||
rpcUrl: 'http://localhost:8545',
|
||||
ticker: 'ETH',
|
||||
networkConfigurationId: 'networkConfigurationId',
|
||||
},
|
||||
},
|
||||
};
|
||||
} else if (
|
||||
process.env.METAMASK_DEBUG ||
|
||||
process.env.METAMASK_ENVIRONMENT === 'test'
|
||||
) {
|
||||
initialProviderConfig = {
|
||||
type: NETWORK_TYPES.GOERLI,
|
||||
chainId: CHAIN_IDS.GOERLI,
|
||||
ticker: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.GOERLI],
|
||||
initialNetworkControllerState = {
|
||||
providerConfig: {
|
||||
type: NETWORK_TYPES.GOERLI,
|
||||
chainId: CHAIN_IDS.GOERLI,
|
||||
ticker: TEST_NETWORK_TICKER_MAP[NETWORK_TYPES.GOERLI],
|
||||
},
|
||||
};
|
||||
}
|
||||
const initialNetworkControllerState = initialProviderConfig
|
||||
? {
|
||||
providerConfig: initialProviderConfig,
|
||||
...initState.NetworkController,
|
||||
}
|
||||
: initState.NetworkController;
|
||||
this.networkController = new NetworkController({
|
||||
messenger: networkControllerMessenger,
|
||||
state: initialNetworkControllerState,
|
||||
@ -577,8 +594,12 @@ export default class MetamaskController extends EventEmitter {
|
||||
),
|
||||
getCurrentAccountEIP1559Compatibility:
|
||||
this.getCurrentAccountEIP1559Compatibility.bind(this),
|
||||
legacyAPIEndpoint: `${gasApiBaseUrl}/networks/<chain_id>/gasPrices`,
|
||||
EIP1559APIEndpoint: `${gasApiBaseUrl}/networks/<chain_id>/suggestedGasFees`,
|
||||
getCurrentNetworkLegacyGasAPICompatibility: () => false,
|
||||
getCurrentNetworkLegacyGasAPICompatibility: () => {
|
||||
const { chainId } = this.networkController.state.providerConfig;
|
||||
return chainId === CHAIN_IDS.BSC;
|
||||
},
|
||||
getChainId: () => this.networkController.state.providerConfig.chainId,
|
||||
});
|
||||
|
||||
@ -624,6 +645,22 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.phishingController.setStalelistRefreshInterval(30 * SECOND);
|
||||
}
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(blockaid)
|
||||
this.ppomController = new PPOMController({
|
||||
messenger: this.controllerMessenger.getRestricted({
|
||||
name: 'PPOMController',
|
||||
}),
|
||||
storageBackend: new IndexedDBPPOMStorage('PPOMDB', 1),
|
||||
provider: this.provider,
|
||||
state: initState.PPOMController,
|
||||
chainId: this.networkController.state.providerConfig.chainId,
|
||||
onNetworkChange: networkControllerMessenger.subscribe.bind(
|
||||
networkControllerMessenger,
|
||||
'NetworkController:stateChange',
|
||||
),
|
||||
});
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
const announcementMessenger = this.controllerMessenger.getRestricted({
|
||||
name: 'AnnouncementController',
|
||||
});
|
||||
@ -1476,6 +1513,18 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.signatureController.newUnsignedPersonalMessage.bind(
|
||||
this.signatureController,
|
||||
),
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
|
||||
setTypedMessageInProgress:
|
||||
this.signatureController.setTypedMessageInProgress.bind(
|
||||
this.signatureController,
|
||||
),
|
||||
setPersonalMessageInProgress:
|
||||
this.signatureController.setPersonalMessageInProgress.bind(
|
||||
this.signatureController,
|
||||
),
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
processEncryptionPublicKey:
|
||||
this.encryptionPublicKeyController.newRequestEncryptionPublicKey.bind(
|
||||
this.encryptionPublicKeyController,
|
||||
@ -1511,6 +1560,9 @@ export default class MetamaskController extends EventEmitter {
|
||||
SwapsController: this.swapsController.store,
|
||||
EnsController: this.ensController.store,
|
||||
ApprovalController: this.approvalController,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(blockaid)
|
||||
PPOMController: this.ppomController,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
};
|
||||
|
||||
this.store.updateStructure({
|
||||
@ -1617,6 +1669,9 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.swapsController.resetState,
|
||||
this.ensController.resetState,
|
||||
this.approvalController.clear.bind(this.approvalController),
|
||||
///: BEGIN:ONLY_INCLUDE_IN(blockaid)
|
||||
this.ppomController.clear.bind(this.ppomController),
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
// WE SHOULD ADD TokenListController.resetState here too. But it's not implemented yet.
|
||||
];
|
||||
|
||||
@ -2455,6 +2510,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.institutionalFeaturesController.removeAddTokenConnectRequest.bind(
|
||||
this.institutionalFeaturesController,
|
||||
),
|
||||
showInteractiveReplacementTokenBanner:
|
||||
appStateController.showInteractiveReplacementTokenBanner.bind(
|
||||
appStateController,
|
||||
),
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(snaps)
|
||||
@ -2479,6 +2538,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.controllerMessenger,
|
||||
'SnapController:handleRequest',
|
||||
),
|
||||
revokeDynamicSnapPermissions: this.controllerMessenger.call.bind(
|
||||
this.controllerMessenger,
|
||||
'SnapController:revokeDynamicPermissions',
|
||||
),
|
||||
dismissNotifications: this.dismissNotifications.bind(this),
|
||||
markNotificationsAsRead: this.markNotificationsAsRead.bind(this),
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
@ -3893,6 +3956,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
engine.push(createLoggerMiddleware({ origin }));
|
||||
engine.push(this.permissionLogController.createMiddleware());
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(blockaid)
|
||||
engine.push(createPPOMMiddleware(this.ppomController));
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
engine.push(
|
||||
createRPCMethodTrackingMiddleware({
|
||||
trackEvent: this.metaMetricsController.trackEvent.bind(
|
||||
@ -3946,6 +4013,12 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.approvalController.setFlowLoadingText.bind(
|
||||
this.approvalController,
|
||||
),
|
||||
showApprovalSuccess: this.approvalController.success.bind(
|
||||
this.approvalController,
|
||||
),
|
||||
showApprovalError: this.approvalController.error.bind(
|
||||
this.approvalController,
|
||||
),
|
||||
sendMetrics: this.metaMetricsController.trackEvent.bind(
|
||||
this.metaMetricsController,
|
||||
),
|
||||
|
@ -87,9 +87,9 @@ buildTypes:
|
||||
- SEGMENT_MMI_WRITE_KEY
|
||||
- INFURA_ENV_KEY_REF: INFURA_MMI_PROJECT_ID
|
||||
- SEGMENT_WRITE_KEY_REF: SEGMENT_MMI_WRITE_KEY
|
||||
- MMI_CONFIGURATION_SERVICE_URL: https://configuration.metamask-institutional.io/v1/configuration/default
|
||||
- SUPPORT_LINK: https://mmi-support.zendesk.com/hc/en-us
|
||||
- SUPPORT_REQUEST_LINK: https://mmi-support.zendesk.com/hc/en-us/requests/new
|
||||
- MMI_CONFIGURATION_SERVICE_URL: https://configuration.metamask-institutional.io/v1/configuration/default
|
||||
# For some reason, MMI uses this type of versioning
|
||||
# Leaving it on for backwards compatibility
|
||||
isPrerelease: true
|
||||
@ -116,6 +116,7 @@ features:
|
||||
- DISABLE_WEB_SOCKET_ENCRYPTION: false
|
||||
- SKIP_OTP_PAIRING_FLOW: false
|
||||
- WEB_SOCKET_PORT: null
|
||||
blockaid:
|
||||
|
||||
###
|
||||
# Build Type code extensions. Things like different support links, warning pages, banners
|
||||
|
@ -11,7 +11,12 @@ const VARIABLES_REQUIRED_IN_PRODUCTION = {
|
||||
main: ['INFURA_PROD_PROJECT_ID', 'SEGMENT_PROD_WRITE_KEY', 'SENTRY_DSN'],
|
||||
beta: ['INFURA_BETA_PROJECT_ID', 'SEGMENT_BETA_WRITE_KEY', 'SENTRY_DSN'],
|
||||
flask: ['INFURA_FLASK_PROJECT_ID', 'SEGMENT_FLASK_WRITE_KEY', 'SENTRY_DSN'],
|
||||
mmi: ['INFURA_MMI_PROJECT_ID', 'SEGMENT_MMI_WRITE_KEY', 'SENTRY_DSN'],
|
||||
mmi: [
|
||||
'INFURA_MMI_PROJECT_ID',
|
||||
'MMI_CONFIGURATION_SERVICE_URL',
|
||||
'SEGMENT_MMI_WRITE_KEY',
|
||||
'SENTRY_DSN',
|
||||
],
|
||||
};
|
||||
|
||||
async function fromIniFile(filepath) {
|
||||
|
@ -22,19 +22,20 @@ module.exports = function createStaticAssetTasks({
|
||||
const copyTargetsProds = {};
|
||||
const copyTargetsDevs = {};
|
||||
|
||||
const buildConfig = loadBuildTypesConfig();
|
||||
|
||||
const activeFeatures = buildConfig.buildTypes[buildType].features ?? [];
|
||||
|
||||
browserPlatforms.forEach((browser) => {
|
||||
const [copyTargetsProd, copyTargetsDev] = getCopyTargets(
|
||||
shouldIncludeLockdown,
|
||||
shouldIncludeSnow,
|
||||
activeFeatures,
|
||||
);
|
||||
copyTargetsProds[browser] = copyTargetsProd;
|
||||
copyTargetsDevs[browser] = copyTargetsDev;
|
||||
});
|
||||
|
||||
const buildConfig = loadBuildTypesConfig();
|
||||
|
||||
const activeFeatures = buildConfig.buildTypes[buildType].features ?? [];
|
||||
|
||||
const additionalAssets = activeFeatures.flatMap(
|
||||
(feature) =>
|
||||
buildConfig.features[feature].assets?.filter(
|
||||
@ -108,7 +109,11 @@ module.exports = function createStaticAssetTasks({
|
||||
}
|
||||
};
|
||||
|
||||
function getCopyTargets(shouldIncludeLockdown, shouldIncludeSnow) {
|
||||
function getCopyTargets(
|
||||
shouldIncludeLockdown,
|
||||
shouldIncludeSnow,
|
||||
activeFeatures,
|
||||
) {
|
||||
const allCopyTargets = [
|
||||
{
|
||||
src: `./app/_locales/`,
|
||||
@ -198,6 +203,14 @@ function getCopyTargets(shouldIncludeLockdown, shouldIncludeSnow) {
|
||||
},
|
||||
];
|
||||
|
||||
if (activeFeatures.includes('blockaid')) {
|
||||
allCopyTargets.push({
|
||||
src: getPathInsideNodeModules('@metamask/ppom-validator', 'dist/'),
|
||||
pattern: '*.wasm',
|
||||
dest: '',
|
||||
});
|
||||
}
|
||||
|
||||
const languageTags = new Set();
|
||||
for (const locale of locales) {
|
||||
const { code } = locale;
|
||||
|
@ -11,13 +11,19 @@
|
||||
* @param {string} args.rejectionMessage - The message for the rejected promise
|
||||
* this function will return in the event of failure. (Default: "Retry limit
|
||||
* reached")
|
||||
* @param {string} args.retryUntilFailure - Retries until the function fails.
|
||||
* @param {Function} functionToRetry - The function that is run and tested for
|
||||
* failure.
|
||||
* @returns {Promise<null | Error>} a promise that either resolves to null if
|
||||
* the function is successful or is rejected with rejectionMessage otherwise.
|
||||
*/
|
||||
async function retry(
|
||||
{ retries, delay = 0, rejectionMessage = 'Retry limit reached' },
|
||||
{
|
||||
retries,
|
||||
delay = 0,
|
||||
rejectionMessage = 'Retry limit reached',
|
||||
retryUntilFailure = false,
|
||||
},
|
||||
functionToRetry,
|
||||
) {
|
||||
let attempts = 0;
|
||||
@ -28,9 +34,14 @@ async function retry(
|
||||
|
||||
try {
|
||||
await functionToRetry();
|
||||
return;
|
||||
if (!retryUntilFailure) {
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
if (retryUntilFailure) {
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
attempts += 1;
|
||||
}
|
||||
|
@ -1162,9 +1162,6 @@
|
||||
"ui/hooks/useUserPreferencedCurrency.test.js",
|
||||
"ui/index.js",
|
||||
"ui/index.test.js",
|
||||
"ui/pages/add-nft/add-nft.js",
|
||||
"ui/pages/add-nft/add-nft.test.js",
|
||||
"ui/pages/add-nft/index.js",
|
||||
"ui/pages/asset/asset.js",
|
||||
"ui/pages/asset/components/asset-breadcrumb.js",
|
||||
"ui/pages/asset/components/asset-navigation.js",
|
||||
|
@ -775,6 +775,9 @@
|
||||
}
|
||||
},
|
||||
"@metamask/approval-controller": {
|
||||
"globals": {
|
||||
"console.info": true
|
||||
},
|
||||
"packages": {
|
||||
"@metamask/approval-controller>nanoid": true,
|
||||
"@metamask/base-controller": true,
|
||||
|
@ -775,6 +775,9 @@
|
||||
}
|
||||
},
|
||||
"@metamask/approval-controller": {
|
||||
"globals": {
|
||||
"console.info": true
|
||||
},
|
||||
"packages": {
|
||||
"@metamask/approval-controller>nanoid": true,
|
||||
"@metamask/base-controller": true,
|
||||
@ -1944,7 +1947,6 @@
|
||||
"@metamask/rpc-methods-flask>@metamask/snaps-ui": true,
|
||||
"@metamask/rpc-methods-flask>@metamask/snaps-utils": true,
|
||||
"@metamask/rpc-methods-flask>@metamask/utils": true,
|
||||
"@metamask/rpc-methods-flask>nanoid": true,
|
||||
"eth-rpc-errors": true,
|
||||
"superstruct": true
|
||||
}
|
||||
@ -2151,7 +2153,6 @@
|
||||
"@metamask/snaps-controllers-flask>@metamask/snaps-utils": true,
|
||||
"@metamask/snaps-controllers-flask>@metamask/snaps-utils>@metamask/snaps-ui": true,
|
||||
"@metamask/snaps-controllers-flask>@metamask/utils": true,
|
||||
"@metamask/snaps-controllers-flask>nanoid": true,
|
||||
"eth-rpc-errors": true,
|
||||
"superstruct": true
|
||||
}
|
||||
@ -4915,9 +4916,9 @@
|
||||
},
|
||||
"react-markdown>unified": {
|
||||
"packages": {
|
||||
"jsdom>request>extend": true,
|
||||
"mocha>yargs-unparser>is-plain-obj": true,
|
||||
"react-markdown>unified>bail": true,
|
||||
"react-markdown>unified>extend": true,
|
||||
"react-markdown>unified>is-buffer": true,
|
||||
"react-markdown>unified>trough": true,
|
||||
"react-markdown>vfile": true
|
||||
|
@ -775,6 +775,9 @@
|
||||
}
|
||||
},
|
||||
"@metamask/approval-controller": {
|
||||
"globals": {
|
||||
"console.info": true
|
||||
},
|
||||
"packages": {
|
||||
"@metamask/approval-controller>nanoid": true,
|
||||
"@metamask/base-controller": true,
|
||||
@ -1944,7 +1947,6 @@
|
||||
"@metamask/rpc-methods-flask>@metamask/snaps-ui": true,
|
||||
"@metamask/rpc-methods-flask>@metamask/snaps-utils": true,
|
||||
"@metamask/rpc-methods-flask>@metamask/utils": true,
|
||||
"@metamask/rpc-methods-flask>nanoid": true,
|
||||
"eth-rpc-errors": true,
|
||||
"superstruct": true
|
||||
}
|
||||
@ -2151,7 +2153,6 @@
|
||||
"@metamask/snaps-controllers-flask>@metamask/snaps-utils": true,
|
||||
"@metamask/snaps-controllers-flask>@metamask/snaps-utils>@metamask/snaps-ui": true,
|
||||
"@metamask/snaps-controllers-flask>@metamask/utils": true,
|
||||
"@metamask/snaps-controllers-flask>nanoid": true,
|
||||
"eth-rpc-errors": true,
|
||||
"superstruct": true
|
||||
}
|
||||
@ -4915,9 +4916,9 @@
|
||||
},
|
||||
"react-markdown>unified": {
|
||||
"packages": {
|
||||
"jsdom>request>extend": true,
|
||||
"mocha>yargs-unparser>is-plain-obj": true,
|
||||
"react-markdown>unified>bail": true,
|
||||
"react-markdown>unified>extend": true,
|
||||
"react-markdown>unified>is-buffer": true,
|
||||
"react-markdown>unified>trough": true,
|
||||
"react-markdown>vfile": true
|
||||
|
@ -775,6 +775,9 @@
|
||||
}
|
||||
},
|
||||
"@metamask/approval-controller": {
|
||||
"globals": {
|
||||
"console.info": true
|
||||
},
|
||||
"packages": {
|
||||
"@metamask/approval-controller>nanoid": true,
|
||||
"@metamask/base-controller": true,
|
||||
|
@ -815,11 +815,18 @@
|
||||
},
|
||||
"packages": {
|
||||
"@ethereumjs/tx>@ethereumjs/util": true,
|
||||
"@metamask-institutional/custody-controller": true,
|
||||
"@metamask-institutional/extension>@metamask-institutional/custody-controller": true,
|
||||
"@metamask-institutional/sdk": true,
|
||||
"@metamask-institutional/sdk>@metamask-institutional/types": true
|
||||
}
|
||||
},
|
||||
"@metamask-institutional/extension>@metamask-institutional/custody-controller": {
|
||||
"packages": {
|
||||
"@ethereumjs/tx>@ethereumjs/util": true,
|
||||
"@metamask-institutional/custody-keyring": true,
|
||||
"@metamask/obs-store": true
|
||||
}
|
||||
},
|
||||
"@metamask-institutional/institutional-features": {
|
||||
"globals": {
|
||||
"chrome.runtime.id": true,
|
||||
@ -996,6 +1003,9 @@
|
||||
}
|
||||
},
|
||||
"@metamask/approval-controller": {
|
||||
"globals": {
|
||||
"console.info": true
|
||||
},
|
||||
"packages": {
|
||||
"@metamask/approval-controller>nanoid": true,
|
||||
"@metamask/base-controller": true,
|
||||
|
@ -3105,12 +3105,12 @@
|
||||
"packages": {
|
||||
"eslint>eslint-visitor-keys": true,
|
||||
"eslint>espree>acorn-jsx": true,
|
||||
"terser>acorn": true
|
||||
"jsdom>acorn": true
|
||||
}
|
||||
},
|
||||
"eslint>espree>acorn-jsx": {
|
||||
"packages": {
|
||||
"terser>acorn": true
|
||||
"jsdom>acorn": true
|
||||
}
|
||||
},
|
||||
"eslint>esquery": {
|
||||
@ -5831,7 +5831,7 @@
|
||||
"gulp>vinyl-fs>glob-stream>pumpify": true,
|
||||
"gulp>vinyl-fs>glob-stream>to-absolute-glob": true,
|
||||
"gulp>vinyl-fs>glob-stream>unique-stream": true,
|
||||
"jsdom>request>extend": true,
|
||||
"react-markdown>unified>extend": true,
|
||||
"readable-stream": true,
|
||||
"vinyl>remove-trailing-separator": true
|
||||
}
|
||||
@ -6104,6 +6104,12 @@
|
||||
"process": true
|
||||
}
|
||||
},
|
||||
"jsdom>acorn": {
|
||||
"globals": {
|
||||
"console": true,
|
||||
"define": true
|
||||
}
|
||||
},
|
||||
"koa>is-generator-function>has-tostringtag": {
|
||||
"packages": {
|
||||
"string.prototype.matchall>has-symbols": true
|
||||
@ -6276,7 +6282,6 @@
|
||||
"events": true,
|
||||
"fs.existsSync": true,
|
||||
"fs.readFileSync": true,
|
||||
"fs.writeFileSync": true,
|
||||
"path.extname": true,
|
||||
"path.join": true
|
||||
},
|
||||
@ -7482,9 +7487,9 @@
|
||||
},
|
||||
"react-markdown>unified": {
|
||||
"packages": {
|
||||
"jsdom>request>extend": true,
|
||||
"mocha>yargs-unparser>is-plain-obj": true,
|
||||
"react-markdown>unified>bail": true,
|
||||
"react-markdown>unified>extend": true,
|
||||
"react-markdown>unified>is-buffer": true,
|
||||
"react-markdown>unified>trough": true,
|
||||
"react-markdown>vfile": true
|
||||
@ -8572,8 +8577,8 @@
|
||||
},
|
||||
"packages": {
|
||||
"eslint>imurmurhash": true,
|
||||
"jsdom>request>is-typedarray": true,
|
||||
"nyc>signal-exit": true,
|
||||
"stylelint>write-file-atomic>is-typedarray": true,
|
||||
"stylelint>write-file-atomic>typedarray-to-buffer": true
|
||||
}
|
||||
},
|
||||
@ -8582,7 +8587,7 @@
|
||||
"Buffer.from": true
|
||||
},
|
||||
"packages": {
|
||||
"jsdom>request>is-typedarray": true
|
||||
"stylelint>write-file-atomic>is-typedarray": true
|
||||
}
|
||||
},
|
||||
"superstruct": {
|
||||
@ -8602,8 +8607,8 @@
|
||||
"process": true
|
||||
},
|
||||
"packages": {
|
||||
"terser>@jridgewell/source-map": true,
|
||||
"terser>acorn": true
|
||||
"jsdom>acorn": true,
|
||||
"terser>@jridgewell/source-map": true
|
||||
}
|
||||
},
|
||||
"terser>@jridgewell/source-map": {
|
||||
@ -8649,12 +8654,6 @@
|
||||
"define": true
|
||||
}
|
||||
},
|
||||
"terser>acorn": {
|
||||
"globals": {
|
||||
"console": true,
|
||||
"define": true
|
||||
}
|
||||
},
|
||||
"terser>source-map-support": {
|
||||
"builtin": {
|
||||
"fs": true,
|
||||
|
26
package.json
26
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "metamask-crx",
|
||||
"version": "10.34.5",
|
||||
"version": "10.35.0",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -100,7 +100,7 @@
|
||||
"resolutions": {
|
||||
"@babel/core": "patch:@babel/core@npm%3A7.21.5#./.yarn/patches/@babel-core-npm-7.21.5-c72c337956.patch",
|
||||
"@babel/runtime": "patch:@babel/runtime@npm%3A7.18.9#./.yarn/patches/@babel-runtime-npm-7.18.9-28ca6b5f61.patch",
|
||||
"@metamask/approval-controller": "^3.3.0",
|
||||
"@metamask/approval-controller": "^3.4.0",
|
||||
"@types/react": "^16.9.53",
|
||||
"analytics-node/axios": "^0.21.2",
|
||||
"ganache-core/lodash": "^4.17.21",
|
||||
@ -165,6 +165,7 @@
|
||||
"regenerator-runtime@^0.13.4": "patch:regenerator-runtime@npm%3A0.13.7#./.yarn/patches/regenerator-runtime-npm-0.13.7-41bcbe64ea.patch",
|
||||
"regenerator-runtime@^0.13.7": "patch:regenerator-runtime@npm%3A0.13.7#./.yarn/patches/regenerator-runtime-npm-0.13.7-41bcbe64ea.patch",
|
||||
"regenerator-runtime@^0.11.0": "patch:regenerator-runtime@npm%3A0.13.7#./.yarn/patches/regenerator-runtime-npm-0.13.7-41bcbe64ea.patch",
|
||||
"jsdom@^16.7.0": "patch:jsdom@npm%3A16.7.0#./.yarn/patches/jsdom-npm-16.7.0-216c5c4bf9.patch",
|
||||
"trim": "^0.0.3",
|
||||
"@eslint/eslintrc@^2.0.1": "patch:@eslint/eslintrc@npm%3A2.0.2#./.yarn/patches/@eslint-eslintrc-npm-2.0.2-d308674d86.patch",
|
||||
"@formatjs/intl-utils@^3.3.1": "patch:@formatjs/intl-utils@npm%3A3.3.1#./.yarn/patches/@formatjs-intl-utils-npm-3.3.1-08510c16ad.patch",
|
||||
@ -173,7 +174,7 @@
|
||||
"@lavamoat/lavapack@^3.1.0": "patch:@lavamoat/lavapack@npm%3A3.1.0#./.yarn/patches/@lavamoat-lavapack-npm-3.1.0-34c65d233b.patch",
|
||||
"fast-json-patch@^3.1.0": "patch:fast-json-patch@npm%3A3.1.1#./.yarn/patches/fast-json-patch-npm-3.1.1-7e8bb70a45.patch",
|
||||
"@reduxjs/toolkit@^1.6.2": "patch:@reduxjs/toolkit@npm%3A1.6.2#./.yarn/patches/@reduxjs-toolkit-npm-1.6.2-67af09515f.patch",
|
||||
"parse5@^7.0.0": "patch:parse5@npm%3A7.0.0#./.yarn/patches/parse5-npm-7.0.0-3158a72394.patch",
|
||||
"parse5@^7.0.0": "patch:parse5@npm%3A7.1.2#./.yarn/patches/parse5-npm-7.1.2-aa9a92c270.patch",
|
||||
"@types/madge@^5.0.0": "patch:@types/madge@npm%3A5.0.0#./.yarn/patches/@types-madge-npm-5.0.0-654566c2d2.patch",
|
||||
"zxcvbn@^4.4.2": "patch:zxcvbn@npm%3A4.4.2#./.yarn/patches/zxcvbn-npm-4.4.2-6527983856.patch",
|
||||
"web3@^0.20.7": "patch:web3@npm%3A0.20.7#./.yarn/patches/web3-npm-0.20.7-ee7ef00c57.patch",
|
||||
@ -196,7 +197,8 @@
|
||||
"request@^2.83.0": "patch:request@npm%3A2.88.2#./.yarn/patches/request-npm-2.88.2-f4a57c72c4.patch",
|
||||
"request@^2.88.2": "patch:request@npm%3A2.88.2#./.yarn/patches/request-npm-2.88.2-f4a57c72c4.patch",
|
||||
"request@^2.85.0": "patch:request@npm%3A2.88.2#./.yarn/patches/request-npm-2.88.2-f4a57c72c4.patch",
|
||||
"@metamask/signature-controller@^4.0.1": "patch:@metamask/signature-controller@npm%3A4.0.1#./.yarn/patches/@metamask-signature-controller-npm-4.0.1-013e64c9fd.patch"
|
||||
"@metamask/signature-controller@^4.0.1": "patch:@metamask/signature-controller@npm%3A4.0.1#./.yarn/patches/@metamask-signature-controller-npm-4.0.1-013e64c9fd.patch",
|
||||
"lavamoat-core@^14.2.0": "patch:lavamoat-core@npm%3A14.2.0#./.yarn/patches/lavamoat-core-npm-14.2.0-c453f4f755.patch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.9",
|
||||
@ -217,7 +219,7 @@
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@metamask-institutional/custody-controller": "0.2.6",
|
||||
"@metamask-institutional/custody-keyring": "^0.0.25",
|
||||
"@metamask-institutional/extension": "^0.1.3",
|
||||
"@metamask-institutional/extension": "^0.1.6",
|
||||
"@metamask-institutional/institutional-features": "^1.1.8",
|
||||
"@metamask-institutional/portfolio-dashboard": "^1.1.3",
|
||||
"@metamask-institutional/rpc-allowlist": "^1.0.0",
|
||||
@ -225,7 +227,7 @@
|
||||
"@metamask-institutional/transaction-update": "^0.1.21",
|
||||
"@metamask/address-book-controller": "^3.0.0",
|
||||
"@metamask/announcement-controller": "^4.0.0",
|
||||
"@metamask/approval-controller": "^3.3.0",
|
||||
"@metamask/approval-controller": "^3.4.0",
|
||||
"@metamask/assets-controllers": "^9.2.0",
|
||||
"@metamask/base-controller": "^3.2.0",
|
||||
"@metamask/browser-passworder": "^4.1.0",
|
||||
@ -252,21 +254,22 @@
|
||||
"@metamask/permission-controller": "^4.0.0",
|
||||
"@metamask/phishing-controller": "^6.0.0",
|
||||
"@metamask/post-message-stream": "^6.0.0",
|
||||
"@metamask/ppom-validator": "^0.0.1",
|
||||
"@metamask/providers": "^11.1.0",
|
||||
"@metamask/rate-limit-controller": "^3.0.0",
|
||||
"@metamask/rpc-methods": "^1.0.0-prerelease.1",
|
||||
"@metamask/rpc-methods-flask": "npm:@metamask/rpc-methods@0.35.2-flask.1",
|
||||
"@metamask/rpc-methods-flask": "npm:@metamask/rpc-methods@0.36.1-flask.1",
|
||||
"@metamask/safe-event-emitter": "^2.0.0",
|
||||
"@metamask/scure-bip39": "^2.0.3",
|
||||
"@metamask/signature-controller": "^4.0.1",
|
||||
"@metamask/slip44": "^3.0.0",
|
||||
"@metamask/smart-transactions-controller": "^3.1.0",
|
||||
"@metamask/snaps-controllers": "^1.0.0-prerelease.1",
|
||||
"@metamask/snaps-controllers-flask": "npm:@metamask/snaps-controllers@0.35.2-flask.1",
|
||||
"@metamask/snaps-controllers-flask": "npm:@metamask/snaps-controllers@0.36.1-flask.1",
|
||||
"@metamask/snaps-ui": "^1.0.0-prerelease.1",
|
||||
"@metamask/snaps-ui-flask": "npm:@metamask/snaps-ui@0.35.2-flask.1",
|
||||
"@metamask/snaps-ui-flask": "npm:@metamask/snaps-ui@0.36.1-flask.1",
|
||||
"@metamask/snaps-utils": "^1.0.0-prerelease.1",
|
||||
"@metamask/snaps-utils-flask": "npm:@metamask/snaps-utils@0.35.2-flask.1",
|
||||
"@metamask/snaps-utils-flask": "npm:@metamask/snaps-utils@0.36.1-flask.1",
|
||||
"@metamask/subject-metadata-controller": "^2.0.0",
|
||||
"@metamask/utils": "^5.0.0",
|
||||
"@ngraveio/bc-ur": "^1.1.6",
|
||||
@ -463,6 +466,7 @@
|
||||
"eslint-plugin-react": "^7.23.1",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"eslint-plugin-storybook": "^0.6.12",
|
||||
"fake-indexeddb": "^4.0.1",
|
||||
"fancy-log": "^1.3.3",
|
||||
"fast-glob": "^3.2.2",
|
||||
"fs-extra": "^8.1.0",
|
||||
@ -492,7 +496,7 @@
|
||||
"jest-canvas-mock": "^2.3.1",
|
||||
"jest-environment-jsdom": "^29.1.2",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsdom": "^11.2.0",
|
||||
"jsdom": "^16.7.0",
|
||||
"junit-report-merger": "^4.0.0",
|
||||
"koa": "^2.7.0",
|
||||
"lavamoat": "^7.1.0",
|
||||
|
@ -138,6 +138,8 @@ export const CHAIN_IDS = {
|
||||
BSC_TESTNET: '0x61',
|
||||
OPTIMISM: '0xa',
|
||||
OPTIMISM_TESTNET: '0x1a4',
|
||||
BASE: '0x2105',
|
||||
BASE_TESTNET: '0x14a33',
|
||||
POLYGON: '0x89',
|
||||
POLYGON_TESTNET: '0x13881',
|
||||
AVALANCHE: '0xa86a',
|
||||
@ -174,8 +176,7 @@ export const BSC_DISPLAY_NAME = 'Binance Smart Chain';
|
||||
export const POLYGON_DISPLAY_NAME = 'Polygon';
|
||||
export const AVALANCHE_DISPLAY_NAME = 'Avalanche Network C-Chain';
|
||||
export const ARBITRUM_DISPLAY_NAME = 'Arbitrum One';
|
||||
export const BNB_DISPLAY_NAME =
|
||||
'BNB Smart Chain (previously Binance Smart Chain Mainnet)';
|
||||
export const BNB_DISPLAY_NAME = 'BNB Chain';
|
||||
export const OPTIMISM_DISPLAY_NAME = 'Optimism';
|
||||
export const FANTOM_DISPLAY_NAME = 'Fantom Opera';
|
||||
export const HARMONY_DISPLAY_NAME = 'Harmony Mainnet Shard 0';
|
||||
@ -543,6 +544,8 @@ export const BUYABLE_CHAINS_MAP: {
|
||||
ChainId,
|
||||
| typeof CHAIN_IDS.LOCALHOST
|
||||
| typeof CHAIN_IDS.OPTIMISM_TESTNET
|
||||
| typeof CHAIN_IDS.BASE_TESTNET
|
||||
| typeof CHAIN_IDS.BASE
|
||||
| typeof CHAIN_IDS.BSC_TESTNET
|
||||
| typeof CHAIN_IDS.POLYGON_TESTNET
|
||||
| typeof CHAIN_IDS.AVALANCHE_TESTNET
|
||||
|
@ -29,3 +29,5 @@ export const ExcludedSnapEndowments = Object.freeze({
|
||||
'endowment:long-running is deprecated. For more information please see https://github.com/MetaMask/snaps-monorepo/issues/945.',
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
});
|
||||
|
||||
export const DynamicSnapPermissions = Object.freeze(['eth_accounts']);
|
||||
|
@ -105,7 +105,9 @@ async function withFixtures(options, testSuite) {
|
||||
});
|
||||
}
|
||||
}
|
||||
const mockedEndpoint = await setupMocking(mockServer, testSpecificMock);
|
||||
const mockedEndpoint = await setupMocking(mockServer, testSpecificMock, {
|
||||
chainId: ganacheOptions?.chainId || 1337,
|
||||
});
|
||||
await mockServer.start(8000);
|
||||
|
||||
driver = (await buildWebDriver(driverOptions)).driver;
|
||||
@ -611,12 +613,6 @@ function generateRandNumBetween(x, y) {
|
||||
return randomNumber;
|
||||
}
|
||||
|
||||
async function switchToWindow(driver, windowTitle) {
|
||||
const windowHandles = await driver.getAllWindowHandles();
|
||||
|
||||
return await driver.switchToWindowWithTitle(windowTitle, windowHandles);
|
||||
}
|
||||
|
||||
async function sleepSeconds(sec) {
|
||||
return new Promise((resolve) => setTimeout(resolve, sec * 1000));
|
||||
}
|
||||
@ -633,7 +629,8 @@ async function terminateServiceWorker(driver) {
|
||||
tag: 'button',
|
||||
});
|
||||
|
||||
const serviceWorkerElements = await driver.findElements({
|
||||
await driver.delay(tinyDelayMs);
|
||||
const serviceWorkerElements = await driver.findClickableElements({
|
||||
text: 'terminate',
|
||||
tag: 'span',
|
||||
});
|
||||
@ -641,8 +638,7 @@ async function terminateServiceWorker(driver) {
|
||||
// 1st one is app-init.js; while 2nd one is service-worker.js
|
||||
await serviceWorkerElements[serviceWorkerElements.length - 1].click();
|
||||
|
||||
const serviceWorkerTab = await switchToWindow(
|
||||
driver,
|
||||
const serviceWorkerTab = await driver.switchToWindowWithTitle(
|
||||
WINDOW_TITLES.ServiceWorkerSettings,
|
||||
);
|
||||
|
||||
@ -727,7 +723,6 @@ module.exports = {
|
||||
generateETHBalance,
|
||||
roundToXDecimalPlaces,
|
||||
generateRandNumBetween,
|
||||
switchToWindow,
|
||||
sleepSeconds,
|
||||
terminateServiceWorker,
|
||||
switchToNotificationWindow,
|
||||
|
@ -291,13 +291,12 @@ describe('MetaMask', function () {
|
||||
|
||||
it('transitions to the confirm screen', async function () {
|
||||
// Continue to next screen
|
||||
await driver.delay(largeDelayMs);
|
||||
await driver.waitForElementNotPresent('.loading-overlay');
|
||||
await driver.clickElement({ text: 'Next', tag: 'button' });
|
||||
await driver.delay(largeDelayMs);
|
||||
});
|
||||
|
||||
it('displays the token transfer data', async function () {
|
||||
await driver.delay(largeDelayMs);
|
||||
await driver.waitForElementNotPresent('.loading-overlay');
|
||||
await driver.clickElement({ text: 'Hex', tag: 'button' });
|
||||
await driver.delay(regularDelayMs);
|
||||
|
||||
@ -340,12 +339,12 @@ describe('MetaMask', function () {
|
||||
|
||||
it('finds the transaction in the transactions list', async function () {
|
||||
await driver.waitForSelector({
|
||||
css: '.transaction-list__completed-transactions .transaction-list-item__primary-currency',
|
||||
css: '.transaction-list__completed-transactions [data-testid="transaction-list-item-primary-currency"]',
|
||||
text: '-1 TST',
|
||||
});
|
||||
|
||||
await driver.waitForSelector({
|
||||
css: '.list-item__heading',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Send TST',
|
||||
});
|
||||
});
|
||||
@ -371,10 +370,12 @@ describe('MetaMask', function () {
|
||||
|
||||
await driver.findElements('.transaction-list__pending-transactions');
|
||||
await driver.waitForSelector({
|
||||
css: '.transaction-list-item__primary-currency',
|
||||
css: '[data-testid="transaction-list-item-primary-currency"]',
|
||||
text: '-1.5 TST',
|
||||
});
|
||||
await driver.clickElement('.transaction-list-item__primary-currency');
|
||||
await driver.clickElement(
|
||||
'[data-testid="transaction-list-item-primary-currency"]',
|
||||
);
|
||||
await driver.delay(regularDelayMs);
|
||||
|
||||
const transactionAmounts = await driver.findElements(
|
||||
@ -416,12 +417,12 @@ describe('MetaMask', function () {
|
||||
|
||||
it('finds the transaction in the transactions list', async function () {
|
||||
await driver.waitForSelector({
|
||||
css: '.transaction-list__completed-transactions .transaction-list-item__primary-currency',
|
||||
css: '.transaction-list__completed-transactions [data-testid="transaction-list-item-primary-currency"]',
|
||||
text: '-1.5 TST',
|
||||
});
|
||||
|
||||
await driver.waitForSelector({
|
||||
css: '.list-item__heading',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Send TST',
|
||||
});
|
||||
});
|
||||
@ -463,25 +464,25 @@ describe('MetaMask', function () {
|
||||
});
|
||||
|
||||
await driver.switchToWindow(extension);
|
||||
await driver.delay(regularDelayMs);
|
||||
await driver.delay(veryLargeDelayMs);
|
||||
|
||||
await driver.wait(async () => {
|
||||
const pendingTxes = await driver.findElements(
|
||||
'.transaction-list__pending-transactions .transaction-list-item',
|
||||
'.transaction-list__pending-transactions .activity-list-item',
|
||||
);
|
||||
return pendingTxes.length === 1;
|
||||
}, 10000);
|
||||
|
||||
await driver.waitForSelector({
|
||||
css: '.transaction-list-item__primary-currency',
|
||||
css: '[data-testid="transaction-list-item-primary-currency"]',
|
||||
text: '-1.5 TST',
|
||||
});
|
||||
await driver.clickElement('.transaction-list-item');
|
||||
await driver.clickElement('.activity-list-item');
|
||||
await driver.delay(regularDelayMs);
|
||||
});
|
||||
|
||||
it('submits the transaction', async function () {
|
||||
await driver.delay(largeDelayMs * 2);
|
||||
await driver.waitForElementNotPresent('.loading-overlay');
|
||||
await driver.clickElement({ text: 'Confirm', tag: 'button' });
|
||||
await driver.delay(largeDelayMs * 2);
|
||||
});
|
||||
@ -490,12 +491,12 @@ describe('MetaMask', function () {
|
||||
await driver.waitForSelector({
|
||||
// Select the heading of the first transaction list item in the
|
||||
// completed transaction list with text matching Send TST
|
||||
css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading',
|
||||
css: '.transaction-list__completed-transactions .activity-list-item [data-testid="activity-list-item-action"]',
|
||||
text: 'Send TST',
|
||||
});
|
||||
|
||||
await driver.waitForSelector({
|
||||
css: '.transaction-list__completed-transactions .transaction-list-item:first-child .transaction-list-item__primary-currency',
|
||||
css: '.transaction-list__completed-transactions .activity-list-item [data-testid="transaction-list-item-primary-currency"]',
|
||||
text: '-1.5 TST',
|
||||
});
|
||||
});
|
||||
|
326
test/e2e/metrics/transaction-finalized.spec.js
Normal file
326
test/e2e/metrics/transaction-finalized.spec.js
Normal file
@ -0,0 +1,326 @@
|
||||
/* eslint-disable no-useless-escape */
|
||||
const { strict: assert } = require('assert');
|
||||
const {
|
||||
defaultGanacheOptions,
|
||||
withFixtures,
|
||||
unlockWallet,
|
||||
sendTransaction,
|
||||
getEventPayloads,
|
||||
} = require('../helpers');
|
||||
const FixtureBuilder = require('../fixture-builder');
|
||||
|
||||
/**
|
||||
* mocks the segment api multiple times for specific payloads that we expect to
|
||||
* see when these tests are run. In this case we are looking for
|
||||
* 'Transaction Submitted' and 'Transaction Finalized'. In addition on the
|
||||
* first event of each series we require a field that should only appear in the
|
||||
* anonymized events so that we can guarantee order of seenRequests and can
|
||||
* properly make assertions. Do not use the constants from the metrics
|
||||
* constants files, because if these change we want a strong indicator to our
|
||||
* data team that the shape of data will change.
|
||||
*
|
||||
* @param {import('mockttp').Mockttp} mockServer
|
||||
* @returns {Promise<import('mockttp/dist/pluggable-admin').MockttpClientResponse>[]}
|
||||
*/
|
||||
async function mockSegment(mockServer) {
|
||||
return [
|
||||
await mockServer
|
||||
.forPost('https://api.segment.io/v1/batch')
|
||||
.withJsonBodyIncluding({
|
||||
batch: [
|
||||
{
|
||||
type: 'track',
|
||||
event: 'Transaction Submitted',
|
||||
properties: { status: 'submitted' },
|
||||
},
|
||||
],
|
||||
})
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
};
|
||||
}),
|
||||
await mockServer
|
||||
.forPost('https://api.segment.io/v1/batch')
|
||||
.withJsonBodyIncluding({
|
||||
batch: [
|
||||
{
|
||||
type: 'track',
|
||||
event: 'Transaction Submitted',
|
||||
},
|
||||
],
|
||||
})
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
};
|
||||
}),
|
||||
await mockServer
|
||||
.forPost('https://api.segment.io/v1/batch')
|
||||
.withJsonBodyIncluding({
|
||||
batch: [
|
||||
{
|
||||
type: 'track',
|
||||
event: 'Transaction Finalized',
|
||||
properties: { status: 'confirmed' },
|
||||
},
|
||||
],
|
||||
})
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
};
|
||||
}),
|
||||
await mockServer
|
||||
.forPost('https://api.segment.io/v1/batch')
|
||||
.withJsonBodyIncluding({
|
||||
batch: [
|
||||
{
|
||||
type: 'track',
|
||||
event: 'Transaction Finalized',
|
||||
},
|
||||
],
|
||||
})
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
};
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
const RECIPIENT = '0x0Cc5261AB8cE458dc977078A3623E2BaDD27afD3';
|
||||
|
||||
describe('Transaction Finalized Event', function () {
|
||||
it('Successfully tracked when sending a transaction', async function () {
|
||||
await withFixtures(
|
||||
{
|
||||
fixtures: new FixtureBuilder()
|
||||
.withMetaMetricsController({
|
||||
metaMetricsId: 'fake-metrics-id',
|
||||
participateInMetaMetrics: true,
|
||||
})
|
||||
.build(),
|
||||
ganacheOptions: defaultGanacheOptions,
|
||||
title: this.test.title,
|
||||
testSpecificMock: mockSegment,
|
||||
},
|
||||
async ({ driver, mockedEndpoint: mockedEndpoints }) => {
|
||||
await driver.navigate();
|
||||
await unlockWallet(driver);
|
||||
|
||||
await sendTransaction(driver, RECIPIENT, '2.0');
|
||||
|
||||
const events = await getEventPayloads(driver, mockedEndpoints);
|
||||
// The order of these events is ensured by the mockSegment function
|
||||
// which requires that the first, and third (0, 2 indexes) have the
|
||||
// status property, which will only appear on the anonymous events.
|
||||
const transactionSubmittedNoMMId = events[0];
|
||||
const transactionSubmittedWithMMId = events[1];
|
||||
const transactionFinalizedNoMMId = events[2];
|
||||
const transactionFinalizedWithMMId = events[3];
|
||||
|
||||
// Assert doesn't have generic matchers so we delete these timestamp related properties.
|
||||
// If we switch to a different assertion library we can use generic matchers in the future.
|
||||
delete transactionSubmittedNoMMId.properties.first_seen;
|
||||
delete transactionFinalizedNoMMId.properties.first_seen;
|
||||
delete transactionFinalizedNoMMId.properties.completion_time;
|
||||
|
||||
// Assert that the event names begin with the appropriate prefixes. Even finalized events begin with transaction-submitted
|
||||
// because they start as event fragments created when the transaction is submitted.
|
||||
assert.ok(
|
||||
transactionSubmittedNoMMId.messageId.startsWith(
|
||||
'transaction-submitted',
|
||||
),
|
||||
`Transaction Submitted event with sensitive properties has messageId \"${transactionSubmittedNoMMId.messageId}\" does not have a messageId beginning with \"transaction-submitted\"`,
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
transactionFinalizedNoMMId.messageId.startsWith(
|
||||
'transaction-submitted',
|
||||
),
|
||||
`Transaction Finalized event with sensitive properties has messageId \"${transactionFinalizedNoMMId.messageId}\" that does not begin with \"transaction-submitted\"`,
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
transactionSubmittedWithMMId.messageId.startsWith(
|
||||
'transaction-submitted',
|
||||
),
|
||||
`Transaction Submitted event has messageId \"${transactionSubmittedWithMMId.messageId}\" that does not begin with \"transaction-submitted\"`,
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
transactionFinalizedWithMMId.messageId.startsWith(
|
||||
'transaction-submitted',
|
||||
),
|
||||
`Transaction Finalized event has messageID \"${transactionFinalizedWithMMId.messageId}\" that does not begin with \"transaction-submitted\"`,
|
||||
);
|
||||
|
||||
// Assert that the events with sensitive properties should have messageIds ending in 0x000
|
||||
// This is important because otherwise the events are seen as duplicates in segment
|
||||
|
||||
assert.ok(
|
||||
transactionSubmittedNoMMId.messageId.endsWith('0x000'),
|
||||
`Transaction Submitted event with sensitive properties has messageId \"${transactionSubmittedNoMMId.messageId}\" that does not end in \"0x000\" to differentiate it from the event that does not include sensitive data.`,
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
transactionFinalizedNoMMId.messageId.endsWith('0x000'),
|
||||
`Transaction Finalized event with sensitive properties has messageID \"${transactionFinalizedNoMMId.messageId}\" that does not end in \"0x000\" to differentiate it from the event that does not include sensitive data.`,
|
||||
);
|
||||
|
||||
// Assert that transaction finalized events contain '-success-' in their messageId
|
||||
assert.ok(
|
||||
transactionFinalizedWithMMId.messageId.includes('-success-'),
|
||||
`Transaction Finalized event has messageId \"${transactionFinalizedWithMMId.messageId}\" that does not contain "-success-"`,
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
transactionFinalizedNoMMId.messageId.includes('-success-'),
|
||||
`Transaction Finalized event with sensitive properties has messageID \"${transactionFinalizedNoMMId.messageId}\" that does not contain "-success-"`,
|
||||
);
|
||||
|
||||
// Assert that the events with sensitive data do not contain a userId (the random anonymous id generated when a user opts into metametrics)
|
||||
assert.ok(
|
||||
typeof transactionSubmittedNoMMId.userId === 'undefined',
|
||||
'Transaction Submitted event with sensitive properties has a userId supplied when it should only have the anonymousId',
|
||||
);
|
||||
assert.ok(
|
||||
typeof transactionFinalizedNoMMId.userId === 'undefined',
|
||||
'Transaction Finalized event with sensitive properties has a userId supplied when it should only have the anonymousId',
|
||||
);
|
||||
|
||||
// Assert that the events with sensitive data have anonymousId set to 0x0000000000000000 which is our universal anonymous record
|
||||
assert.ok(
|
||||
transactionSubmittedNoMMId.anonymousId === '0x0000000000000000',
|
||||
'Transaction Submitted event with sensitive properties has an anonymousId that does not match our universal anonymous id of 0x0000000000000000',
|
||||
);
|
||||
assert.ok(
|
||||
transactionFinalizedNoMMId.anonymousId === '0x0000000000000000',
|
||||
'Transaction Finalized event with sensitive properties has an anonymousId that does not match our universal anonymous id of 0x0000000000000000',
|
||||
);
|
||||
|
||||
// Assert that our events without sensitive data have a userId but no anonymousId
|
||||
assert.ok(
|
||||
typeof transactionSubmittedWithMMId.userId === 'string' &&
|
||||
typeof transactionSubmittedWithMMId.anonymousId === 'undefined',
|
||||
'Transaction Submitted event without sensitive properties should only have a userId specified, and no anonymousId',
|
||||
);
|
||||
assert.ok(
|
||||
typeof transactionFinalizedWithMMId.userId === 'string' &&
|
||||
typeof transactionFinalizedWithMMId.anonymousId === 'undefined',
|
||||
'Transaction Finalized event without sensitive properties should only have a userId specified, and no anonymousId',
|
||||
);
|
||||
|
||||
// Assert on the properties
|
||||
|
||||
assert.deepStrictEqual(
|
||||
transactionSubmittedNoMMId.properties,
|
||||
{
|
||||
status: 'submitted',
|
||||
transaction_envelope_type: 'legacy',
|
||||
gas_limit: '0x5208',
|
||||
gas_price: '2',
|
||||
default_gas: '0.000021',
|
||||
default_gas_price: '2',
|
||||
chain_id: '0x539',
|
||||
referrer: 'metamask',
|
||||
source: 'user',
|
||||
network: '1337',
|
||||
eip_1559_version: '0',
|
||||
gas_edit_type: 'none',
|
||||
gas_edit_attempted: 'none',
|
||||
account_type: 'MetaMask',
|
||||
device_model: 'N/A',
|
||||
asset_type: 'NATIVE',
|
||||
token_standard: 'NONE',
|
||||
transaction_type: 'simpleSend',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
category: 'Transactions',
|
||||
locale: 'en',
|
||||
environment_type: 'background',
|
||||
},
|
||||
'Transaction Submitted event with sensitive properties does not match the expected payload',
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
transactionSubmittedWithMMId.properties,
|
||||
{
|
||||
chain_id: '0x539',
|
||||
referrer: 'metamask',
|
||||
source: 'user',
|
||||
network: '1337',
|
||||
eip_1559_version: '0',
|
||||
gas_edit_type: 'none',
|
||||
gas_edit_attempted: 'none',
|
||||
account_type: 'MetaMask',
|
||||
device_model: 'N/A',
|
||||
asset_type: 'NATIVE',
|
||||
token_standard: 'NONE',
|
||||
transaction_type: 'simpleSend',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
category: 'Transactions',
|
||||
locale: 'en',
|
||||
environment_type: 'background',
|
||||
},
|
||||
'Transaction Submitted event without sensitive properties does not match the expected payload',
|
||||
);
|
||||
|
||||
assert.deepStrictEqual(
|
||||
transactionFinalizedNoMMId.properties,
|
||||
{
|
||||
status: 'confirmed',
|
||||
transaction_envelope_type: 'legacy',
|
||||
gas_limit: '0x5208',
|
||||
gas_price: '2',
|
||||
default_gas: '0.000021',
|
||||
default_gas_price: '2',
|
||||
chain_id: '0x539',
|
||||
referrer: 'metamask',
|
||||
source: 'user',
|
||||
network: '1337',
|
||||
eip_1559_version: '0',
|
||||
gas_edit_type: 'none',
|
||||
gas_edit_attempted: 'none',
|
||||
account_type: 'MetaMask',
|
||||
device_model: 'N/A',
|
||||
asset_type: 'NATIVE',
|
||||
token_standard: 'NONE',
|
||||
transaction_type: 'simpleSend',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
gas_used: '5208',
|
||||
category: 'Transactions',
|
||||
locale: 'en',
|
||||
environment_type: 'background',
|
||||
},
|
||||
'Transaction Finalized event with sensitive properties does not match the expected payload',
|
||||
);
|
||||
assert.deepStrictEqual(
|
||||
transactionFinalizedWithMMId.properties,
|
||||
{
|
||||
chain_id: '0x539',
|
||||
referrer: 'metamask',
|
||||
source: 'user',
|
||||
network: '1337',
|
||||
eip_1559_version: '0',
|
||||
gas_edit_type: 'none',
|
||||
gas_edit_attempted: 'none',
|
||||
account_type: 'MetaMask',
|
||||
device_model: 'N/A',
|
||||
asset_type: 'NATIVE',
|
||||
token_standard: 'NONE',
|
||||
transaction_type: 'simpleSend',
|
||||
transaction_speed_up: false,
|
||||
ui_customizations: null,
|
||||
category: 'Transactions',
|
||||
locale: 'en',
|
||||
environment_type: 'background',
|
||||
},
|
||||
'Transaction Finalized event without sensitive properties does not match the expected payload',
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
@ -8,7 +8,16 @@ const {
|
||||
mockEmptyStalelistAndHotlist,
|
||||
} = require('./tests/phishing-controller/mocks');
|
||||
|
||||
async function setupMocking(server, testSpecificMock) {
|
||||
/**
|
||||
* Setup E2E network mocks.
|
||||
*
|
||||
* @param {object} server - The mock server used for network mocks.
|
||||
* @param {Function} testSpecificMock - A function for setting up test-specific network mocks
|
||||
* @param {object} options - Network mock options.
|
||||
* @param {string} options.chainId - The chain ID used by the default configured network.
|
||||
* @returns
|
||||
*/
|
||||
async function setupMocking(server, testSpecificMock, { chainId }) {
|
||||
await server.forAnyRequest().thenPassThrough({
|
||||
beforeRequest: (req) => {
|
||||
const { host } = req.headers;
|
||||
@ -87,7 +96,9 @@ async function setupMocking(server, testSpecificMock) {
|
||||
});
|
||||
|
||||
await server
|
||||
.forGet('https://gas-api.metaswap.codefi.network/networks/1337/gasPrices')
|
||||
.forGet(
|
||||
`https://gas-api.metaswap.codefi.network/networks/${chainId}/gasPrices`,
|
||||
)
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
@ -118,7 +129,7 @@ async function setupMocking(server, testSpecificMock) {
|
||||
|
||||
await server
|
||||
.forGet(
|
||||
'https://gas-api.metaswap.codefi.network/networks/1337/suggestedGasFees',
|
||||
`https://gas-api.metaswap.codefi.network/networks/${chainId}/suggestedGasFees`,
|
||||
)
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
@ -191,7 +202,7 @@ async function setupMocking(server, testSpecificMock) {
|
||||
});
|
||||
|
||||
await server
|
||||
.forGet('https://token-api.metaswap.codefi.network/tokens/1337')
|
||||
.forGet(`https://token-api.metaswap.codefi.network/tokens/${chainId}`)
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
@ -331,7 +342,7 @@ async function setupMocking(server, testSpecificMock) {
|
||||
});
|
||||
|
||||
await server
|
||||
.forGet('https://token-api.metaswap.codefi.network/token/1337')
|
||||
.forGet(`https://token-api.metaswap.codefi.network/token/${chainId}`)
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
@ -340,15 +351,15 @@ async function setupMocking(server, testSpecificMock) {
|
||||
});
|
||||
|
||||
// It disables loading of token icons, e.g. this URL: https://static.metafi.codefi.network/api/v1/tokenIcons/1337/0x0000000000000000000000000000000000000000.png
|
||||
await server
|
||||
.forGet(
|
||||
/^https:\/\/static\.metafi\.codefi\.network\/api\/v1\/tokenIcons\/1337\/.*\.png/u,
|
||||
)
|
||||
.thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
};
|
||||
});
|
||||
const tokenIconRegex = new RegExp(
|
||||
`^https:\\/\\/static\\.metafi\\.codefi\\.network\\/api\\/vi\\/tokenIcons\\/${chainId}\\/.*\\.png`,
|
||||
'u',
|
||||
);
|
||||
await server.forGet(tokenIconRegex).thenCallback(() => {
|
||||
return {
|
||||
statusCode: 200,
|
||||
};
|
||||
});
|
||||
|
||||
await server
|
||||
.forGet('https://min-api.cryptocompare.com/data/price')
|
||||
|
@ -9,10 +9,10 @@ const {
|
||||
generateETHBalance,
|
||||
roundToXDecimalPlaces,
|
||||
generateRandNumBetween,
|
||||
switchToWindow,
|
||||
sleepSeconds,
|
||||
terminateServiceWorker,
|
||||
unlockWallet,
|
||||
largeDelayMs,
|
||||
} = require('../helpers');
|
||||
const FixtureBuilder = require('../fixture-builder');
|
||||
|
||||
@ -114,7 +114,9 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
);
|
||||
|
||||
async function simpleSendETH(driver, value, recipient) {
|
||||
await switchToWindow(driver, WINDOW_TITLES.ExtensionInFullScreenView);
|
||||
await driver.switchToWindowWithTitle(
|
||||
WINDOW_TITLES.ExtensionInFullScreenView,
|
||||
);
|
||||
|
||||
await driver.clickElement('[data-testid="eth-overview-send"]');
|
||||
await driver.fill('[data-testid="ens-input"]', recipient);
|
||||
@ -130,7 +132,7 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
|
||||
await driver.clickElement('[data-testid="page-container-footer-next"]');
|
||||
await driver.clickElement('[data-testid="home__activity-tab"]');
|
||||
await driver.findElement('.transaction-list-item');
|
||||
await driver.findElement('.activity-list-item');
|
||||
// reset view to assets tab
|
||||
await driver.clickElement('[data-testid="home__asset-tab"]');
|
||||
|
||||
@ -138,7 +140,9 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
}
|
||||
|
||||
async function assertETHBalance(driver, expectedBalance) {
|
||||
await switchToWindow(driver, WINDOW_TITLES.ExtensionInFullScreenView);
|
||||
await driver.switchToWindowWithTitle(
|
||||
WINDOW_TITLES.ExtensionInFullScreenView,
|
||||
);
|
||||
|
||||
const isETHBalanceOverviewPresentAndVisible =
|
||||
await driver.isElementPresentAndVisible({
|
||||
@ -175,12 +179,11 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
await openDapp(driver);
|
||||
|
||||
// Click add Ethereum chain
|
||||
await switchToWindow(driver, WINDOW_TITLES.TestDApp);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);
|
||||
await driver.clickElement('#addEthereumChain');
|
||||
await driver.waitUntilXWindowHandles(2);
|
||||
|
||||
// Notification pop up opens
|
||||
await switchToWindow(driver, WINDOW_TITLES.Notification);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.Notification);
|
||||
let notification = await driver.isElementPresent({
|
||||
text: 'Allow this site to add a network?',
|
||||
tag: 'h3',
|
||||
@ -189,19 +192,18 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
|
||||
// Cancel Notification
|
||||
await driver.clickElement({ text: 'Cancel', tag: 'button' });
|
||||
await driver.waitUntilXWindowHandles(2);
|
||||
|
||||
// Terminate Service Worker
|
||||
await switchToWindow(driver, WINDOW_TITLES.TestDApp);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);
|
||||
|
||||
await terminateServiceWorker(driver);
|
||||
|
||||
// Click add Ethereum chain #2
|
||||
await switchToWindow(driver, WINDOW_TITLES.TestDApp);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);
|
||||
await driver.clickElement('#addEthereumChain');
|
||||
await driver.waitUntilXWindowHandles(2);
|
||||
|
||||
// Notification pop up opens
|
||||
await switchToWindow(driver, WINDOW_TITLES.Notification);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.Notification);
|
||||
notification = await driver.isElementPresent({
|
||||
text: 'Allow this site to add a network?',
|
||||
tag: 'h3',
|
||||
@ -210,19 +212,17 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
|
||||
// Cancel Notification
|
||||
await driver.clickElement({ text: 'Cancel', tag: 'button' });
|
||||
await driver.waitUntilXWindowHandles(2);
|
||||
|
||||
// Terminate Service Worker
|
||||
await switchToWindow(driver, WINDOW_TITLES.TestDApp);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);
|
||||
await terminateServiceWorker(driver);
|
||||
|
||||
// Click add Ethereum chain #3
|
||||
await switchToWindow(driver, WINDOW_TITLES.TestDApp);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);
|
||||
await driver.clickElement('#addEthereumChain');
|
||||
await driver.waitUntilXWindowHandles(2);
|
||||
|
||||
// Notification pop up opens
|
||||
await switchToWindow(driver, WINDOW_TITLES.Notification);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.Notification);
|
||||
notification = await driver.isElementPresent({
|
||||
text: 'Allow this site to add a network?',
|
||||
tag: 'h3',
|
||||
@ -232,7 +232,6 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
// Accept Notification
|
||||
await driver.clickElement({ text: 'Approve', tag: 'button' });
|
||||
await driver.clickElement({ text: 'Switch network', tag: 'button' });
|
||||
await driver.waitUntilXWindowHandles(2);
|
||||
},
|
||||
);
|
||||
});
|
||||
@ -257,21 +256,20 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
|
||||
await openDapp(driver);
|
||||
|
||||
await clickSendButton(driver);
|
||||
await driver.waitUntilXWindowHandles(2);
|
||||
|
||||
await switchToWindow(driver, WINDOW_TITLES.TestDApp);
|
||||
await terminateServiceWorker(driver);
|
||||
await driver.waitUntilXWindowHandles(2);
|
||||
await driver.delay(largeDelayMs);
|
||||
|
||||
await clickSendButton(driver);
|
||||
await driver.waitUntilXWindowHandles(2);
|
||||
|
||||
await switchToWindow(driver, WINDOW_TITLES.TestDApp);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);
|
||||
|
||||
await terminateServiceWorker(driver);
|
||||
|
||||
await clickSendButton(driver);
|
||||
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);
|
||||
await terminateServiceWorker(driver);
|
||||
|
||||
await clickSendButton(driver);
|
||||
await driver.waitUntilXWindowHandles(2);
|
||||
|
||||
await assertNumberOfTransactionsInPopUp(driver, 3);
|
||||
|
||||
@ -287,7 +285,7 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
|
||||
async function clickSendButton(driver) {
|
||||
// Click send button
|
||||
await switchToWindow(driver, WINDOW_TITLES.TestDApp);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);
|
||||
|
||||
await driver.waitForSelector({
|
||||
css: '#sendButton',
|
||||
@ -297,7 +295,7 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
}
|
||||
|
||||
async function confirmETHSendNotification(driver, amount) {
|
||||
await switchToWindow(driver, WINDOW_TITLES.Notification);
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.Notification);
|
||||
|
||||
await driver.clickElement({
|
||||
text: 'Edit',
|
||||
@ -318,14 +316,16 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
}
|
||||
|
||||
async function assertNumberOfTransactionsInPopUp(driver, number) {
|
||||
await switchToWindow(driver, WINDOW_TITLES.Notification);
|
||||
const navEl = await driver.findElement(
|
||||
'.confirm-page-container-navigation__navtext',
|
||||
);
|
||||
await driver.delay(largeDelayMs);
|
||||
|
||||
const notificationProgress = await navEl.getText();
|
||||
await driver.switchToWindowWithTitle(WINDOW_TITLES.Notification);
|
||||
|
||||
assert.ok(notificationProgress, `1 of ${number}`);
|
||||
const foundElement = await driver.findElements({
|
||||
css: '.confirm-page-container-navigation__navtext',
|
||||
text: `1 of ${number}`,
|
||||
});
|
||||
|
||||
assert.ok(foundElement, true);
|
||||
}
|
||||
});
|
||||
|
||||
@ -365,7 +365,9 @@ describe('MV3 - Restart service worker multiple times', function () {
|
||||
);
|
||||
|
||||
async function reloadExtension(driver, extensionId) {
|
||||
await switchToWindow(driver, WINDOW_TITLES.ExtensionInFullScreenView);
|
||||
await driver.switchToWindowWithTitle(
|
||||
WINDOW_TITLES.ExtensionInFullScreenView,
|
||||
);
|
||||
|
||||
await driver.openNewPage('chrome://extensions/');
|
||||
|
||||
|
@ -66,7 +66,7 @@ describe('ERC1155 NFTs testdapp interaction', function () {
|
||||
await driver.switchToWindow(extension);
|
||||
await driver.clickElement('[data-testid="home__activity-tab"]');
|
||||
const transactionItem = await driver.waitForSelector({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Deposit',
|
||||
});
|
||||
assert.equal(
|
||||
@ -120,7 +120,7 @@ describe('ERC1155 NFTs testdapp interaction', function () {
|
||||
await driver.switchToWindow(extension);
|
||||
await driver.clickElement('[data-testid="home__activity-tab"]');
|
||||
const transactionItem = await driver.waitForSelector({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Deposit',
|
||||
});
|
||||
assert.equal(
|
||||
|
@ -58,7 +58,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
|
||||
await driver.switchToWindow(extension);
|
||||
await driver.clickElement('[data-testid="home__activity-tab"]');
|
||||
const transactionItem = await driver.waitForSelector({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Deposit',
|
||||
});
|
||||
assert.equal(await transactionItem.isDisplayed(), true);
|
||||
@ -169,7 +169,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
|
||||
await driver.switchToWindow(extension);
|
||||
await driver.clickElement('[data-testid="home__activity-tab"]');
|
||||
const transactionItem = await driver.waitForSelector({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Deposit',
|
||||
});
|
||||
assert.equal(await transactionItem.isDisplayed(), true);
|
||||
@ -266,7 +266,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
|
||||
await driver.switchToWindow(extension);
|
||||
await driver.clickElement('[data-testid="home__activity-tab"]');
|
||||
await driver.waitForSelector(
|
||||
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
|
||||
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
|
||||
);
|
||||
|
||||
// Verify transaction
|
||||
@ -339,7 +339,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
|
||||
|
||||
// Verify transaction
|
||||
const completedTx = await driver.waitForSelector({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Approve TDN spending cap',
|
||||
});
|
||||
assert.equal(await completedTx.isDisplayed(), true);
|
||||
@ -405,12 +405,12 @@ describe('ERC721 NFTs testdapp interaction', function () {
|
||||
await driver.switchToWindow(extension);
|
||||
await driver.clickElement('[data-testid="home__activity-tab"]');
|
||||
await driver.waitForSelector(
|
||||
'.transaction-list__completed-transactions .transaction-list-item:nth-of-type(1)',
|
||||
'.transaction-list__completed-transactions .activity-list-item:nth-of-type(1)',
|
||||
);
|
||||
|
||||
// Verify transaction
|
||||
const completedTx = await driver.waitForSelector({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Approve TDN with no spend limit',
|
||||
});
|
||||
assert.equal(await completedTx.isDisplayed(), true);
|
||||
@ -484,7 +484,7 @@ describe('ERC721 NFTs testdapp interaction', function () {
|
||||
|
||||
// Verify transaction
|
||||
const completedTx = await driver.waitForSelector({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Approve TDN with no spend limit',
|
||||
});
|
||||
assert.equal(await completedTx.isDisplayed(), true);
|
||||
|
@ -38,9 +38,11 @@ describe('Import ERC1155 NFT', function () {
|
||||
await driver.clickElement({ text: 'Import NFT', tag: 'button' });
|
||||
|
||||
// Enter a valid NFT that belongs to user and check success message appears
|
||||
await driver.fill('[data-testid="address"]', contractAddress);
|
||||
await driver.fill('[data-testid="token-id"]', '1');
|
||||
await driver.clickElement({ text: 'Add', tag: 'button' });
|
||||
await driver.fill('#address', contractAddress);
|
||||
await driver.fill('#token-id', '1');
|
||||
await driver.clickElement(
|
||||
'[data-testid="import-nfts-modal-import-button"]',
|
||||
);
|
||||
|
||||
const newNftNotification = await driver.findVisibleElement({
|
||||
text: 'NFT was successfully added!',
|
||||
@ -86,14 +88,15 @@ describe('Import ERC1155 NFT', function () {
|
||||
await driver.clickElement({ text: 'Import NFT', tag: 'button' });
|
||||
|
||||
// Enter an NFT that not belongs to user with a valid address and an invalid token id
|
||||
await driver.fill('[data-testid="address"]', contractAddress);
|
||||
await driver.fill('[data-testid="token-id"]', '4');
|
||||
await driver.clickElement({ text: 'Add', tag: 'button' });
|
||||
|
||||
await driver.fill('#address', contractAddress);
|
||||
await driver.fill('#token-id', '4');
|
||||
await driver.clickElement(
|
||||
'[data-testid="import-nfts-modal-import-button"]',
|
||||
);
|
||||
// Check error message appears
|
||||
const invalidNftNotification = await driver.findElement({
|
||||
text: 'NFT can’t be added as the ownership details do not match. Make sure you have entered correct information.',
|
||||
tag: 'h6',
|
||||
tag: 'p',
|
||||
});
|
||||
assert.equal(await invalidNftNotification.isDisplayed(), true);
|
||||
},
|
||||
|
@ -38,9 +38,11 @@ describe('Import NFT', function () {
|
||||
await driver.clickElement({ text: 'Import NFT', tag: 'button' });
|
||||
|
||||
// Enter a valid NFT that belongs to user and check success message appears
|
||||
await driver.fill('[data-testid="address"]', contractAddress);
|
||||
await driver.fill('[data-testid="token-id"]', '1');
|
||||
await driver.clickElement({ text: 'Add', tag: 'button' });
|
||||
await driver.fill('#address', contractAddress);
|
||||
await driver.fill('#token-id', '1');
|
||||
await driver.clickElement(
|
||||
'[data-testid="import-nfts-modal-import-button"]',
|
||||
);
|
||||
|
||||
const newNftNotification = await driver.findElement({
|
||||
text: 'NFT was successfully added!',
|
||||
@ -85,14 +87,16 @@ describe('Import NFT', function () {
|
||||
await driver.clickElement({ text: 'Import NFT', tag: 'button' });
|
||||
|
||||
// Enter an NFT that not belongs to user with a valid address and an invalid token id
|
||||
await driver.fill('[data-testid="address"]', contractAddress);
|
||||
await driver.fill('[data-testid="token-id"]', '2');
|
||||
await driver.clickElement({ text: 'Add', tag: 'button' });
|
||||
await driver.fill('#address', contractAddress);
|
||||
await driver.fill('#token-id', '2');
|
||||
await driver.clickElement(
|
||||
'[data-testid="import-nfts-modal-import-button"]',
|
||||
);
|
||||
|
||||
// Check error message appears
|
||||
const invalidNftNotification = await driver.findElement({
|
||||
text: 'NFT can’t be added as the ownership details do not match. Make sure you have entered correct information.',
|
||||
tag: 'h6',
|
||||
tag: 'p',
|
||||
});
|
||||
assert.equal(await invalidNftNotification.isDisplayed(), true);
|
||||
},
|
||||
|
@ -64,13 +64,13 @@ describe('Send NFT', function () {
|
||||
// When transaction complete, check the send NFT is displayed in activity tab
|
||||
await driver.wait(async () => {
|
||||
const confirmedTxes = await driver.findElements(
|
||||
'.transaction-list__completed-transactions .transaction-list-item',
|
||||
'.transaction-list__completed-transactions .activity-list-item',
|
||||
);
|
||||
return confirmedTxes.length === 1;
|
||||
}, 10000);
|
||||
|
||||
const sendNftItem = await driver.findElement({
|
||||
css: 'h2',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Send Test Dapp NFTs',
|
||||
});
|
||||
assert.equal(await sendNftItem.isDisplayed(), true);
|
||||
|
@ -31,6 +31,11 @@ async function main() {
|
||||
'Set how many times the test should be retried upon failure.',
|
||||
type: 'number',
|
||||
})
|
||||
.option('retry-until-failure', {
|
||||
default: false,
|
||||
description: 'Retries until the test fails',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('leave-running', {
|
||||
default: false,
|
||||
description:
|
||||
@ -46,7 +51,14 @@ async function main() {
|
||||
.strict()
|
||||
.help('help');
|
||||
|
||||
const { browser, debug, e2eTestPath, retries, leaveRunning } = argv;
|
||||
const {
|
||||
browser,
|
||||
debug,
|
||||
e2eTestPath,
|
||||
retries,
|
||||
retryUntilFailure,
|
||||
leaveRunning,
|
||||
} = argv;
|
||||
|
||||
if (!browser) {
|
||||
exitWithError(
|
||||
@ -97,7 +109,7 @@ async function main() {
|
||||
const dir = 'test/test-results/e2e';
|
||||
fs.mkdir(dir, { recursive: true });
|
||||
|
||||
await retry({ retries }, async () => {
|
||||
await retry({ retries, retryUntilFailure }, async () => {
|
||||
await runInShell(
|
||||
'yarn',
|
||||
[
|
||||
|
@ -122,10 +122,10 @@ const waitForTransactionToComplete = async (driver, options) => {
|
||||
|
||||
const checkActivityTransaction = async (driver, options) => {
|
||||
await driver.clickElement('[data-testid="home__activity-tab"]');
|
||||
await driver.waitForSelector('[data-testid="list-item-title"]');
|
||||
await driver.waitForSelector('.activity-list-item');
|
||||
|
||||
const transactionList = await driver.findElements(
|
||||
'[data-testid="list-item-title"]',
|
||||
'[data-testid="activity-list-item-action"]',
|
||||
);
|
||||
const transactionText = await transactionList[options.index].getText();
|
||||
assert.equal(
|
||||
@ -135,7 +135,7 @@ const checkActivityTransaction = async (driver, options) => {
|
||||
);
|
||||
|
||||
await driver.findElement({
|
||||
css: '[data-testid="list-item-right-content"]',
|
||||
css: '[data-testid="transaction-list-item-primary-currency"]',
|
||||
text: `-${options.amount} ${options.swapFrom}`,
|
||||
});
|
||||
|
||||
@ -143,8 +143,8 @@ const checkActivityTransaction = async (driver, options) => {
|
||||
await driver.delay(regularDelayMs);
|
||||
|
||||
await driver.findElement({
|
||||
css: '[data-testid="transaction-list-item-details-tx-status"]',
|
||||
text: `Confirmed`,
|
||||
css: '.transaction-status-label',
|
||||
text: 'Confirmed',
|
||||
});
|
||||
|
||||
await driver.findElement({
|
||||
@ -173,9 +173,7 @@ const checkNotification = async (driver, options) => {
|
||||
};
|
||||
|
||||
const changeExchangeRate = async (driver) => {
|
||||
await driver.clickElement(
|
||||
'[data-testid="exchange-rate-display-base-symbol"]',
|
||||
);
|
||||
await driver.clickElement('[data-testid="review-quote-view-all-quotes"]');
|
||||
await driver.waitForSelector({ text: 'Quote details', tag: 'h2' });
|
||||
|
||||
const networkFees = await driver.findElements(
|
||||
|
@ -62,13 +62,13 @@ describe('Address Book', function () {
|
||||
await driver.clickElement('[data-testid="home__activity-tab"]');
|
||||
await driver.wait(async () => {
|
||||
const confirmedTxes = await driver.findElements(
|
||||
'.transaction-list__completed-transactions .transaction-list-item',
|
||||
'.transaction-list__completed-transactions .activity-list-item',
|
||||
);
|
||||
return confirmedTxes.length === 1;
|
||||
}, 10000);
|
||||
|
||||
await driver.waitForSelector({
|
||||
css: '.transaction-list-item__primary-currency',
|
||||
css: '[data-testid="transaction-list-item-primary-currency"]',
|
||||
text: '-2 ETH',
|
||||
});
|
||||
},
|
||||
|
@ -35,11 +35,11 @@ describe('Clear account activity', function () {
|
||||
// Check send transaction and receive transaction history are all displayed
|
||||
await driver.clickElement('[data-testid="home__activity-tab"]');
|
||||
await driver.waitForSelector({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Send',
|
||||
});
|
||||
await driver.waitForSelector({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Receive',
|
||||
});
|
||||
|
||||
@ -58,11 +58,11 @@ describe('Clear account activity', function () {
|
||||
|
||||
// Check send transaction history is cleared and receive transaction history is kept
|
||||
const sendTransaction = await driver.isElementPresent({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Send',
|
||||
});
|
||||
const receiveTransaction = await driver.isElementPresent({
|
||||
css: '.list-item__title',
|
||||
css: '[data-testid="activity-list-item-action"]',
|
||||
text: 'Receive',
|
||||
});
|
||||
assert.equal(sendTransaction, false);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user