diff --git a/package.json b/package.json index 6ade33af..53a69084 100644 --- a/package.json +++ b/package.json @@ -12,17 +12,17 @@ "scripts": { "install:extension": "(cd ./packages/common && npm install); (cd ./packages/crypto && npm install); (cd ./packages/storage && npm install); (cd ./packages/ui && npm install); (cd ./packages/extension && npm install); (cd ./packages/dapp && npm install);", "install:test": "(cd ./packages/test-project && npm install);", - "removelocks": "rm -rf ./package-lock.json && find -path \"./packages/*\" -name \"package-lock.json\" -not -path \"*/node_modules/*\" -exec rm -rf {} \\;", - "update": "npm update && find -maxdepth 2 -path \"./packages/*\" -exec npm update {} \\;", + "removelocks": "rm -rf ./package-lock.json && find . -path \"./packages/*\" -name \"package-lock.json\" -not -path \"*/node_modules/*\" -exec rm -rf {} \\;", + "removemodules": "rm -rf node_modules && find . -path \"./packages/*\" -name \"node_modules*\" -exec rm -rf {} \\;", "build": "(cd ./packages/common && npm run build); (cd ./packages/crypto && npm run build); (cd ./packages/dapp && npm run build); (cd ./packages/storage && npm run build); (cd ./packages/ui && npm run build); (cd ./packages/extension && npm run build);", "build:ui": "cd ./packages/ui && npm run build && cp -r ./dist/* ../../dist/", "build:extension": "cd ./packages/extension && npm run build && cp -r ./dist/* ../../dist/", - "clean": "rm -rf ./dist/* && rm -rf ./packages/common/dist/* && rm -rf ./packages/crypto/dist/* && rm -rf ./packages/dapp/dist/* && rm -rf ./packages/extension/dist/* && rm -rf ./packages/storage/dist/* && rm -rf ./packages/ui/dist/* && rm -rf ./packages/dapp/lib/*", + "clean": "rm -rf ./dist && rm -rf ./packages/common/dist && rm -rf ./packages/crypto/dist && rm -rf ./packages/dapp/dist && rm -rf ./packages/extension/dist && rm -rf ./packages/storage/dist && rm -rf ./packages/ui/dist && rm -rf ./packages/dapp/dist", "copy": "mkdir -p ./dist && cp -r ./packages/extension/dist/* dist/ && cp -r ./packages/ui/dist/* dist/ && cp -r ./packages/dapp/dist/* dist/ && mkdir -p ./dist/docs && cp -r ./docs/* dist/docs/", "prebuild": "rm -rf ./dist/*", "postbuild": "npm run copy", "postinstall": "npm run install:extension && npm run install:test", - "rebuild": "npm run clean && npm run removelocks && npm install && npm run update && npm run build", + "rebuild": "npm run clean && npm run removelocks && npm run removemodules && npm install && npm run build", "coveragetest": "(cd ./packages/test-project && npm run coveragetest)", "test": "npm run test:unit && npm run test:e2e", "test:unit": "(cd ./packages/crypto && npm run test) && (cd ./packages/extension && npm run test) && (cd ./packages/ui && npm run test) && (cd ./packages/dapp && npm run test) && (cd ./packages/common && npm run test)", diff --git a/packages/common/src/interfaces/axfer_close.ts b/packages/common/src/interfaces/axfer_close.ts new file mode 100644 index 00000000..a4dae778 --- /dev/null +++ b/packages/common/src/interfaces/axfer_close.ts @@ -0,0 +1,13 @@ +import { IBaseTx } from './baseTx'; + +/// +// Mapping interface of allowable fields for axfer transactions. +/// + +// prettier-ignore +export interface IAssetCloseTx extends IBaseTx { + type: string, //"axfer" + assetIndex: number, //uint64 "xaid" The unique ID of the asset to be transferred. + closeRemainderTo: string, //Address "aclose" Specify this field to remove the asset holding from the sender account and reduce the account's minimum balance. + to: string, //Address +} diff --git a/packages/common/src/messaging/types.ts b/packages/common/src/messaging/types.ts index 0436d04c..3f1cdff1 100644 --- a/packages/common/src/messaging/types.ts +++ b/packages/common/src/messaging/types.ts @@ -36,6 +36,7 @@ export enum JsonRpcMethod { AssetDetails = 'asset-details', AssetsAPIList = 'assets-api-list', AssetsVerifiedList = 'assets-verified-list', + AssetOptOut = 'asset-opt-out', SignSendTransaction = 'sign-send-transaction', ChangeLedger = 'change-ledger', SaveNetwork = 'save-network', diff --git a/packages/extension/src/background/config.ts b/packages/extension/src/background/config.ts index 1f3809fc..cfb29290 100644 --- a/packages/extension/src/background/config.ts +++ b/packages/extension/src/background/config.ts @@ -92,9 +92,9 @@ export class Settings { } // Setup port splits for algod and indexer - used in sandbox installs - const parsedAlgodUrlObj = parseUrlServerAndPort(ledger.algodUrl) + const parsedAlgodUrlObj = parseUrlServerAndPort(ledger.algodUrl); const parsedIndexerUrlObj = parseUrlServerAndPort(ledger.indexerUrl); - + // Add algod links const injectedAlgod = { url: parsedAlgodUrlObj.server || `${defaultUrl}/algod`, @@ -111,15 +111,14 @@ export class Settings { headers: headersIndexer || headers, }; - if (isCheckOnly) { + if (isCheckOnly) { return { - 'algod': injectedAlgod, - 'indexer': injectedIndexer - } - } - else { + algod: injectedAlgod, + indexer: injectedIndexer, + }; + } else { this.backend_settings.InjectedNetworks[ledger.name][API.Algod] = injectedAlgod; - this.backend_settings.InjectedNetworks[ledger.name][API.Indexer] = injectedIndexer; + this.backend_settings.InjectedNetworks[ledger.name][API.Indexer] = injectedIndexer; this.backend_settings.InjectedNetworks[ledger.name].headers = headers; } } @@ -132,20 +131,40 @@ export class Settings { }; this.setInjectedHeaders(ledger); - logging.log(`Added Network:\n${JSON.stringify(this.backend_settings.InjectedNetworks[ledger.name],null,1)}`,2); + logging.log( + `Added Network:\n${JSON.stringify( + this.backend_settings.InjectedNetworks[ledger.name], + null, + 1 + )}`, + 2 + ); } - public static updateInjectedNetwork(updatedLedger: LedgerTemplate) { - this.backend_settings.InjectedNetworks[updatedLedger.name].genesisId = updatedLedger.genesisId; - this.backend_settings.InjectedNetworks[updatedLedger.name].symbol = updatedLedger.symbol; - this.backend_settings.InjectedNetworks[updatedLedger.name].genesisHash = + public static updateInjectedNetwork(updatedLedger: LedgerTemplate, previousName: string = '') { + const targetName = updatedLedger.uniqueName; + + if (previousName) { + this.deleteInjectedNetwork(previousName); + this.backend_settings.InjectedNetworks[targetName] = {}; + } + this.backend_settings.InjectedNetworks[targetName].genesisId = updatedLedger.genesisId; + this.backend_settings.InjectedNetworks[targetName].symbol = updatedLedger.symbol; + this.backend_settings.InjectedNetworks[targetName].genesisHash = updatedLedger.genesisHash; - this.backend_settings.InjectedNetworks[updatedLedger.name].algodUrl = updatedLedger.algodUrl; - this.backend_settings.InjectedNetworks[updatedLedger.name].indexerUrl = + this.backend_settings.InjectedNetworks[targetName].algodUrl = updatedLedger.algodUrl; + this.backend_settings.InjectedNetworks[targetName].indexerUrl = updatedLedger.indexerUrl; this.setInjectedHeaders(updatedLedger); - logging.log(`Updated Network:\n${JSON.stringify(this.backend_settings.InjectedNetworks[updatedLedger.name],null,1)}`,2); + logging.log( + `Updated Network:\n${JSON.stringify( + this.backend_settings.InjectedNetworks[targetName], + null, + 1 + )}`, + 2 + ); } public static getBackendParams(ledger: string, api: API) { @@ -169,7 +188,7 @@ export class Settings { } public static checkNetwork(ledger: LedgerTemplate) { - const networks = this.setInjectedHeaders(ledger, true); + const networks = this.setInjectedHeaders(ledger, true); return networks; } } diff --git a/packages/extension/src/background/messaging/internalMethods.ts b/packages/extension/src/background/messaging/internalMethods.ts index f1198cda..94674e8e 100644 --- a/packages/extension/src/background/messaging/internalMethods.ts +++ b/packages/extension/src/background/messaging/internalMethods.ts @@ -334,7 +334,7 @@ export class InternalMethods { const sessTxn = session.txnWrap.body.params.transaction; // Set the fee to the estimate we showed on the screen for validation if there is one. - if(session.txnWrap.body.params.estimatedFee) { + if (session.txnWrap.body.params.estimatedFee) { sessTxn['fee'] = session.txnWrap.body.params.estimatedFee; } const sessTxnEntries = Object.entries(sessTxn).sort(); @@ -371,18 +371,18 @@ export class InternalMethods { // If v2 then it needs to return an array if (session.txnWrap?.body?.params?.transactionsOrGroups) { - message.response = [{ - blob: request.body.params.txn - }]; - } - else { + message.response = [ + { + blob: request.body.params.txn, + }, + ]; + } else { message.response = { - blob: request.body.params.txn + blob: request.body.params.txn, }; } sendResponse({ message: message }); - } // If this is a ui transaction then we need to also submit else if (session.txnWrap.source === 'ui') { @@ -678,6 +678,130 @@ export class InternalMethods { return true; } + public static [JsonRpcMethod.AssetOptOut](request: any, sendResponse: Function) { + const { ledger, address, passphrase, id } = request.body.params; + this._encryptionWrap = new encryptionWrap(passphrase); + const algod = this.getAlgod(ledger); + + this._encryptionWrap.unlock(async (unlockedValue: any) => { + if ('error' in unlockedValue) { + sendResponse(unlockedValue); + return false; + } + let account; + + // Find address to send algos from + for (var i = unlockedValue[ledger].length - 1; i >= 0; i--) { + if (unlockedValue[ledger][i].address === address) { + account = unlockedValue[ledger][i]; + break; + } + } + + const params = await algod.getTransactionParams().do(); + const txn = { + type: 'axfer', + from: address, + to: address, + closeRemainderTo: address, + assetIndex: id, + fee: params.fee, + firstRound: params.firstRound, + lastRound: params.lastRound, + genesisID: params.genesisID, + genesisHash: params.genesisHash, + }; + + let transactionWrap: BaseValidatedTxnWrap = undefined; + try { + transactionWrap = getValidatedTxnWrap(txn, txn['type']); + } catch (e) { + logging.log(`Validation failed. ${e}`); + sendResponse({ error: `Validation failed. ${e}` }); + return; + } + if (!transactionWrap) { + // We don't have a transaction wrap. We have an unknow error or extra fields, reject the transaction. + logging.log( + 'A transaction has failed because of an inability to build the specified transaction type.' + ); + sendResponse({ + error: + 'A transaction has failed because of an inability to build the specified transaction type.', + }); + return; + } else if ( + transactionWrap.validityObject && + Object.values(transactionWrap.validityObject).some( + (value) => value['status'] === ValidationStatus.Invalid + ) + ) { + // We have a transaction that contains fields which are deemed invalid. We should reject the transaction. + const e = + 'One or more fields are not valid. Please check and try again.\n' + + Object.values(transactionWrap.validityObject) + .filter((value) => value['status'] === ValidationStatus.Invalid) + .map((vo) => vo['info']); + sendResponse({ error: e }); + return; + } else { + // We have a transaction which does not contain invalid fields, + // but may still contain fields that are dangerous + // or ones we've flagged as needing to be reviewed. + // Perform a change based on if this is a ledger device account + if (account.isHardware) { + // TODO: Temporary workaround by adding min-fee for estimate calculations since it's not in the sdk get params. + params['min-fee'] = 1000; + calculateEstimatedFee(transactionWrap, params); + + // Pass the transaction wrap we can pass to the + // central sign ledger function for consistency + this[JsonRpcMethod.LedgerSignTransaction]( + { source: 'ui', body: { params: transactionWrap } }, + (response) => { + // We only have to worry about possible errors here so we can ignore the created tab + if ('error' in response) { + sendResponse(response); + } else { + // Respond with a 0 tx id so that the page knows not to try and show it. + sendResponse({ txId: 0 }); + } + } + ); + + // Return to close connection + return true; + } else { + // We can use a modified popup to allow the normal flow, but require extra scrutiny. + const recoveredAccount = algosdk.mnemonicToSecretKey(account.mnemonic); + let signedTxn; + try { + const builtTx = buildTransaction(txn); + signedTxn = { + txID: builtTx.txID().toString(), + blob: builtTx.signTxn(recoveredAccount.sk), + }; + } catch (e) { + sendResponse({ error: e.message }); + return false; + } + + algod + .sendRawTransaction(signedTxn.blob) + .do() + .then((resp: any) => { + sendResponse({ txId: resp.txId }); + }) + .catch((e: any) => { + sendResponse({ error: e.message }); + }); + } + } + }); + + return true; + } + public static [JsonRpcMethod.SignSendTransaction](request: any, sendResponse: Function) { const { ledger, address, passphrase, txnParams } = request.body.params; this._encryptionWrap = new encryptionWrap(passphrase); @@ -891,9 +1015,10 @@ export class InternalMethods { public static [JsonRpcMethod.SaveNetwork](request: any, sendResponse: Function) { try { + const params = request.body.params; // If we have a passphrase then we are modifying. // There may be accounts attatched, if we match on a unique name, we should update. - if (request.body.params['passphrase'] !== undefined) { + if (params['passphrase'] !== undefined) { this._encryptionWrap = new encryptionWrap(request.body.params['passphrase']); this._encryptionWrap.unlock((unlockedValue: any) => { if ('error' in unlockedValue) { @@ -902,14 +1027,17 @@ export class InternalMethods { // We have evaluated the passphrase and it was valid. }); } + + const previousName = params['previousName'].toLowerCase(); + const targetName = previousName ? previousName : params['name'].toLowerCase(); const addedLedger = new LedgerTemplate({ - name: request.body.params['name'], - genesisId: request.body.params['genesisId'], - genesisHash: request.body.params['genesisHash'], - symbol: request.body.params['symbol'], - algodUrl: request.body.params['algodUrl'], - indexerUrl: request.body.params['indexerUrl'], - headers: request.body.params['headers'], + name: params['name'], + genesisId: params['genesisId'], + genesisHash: params['genesisHash'], + symbol: params['symbol'], + algodUrl: params['algodUrl'], + indexerUrl: params['indexerUrl'], + headers: params['headers'], }); // Specifically get the base ledgers to check and prevent them from being overriden. @@ -919,19 +1047,17 @@ export class InternalMethods { const comboLedgers = [...availiableLedgers]; // Add the new ledger if it isn't there. - if (!comboLedgers.some((cledg) => cledg.uniqueName === addedLedger.uniqueName)) { + if (!comboLedgers.some((cledg) => cledg.uniqueName === targetName)) { comboLedgers.push(addedLedger); // Also add the ledger to the injected ledgers in settings Settings.addInjectedNetwork(addedLedger); - } - // If the new ledger name does exist, we sould update the values as long as it is not a default ledger. - else { - const matchingLedger = comboLedgers.find( - (cledg) => cledg.uniqueName === addedLedger.uniqueName - ); + } else { + // If the new ledger name does exist, we sould update the values as long as it is not a default ledger. + const matchingLedger = comboLedgers.find((cledg) => cledg.uniqueName === targetName); if (!defaultLedgers.some((dledg) => dledg.uniqueName === matchingLedger.uniqueName)) { - Settings.updateInjectedNetwork(addedLedger); + Settings.updateInjectedNetwork(addedLedger, previousName); + matchingLedger.name = addedLedger.name; matchingLedger.genesisId = addedLedger.genesisId; matchingLedger.symbol = addedLedger.symbol; matchingLedger.genesisHash = addedLedger.genesisHash; diff --git a/packages/extension/src/background/messaging/task.ts b/packages/extension/src/background/messaging/task.ts index 24166291..f507d45c 100644 --- a/packages/extension/src/background/messaging/task.ts +++ b/packages/extension/src/background/messaging/task.ts @@ -1463,6 +1463,9 @@ export class Task { [JsonRpcMethod.AssetsVerifiedList]: (request: any, sendResponse: Function) => { return InternalMethods[JsonRpcMethod.AssetsVerifiedList](request, sendResponse); }, + [JsonRpcMethod.AssetOptOut]: (request: any, sendResponse: Function) => { + return InternalMethods[JsonRpcMethod.AssetOptOut](request, sendResponse); + }, [JsonRpcMethod.SignSendTransaction]: (request: any, sendResponse: Function) => { return InternalMethods[JsonRpcMethod.SignSendTransaction](request, sendResponse); }, diff --git a/packages/extension/src/background/transaction/actions.test.ts b/packages/extension/src/background/transaction/actions.test.ts index ecfbef6d..c4a50736 100644 --- a/packages/extension/src/background/transaction/actions.test.ts +++ b/packages/extension/src/background/transaction/actions.test.ts @@ -2,6 +2,7 @@ import { getValidatedTxnWrap } from './actions'; import { BaseValidatedTxnWrap } from './baseValidatedTxnWrap'; import { AssetConfigTransaction } from './acfgTransaction'; import { AssetTransferTransaction } from './axferTransaction'; +import { AssetCloseTransaction } from './axferCloseTransaction'; import { AssetFreezeTransaction } from './afrzTransaction'; test('Validate build of pay transaction', () => { @@ -96,10 +97,33 @@ test('Validate build of axfer transaction', () => { }; const result = getValidatedTxnWrap(preTransaction, 'axfer'); + console.log(result) expect(result instanceof BaseValidatedTxnWrap).toBe(true); expect(result instanceof AssetTransferTransaction).toBe(true); }); +test('Validate build of axfer close transaction', () => { + const preTransaction = { + type: 'axfer', + from: 'NM2MBC673SL7TQIKUXD4JOBR3XQITDCHIMIEODQBUGFMAN54QV2VUYWZNQ', + to: 'NM2MBC673SL7TQIKUXD4JOBR3XQITDCHIMIEODQBUGFMAN54QV2VUYWZNQ', + closeRemainderTo: 'NM2MBC673SL7TQIKUXD4JOBR3XQITDCHIMIEODQBUGFMAN54QV2VUYWZNQ', + fee: 1000, + assetIndex: 1, + amount: 12345, + firstRound: 1, + lastRound: 1001, + genesisID: 'testnet-v1.0', + genesisHash: 'SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=', + note: new Uint8Array(0), + }; + + const result = getValidatedTxnWrap(preTransaction, 'axfer'); + console.log(result); + expect(result instanceof BaseValidatedTxnWrap).toBe(true); + expect(result instanceof AssetCloseTransaction).toBe(true); +}); + test('Validate build of transaction', () => { const preTransaction = { type: 'faketype', diff --git a/packages/extension/src/background/transaction/actions.ts b/packages/extension/src/background/transaction/actions.ts index fae12007..f413739f 100644 --- a/packages/extension/src/background/transaction/actions.ts +++ b/packages/extension/src/background/transaction/actions.ts @@ -5,6 +5,7 @@ import { IAssetDestroyTx } from '@algosigner/common/interfaces/acfg_destroy'; import { IAssetFreezeTx } from '@algosigner/common/interfaces/afrz'; import { IAssetTransferTx } from '@algosigner/common/interfaces/axfer'; import { IAssetAcceptTx } from '@algosigner/common/interfaces/axfer_accept'; +import { IAssetCloseTx } from '@algosigner/common/interfaces/axfer_close'; import { IAssetClawbackTx } from '@algosigner/common/interfaces/axfer_clawback'; import { IKeyRegistrationTx } from '@algosigner/common/interfaces/keyreg'; import { IApplTx } from '@algosigner/common/interfaces/appl'; @@ -15,6 +16,7 @@ import { AssetDestroyTransaction } from './acfgDestroyTransaction'; import { AssetFreezeTransaction } from './afrzTransaction'; import { AssetTransferTransaction } from './axferTransaction'; import { AssetAcceptTransaction } from './axferAcceptTransaction'; +import { AssetCloseTransaction } from './axferCloseTransaction'; import { AssetClawbackTransaction } from './axferClawbackTransaction'; import { KeyregTransaction } from './keyregTransaction'; import { ApplTransaction } from './applTransaction'; @@ -76,13 +78,21 @@ export function getValidatedTxnWrap( validatedTxnWrap = new AssetFreezeTransaction(txn as IAssetFreezeTx, v1Validations); break; case TransactionType.Axfer: - // Validate any of the 3 types of transactions that can occur with axfer + // Validate any of the 4 types of transactions that can occur with axfer // Use the first error as the passback error. try { validatedTxnWrap = new AssetAcceptTransaction(txn as IAssetAcceptTx, v1Validations); } catch (e) { error = e; } + if (!validatedTxnWrap) { + try { + validatedTxnWrap = new AssetCloseTransaction(txn as IAssetCloseTx, v1Validations); + } catch (e) { + e.message = [error.message, e.message].join(' '); + error = e; + } + } if (!validatedTxnWrap) { try { validatedTxnWrap = new AssetTransferTransaction(txn as IAssetTransferTx, v1Validations); diff --git a/packages/extension/src/background/transaction/axferCloseTransaction.ts b/packages/extension/src/background/transaction/axferCloseTransaction.ts new file mode 100644 index 00000000..6ca40c03 --- /dev/null +++ b/packages/extension/src/background/transaction/axferCloseTransaction.ts @@ -0,0 +1,43 @@ +import { IAssetCloseTx } from '@algosigner/common/interfaces/axfer_close'; +import { BaseValidatedTxnWrap } from './baseValidatedTxnWrap'; +import { InvalidTransactionStructure } from '../../errors/validation'; + +/// +// Base implementation of the transactions type interface, for use in the export wrapper class below. +/// +class AssetCloseTx implements IAssetCloseTx { + type: string = undefined; + assetIndex: number = undefined; + from: string = undefined; + fee?: number = 0; + to: any = undefined; + closeRemainderTo: string = undefined; + firstRound: number = undefined; + lastRound: number = undefined; + note?: string = null; + genesisID: string = undefined; + genesisHash: any = undefined; + group?: string = null; + lease?: any = null; + reKeyTo?: any = null; + amount?: BigInt = null; + flatFee?: any = null; + name?: string = null; + tag?: string = null; +} + +/// +// Mapping, validation and error checking for axfer accept transactions prior to sign. +/// +export class AssetCloseTransaction extends BaseValidatedTxnWrap { + txDerivedTypeText: string = 'Asset Opt-Out'; + constructor(params: IAssetCloseTx, v1Validations: boolean) { + super(params, AssetCloseTx, v1Validations); + // Additional check to verify that address from and to are the same + if (this.transaction && this.transaction['to'] !== this.transaction['from']) { + throw new InvalidTransactionStructure( + `Creation of AssetCloseTx has non identical to and from fields.` + ); + } + } +} diff --git a/packages/test-project/tests/basic-e2e-dapp.test.js b/packages/test-project/tests/basic-e2e-dapp.test.js index 863405b9..3bf8b175 100644 --- a/packages/test-project/tests/basic-e2e-dapp.test.js +++ b/packages/test-project/tests/basic-e2e-dapp.test.js @@ -438,9 +438,9 @@ describe('dApp POST Txn Tests (plus Teal compile)', () => { var popup = pages[pages.length - 1]; await appPage.waitForTimeout(500); await popup.waitForSelector('#txAlerts'); - await expect( - popup.$eval('#danger-tx-list b', (e) => e.innerText) - ).resolves.toContain('Deprecate'); + await expect(popup.$eval('#danger-tx-list', (e) => e.innerText)).resolves.toContain( + 'Deprecated' + ); await popup.waitForSelector('#approveTx'); await popup.click('#approveTx', { waitUntil: 'networkidle' }); await popup.waitForSelector('#enterPassword'); diff --git a/packages/test-project/tests/common/tests.js b/packages/test-project/tests/common/tests.js index e9476117..169781e3 100644 --- a/packages/test-project/tests/common/tests.js +++ b/packages/test-project/tests/common/tests.js @@ -65,7 +65,7 @@ function VerifyAccount(account) { await expect(extensionPage.$eval('#accountAddress', (e) => e.innerText)).resolves.toBe( account.address ); - await closeModal(); + await goBack(); await goBack(); }); } diff --git a/packages/test-project/tests/ui-networks-e2e.test.js b/packages/test-project/tests/ui-networks-e2e.test.js index 04dce1c8..70c57bb1 100644 --- a/packages/test-project/tests/ui-networks-e2e.test.js +++ b/packages/test-project/tests/ui-networks-e2e.test.js @@ -98,16 +98,6 @@ describe('Create and Test Custom Networks', () => { test('Test Deleting Networks', async () => { await openNetworkMenu(); - // Delete E2ENet - await extensionPage.waitForSelector(e2eNetSelector); - await extensionPage.click(e2eNetSelector); - await extensionPage.click('#deleteNetwork'); - await inputPassword(); - - // Check network was deleted - await openNetworkMenu(); - await expect(extensionPage.select(e2eNetSelector)).rejects.toThrow(); - // Delete OtherNet await extensionPage.waitForSelector(otherNetSelector); await extensionPage.click(otherNetSelector); diff --git a/packages/ui/src/components/Account/AccountDetails.test.ts b/packages/ui/src/components/Account/AccountDetails.test.ts deleted file mode 100644 index 8f0a3b94..00000000 --- a/packages/ui/src/components/Account/AccountDetails.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @jest-environment jsdom - */ -import { shallow } from 'enzyme'; -import { html } from 'htm/preact'; -import AccountDetails from './AccountDetails'; - -let component; -const account = { - address: "PBZHOKKNBUCCDJB7KB2KLHUMWCGAMBXZKGBFGGBHYNNXFIBOYI7ONYBWK4" -} -const ledger = "TestNet"; - -describe('AccountDetails', () => { - beforeEach(() => { - component = shallow(html` - <${AccountDetails} account=${account} ledger=${ledger} /> - `); - }); - - it('should display account address', () => { - expect(component.contains(html`
${account.address}
`)).toBe(true); - }); - - it('should display account address QR', () => { - expect(component.find('#accountQR').exists()).toBe(true); - }); - - it('should match snapshot', () => { - expect(component).toMatchSnapshot(); - }); -}); diff --git a/packages/ui/src/components/Account/AccountDetails.ts b/packages/ui/src/components/Account/AccountDetails.ts deleted file mode 100644 index ff528858..00000000 --- a/packages/ui/src/components/Account/AccountDetails.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { FunctionalComponent } from 'preact'; -import { html } from 'htm/preact'; -import { useContext, useState } from 'preact/hooks'; -import { route } from 'preact-router'; -import qrcode from 'qrcode-generator'; -import { JsonRpcMethod } from '@algosigner/common/messaging/types'; - -import { sendMessage } from 'services/Messaging'; -import { StoreContext } from 'services/StoreContext'; - -import Authenticate from 'components/Authenticate'; -import ToClipboard from 'components/ToClipboard'; - -const AccountDetails: FunctionalComponent = (props: any) => { - const { account, ledger } = props; - const store: any = useContext(StoreContext); - const [deleting, setDeleting] = useState${account.address}
- -