diff --git a/.gitignore b/.gitignore index 6e1aa0b3..03cef6b4 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ dist.7z /playwright-report/ /blob-report/ /playwright/.cache/ +dependency-usage.md +extension-dependencies.md diff --git a/.vscode/settings.json b/.vscode/settings.json index cd384a8c..d6093fce 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -21,5 +21,6 @@ "typescript.updateImportsOnFileMove.enabled": "always", "eslint.useFlatConfig": true, "githubPullRequests.overrideDefaultBranch": "dev", - "githubIssues.issueBranchTitle": "${issueNumber}-${sanitizedIssueTitle}" + "githubIssues.issueBranchTitle": "${issueNumber}-${sanitizedIssueTitle}", + "cSpell.words": ["Cbor", "secp"] } diff --git a/package.json b/package.json index 86670118..e9813614 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "@sentry/browser": "^6.19.7", "@sentry/react": "^6.19.7", "@sentry/tracing": "^6.19.7", - "@trustwallet/wallet-core": "^4.1.19", + "@trustwallet/wallet-core": "^4.1.21", "@tsparticles/engine": "^3.6.0", "@tsparticles/react": "^3.0.0", "@walletconnect/core": "^2.17.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index abac024c..82f2e8c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -96,7 +96,7 @@ importers: specifier: ^6.19.7 version: 6.19.7 '@trustwallet/wallet-core': - specifier: ^4.1.19 + specifier: ^4.1.21 version: 4.1.21 '@tsparticles/engine': specifier: ^3.6.0 diff --git a/src/background/controller/provider/controller.ts b/src/background/controller/provider/controller.ts index 84b8de67..ff07a350 100644 --- a/src/background/controller/provider/controller.ts +++ b/src/background/controller/provider/controller.ts @@ -8,6 +8,7 @@ import RLP from 'rlp'; import Web3 from 'web3'; import { stringToHex } from 'web3-utils'; +import { signWithKey } from '@/background/utils/modules/publicPrivateKey'; import { ensureEvmAddressPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { permissionService, @@ -22,9 +23,6 @@ import { storage } from '../../webapi'; import BaseController from '../base'; import Wallet from '../wallet'; -// eslint-disable-next-line import/order,no-restricted-imports -import { signWithKey } from '@/ui/utils/modules/passkey.js'; - interface Web3WalletPermission { // The name of the method corresponding to the permission parentCapability: string; diff --git a/src/background/controller/wallet.ts b/src/background/controller/wallet.ts index afe306ed..dd64e1b6 100644 --- a/src/background/controller/wallet.ts +++ b/src/background/controller/wallet.ts @@ -10,13 +10,22 @@ import { getApp } from 'firebase/app'; import { getAuth } from 'firebase/auth'; import web3, { TransactionError } from 'web3'; +import { + findAddressWithNetwork, + findAddressWithSeed, + findAddressWithPK, +} from '@/background/utils/modules/findAddressWithPK'; +import { + pk2PubKey, + seed2PubKey, + formPubKey, + jsonToKey, +} from '@/background/utils/modules/publicPrivateKey'; import eventBus from '@/eventBus'; import { type FeatureFlags } from '@/shared/types/feature-types'; import { type TrackingEvents } from '@/shared/types/tracking-types'; import { isValidEthereumAddress, withPrefix } from '@/shared/utils/address'; import { getHashAlgo, getSignAlgo } from '@/shared/utils/algo'; -// eslint-disable-next-line no-restricted-imports -import { findAddressWithNetwork } from '@/ui/utils/modules/findAddressWithPK'; import { keyringService, preferenceService, @@ -64,9 +73,6 @@ import { getStoragedAccount } from '../utils/getStoragedAccount'; import BaseController from './base'; import provider from './provider'; -// eslint-disable-next-line import/order,no-restricted-imports -import { pk2PubKey, seed2PubKey, formPubKey } from '@/ui/utils/modules/passkey.js'; - interface Keyring { type: string; getAccounts(): Promise; @@ -380,6 +386,16 @@ export class WalletController extends BaseController { const { origin } = sessionService.getSession(tabId) || {}; return permissionService.getWithoutUpdate(origin); }; + addConnectedSite = ( + origin: string, + name: string, + icon: string, + defaultChain = 747, + isSigned = false + ) => { + permissionService.addConnectedSite(origin, name, icon, defaultChain, isSigned); + }; + updateConnectSite = (origin: string, data: ConnectedSite) => { permissionService.updateConnectSite(origin, data); // sessionService.broadcastEvent( @@ -512,6 +528,16 @@ export class WalletController extends BaseController { return this._setCurrentAccountFromKeyring(keyring); }; + jsonToPrivateKeyHex = async (json: string, password: string): Promise => { + const pk = await jsonToKey(json, password); + return pk ? Buffer.from(pk.data()).toString('hex') : null; + }; + findAddressWithPrivateKey = async (pk: string, address: string) => { + return await findAddressWithPK(pk, address); + }; + findAddressWithSeedPhrase = async (seed: string, address: string, isTemp: boolean = false) => { + return await findAddressWithSeed(seed, address, isTemp); + }; getPreMnemonics = () => keyringService.getPreMnemonics(); generatePreMnemonic = () => keyringService.generatePreMnemonic(); removePreMnemonics = () => keyringService.removePreMnemonics(); @@ -3840,12 +3866,12 @@ export class WalletController extends BaseController { await googleDriveService.uploadMnemonicToGoogleDrive(mnemonic, username, user!.uid, password); mixpanelTrack.track('multi_backup_created', { address: (await this.getCurrentAddress()) || '', - providers: ['google_drive'], + providers: ['GoogleDrive'], }); } catch { mixpanelTrack.track('multi_backup_creation_failed', { address: (await this.getCurrentAddress()) || '', - providers: ['google_drive'], + providers: ['GoogleDrive'], }); } }; @@ -4103,7 +4129,7 @@ export class WalletController extends BaseController { trackAccountRecovered = async () => { mixpanelTrack.track('account_recovered', { address: (await this.getCurrentAddress()) || '', - mechanism: 'multi-backup', + mechanism: 'Multi-Backup', methods: [], }); }; diff --git a/src/background/index.ts b/src/background/index.ts index 06710139..98c5c6b0 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -147,7 +147,7 @@ async function restoreAppState() { restoreAppState(); -chrome.runtime.onInstalled.addListener(({ reason }) => { +chrome.runtime.onInstalled.addListener(({ reason }: chrome.runtime.InstalledDetails) => { // chrome.runtime.OnInstalledReason.Install if (reason === 'install') { chrome.tabs.create({ @@ -179,7 +179,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { }); // for page provider -chrome.runtime.onConnect.addListener((port) => { +chrome.runtime.onConnect.addListener((port: chrome.runtime.Port) => { // openapiService.getConfig(); // @ts-ignore diff --git a/src/background/service/flowns.ts b/src/background/service/flowns.ts index e6d85ea1..4eef2100 100644 --- a/src/background/service/flowns.ts +++ b/src/background/service/flowns.ts @@ -1,7 +1,7 @@ import * as secp from '@noble/secp256k1'; import * as fcl from '@onflow/fcl'; -import { signMessageHash } from '@/ui/utils/modules/passkey.js'; +import { signMessageHash } from '@/background/utils/modules/publicPrivateKey'; import wallet from 'background/controller/wallet'; import { keyringService, openapiService } from 'background/service'; import { createPersistStore } from 'background/utils'; diff --git a/src/background/service/userWallet.ts b/src/background/service/userWallet.ts index 7eecb693..9114ad3f 100644 --- a/src/background/service/userWallet.ts +++ b/src/background/service/userWallet.ts @@ -3,18 +3,16 @@ import * as fcl from '@onflow/fcl'; import { getApp } from 'firebase/app'; import { getAuth, signInAnonymously } from 'firebase/auth'; +import { signWithKey, seed2PubKey } from '@/background/utils/modules/publicPrivateKey'; import { type ActiveChildType } from '@/shared/types/wallet-types'; import { withPrefix } from '@/shared/utils/address'; import { getHashAlgo, getSignAlgo } from '@/shared/utils/algo'; -// eslint-disable-next-line no-restricted-imports -import { findAddressWithSeed, findAddressWithPK } from '@/ui/utils/modules/findAddressWithPK'; -// eslint-disable-next-line no-restricted-imports -import { signWithKey, seed2PubKey } from '@/ui/utils/modules/passkey.js'; import wallet from 'background/controller/wallet'; import { keyringService, mixpanelTrack, openapiService } from 'background/service'; import { createPersistStore } from 'background/utils'; import { getStoragedAccount } from 'background/utils/getStoragedAccount'; +import { findAddressWithSeed, findAddressWithPK } from '../utils/modules/findAddressWithPK'; import { storage } from '../webapi'; import type { diff --git a/src/background/utils/index.ts b/src/background/utils/index.ts index 85f6ac36..f3026eb9 100644 --- a/src/background/utils/index.ts +++ b/src/background/utils/index.ts @@ -4,7 +4,7 @@ import packageJson from '@/../package.json'; import { storage } from '@/background/webapi'; const { version } = packageJson; -import { mixpanelTrack } from '../service'; +import { mixpanelTrack } from '../service/mixpanel'; import pageStateCache from '../service/pageStateCache'; export { default as createPersistStore } from './persisitStore'; diff --git a/src/ui/utils/modules/CborSimpleDecoder.js b/src/background/utils/modules/CborSimpleDecoder.ts similarity index 90% rename from src/ui/utils/modules/CborSimpleDecoder.js rename to src/background/utils/modules/CborSimpleDecoder.ts index e309114c..2086eade 100644 --- a/src/ui/utils/modules/CborSimpleDecoder.js +++ b/src/background/utils/modules/CborSimpleDecoder.ts @@ -1,5 +1,3 @@ -/* eslint-disable no-case-declarations */ -/* eslint-disable @typescript-eslint/ban-ts-comment */ // @ts-nocheck const PositiveInteger = 0; const NegativeInteger = 1; @@ -64,26 +62,26 @@ class Header { } export class CborSimpleDecoder { - static readHeader(reader) { + static readHeader(reader: BinaryReader): Header { if (!(reader instanceof BinaryReader)) throw new TypeError(); const h = reader.readUInt8(); const header = new Header(h); if (header.information >= 0 && header.information <= 23) { header.length = header.information; - } else if (header.information == 24) { + } else if (header.information === 24) { header.length = reader.readUInt8(); - } else if (header.information == 25) { + } else if (header.information === 25) { header.length = reader.readUInt16(); - } else if (header.information == 26) { + } else if (header.information === 26) { header.length = reader.readUInt32(); - } else if (header.information == 27) { + } else if (header.information === 27) { header.length = reader.readUInt64(); } else { throw new Error(`not implemented: major=${header.major} information=${header.information}`); } return header; } - static readObject(reader) { + static readObject(reader: BinaryReader) { if (!(reader instanceof BinaryReader)) throw new TypeError(); const header = CborSimpleDecoder.readHeader(reader); switch (header.major) { diff --git a/src/ui/utils/modules/Crypto.js b/src/background/utils/modules/Crypto.ts similarity index 93% rename from src/ui/utils/modules/Crypto.js rename to src/background/utils/modules/Crypto.ts index 18646920..4c202a04 100644 --- a/src/ui/utils/modules/Crypto.js +++ b/src/background/utils/modules/Crypto.ts @@ -1,6 +1,4 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck -import { encodeArray } from './base64.js'; +import { encodeArray } from './base64'; /** * Convert Cose key to JWK @@ -65,7 +63,7 @@ export function coseToJwk(data) { * @returns {object} - WebCrypto algorithm */ export function getAlgorithm(jwk, alg) { - var algorithm; + let algorithm; switch (jwk.kty) { case 'EC': algorithm = { @@ -81,7 +79,7 @@ export function getAlgorithm(jwk, alg) { default: throw new Error('invalid argument: kty=' + jwk.kty); } - var a = alg ?? jwk.alg ?? 'S256'; + const a = alg ?? jwk.alg ?? 'S256'; switch (a) { case 'RS512': case 'ES512': @@ -118,7 +116,7 @@ export function getAlgorithm(jwk, alg) { * @returns {Promise 32) { b2--; reader.readUInt8(); } const r = reader.readBytes(b2); - if (reader.readUInt8() != 0x02) throw new Error('invalid argument'); + if (reader.readUInt8() !== 0x02) throw new Error('invalid argument'); let b3 = reader.readUInt8(); if (b3 > 32) { b3--; diff --git a/src/ui/utils/modules/WebAuthnDecoder.js b/src/background/utils/modules/WebAuthnDecoder.ts similarity index 63% rename from src/ui/utils/modules/WebAuthnDecoder.js rename to src/background/utils/modules/WebAuthnDecoder.ts index 16d10c6d..a1e99c52 100644 --- a/src/ui/utils/modules/WebAuthnDecoder.js +++ b/src/background/utils/modules/WebAuthnDecoder.ts @@ -1,8 +1,6 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck -import { CborSimpleDecoder, BinaryReader } from './CborSimpleDecoder.js'; -import * as WebAuthn from './WebAuthnTypes.js'; -import { coseToJwk } from './Crypto.js'; +import { CborSimpleDecoder, BinaryReader } from './CborSimpleDecoder'; +import { coseToJwk } from './Crypto'; +import { AttestedCredentialData, AuthenticatorData } from './WebAuthnTypes'; /** * Convert to Uint8Array @@ -24,7 +22,7 @@ export function toUint8Array(data) { * @param {Uint8Array|ArrayBuffer} data * @returns {ArrayBuffer} */ -export function toArrayBuffer(data) { +export function toArrayBuffer(data: Uint8Array | ArrayBuffer): ArrayBuffer { if (data instanceof Uint8Array) { return data.buffer; } @@ -39,7 +37,7 @@ export function toArrayBuffer(data) { * @param {Uint8Array|ArrayBuffer|DataView} data * @returns {DataView} */ -export function toDataView(data) { +export function toDataView(data: DataView | ArrayBuffer | Uint8Array): DataView { if (data instanceof DataView) { return data; } @@ -47,7 +45,7 @@ export function toDataView(data) { return new DataView(data); } if (data instanceof Uint8Array) { - return new DataView(data); + return new DataView(data.buffer); } throw new Error('invalid argument'); } @@ -58,20 +56,47 @@ export function toDataView(data) { * @param {Uint8Array|ArrayBuffer} data * @returns {object} */ -export function decodeClientDataJSON(data) { - data = toUint8Array(data); - return JSON.parse(Array.from(data, (t) => String.fromCharCode(t)).join('')); +export function decodeClientDataJSON(data: ArrayBuffer): object { + const uint8Array = toUint8Array(data); + return JSON.parse(Array.from(uint8Array, (t: number) => String.fromCharCode(t)).join('')); } +export type AttestationFormat = + | 'fido-u2f' + | 'packed' + | 'android-safetynet' + | 'android-key' + | 'tpm' + | 'apple' + | 'none'; + +export type AttestationStatement = { + get(key: 'sig'): Uint8Array | undefined; + get(key: 'x5c'): Uint8Array[] | undefined; + get(key: 'response'): Uint8Array | undefined; + get(key: 'alg'): number | undefined; + get(key: 'ver'): string | undefined; + get(key: 'certInfo'): Uint8Array | undefined; + get(key: 'pubArea'): Uint8Array | undefined; + // `Map` properties + readonly size: number; +}; +export type AttestationObject = { + fmt: AttestationFormat; + attStmt: AttestationStatement; + authData: Uint8Array; +}; + /** * Invokes CborSimpleDecoder.readObject to decode attestationObject * @see https://w3c.github.io/webauthn/#dom-authenticatorattestationresponse-attestationobject * @param {Uint8Array|ArrayBuffer} data * @returns {object} */ -export function decodeAttestationObject(data) { - data = toArrayBuffer(data); - return CborSimpleDecoder.readObject(new BinaryReader(data)); + +export function decodeAttestationObject(data: ArrayBuffer): AttestationObject { + const arrayBuffer = toArrayBuffer(data); + return CborSimpleDecoder.readObject(new BinaryReader(arrayBuffer)); } /** @@ -80,9 +105,9 @@ export function decodeAttestationObject(data) { * @param {Uint8Array|ArrayBuffer} data * @returns {WebAuthn.AuthenticatorData} */ -export function decodeAuthenticatorData(data) { - data = toArrayBuffer(data); - const reader = new BinaryReader(data); +export function decodeAuthenticatorData(data: ArrayBuffer) { + const arrayBuffer = toArrayBuffer(data); + const reader = new BinaryReader(arrayBuffer); /** * https://w3c.github.io/webauthn/#sec-authenticator-data @@ -97,7 +122,7 @@ export function decodeAuthenticatorData(data) { * attestedCredentialData variable * extensions variable */ - const authenticatorData = new WebAuthn.AuthenticatorData(); + const authenticatorData = new AuthenticatorData(); // rpIdHash authenticatorData.rpIdHash = reader.readBytes(32); // flags @@ -115,7 +140,7 @@ export function decodeAuthenticatorData(data) { * credentialId L * credentialPublicKey variable */ - authenticatorData.attestedCredentialData = new WebAuthn.AttestedCredentialData(); + authenticatorData.attestedCredentialData = new AttestedCredentialData(); // aaguid authenticatorData.attestedCredentialData.aaguid = reader.readBytes(16); // credentialIdLength @@ -139,4 +164,4 @@ export function decodeAuthenticatorData(data) { export { coseToJwk, CborSimpleDecoder, BinaryReader }; -export { verifyAssertionSignature } from './Signature.js'; +export { verifyAssertionSignature } from './Signature'; diff --git a/src/ui/utils/modules/WebAuthnTypes.js b/src/background/utils/modules/WebAuthnTypes.ts similarity index 92% rename from src/ui/utils/modules/WebAuthnTypes.js rename to src/background/utils/modules/WebAuthnTypes.ts index f38d5270..67cb9fc0 100644 --- a/src/ui/utils/modules/WebAuthnTypes.js +++ b/src/background/utils/modules/WebAuthnTypes.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck export class PublicKeyCredentialEntity { name; // string constructor(obj) { @@ -9,7 +7,7 @@ export class PublicKeyCredentialEntity { export class PublicKeyCredentialRpEntity extends PublicKeyCredentialEntity { id; // string - constructor(obj) { + constructor(obj?: { name: string; id: string }) { super(obj); this.id = obj?.id; } @@ -29,7 +27,7 @@ export class PublicKeyCredentialRpEntity extends PublicKeyCredentialEntity { export class PublicKeyCredentialUserEntity extends PublicKeyCredentialEntity { id; // BufferSource displayName; // string - constructor(obj) { + constructor(obj?: { name: string; id: string; displayName: string }) { super(obj); this.displayName = obj?.displayName; } @@ -50,7 +48,7 @@ export class PublicKeyCredentialUserEntity extends PublicKeyCredentialEntity { export class PublicKeyCredentialParameters { type; // string alg; // long - constructor(obj) { + constructor(obj?) { this.type = obj?.type; this.alg = obj?.alg; } @@ -72,7 +70,7 @@ export class PublicKeyCredentialDescriptor { type; // string id; // BufferSource transports; // string[] - constructor(obj) { + constructor(obj?) { this.type = obj?.type; this.id = obj?.id; this.transports = obj?.transports; @@ -97,7 +95,11 @@ export class AuthenticatorSelectionCriteria { residentKey; // string // requireResidentKey // bool userVerification; // string - constructor(obj) { + constructor(obj?: { + authenticatorAttachment: string; + residentKey: string; + userVerification: string; + }) { this.authenticatorAttachment = obj?.authenticatorAttachment; this.residentKey = obj?.residentKey; this.userVerification = obj?.userVerification; @@ -129,7 +131,7 @@ export class PublicKeyCredentialCreationOptions { authenticatorSelection = new AuthenticatorSelectionCriteria(); // AuthenticatorSelectionCriteria attestation; // string extensions; - constructor(obj) { + constructor(obj?) { this.rp = new PublicKeyCredentialRpEntity(obj?.rp); this.user = new PublicKeyCredentialUserEntity(obj?.user); this.challenge = obj?.challenge; @@ -160,7 +162,7 @@ export class PublicKeyCredentialCreationOptions { export class CredentialCreationOptions { signal; // AbortSignal publicKey = new PublicKeyCredentialCreationOptions(); - constructor(obj) { + constructor(obj?) { this.publicKey = new PublicKeyCredentialCreationOptions(obj?.publicKey); } toJSON() { @@ -178,7 +180,7 @@ export class PublicKeyCredentialRequestOptions { allowCredentials; // PublicKeyCredentialDescriptor[] userVerification; // string extensions; - constructor(obj) { + constructor(obj?) { this.challenge = obj?.challenge; this.timeout = obj?.timeout; this.rpId = obj?.rpId; @@ -202,7 +204,7 @@ export class CredentialRequestOptions { mediation; // CredentialMediationRequirement signal; // AbortSignal publicKey = new PublicKeyCredentialRequestOptions(); - constructor(obj) { + constructor(obj?) { this.publicKey = new PublicKeyCredentialRequestOptions(obj?.publicKey); } toJSON() { @@ -217,7 +219,7 @@ export class CredentialRequestOptions { export class Credential { id; // string type; // string - constructor(obj) { + constructor(obj?) { this.id = obj?.id; this.type = obj?.type; } @@ -226,7 +228,7 @@ export class Credential { export class PublicKeyCredential extends Credential { rawId; // ArrayBuffer response; // AuthenticatorResponse (AuthenticatorAttestationResponse or AuthenticatorAssertionResponse) - constructor(obj) { + constructor(obj?) { super(obj); this.rawId = obj?.rawId; if ('attestationObject' in (obj?.response ?? {})) @@ -246,14 +248,14 @@ export class PublicKeyCredential extends Credential { export class AuthenticatorResponse { clientDataJSON; // ArrayBuffer - constructor(obj) { + constructor(obj?) { this.clientDataJSON = obj?.clientDataJSON; } } export class AuthenticatorAttestationResponse extends AuthenticatorResponse { attestationObject; // ArrayBuffer - constructor(obj) { + constructor(obj?) { super(obj); this.attestationObject = obj?.attestationObject; } @@ -269,7 +271,7 @@ export class AuthenticatorAssertionResponse extends AuthenticatorResponse { authenticatorData; // ArrayBuffer signature; // ArrayBuffer userHandle; // ArrayBuffer - constructor(obj) { + constructor(obj?) { super(obj); this.authenticatorData = obj?.authenticatorData; this.signature = obj?.signature; @@ -289,27 +291,27 @@ export class AuthenticatorData { rpIdHash; // ArrayBuffer flags; // int get up() { - return (this.flags & 0x01) != 0; + return (this.flags & 0x01) !== 0; } get uv() { - return (this.flags & 0x04) != 0; + return (this.flags & 0x04) !== 0; } get be() { - return (this.flags & 0x08) != 0; + return (this.flags & 0x08) !== 0; } get bs() { - return (this.flags & 0x10) != 0; + return (this.flags & 0x10) !== 0; } get at() { - return (this.flags & 0x40) != 0; + return (this.flags & 0x40) !== 0; } get ed() { - return (this.flags & 0x80) != 0; + return (this.flags & 0x80) !== 0; } signCount; // int attestedCredentialData; // AttestedCredentialData extensions; // ArrayBuffer - constructor(obj) { + constructor(obj?) { this.rpIdHash = obj?.rpIdHash; this.flags = obj?.flags; this.signCount = obj?.signCount; @@ -339,7 +341,7 @@ export class AttestedCredentialData { aaguid; // ArrayBuffer credentialId; // ArrayBuffer credentialPublicKey; // Jwk - constructor(obj) { + constructor(obj?) { this.aaguid = obj?.aaguid; this.credentialId = obj?.credentialId; this.credentialPublicKey = obj?.credentialPublicKey; diff --git a/src/ui/utils/modules/base64.js b/src/background/utils/modules/base64.ts similarity index 74% rename from src/ui/utils/modules/base64.js rename to src/background/utils/modules/base64.ts index 13deeea0..3474bf45 100644 --- a/src/ui/utils/modules/base64.js +++ b/src/background/utils/modules/base64.ts @@ -1,12 +1,6 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck +import { toUint8Array } from './WebAuthnDecoder'; -import { toUint8Array } from './WebAuthnDecoder.js'; - -function atobUrlSafe(text) { - if (text == null) { - return null; - } +function atobUrlSafe(text: string): string { text = text .replace(/\s+/g, '') // removes whitespace such as linefeeds from input encoded string .replace(/-/g, '+') // replace '-' with '+' @@ -29,10 +23,7 @@ function atobUrlSafe(text) { * https://tools.ietf.org/html/rfc7515#appendix-C * https://tools.ietf.org/html/rfc4648#section-5 */ -function btoaUrlSafe(text) { - if (text == null) { - return null; - } +function btoaUrlSafe(text: string): string { text = btoa(text) .replace(/\+/g, '-') // replace '+' with '-' .replace(/\//g, '_') // replace '/' with '_' @@ -45,9 +36,9 @@ function btoaUrlSafe(text) { * @param {ArrayBuffer|Uint8Array} array - array of bytes * @returns {string} - base64url encoded string */ -function encodeArray(array) { - array = toUint8Array(array); - return btoaUrlSafe(Array.from(array, (t) => String.fromCharCode(t)).join('')); +function encodeArray(array: ArrayBuffer | Uint8Array): string { + const arrayUint8 = toUint8Array(array); + return btoaUrlSafe(Array.from(arrayUint8, (t) => String.fromCharCode(t)).join('')); } /** @@ -55,7 +46,7 @@ function encodeArray(array) { * @param {string} value - base64url encoded string * @returns {Uint8Array} - array of bytes */ -function decodeArray(value) { +function decodeArray(value: string): Uint8Array { if (typeof value !== 'string') { throw new Error('invalid argument'); } diff --git a/src/ui/utils/modules/findAddressWithPK.tsx b/src/background/utils/modules/findAddressWithPK.ts similarity index 96% rename from src/ui/utils/modules/findAddressWithPK.tsx rename to src/background/utils/modules/findAddressWithPK.ts index dd24750c..a097e962 100644 --- a/src/ui/utils/modules/findAddressWithPK.tsx +++ b/src/background/utils/modules/findAddressWithPK.ts @@ -1,5 +1,5 @@ import { findAddressWithKey, findAddressOnlyKey } from './findAddressWithPubKey'; -import { pk2PubKey, seed2PubKey, seed2PubKeyTemp } from './passkey'; +import { pk2PubKey, seed2PubKey, seed2PubKeyTemp } from './publicPrivateKey'; export const findAddress = async (pubKTuple, address) => { const { P256, SECP256K1 } = pubKTuple; diff --git a/src/ui/utils/modules/findAddressWithPubKey.tsx b/src/background/utils/modules/findAddressWithPubKey.ts similarity index 100% rename from src/ui/utils/modules/findAddressWithPubKey.tsx rename to src/background/utils/modules/findAddressWithPubKey.ts diff --git a/src/background/utils/modules/passkey.ts b/src/background/utils/modules/passkey.ts new file mode 100644 index 00000000..33be1e0f --- /dev/null +++ b/src/background/utils/modules/passkey.ts @@ -0,0 +1,143 @@ +import { initWasm } from '@trustwallet/wallet-core'; + +import { + FLOW_BIP44_PATH, + HASH_ALGO, + KEY_TYPE, + SIGN_ALGO, +} from '../../../shared/utils/algo-constants'; + +import { decodeArray } from './base64'; +import { addCredential, readSettings } from './settings'; +import { + decodeAuthenticatorData, + decodeClientDataJSON, + decodeAttestationObject, +} from './WebAuthnDecoder'; + +function getRandomBytes(length) { + const array = new Uint8Array(length ?? 32); + crypto.getRandomValues(array); + return array; +} + +const createPasskey = async (name, displayName, rpName) => { + const userId = getRandomBytes(16); + const setup: CredentialCreationOptions = { + publicKey: { + challenge: getRandomBytes(20), + rp: { + name: rpName, + }, + user: { + id: userId, + name: name, + displayName: displayName, + }, + pubKeyCredParams: [ + { + type: 'public-key', + alg: -7, + }, + ], + }, + }; + + const result = await navigator.credentials.create(setup); + if ( + !result || + !(result instanceof PublicKeyCredential) || + !(result.response instanceof AuthenticatorAttestationResponse) + ) { + return null; + } + const authenticatorResponse: AuthenticatorAttestationResponse = result.response; + const attestationObject = decodeAttestationObject(authenticatorResponse.attestationObject); + const authData = decodeAuthenticatorData(attestationObject.authData); + addCredential( + await readSettings(), + setup.publicKey!.user, + result.id, + authData.attestedCredentialData.credentialPublicKey, + result.response + ); + return { userId, result, userName: name }; +}; + +const getPasskey = async (id, rpName) => { + const setup: CredentialRequestOptions = { + publicKey: { + challenge: getRandomBytes(20), + rpId: rpName, + }, + }; + + if (id && id.length > 0) { + setup.publicKey!.allowCredentials = [ + { + type: 'public-key', + id: decodeArray(id), + }, + ]; + } + + const result = await navigator.credentials.get(setup); + if ( + !result || + !(result instanceof PublicKeyCredential) || + !(result.response instanceof AuthenticatorAssertionResponse) + ) { + return null; + } + const json = decodeClientDataJSON(result.response.clientDataJSON); + const authenticatorResponse: AuthenticatorAssertionResponse = result.response; + const test = decodeAuthenticatorData(authenticatorResponse.authenticatorData); + return result; +}; + +const getPKfromLogin = async (result) => { + const { HDWallet, Curve } = await initWasm(); + const wallet = HDWallet.createWithEntropy(result.response.userHandle, ''); + const pk = wallet.getKeyByCurve(Curve.nist256p1, FLOW_BIP44_PATH); + const pubk = pk.getPublicKeyNist256p1().uncompressed().data(); + const json = decodeClientDataJSON(result.response.clientDataJSON); + + return { + mnemonic: wallet.mnemonic(), + type: KEY_TYPE.PASSKEY, + pk: uint8Array2Hex(pk.data()), + pubK: uint8Array2Hex(pubk).replace(/^04/, ''), + keyIndex: 0, + signAlgo: SIGN_ALGO.P256, + hashAlgo: HASH_ALGO.SHA256, + addtional: { + clientDataJSON: json, + }, + }; +}; + +const getPKfromRegister = async ({ userId, result }) => { + if (!userId) { + return null; + } + const { HDWallet, Curve } = await initWasm(); + const wallet = HDWallet.createWithEntropy(userId, ''); + const pk = wallet.getKeyByCurve(Curve.nist256p1, FLOW_BIP44_PATH); + const pubk = pk.getPublicKeyNist256p1().uncompressed().data(); + return { + type: KEY_TYPE.PASSKEY, + mnemonic: wallet.mnemonic(), + pk: uint8Array2Hex(pk.data()), + pubK: uint8Array2Hex(pubk).replace(/^04/, ''), + keyIndex: 0, + signAlgo: SIGN_ALGO.P256, + hashAlgo: HASH_ALGO.SHA256, + }; +}; + +const uint8Array2Hex = (input) => { + const buffer = Buffer.from(input); + return buffer.toString('hex'); +}; + +export { createPasskey, getPasskey, getPKfromLogin, getPKfromRegister }; diff --git a/src/background/utils/modules/publicPrivateKey.ts b/src/background/utils/modules/publicPrivateKey.ts new file mode 100644 index 00000000..2d19250f --- /dev/null +++ b/src/background/utils/modules/publicPrivateKey.ts @@ -0,0 +1,153 @@ +import { initWasm } from '@trustwallet/wallet-core'; + +import { getStringFromHashAlgo, getStringFromSignAlgo } from '@/shared/utils/algo'; + +import { FLOW_BIP44_PATH, HASH_ALGO, SIGN_ALGO } from '../../../shared/utils/algo-constants'; +import storage from '../../webapi/storage'; + +const jsonToKey = async (json: string, password: string) => { + try { + const { StoredKey, PrivateKey } = await initWasm(); + // It appears StoredKey.importJSON expects a Buffer, not a string + const jsonBuffer = Buffer.from(json); + const keystore = StoredKey.importJSON(jsonBuffer); + const privateKeyData = keystore.decryptPrivateKey(Buffer.from(password)); + const privateKey = PrivateKey.createWithData(privateKeyData); + return privateKey; + } catch (error) { + console.error(error); + return null; + } +}; + +const pk2PubKey = async (pk: string) => { + const { PrivateKey } = await initWasm(); + const privateKey = PrivateKey.createWithData(Buffer.from(pk, 'hex')); + + const p256PubK = Buffer.from(privateKey.getPublicKeyNist256p1().uncompressed().data()) + .toString('hex') + .replace(/^04/, ''); + const secp256PubK = Buffer.from(privateKey.getPublicKeySecp256k1(false).data()) + .toString('hex') + .replace(/^04/, ''); + return { + P256: { + pubK: p256PubK, + pk, + }, + SECP256K1: { + pubK: secp256PubK, + pk, + }, + }; +}; + +const formPubKey = async (pubKey) => { + return { + P256: { + pubK: pubKey, + }, + SECP256K1: { + pubK: pubKey, + }, + }; +}; + +const seed2PubKey = async (seed: string) => { + const { HDWallet, Curve } = await initWasm(); + + const currentId = (await storage.get('currentId')) ?? 0; + const accountIndex = (await storage.get('currentAccountIndex')) ?? 0; + const pathKeyIndex = `user${accountIndex}_path`; + const phraseKeyIndex = `user${accountIndex}_phrase`; + + const pathKeyId = `user${currentId}_path`; + const phraseKeyId = `user${currentId}_phrase`; + + const path = + (await storage.get(pathKeyId)) ?? (await storage.get(pathKeyIndex)) ?? FLOW_BIP44_PATH; + + const passphrase = (await storage.get(phraseKeyId)) ?? (await storage.get(phraseKeyIndex)) ?? ''; + + const wallet = HDWallet.createWithMnemonic(seed, passphrase); + const p256PK = wallet.getKeyByCurve(Curve.nist256p1, path); + const p256PubK = Buffer.from(p256PK.getPublicKeyNist256p1().uncompressed().data()) + .toString('hex') + .replace(/^04/, ''); + const SECP256PK = wallet.getKeyByCurve(Curve.secp256k1, path); + const secp256PubK = Buffer.from(SECP256PK.getPublicKeySecp256k1(false).data()) + .toString('hex') + .replace(/^04/, ''); + return { + P256: { + pubK: p256PubK, + pk: Buffer.from(p256PK.data()).toString('hex'), + }, + SECP256K1: { + pubK: secp256PubK, + pk: Buffer.from(SECP256PK.data()).toString('hex'), + }, + }; +}; + +const seed2PubKeyTemp = async (seed: string) => { + const { HDWallet, Curve } = await initWasm(); + + const path = (await storage.get('temp_path')) || FLOW_BIP44_PATH; + const passphrase = (await storage.get('temp_phrase')) || ''; + const wallet = HDWallet.createWithMnemonic(seed, passphrase); + const p256PK = wallet.getKeyByCurve(Curve.nist256p1, path); + const p256PubK = Buffer.from(p256PK.getPublicKeyNist256p1().uncompressed().data()) + .toString('hex') + .replace(/^04/, ''); + const SECP256PK = wallet.getKeyByCurve(Curve.secp256k1, path); + const secp256PubK = Buffer.from(SECP256PK.getPublicKeySecp256k1(false).data()) + .toString('hex') + .replace(/^04/, ''); + return { + P256: { + pubK: p256PubK, + pk: Buffer.from(p256PK.data()).toString('hex'), + }, + SECP256K1: { + pubK: secp256PubK, + pk: Buffer.from(SECP256PK.data()).toString('hex'), + }, + }; +}; + +const signMessageHash = async (hashAlgo, messageData) => { + // Other key + const { Hash } = await initWasm(); + const messageHash = + hashAlgo === HASH_ALGO.SHA3_256 ? Hash.sha3_256(messageData) : Hash.sha256(messageData); + return messageHash; +}; + +const signWithKey = async (message, signAlgo, hashAlgo, pk) => { + // Other key + if (typeof signAlgo === 'number') { + signAlgo = getStringFromSignAlgo(signAlgo); + } + if (typeof hashAlgo === 'number') { + hashAlgo = getStringFromHashAlgo(hashAlgo); + } + const { Curve, Hash, PrivateKey } = await initWasm(); + const messageData = Buffer.from(message, 'hex'); + const privateKey = PrivateKey.createWithData(Buffer.from(pk, 'hex')); + const curve = signAlgo === SIGN_ALGO.P256 ? Curve.nist256p1 : Curve.secp256k1; + const messageHash = + hashAlgo === HASH_ALGO.SHA3_256 ? Hash.sha3_256(messageData) : Hash.sha256(messageData); + const signature = privateKey.sign(messageHash, curve); + return Buffer.from(signature.subarray(0, signature.length - 1)).toString('hex'); +}; + +export { + jsonToKey, + pk2PubKey, + seed2PubKey, + signMessageHash, + signWithKey, + seed2PubKeyTemp, + formPubKey, +}; diff --git a/src/background/utils/modules/settings.ts b/src/background/utils/modules/settings.ts new file mode 100644 index 00000000..c8dbee6a --- /dev/null +++ b/src/background/utils/modules/settings.ts @@ -0,0 +1,91 @@ +import storage from '../../webapi/storage'; + +import { jsonToString } from './utils'; + +type CredentialSetting = { + instant: string; + user: { + name: string; + displayName: string; + }; + id: string; + credentialPublicKey: Uint8Array; + response: AuthenticatorAttestationResponse; +}; +type Settings = { + credentials: Record; + rp?: Record; + user?: Record; +}; + +export function addCredential( + settings: Settings, + user: PublicKeyCredentialUserEntity, + id: string, + credentialPublicKey: Uint8Array, + response: AuthenticatorAttestationResponse +) { + if (id && id.length > 0) { + settings.credentials[id] = { + instant: new Date().toISOString(), + user: { + name: user.name, + displayName: user.displayName, + }, + id: id, + credentialPublicKey: credentialPublicKey, + response: response, + }; + saveSettings(settings); + } +} + +export function getCredential(settings: Settings, id: string) { + const cred = settings.credentials[id]; + return cred; +} + +export async function getUsername(id: string): Promise { + const settings = await readSettings(); + if (id in settings.credentials) { + const cred = settings.credentials[id]; + return cred.user.name; + } + return null; +} + +export async function readSettings(): Promise { + let settings: Settings = { + credentials: {}, + }; + const s = await storage.get('passkey-settings'); + if (!s) { + return settings; + } + + try { + settings = JSON.parse(s); + + if (!settings.credentials) { + settings.credentials = {}; + } + if ('rp' in settings) { + delete settings.rp; + } + if ('user' in settings) { + delete settings.user; + } + } catch { + console.error('Error parsing settings'); + } + + return settings; +} + +export function saveSettings(settings: Settings) { + if (settings) { + storage.set('passkey-settings', jsonToString(settings)); + } else { + storage.remove('passkey-settings'); + } +} diff --git a/src/background/utils/modules/utils.ts b/src/background/utils/modules/utils.ts new file mode 100644 index 00000000..98204bcb --- /dev/null +++ b/src/background/utils/modules/utils.ts @@ -0,0 +1,15 @@ +import { encodeArray } from './base64'; + +export function replacer(_k: string, v: unknown) { + if (v instanceof ArrayBuffer) { + return encodeArray(v); + } + if (v instanceof Uint8Array) { + return encodeArray(v); + } + return v; +} + +export function jsonToString(obj: unknown) { + return JSON.stringify(obj, replacer, 2); +} diff --git a/src/background/webapi/storage.ts b/src/background/webapi/storage.ts index 588ecc4b..e36905ae 100644 --- a/src/background/webapi/storage.ts +++ b/src/background/webapi/storage.ts @@ -1,10 +1,10 @@ -const get = async (prop?) => { +const get = async (prop: string) => { const result = await chrome.storage.local.get(prop); return prop ? result[prop] : result; }; -const getSession = async (prop?) => { +const getSession = async (prop: string) => { // @ts-ignore const result = await chrome.storage.session?.get(prop); @@ -12,7 +12,7 @@ const getSession = async (prop?) => { return prop ? result[prop] : result; }; -const getExpiry = async (prop?) => { +const getExpiry = async (prop: string) => { const result = await chrome.storage.local.get(prop); const data = result[prop]; @@ -21,16 +21,15 @@ const getExpiry = async (prop?) => { return storageData; }; -const set = async (prop, value): Promise => { - await chrome.storage.local.set({ [prop]: value }); +const set = (prop: string, value: any): Promise => { + return chrome.storage.local.set({ [prop]: value }); }; -const setSession = async (prop, value): Promise => { - // @ts-ignore - await chrome.storage.session?.set({ [prop]: value }); +const setSession = (prop: string, value: any): Promise => { + return chrome.storage.session?.set({ [prop]: value }); }; -const setExpiry = async (prop, value, ttl): Promise => { +const setExpiry = async (prop: string, value: any, ttl: number): Promise => { const now = new Date(); // `item` is an object which contains the original value @@ -41,10 +40,10 @@ const setExpiry = async (prop, value, ttl): Promise => { }; const newValue = JSON.stringify(item); - await chrome.storage.local.set({ [prop]: newValue }); + return await chrome.storage.local.set({ [prop]: newValue }); }; -const checkExpiry = async (value, prop) => { +const checkExpiry = async (value: string, prop: string) => { if (!value) { return null; } @@ -57,14 +56,14 @@ const checkExpiry = async (value, prop) => { if (now.getTime() > item.expiry) { // If the item is expired, delete the item from storage // and return null - chrome.storage.local.remove(prop); + await remove(prop); return null; } return item.value; } catch (error) { console.error('Error parsing storage data', error); try { - chrome.storage.local.remove(prop); + await remove(prop); } catch (error) { console.error('Error removing expired storage data', error); } @@ -72,11 +71,11 @@ const checkExpiry = async (value, prop) => { } }; -const remove = async (prop) => { +const remove = async (prop: string) => { await chrome.storage.local.remove(prop); }; -const removeSession = async (prop) => { +const removeSession = async (prop: string) => { // @ts-ignore await chrome.storage.session?.remove(prop); }; diff --git a/src/shared/types/algo-types.ts b/src/shared/types/algo-types.ts index 707e68de..4953e5b4 100644 --- a/src/shared/types/algo-types.ts +++ b/src/shared/types/algo-types.ts @@ -1,3 +1,6 @@ export type SignAlgoType = 'ECDSA_P256' | 'ECDSA_secp256k1' | 'unknown'; export type HashAlgoType = 'SHA256' | 'SHA2_256' | 'SHA3_256' | 'SHA2_384' | 'SHA3_384' | 'unknown'; +export type ImportKeyType = 'Passkey' | 'GoogleDrive' | 'SeedPhrase' | 'Keystore' | 'PrivateKey'; + +export type RecoveryMechanismType = ImportKeyType | 'Multi-Backup' | 'Device-Backup'; diff --git a/src/shared/types/tracking-types.ts b/src/shared/types/tracking-types.ts index 8f274f42..f0f1f512 100644 --- a/src/shared/types/tracking-types.ts +++ b/src/shared/types/tracking-types.ts @@ -1,16 +1,12 @@ -import type { HashAlgoType, SignAlgoType } from './algo-types'; +import type { + HashAlgoType, + SignAlgoType, + ImportKeyType, + RecoveryMechanismType, +} from './algo-types'; type OnRampSourceType = 'moonpay' | 'coinbase'; -type KeyType = 'passkey' | 'google_drive' | 'seed_phrase' | 'keystore' | 'private_key'; - -type RecoveryMechanismType = - | 'multi-backup' - | 'seed-phrase' - | 'private_key' - | 'KeyStore' - | 'device_backup'; - type AddressType = 'flow' | 'evm' | 'child' | 'coa'; export type TrackingEvents = { @@ -51,11 +47,11 @@ export type TrackingEvents = { // Backup Events multi_backup_created: { address: string; // Address of the account that set up multi-backup - providers: KeyType[]; // Providers used in the multi-backup, GoogleDrive, iCloud, Seed e.g. google_drive icloud seed_phrase + providers: ImportKeyType[]; // Providers used in the multi-backup, GoogleDrive, iCloud, Seed e.g. google_drive icloud seed_phrase }; multi_backup_creation_failed: { address: string; // Address of the account that set up multi-backup - providers: KeyType[]; // Providers used in the multi-backup, GoogleDrive, iCloud, Seed e.g. google_drive icloud seed_phrase + providers: ImportKeyType[]; // Providers used in the multi-backup, GoogleDrive, iCloud, Seed e.g. google_drive icloud seed_phrase }; // Transaction Events @@ -99,7 +95,7 @@ export type TrackingEvents = { // Account Events account_created: { public_key: string; // The public key used for creating the new account - key_type?: KeyType; // The key type of the account (if available) + key_type?: ImportKeyType; // The key type of the account (if available) sign_algo: SignAlgoType; // Signature algorithm of the key hash_algo: HashAlgoType; // Hash algo Hash algorithm of the key }; @@ -110,7 +106,7 @@ export type TrackingEvents = { account_recovered: { address: string; // Address that was recovered mechanism: RecoveryMechanismType; // The way the account was recovered - methods: KeyType[]; // Array of providers used in the multi-backup, GoogleDrive, iCloud, Seed + methods: ImportKeyType[]; // Array of providers used in the multi-backup, GoogleDrive, iCloud, Seed }; }; diff --git a/src/ui/utils/modules/constants.tsx b/src/shared/utils/algo-constants.ts similarity index 57% rename from src/ui/utils/modules/constants.tsx rename to src/shared/utils/algo-constants.ts index f54ecf8d..cc6f1385 100644 --- a/src/ui/utils/modules/constants.tsx +++ b/src/shared/utils/algo-constants.ts @@ -1,6 +1,8 @@ +import { type SignAlgoType, type HashAlgoType, type ImportKeyType } from '../types/algo-types'; + const FLOW_BIP44_PATH = "m/44'/539'/0'/0/0"; -const KEY_TYPE = { +const KEY_TYPE: { [key: string]: ImportKeyType } = { PASSKEY: 'Passkey', GOOGLE_DRIVE: 'GoogleDrive', SEED_PHRASE: 'SeedPhrase', @@ -8,12 +10,12 @@ const KEY_TYPE = { PRIVATE_KEY: 'PrivateKey', }; -const SIGN_ALGO = { +const SIGN_ALGO: { [key: string]: SignAlgoType } = { P256: 'ECDSA_P256', SECP256K1: 'ECDSA_secp256k1', }; -const HASH_ALGO = { +const HASH_ALGO: { [key: string]: HashAlgoType } = { SHA256: 'SHA256', SHA3_256: 'SHA3_256', }; diff --git a/src/ui/utils/modules/common.js b/src/ui/utils/modules/common.js deleted file mode 100644 index 76464e48..00000000 --- a/src/ui/utils/modules/common.js +++ /dev/null @@ -1,20 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck -export const invalidArgument = () => { - throw new Error('invalid argument'); -}; -export const isNull = (value) => value === null || value === undefined; -export const notNull = (value) => value !== null && value !== undefined; -export const isEmpty = (value) => isNull(value) || value === ''; -export const notEmpty = (value) => notNull(value) && value !== ''; -export const isString = (value) => notNull(value) && typeof value === 'string'; -export const isFunction = (value) => notNull(value) && typeof value === 'function'; - -export const assertNotNull = (value) => notNull(value) || invalidArgument(); -export const assertString = (value) => isString(value) || invalidArgument(); -export const assertFunction = (value) => isFunction(value) || invalidArgument(); - -export const ifNotNull = (value, func) => - notNull(value) ? (notNull(func) && assertFunction(func) ? func(value) : value) : undefined; -export const ifNotEmpty = (value, func) => - notEmpty(value) ? (notNull(func) && assertFunction(func) ? func(value) : value) : undefined; diff --git a/src/ui/utils/modules/constants.ts b/src/ui/utils/modules/constants.ts new file mode 100644 index 00000000..933bce00 --- /dev/null +++ b/src/ui/utils/modules/constants.ts @@ -0,0 +1 @@ +export * from '@/shared/utils/algo-constants'; diff --git a/src/ui/utils/modules/passkey.js b/src/ui/utils/modules/passkey.js deleted file mode 100644 index 867d3528..00000000 --- a/src/ui/utils/modules/passkey.js +++ /dev/null @@ -1,285 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck - -import { initWasm } from '@trustwallet/wallet-core'; - -import { getStringFromHashAlgo, getStringFromSignAlgo } from '@/shared/utils/algo'; -import { storage } from 'background/webapi'; - -import { decodeArray, encodeArray } from './base64'; -import { FLOW_BIP44_PATH, HASH_ALGO, KEY_TYPE, SIGN_ALGO } from './constants'; -import { addCredential, readSettings } from './settings'; -import { - decodeAuthenticatorData, - decodeClientDataJSON, - decodeAttestationObject, -} from './WebAuthnDecoder'; - -const jsonToKey = async (json, password) => { - try { - const { StoredKey, PrivateKey } = await initWasm(); - const keystore = StoredKey.importJSON(json); - const privateKeyData = await keystore.decryptPrivateKey(password); - const privateKey = PrivateKey.createWithData(privateKeyData); - return privateKey; - } catch (error) { - console.log(error); - return null; - } -}; - -const pk2PubKey = async (pk) => { - const { PrivateKey } = await initWasm(); - const privateKey = PrivateKey.createWithData(Buffer.from(pk, 'hex')); - - const p256PubK = Buffer.from(privateKey.getPublicKeyNist256p1().uncompressed().data()) - .toString('hex') - .replace(/^04/, ''); - const secp256PubK = Buffer.from(privateKey.getPublicKeySecp256k1(false).data()) - .toString('hex') - .replace(/^04/, ''); - return { - P256: { - pubK: p256PubK, - pk, - }, - SECP256K1: { - pubK: secp256PubK, - pk, - }, - }; -}; - -const formPubKey = async (pubKey) => { - return { - P256: { - pubK: pubKey, - }, - SECP256K1: { - pubK: pubKey, - }, - }; -}; - -const seed2PubKey = async (seed) => { - const { HDWallet, Curve } = await initWasm(); - - const currentId = (await storage.get('currentId')) ?? 0; - const accountIndex = (await storage.get('currentAccountIndex')) ?? 0; - const pathKeyIndex = `user${accountIndex}_path`; - const phraseKeyIndex = `user${accountIndex}_phrase`; - - const pathKeyId = `user${currentId}_path`; - const phraseKeyId = `user${currentId}_phrase`; - - const path = - (await storage.get(pathKeyId)) ?? (await storage.get(pathKeyIndex)) ?? FLOW_BIP44_PATH; - - const passphrase = (await storage.get(phraseKeyId)) ?? (await storage.get(phraseKeyIndex)) ?? ''; - - const wallet = HDWallet.createWithMnemonic(seed, passphrase); - const p256PK = wallet.getKeyByCurve(Curve.nist256p1, path); - const p256PubK = Buffer.from(p256PK.getPublicKeyNist256p1().uncompressed().data()) - .toString('hex') - .replace(/^04/, ''); - const SECP256PK = wallet.getKeyByCurve(Curve.secp256k1, path); - const secp256PubK = Buffer.from(SECP256PK.getPublicKeySecp256k1(false).data()) - .toString('hex') - .replace(/^04/, ''); - return { - P256: { - pubK: p256PubK, - pk: Buffer.from(p256PK.data()).toString('hex'), - }, - SECP256K1: { - pubK: secp256PubK, - pk: Buffer.from(SECP256PK.data()).toString('hex'), - }, - }; -}; - -const seed2PubKeyTemp = async (seed) => { - const { HDWallet, Curve } = await initWasm(); - - const path = (await storage.get('temp_path')) || FLOW_BIP44_PATH; - const passphrase = (await storage.get('temp_phrase')) || ''; - console.log('pathpathpath ', path); - console.log('passphrase ', passphrase); - const wallet = HDWallet.createWithMnemonic(seed, passphrase); - const p256PK = wallet.getKeyByCurve(Curve.nist256p1, path); - const p256PubK = Buffer.from(p256PK.getPublicKeyNist256p1().uncompressed().data()) - .toString('hex') - .replace(/^04/, ''); - const SECP256PK = wallet.getKeyByCurve(Curve.secp256k1, path); - const secp256PubK = Buffer.from(SECP256PK.getPublicKeySecp256k1(false).data()) - .toString('hex') - .replace(/^04/, ''); - return { - P256: { - pubK: p256PubK, - pk: Buffer.from(p256PK.data()).toString('hex'), - }, - SECP256K1: { - pubK: secp256PubK, - pk: Buffer.from(SECP256PK.data()).toString('hex'), - }, - }; -}; - -function getRandomBytes(length) { - const array = new Uint8Array(length ?? 32); - crypto.getRandomValues(array); - return array; -} - -const createPasskey = async (name, displayName) => { - const userId = getRandomBytes(16); - const setup = { - publicKey: { - challenge: getRandomBytes(20), - rp: { - name: window.location.hostname, - }, - user: { - id: userId, - name: name, - displayName: displayName, - }, - pubKeyCredParams: [ - { - type: 'public-key', - alg: -7, - }, - ], - }, - }; - const result = await navigator.credentials.create(setup); - console.log('result ==>', result); - const attestationObject = decodeAttestationObject(result.response.attestationObject); - console.log('attestationObject ==>', attestationObject); - const authData = decodeAuthenticatorData(attestationObject.authData); - console.log('authData ==>', authData); - addCredential( - readSettings(), - setup.publicKey.user, - result.id, - authData.attestedCredentialData.credentialPublicKey, - result.response - ); - return { userId, result, userName: name }; -}; - -const getPasskey = async (id) => { - const setup = { - publicKey: { - challenge: getRandomBytes(20), - rpId: window.location.hostname, - }, - }; - - if (id && id.length > 0) { - setup.publicKey.allowCredentials = [ - { - type: 'public-key', - id: decodeArray(id), - }, - ]; - } - - console.log('getPasskey setup ==>', setup); - const result = await navigator.credentials.get(setup); - console.log('getPasskey result ==>', result); - const json = decodeClientDataJSON(result.response.clientDataJSON); - console.log('clientDataJSON =>', json); - const test = decodeAuthenticatorData(result.response.authenticatorData); - console.log('authenticatorData =>', test); - return result; -}; - -const getPKfromLogin = async (result) => { - const { HDWallet, Curve } = await initWasm(); - const wallet = HDWallet.createWithEntropy(result.response.userHandle, ''); - const pk = wallet.getKeyByCurve(Curve.nist256p1, FLOW_BIP44_PATH); - const pubk = pk.getPublicKeyNist256p1().uncompressed().data(); - const json = decodeClientDataJSON(result.response.clientDataJSON); - - return { - mnemonic: wallet.mnemonic(), - type: KEY_TYPE.PASSKEY, - pk: uint8Array2Hex(pk.data()), - pubK: uint8Array2Hex(pubk).replace(/^04/, ''), - keyIndex: 0, - signAlgo: SIGN_ALGO.P256, - hashAlgo: HASH_ALGO.SHA256, - addtional: { - clientDataJSON: json, - }, - }; -}; - -const getPKfromRegister = async ({ userId, result }) => { - console.log(userId, result); - if (!userId) { - return null; - } - const { HDWallet, Curve } = await initWasm(); - const wallet = HDWallet.createWithEntropy(userId, ''); - const pk = wallet.getKeyByCurve(Curve.nist256p1, FLOW_BIP44_PATH); - const pubk = pk.getPublicKeyNist256p1().uncompressed().data(); - return { - type: KEY_TYPE.PASSKEY, - mnemonic: wallet.mnemonic(), - pk: uint8Array2Hex(pk.data()), - pubK: uint8Array2Hex(pubk).replace(/^04/, ''), - keyIndex: 0, - signAlgo: SIGN_ALGO.P256, - hashAlgo: HASH_ALGO.SHA256, - }; -}; - -const uint8Array2Hex = (input) => { - const buffer = new Buffer.from(input); - return buffer.toString('hex'); -}; - -const signMessageHash = async (hashAlgo, messageData) => { - // Other key - const { Hash } = await initWasm(); - const messageHash = - hashAlgo === HASH_ALGO.SHA3_256 ? Hash.sha3_256(messageData) : Hash.sha256(messageData); - return messageHash; -}; - -const signWithKey = async (message, signAlgo, hashAlgo, pk) => { - // Other key - if (typeof signAlgo === 'number') { - signAlgo = getStringFromSignAlgo(signAlgo); - } - if (typeof hashAlgo === 'number') { - hashAlgo = getStringFromHashAlgo(hashAlgo); - } - console.log(' signAlgo ', signAlgo); - console.log(' hashAlgo ', hashAlgo); - const { HDWallet, Curve, Hash, PrivateKey } = await initWasm(); - const messageData = Buffer.from(message, 'hex'); - const privateKey = PrivateKey.createWithData(Buffer.from(pk, 'hex')); - const curve = signAlgo === SIGN_ALGO.P256 ? Curve.nist256p1 : Curve.secp256k1; - const messageHash = - hashAlgo === HASH_ALGO.SHA3_256 ? Hash.sha3_256(messageData) : Hash.sha256(messageData); - const signature = privateKey.sign(messageHash, curve); - return Buffer.from(signature.subarray(0, signature.length - 1)).toString('hex'); -}; - -export { - createPasskey, - getPasskey, - getPKfromLogin, - getPKfromRegister, - jsonToKey, - pk2PubKey, - seed2PubKey, - signMessageHash, - signWithKey, - seed2PubKeyTemp, - formPubKey, -}; diff --git a/src/ui/utils/modules/settings.js b/src/ui/utils/modules/settings.js deleted file mode 100644 index f06e6efe..00000000 --- a/src/ui/utils/modules/settings.js +++ /dev/null @@ -1,99 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck -import { jsonToString } from './utils.js'; -import { notEmpty, notNull } from './common.js'; - -export function createCredentialsList(select, settings, id) { - select.innerHTML = ''; - - let option = document.createElement('option'); - option.setAttribute('value', ''); - option.innerText = ''; - select.appendChild(option); - - let selected = option; - - option = document.createElement('option'); - option.setAttribute('value', '*'); - option.innerText = 'All'; - select.appendChild(option); - - for (const i in settings.credentials) { - const cred = settings.credentials[i]; - //const text = cred.instant + " - " + cred.user.name + " (" + cred.user.displayName + ")"; - const text = `${cred.instant} - ${cred.user.name} (${cred.user.displayName})`; - option = document.createElement('option'); - option.setAttribute('value', cred.id); - option.innerText = text; - select.appendChild(option); - if (notEmpty(id) && cred.id === id) { - selected = option; - } - } - - selected.setAttribute('selected', 'selected'); - - return select; -} - -export function addCredential(settings, user, id, credentialPublicKey, response) { - if (notEmpty(id)) { - settings.credentials[id] = { - instant: new Date().toISOString(), - user: { - name: user.name, - displayName: user.displayName, - }, - id: id, - credentialPublicKey: credentialPublicKey, - response: response, - }; - saveSettings(settings); - } -} - -export function getCredential(settings, id) { - const cred = settings.credentials[id]; - return cred; -} - -export function getUsername(id) { - const seetings = readSettings(); - if (id in seetings.credentials) { - const cred = seetings.credentials[id]; - return cred.user.name; - } - return null; -} - -export function readSettings() { - let settings = { - credentials: {}, - }; - const s = window.localStorage.getItem('settings'); - if (notEmpty(s)) { - try { - settings = JSON.parse(s); - } catch { - console.log('Error parsing settings'); - } - if ('rp' in settings) { - delete settings.rp; - } - if ('user' in settings) { - delete settings.user; - } - if (!('credentials' in settings)) { - settings.credentials = {}; - } - } - return settings; -} - -export function saveSettings(settings) { - if (notNull(settings)) { - window.localStorage.setItem('settings', jsonToString(settings)); - } else { - window.localStorage.removeItem('settings'); - } -} diff --git a/src/ui/utils/modules/utils.js b/src/ui/utils/modules/utils.js deleted file mode 100644 index 392cf65b..00000000 --- a/src/ui/utils/modules/utils.js +++ /dev/null @@ -1,27 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-ts-comment */ -// @ts-nocheck -import { encodeArray } from './base64.js'; - -export function replacer(k, v) { - if (v instanceof ArrayBuffer) { - return encodeArray(v); - } - if (v instanceof Uint8Array) { - return encodeArray(v); - } - return v; -} - -export function jsonToString(obj) { - return JSON.stringify(obj, replacer, 2); -} - -export function toggle_section(id, visible) { - const section = document.getElementById(id); - section.querySelector(":scope > input[type='checkbox']").checked = visible == false; -} - -export function clear_error(id) { - const section = document.getElementById(id); - section.querySelectorAll('.error').forEach((e) => e.classList.remove('error')); -} diff --git a/src/ui/views/AddWelcome/AddressImport/importComponent/JsonImport.tsx b/src/ui/views/AddWelcome/AddressImport/importComponent/JsonImport.tsx index 9ce5a690..7176c50c 100644 --- a/src/ui/views/AddWelcome/AddressImport/importComponent/JsonImport.tsx +++ b/src/ui/views/AddWelcome/AddressImport/importComponent/JsonImport.tsx @@ -1,7 +1,4 @@ -import { useEffect, useState, useContext } from 'react'; -import { findAddressWithPK } from '../../../../utils/modules/findAddressWithPK'; -import { KEY_TYPE } from '../../../../utils/modules/constants'; -import React from 'react'; +import { Visibility, VisibilityOff } from '@mui/icons-material'; import { Box, Button, @@ -11,11 +8,14 @@ import { TextareaAutosize, InputAdornment, } from '@mui/material'; -import { Visibility, VisibilityOff } from '@mui/icons-material'; import { makeStyles } from '@mui/styles'; +import React, { useState } from 'react'; + +import { KEY_TYPE } from '@/shared/utils/algo-constants'; +import { useWallet } from '@/ui/utils/WalletContext'; import { LLSpinner } from 'ui/FRWComponent'; + import ErrorModel from '../../../../FRWComponent/PopupModal/errorModel'; -import { jsonToKey } from '../../../../utils/modules/passkey'; const useStyles = makeStyles((theme) => ({ form: { @@ -61,6 +61,7 @@ const useStyles = makeStyles((theme) => ({ const JsonImport = ({ onOpen, onImport, setPk, isSignLoading }) => { const classes = useStyles(); + const wallet = useWallet(); const [isLoading, setLoading] = useState(false); const [isInvalid, setIsInvalid] = useState(false); const [json, setJson] = useState(''); @@ -91,14 +92,12 @@ const JsonImport = ({ onOpen, onImport, setPk, isSignLoading }) => { } const password = e.target[2].value; const address = e.target[5].value; - const pk = await jsonToKey(keystore, password); - if (pk == null) { + const pkHex = await wallet.jsonToPrivateKeyHex(keystore, password); + if (pkHex === null) { setErrorMessage('Password incorrect'); return; } - const pkHex = Buffer.from(pk.data()).toString('hex'); - const result = await findAddressWithPK(pkHex, address); - console.log(result); + const result = await wallet.findAddressWithPrivateKey(pkHex, address); setPk(pkHex); if (!result) { onOpen(); @@ -180,7 +179,7 @@ const JsonImport = ({ onOpen, onImport, setPk, isSignLoading }) => { - {errorMesssage != '' && ( + {errorMesssage !== '' && ( { diff --git a/src/ui/views/AddWelcome/AddressImport/importComponent/KeyImport.tsx b/src/ui/views/AddWelcome/AddressImport/importComponent/KeyImport.tsx index 5111453a..d41fbd2e 100644 --- a/src/ui/views/AddWelcome/AddressImport/importComponent/KeyImport.tsx +++ b/src/ui/views/AddWelcome/AddressImport/importComponent/KeyImport.tsx @@ -1,9 +1,9 @@ -import { useEffect, useState, useContext } from 'react'; -import { findAddressWithPK } from '../../../../utils/modules/findAddressWithPK'; -import { KEY_TYPE } from '../../../../utils/modules/constants'; -import React from 'react'; import { Box, Button, Typography, TextField, TextareaAutosize } from '@mui/material'; import { makeStyles } from '@mui/styles'; +import React, { useState } from 'react'; + +import { KEY_TYPE } from '@/shared/utils/algo-constants'; +import { useWallet } from '@/ui/utils/WalletContext'; import { LLSpinner } from 'ui/FRWComponent'; const useStyles = makeStyles((theme) => ({ @@ -31,7 +31,7 @@ const useStyles = makeStyles((theme) => ({ const KeyImport = ({ onOpen, onImport, setPk, isSignLoading }) => { // const classes = useStyles(); const classes = useStyles(); - + const wallet = useWallet(); const [isLoading, setLoading] = useState(false); const handleImport = async (e) => { @@ -43,7 +43,7 @@ const KeyImport = ({ onOpen, onImport, setPk, isSignLoading }) => { const inputValue = e.target[2].value; setPk(pk); const address = flowAddressRegex.test(inputValue) ? inputValue : null; - const result = await findAddressWithPK(pk, address); + const result = await wallet.findAddressWithPrivateKey(pk, address); if (!result) { onOpen(); return; diff --git a/src/ui/views/AddWelcome/AddressImport/importComponent/SeedPhrase.tsx b/src/ui/views/AddWelcome/AddressImport/importComponent/SeedPhrase.tsx index 75d1b6d3..7ef03300 100644 --- a/src/ui/views/AddWelcome/AddressImport/importComponent/SeedPhrase.tsx +++ b/src/ui/views/AddWelcome/AddressImport/importComponent/SeedPhrase.tsx @@ -1,11 +1,12 @@ -import { useEffect, useState, useContext } from 'react'; -import { findAddressWithSeed } from '../../../../utils/modules/findAddressWithPK'; -import { KEY_TYPE } from '../../../../utils/modules/constants'; -import React from 'react'; import { Box, Button, Typography, TextField, TextareaAutosize } from '@mui/material'; import { makeStyles } from '@mui/styles'; +import React, { useState } from 'react'; + +import { useWallet } from '@/ui/utils/WalletContext'; import { LLSpinner } from 'ui/FRWComponent'; + import KeyPathInput from '../../../../FRWComponent/KeyPathInputs'; +import { KEY_TYPE } from '../../../../utils/modules/constants'; const useStyles = makeStyles((theme) => ({ form: { @@ -32,6 +33,7 @@ const useStyles = makeStyles((theme) => ({ const SeedPhraseImport = ({ onOpen, onImport, setmnemonic, isSignLoading }) => { const classes = useStyles(); + const wallet = useWallet(); const [isLoading, setLoading] = useState(false); const handleImport = async (e) => { @@ -44,7 +46,7 @@ const SeedPhraseImport = ({ onOpen, onImport, setmnemonic, isSignLoading }) => { const inputValue = e.target[2].value; const address = flowAddressRegex.test(inputValue) ? inputValue : null; - const result = await findAddressWithSeed(seed, address, true); + const result = await wallet.findAddressWithSeedPhrase(seed, address, true); if (!result) { onOpen(); return; diff --git a/src/ui/views/AddressImport/importComponent/JsonImport.tsx b/src/ui/views/AddressImport/importComponent/JsonImport.tsx index 09b8499f..ac927411 100644 --- a/src/ui/views/AddressImport/importComponent/JsonImport.tsx +++ b/src/ui/views/AddressImport/importComponent/JsonImport.tsx @@ -1,7 +1,4 @@ -import { useEffect, useState, useContext } from 'react'; -import { findAddressWithPK } from '../../../utils/modules/findAddressWithPK'; -import { KEY_TYPE } from '../../../utils/modules/constants'; -import React from 'react'; +import { Visibility, VisibilityOff } from '@mui/icons-material'; import { Box, Button, @@ -11,11 +8,14 @@ import { TextareaAutosize, InputAdornment, } from '@mui/material'; -import { Visibility, VisibilityOff } from '@mui/icons-material'; import { makeStyles } from '@mui/styles'; +import React, { useState } from 'react'; + +import { useWallet } from '@/ui/utils/WalletContext'; import { LLSpinner } from 'ui/FRWComponent'; -import { jsonToKey } from '../../../utils/modules/passkey'; + import ErrorModel from '../../../FRWComponent/PopupModal/errorModel'; +import { KEY_TYPE } from '../../../utils/modules/constants'; const useStyles = makeStyles((theme) => ({ form: { @@ -61,6 +61,7 @@ const useStyles = makeStyles((theme) => ({ const JsonImport = ({ onOpen, onImport, setPk, isSignLoading }) => { const classes = useStyles(); + const wallet = useWallet(); const [isLoading, setLoading] = useState(false); const [isInvalid, setIsInvalid] = useState(false); const [json, setJson] = useState(''); @@ -91,14 +92,12 @@ const JsonImport = ({ onOpen, onImport, setPk, isSignLoading }) => { } const password = e.target[2].value; const address = e.target[5].value; - const pk = await jsonToKey(keystore, password); - if (pk == null) { + const pkHex = await wallet.jsonToPrivateKeyHex(keystore, password); + if (pkHex === null) { setErrorMessage('Password incorrect'); return; } - const pkHex = Buffer.from(pk!.data()).toString('hex'); - const result = await findAddressWithPK(pkHex, address); - console.log(result); + const result = await wallet.findAddressWithPrivateKey(pkHex, address); setPk(pkHex); if (!result) { onOpen(); @@ -179,7 +178,7 @@ const JsonImport = ({ onOpen, onImport, setPk, isSignLoading }) => { - {errorMesssage != '' && ( + {errorMesssage !== '' && ( { diff --git a/src/ui/views/AddressImport/importComponent/KeyImport.tsx b/src/ui/views/AddressImport/importComponent/KeyImport.tsx index 35259955..05c8c341 100644 --- a/src/ui/views/AddressImport/importComponent/KeyImport.tsx +++ b/src/ui/views/AddressImport/importComponent/KeyImport.tsx @@ -1,11 +1,12 @@ -import { useEffect, useState, useContext } from 'react'; -import { findAddressWithPK } from '../../../utils/modules/findAddressWithPK'; -import { KEY_TYPE } from '../../../utils/modules/constants'; -import React from 'react'; import { Box, Button, Typography, TextField, TextareaAutosize } from '@mui/material'; import { makeStyles } from '@mui/styles'; +import React, { useState } from 'react'; + +import { useWallet } from '@/ui/utils/WalletContext'; import { LLSpinner } from 'ui/FRWComponent'; +import { KEY_TYPE } from '../../../utils/modules/constants'; + const useStyles = makeStyles((theme) => ({ form: { width: '100%', // Fix full width @@ -31,6 +32,7 @@ const useStyles = makeStyles((theme) => ({ const KeyImport = ({ onOpen, onImport, setPk, isSignLoading }) => { // const classes = useStyles(); const classes = useStyles(); + const wallet = useWallet(); const [isLoading, setLoading] = useState(false); @@ -43,7 +45,7 @@ const KeyImport = ({ onOpen, onImport, setPk, isSignLoading }) => { const inputValue = e.target[2].value; setPk(pk); const address = flowAddressRegex.test(inputValue) ? inputValue : null; - const result = await findAddressWithPK(pk, address); + const result = await wallet.findAddressWithPrivateKey(pk, address); if (!result) { onOpen(); return; diff --git a/src/ui/views/AddressImport/importComponent/SeedPhrase.tsx b/src/ui/views/AddressImport/importComponent/SeedPhrase.tsx index dc6e4748..b7633456 100644 --- a/src/ui/views/AddressImport/importComponent/SeedPhrase.tsx +++ b/src/ui/views/AddressImport/importComponent/SeedPhrase.tsx @@ -1,11 +1,12 @@ -import { useEffect, useState, useContext } from 'react'; -import { findAddressWithSeed } from '../../../utils/modules/findAddressWithPK'; -import { KEY_TYPE } from '../../../utils/modules/constants'; -import React from 'react'; import { Box, Button, Typography, TextareaAutosize } from '@mui/material'; import { makeStyles } from '@mui/styles'; +import React, { useState } from 'react'; + +import { useWallet } from '@/ui/utils/WalletContext'; import { LLSpinner } from 'ui/FRWComponent'; + import KeyPathInput from '../../../FRWComponent/KeyPathInputs'; +import { KEY_TYPE } from '../../../utils/modules/constants'; const useStyles = makeStyles((theme) => ({ form: { @@ -32,6 +33,7 @@ const useStyles = makeStyles((theme) => ({ const SeedPhraseImport = ({ onOpen, onImport, setmnemonic, isSignLoading }) => { const classes = useStyles(); + const wallet = useWallet(); const [isLoading, setLoading] = useState(false); const handleImport = async (e) => { @@ -45,8 +47,7 @@ const SeedPhraseImport = ({ onOpen, onImport, setmnemonic, isSignLoading }) => { const address = flowAddressRegex.test(inputValue) ? inputValue : null; - console.log('address ', address); - const result = await findAddressWithSeed(seed, address, true); + const result = await wallet.findAddressWithSeedPhrase(seed, address, true); if (!result) { onOpen(); return; diff --git a/src/ui/views/Approval/components/Connect.tsx b/src/ui/views/Approval/components/Connect.tsx index c8baa075..7aee7b3a 100644 --- a/src/ui/views/Approval/components/Connect.tsx +++ b/src/ui/views/Approval/components/Connect.tsx @@ -4,7 +4,6 @@ import React, { useCallback, useEffect, useState } from 'react'; import { storage } from '@/background/webapi'; import { authnServiceDefinition, serviceDefinition } from 'background/controller/serviceDefinition'; -import { permissionService } from 'background/service'; import flowgrey from 'ui/FRWAssets/svg/flow-grey.svg'; import Link from 'ui/FRWAssets/svg/link.svg'; import linkGlobe from 'ui/FRWAssets/svg/linkGlobe.svg'; @@ -97,7 +96,7 @@ const Connect = ({ params: { /*icon, origin,*/ tabId } }: ConnectProps) => { chainId = 747; } console.log('permission add ', host, title, logo, chainId); - permissionService.addConnectedSite(host, title, logo, chainId); + wallet.addConnectedSite(host, title, logo, chainId); if (appIdentifier && nonce) { const message = WalletUtils.encodeAccountProof({ diff --git a/src/ui/views/EvmMove/MoveFromChild/index.tsx b/src/ui/views/EvmMove/MoveFromChild/index.tsx index d65104b6..f1c00d37 100644 --- a/src/ui/views/EvmMove/MoveFromChild/index.tsx +++ b/src/ui/views/EvmMove/MoveFromChild/index.tsx @@ -3,7 +3,6 @@ import { Box, Button, Typography, Drawer, IconButton, Grid } from '@mui/material import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import wallet from '@/background/controller/wallet'; import { isValidEthereumAddress, withPrefix } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; @@ -159,7 +158,7 @@ const MoveFromChild = (props: TransferConfirmationProps) => { const moveToken = useCallback(async () => { setLoading(true); - const tokenResult = await wallet.openapi.getTokenInfo(currentCoin, network); + const tokenResult = await usewallet.openapi.getTokenInfo(currentCoin, network); usewallet .moveFTfromChild(childUserInfo!.address, 'flowTokenProvider', amount!, tokenResult!.name) .then(async (createRes) => { diff --git a/src/ui/views/EvmMove/MoveFromEvm/index.tsx b/src/ui/views/EvmMove/MoveFromEvm/index.tsx index af1efe65..0539dfcc 100644 --- a/src/ui/views/EvmMove/MoveFromEvm/index.tsx +++ b/src/ui/views/EvmMove/MoveFromEvm/index.tsx @@ -3,7 +3,6 @@ import { Box, Button, Typography, Drawer, IconButton, Grid } from '@mui/material import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import wallet from '@/background/controller/wallet'; import { isValidEthereumAddress, withPrefix } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; @@ -164,7 +163,7 @@ const MoveFromEvm = (props: TransferConfirmationProps) => { const bridgeToken = async () => { setLoading(true); - const tokenResult = await wallet.openapi.getEvmTokenInfo(currentCoin, network); + const tokenResult = await usewallet.openapi.getEvmTokenInfo(currentCoin, network); let flowId = tokenResult!['flowIdentifier']; diff --git a/src/ui/views/EvmMove/MoveFromFlow/index.tsx b/src/ui/views/EvmMove/MoveFromFlow/index.tsx index 219aff5a..d80d93c2 100644 --- a/src/ui/views/EvmMove/MoveFromFlow/index.tsx +++ b/src/ui/views/EvmMove/MoveFromFlow/index.tsx @@ -3,7 +3,6 @@ import { Box, Button, Typography, Drawer, IconButton, Grid } from '@mui/material import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import wallet from '@/background/controller/wallet'; import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; @@ -177,7 +176,7 @@ const MoveFromFlow = (props: TransferConfirmationProps) => { const bridgeToken = async () => { setLoading(true); - const tokenResult = await wallet.openapi.getTokenInfo(currentCoin, network); + const tokenResult = await usewallet.openapi.getTokenInfo(currentCoin, network); console.log('tokenResult ', tokenResult); const address = tokenResult!.address.startsWith('0x') ? tokenResult!.address.slice(2) diff --git a/src/ui/views/EvmMove/MoveFromParent/index.tsx b/src/ui/views/EvmMove/MoveFromParent/index.tsx index bd56fd99..5e6f3a8d 100644 --- a/src/ui/views/EvmMove/MoveFromParent/index.tsx +++ b/src/ui/views/EvmMove/MoveFromParent/index.tsx @@ -4,7 +4,6 @@ import { ThemeProvider } from '@mui/material/styles'; import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import wallet from '@/background/controller/wallet'; import { isValidEthereumAddress, withPrefix } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; @@ -160,7 +159,7 @@ const MoveFromParent = (props: TransferConfirmationProps) => { const moveToken = async () => { setLoading(true); - const tokenResult = await wallet.openapi.getTokenInfo(currentCoin, network); + const tokenResult = await usewallet.openapi.getTokenInfo(currentCoin, network); console.log('tokenResult ', tokenResult); usewallet .moveFTfromChild(childUserInfo!.address, 'flowTokenProvider', amount!, tokenResult!.name) diff --git a/tsconfig.json b/tsconfig.json index b0b1a583..131e6730 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -36,6 +36,6 @@ ], "outDir": "./dist" }, - "exclude": ["./node_modules", "src/ui/utils/modules"], + "exclude": ["./node_modules"], "include": ["src", "__tests__"] }