mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 09:23:21 +01:00
Integrating ppom-validator with extension (#19511)
This commit is contained in:
parent
177ea83f20
commit
73a203f106
@ -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": ["*"]
|
||||
|
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
|
||||
@ -210,6 +213,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 = {
|
||||
@ -630,6 +636,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',
|
||||
});
|
||||
@ -1529,6 +1551,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({
|
||||
@ -1633,6 +1658,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.
|
||||
];
|
||||
|
||||
@ -3910,6 +3938,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(
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -253,6 +253,7 @@
|
||||
"@metamask/permission-controller": "^4.0.0",
|
||||
"@metamask/phishing-controller": "^3.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",
|
||||
@ -464,6 +465,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",
|
||||
|
105
yarn.lock
105
yarn.lock
@ -1619,6 +1619,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@blockaid/ppom-mock@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "@blockaid/ppom-mock@npm:1.0.0"
|
||||
checksum: 297efc29210aae5fb258bbecefcd742645966041bd9af6f256aa80c671920d5e7d9e669c4d1e34795f8556997663abc42422bfafc511ab8379134ce1c8ac324e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@chainsafe/as-sha256@npm:^0.3.1":
|
||||
version: 0.3.1
|
||||
resolution: "@chainsafe/as-sha256@npm:0.3.1"
|
||||
@ -4551,6 +4558,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@metamask/ppom-validator@npm:^0.0.1":
|
||||
version: 0.0.1
|
||||
resolution: "@metamask/ppom-validator@npm:0.0.1"
|
||||
dependencies:
|
||||
"@blockaid/ppom-mock": ^1.0.0
|
||||
"@metamask/base-controller": ^3.0.0
|
||||
"@metamask/controller-utils": ^4.0.0
|
||||
await-semaphore: ^0.1.3
|
||||
checksum: a94edcd618f670b392a84caa236bbc951a6a99100d8a5fa7bd89b78747c3b06b289738b42aee433659b647441eab0a8741e1951a0e29ef6aa98ffa10a3f33f5b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@metamask/preferences-controller@npm:^4.1.0":
|
||||
version: 4.1.0
|
||||
resolution: "@metamask/preferences-controller@npm:4.1.0"
|
||||
@ -10703,6 +10722,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"base64-arraybuffer-es6@npm:^0.7.0":
|
||||
version: 0.7.0
|
||||
resolution: "base64-arraybuffer-es6@npm:0.7.0"
|
||||
checksum: 6d2fd114df49201b476cea5d470504e5d4e8c4cd42544152b312c9bdcb824313086fe83f1ffc34262e9e276b82d46aefc6e63bb85553f016932061137b355cdf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"base64-arraybuffer@npm:^0.1.5":
|
||||
version: 0.1.5
|
||||
resolution: "base64-arraybuffer@npm:0.1.5"
|
||||
@ -14689,10 +14715,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"domexception@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "domexception@npm:1.0.0"
|
||||
checksum: a580e233689e9dcd5e5322f4b58da618bdbf9c4b96532bd11065903b43e81acbe6ec936ceacc57ce2014b695f778ac6368eb079fe3efb1276073a363d59500a8
|
||||
"domexception@npm:^1.0.0, domexception@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "domexception@npm:1.0.1"
|
||||
dependencies:
|
||||
webidl-conversions: ^4.0.2
|
||||
checksum: f564a9c0915dcb83ceefea49df14aaed106b1468fbe505119e8bcb0b77e242534f3aba861978537c0fc9dc6f35b176d0ffc77b3e342820fb27a8f215e7ae4d52
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -17083,6 +17111,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fake-indexeddb@npm:^4.0.1":
|
||||
version: 4.0.1
|
||||
resolution: "fake-indexeddb@npm:4.0.1"
|
||||
dependencies:
|
||||
realistic-structured-clone: ^3.0.0
|
||||
checksum: dd1c82111e3b97c262a647a29dc012209f8c3bed0fbe7ae9630927772842fe8d3276794ff196d0021a5e60563a25a4323eca622a6a7bc6575b62e074328a0c90
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fake-merkle-patricia-tree@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "fake-merkle-patricia-tree@npm:1.0.1"
|
||||
@ -23714,7 +23751,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lodash@npm:^4.13.1, lodash@npm:^4.16.4, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4":
|
||||
"lodash@npm:^4.13.1, lodash@npm:^4.16.4, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0":
|
||||
version: 4.17.21
|
||||
resolution: "lodash@npm:4.17.21"
|
||||
checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7
|
||||
@ -24631,6 +24668,7 @@ __metadata:
|
||||
"@metamask/phishing-controller": ^3.0.0
|
||||
"@metamask/phishing-warning": ^2.1.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
|
||||
@ -24769,6 +24807,7 @@ __metadata:
|
||||
ethjs-contract: ^0.2.3
|
||||
ethjs-query: ^0.3.4
|
||||
extension-port-stream: ^2.0.0
|
||||
fake-indexeddb: ^4.0.1
|
||||
fancy-log: ^1.3.3
|
||||
fast-glob: ^3.2.2
|
||||
fast-json-patch: ^3.1.1
|
||||
@ -29794,6 +29833,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"realistic-structured-clone@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "realistic-structured-clone@npm:3.0.0"
|
||||
dependencies:
|
||||
domexception: ^1.0.1
|
||||
typeson: ^6.1.0
|
||||
typeson-registry: ^1.0.0-alpha.20
|
||||
checksum: b4521b299c8dc320a5e3ef44678f80a92b0f1837901a5fbd1c7be06808110fb0b591b417114306ec55b44ef47fd17968aacca079afc9665afbe1c528026295ec
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"recast@npm:^0.21.0":
|
||||
version: 0.21.5
|
||||
resolution: "recast@npm:0.21.5"
|
||||
@ -33580,6 +33630,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tr46@npm:^2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "tr46@npm:2.1.0"
|
||||
dependencies:
|
||||
punycode: ^2.1.1
|
||||
checksum: ffe6049b9dca3ae329b059aada7f515b0f0064c611b39b51ff6b53897e954650f6f63d9319c6c008d36ead477c7b55e5f64c9dc60588ddc91ff720d64eb710b3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tr46@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "tr46@npm:3.0.0"
|
||||
@ -34052,6 +34111,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typeson-registry@npm:^1.0.0-alpha.20":
|
||||
version: 1.0.0-alpha.39
|
||||
resolution: "typeson-registry@npm:1.0.0-alpha.39"
|
||||
dependencies:
|
||||
base64-arraybuffer-es6: ^0.7.0
|
||||
typeson: ^6.0.0
|
||||
whatwg-url: ^8.4.0
|
||||
checksum: c6b629697acf4652aecfff7be760356d764600afc9beca253278bbfc44fae0fe635b7619201b83e497cdc30645cbce7614d12a04b5726d9b8b505f73e6a3fc2a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typeson@npm:^6.0.0, typeson@npm:^6.1.0":
|
||||
version: 6.1.0
|
||||
resolution: "typeson@npm:6.1.0"
|
||||
checksum: 00a77b03ac8f704acb103307bad9295fe47d6b304c386297f078ec3be63875c0b81e022a4815edb9dc2c7da0a72a431345411d35c755a8510af4a420e9e46cdc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"uglify-js@npm:^3.1.4":
|
||||
version: 3.17.0
|
||||
resolution: "uglify-js@npm:3.17.0"
|
||||
@ -35404,6 +35481,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"webidl-conversions@npm:^6.1.0":
|
||||
version: 6.1.0
|
||||
resolution: "webidl-conversions@npm:6.1.0"
|
||||
checksum: 1f526507aa491f972a0c1409d07f8444e1d28778dfa269a9971f2e157182f3d496dc33296e4ed45b157fdb3bf535bb90c90bf10c50dcf1dd6caacb2a34cc84fb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"webidl-conversions@npm:^7.0.0":
|
||||
version: 7.0.0
|
||||
resolution: "webidl-conversions@npm:7.0.0"
|
||||
@ -35578,6 +35662,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"whatwg-url@npm:^8.4.0":
|
||||
version: 8.7.0
|
||||
resolution: "whatwg-url@npm:8.7.0"
|
||||
dependencies:
|
||||
lodash: ^4.7.0
|
||||
tr46: ^2.1.0
|
||||
webidl-conversions: ^6.1.0
|
||||
checksum: a87abcc6cefcece5311eb642858c8fdb234e51ec74196bfacf8def2edae1bfbffdf6acb251646ed6301f8cee44262642d8769c707256125a91387e33f405dd1e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"which-boxed-primitive@npm:^1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "which-boxed-primitive@npm:1.0.2"
|
||||
|
Loading…
Reference in New Issue
Block a user