diff --git a/ironfish-cli/src/commands/wallet/account.ts b/ironfish-cli/src/commands/wallet/account.ts index 8048a75b57..0e7d33156f 100644 --- a/ironfish-cli/src/commands/wallet/account.ts +++ b/ironfish-cli/src/commands/wallet/account.ts @@ -53,6 +53,7 @@ export class AccountsCommand extends IronfishCommand { Scanning: response.content.account.scanningEnabled ? chalk.green('✓') : '', Sequence: response.content.account.head?.sequence, Head: response.content.account.head?.hash, + Ledger: response.content.account.isLedger ? chalk.green('✓') : '', } this.log(ui.card(status)) diff --git a/ironfish-cli/src/commands/wallet/burn.ts b/ironfish-cli/src/commands/wallet/burn.ts index d6288e60f7..f6f0291694 100644 --- a/ironfish-cli/src/commands/wallet/burn.ts +++ b/ironfish-cli/src/commands/wallet/burn.ts @@ -87,10 +87,6 @@ This will destroy tokens and decrease supply for a given asset.` default: false, description: 'Wait for the transaction to be confirmed', }), - ledger: Flags.boolean({ - default: false, - description: 'Burn a transaction using a Ledger device', - }), } async start(): Promise { @@ -109,6 +105,7 @@ This will destroy tokens and decrease supply for a given asset.` } const account = await useAccount(client, flags.account) + const accountStatus = (await client.wallet.getAccountStatus({ account })).content.account let assetId = flags.assetId @@ -225,7 +222,7 @@ This will destroy tokens and decrease supply for a given asset.` await this.confirm(assetData, amount, raw.fee, account, flags.confirm) - if (flags.ledger) { + if (accountStatus.isLedger) { await ui.sendTransactionWithLedger( client, raw, diff --git a/ironfish-cli/src/commands/wallet/chainport/send.ts b/ironfish-cli/src/commands/wallet/chainport/send.ts index b74437911b..4d9da8c9d3 100644 --- a/ironfish-cli/src/commands/wallet/chainport/send.ts +++ b/ironfish-cli/src/commands/wallet/chainport/send.ts @@ -79,10 +79,6 @@ export class BridgeCommand extends IronfishCommand { description: 'Return a serialized UnsignedTransaction. Use it to create a transaction and build proofs but not post to the network', }), - ledger: Flags.boolean({ - default: false, - description: 'Send a transaction using a Ledger device', - }), } async start(): Promise { @@ -107,7 +103,7 @@ export class BridgeCommand extends IronfishCommand { } } - const { targetToken, from, to, amount, asset, assetData, expiration } = + const { targetToken, from, to, amount, asset, assetData, expiration, isLedger } = await this.getAndValidateInputs(client, networkId) const rawTransaction = await this.constructBridgeTransaction( @@ -132,7 +128,7 @@ export class BridgeCommand extends IronfishCommand { this.exit(0) } - if (flags.ledger) { + if (isLedger) { await ui.sendTransactionWithLedger( client, rawTransaction, @@ -305,7 +301,20 @@ export class BridgeCommand extends IronfishCommand { }, }) } - return { targetToken, from, to, amount, asset, assetData, expiration } + + const accountStatus = (await client.wallet.getAccountStatus({ account: from })).content + .account + + return { + targetToken, + from, + to, + amount, + asset, + assetData, + expiration, + isLedger: accountStatus.isLedger, + } } private async constructBridgeTransaction( diff --git a/ironfish-cli/src/commands/wallet/import.ts b/ironfish-cli/src/commands/wallet/import.ts index 17339c0711..3ef894ded7 100644 --- a/ironfish-cli/src/commands/wallet/import.ts +++ b/ironfish-cli/src/commands/wallet/import.ts @@ -6,8 +6,8 @@ import { Args, Flags, ux } from '@oclif/core' import { IronfishCommand } from '../../command' import { RemoteFlags } from '../../flags' import { LedgerError, LedgerMultiSigner, LedgerSingleSigner } from '../../ledger' -import { checkWalletUnlocked, inputPrompt } from '../../ui' import * as ui from '../../ui' +import { checkWalletUnlocked, inputPrompt } from '../../ui' import { importFile, importPipe, longPrompt } from '../../ui/longPrompt' import { importAccount } from '../../utils' diff --git a/ironfish-cli/src/commands/wallet/index.ts b/ironfish-cli/src/commands/wallet/index.ts index 37f6653122..865db6d0b3 100644 --- a/ironfish-cli/src/commands/wallet/index.ts +++ b/ironfish-cli/src/commands/wallet/index.ts @@ -73,6 +73,11 @@ export class AccountsCommand extends IronfishCommand { header: 'Head', extended: true, }, + isLedger: { + get: (row) => (row.isLedger ? chalk.green('✓') : ''), + header: 'Ledger', + extended: true, + }, }, { ...flags, diff --git a/ironfish-cli/src/commands/wallet/mint.ts b/ironfish-cli/src/commands/wallet/mint.ts index cba11b74a8..1a44df4ac8 100644 --- a/ironfish-cli/src/commands/wallet/mint.ts +++ b/ironfish-cli/src/commands/wallet/mint.ts @@ -108,10 +108,6 @@ This will create tokens and increase supply for a given asset.` 'Return a serialized UnsignedTransaction. Use it to create a transaction and build proofs but not post to the network', exclusive: ['rawTransaction'], }), - ledger: Flags.boolean({ - default: false, - description: 'Mint a transaction using a Ledger device', - }), } async start(): Promise { @@ -130,6 +126,7 @@ This will create tokens and increase supply for a given asset.` } const account = await useAccount(client, flags.account) + const accountStatus = (await client.wallet.getAccountStatus({ account })).content.account const publicKeyResponse = await client.wallet.getAccountPublicKey({ account }) const accountPublicKey = publicKeyResponse.content.publicKey @@ -311,7 +308,7 @@ This will create tokens and increase supply for a given asset.` assetData, ) - if (flags.ledger) { + if (accountStatus.isLedger) { await ui.sendTransactionWithLedger( client, raw, diff --git a/ironfish-cli/src/commands/wallet/multisig/commitment/create.ts b/ironfish-cli/src/commands/wallet/multisig/commitment/create.ts index f35a05cf03..f9a9f3210d 100644 --- a/ironfish-cli/src/commands/wallet/multisig/commitment/create.ts +++ b/ironfish-cli/src/commands/wallet/multisig/commitment/create.ts @@ -38,10 +38,6 @@ export class CreateSigningCommitmentCommand extends IronfishCommand { path: Flags.string({ description: 'Path to a JSON file containing multisig transaction data', }), - ledger: Flags.boolean({ - default: false, - description: 'Create signing commitment using a Ledger device', - }), } async start(): Promise { @@ -58,6 +54,9 @@ export class CreateSigningCommitmentCommand extends IronfishCommand { participantName = await ui.multisigSecretPrompt(client) } + const accountStatus = (await client.wallet.getAccountStatus({ account: participantName })) + .content.account + let identities = options.identity if (!identities || identities.length < 2) { const input = await ui.longPrompt( @@ -94,7 +93,7 @@ export class CreateSigningCommitmentCommand extends IronfishCommand { await ui.confirmOrQuit('Confirm signing commitment creation', flags.confirm) - if (flags.ledger) { + if (accountStatus.isLedger) { await this.createSigningCommitmentWithLedger( client, participantName, diff --git a/ironfish-cli/src/commands/wallet/multisig/dealer/create.ts b/ironfish-cli/src/commands/wallet/multisig/dealer/create.ts index e56e8eeda0..d8e4b25d19 100644 --- a/ironfish-cli/src/commands/wallet/multisig/dealer/create.ts +++ b/ironfish-cli/src/commands/wallet/multisig/dealer/create.ts @@ -98,6 +98,7 @@ export class MultisigCreateDealer extends IronfishCommand { multisigKeys: { publicKeyPackage: response.content.publicKeyPackage, }, + isLedger: false, } await client.wallet.importAccount({ diff --git a/ironfish-cli/src/commands/wallet/multisig/dkg/create.ts b/ironfish-cli/src/commands/wallet/multisig/dkg/create.ts index c150ce4854..03a274ff25 100644 --- a/ironfish-cli/src/commands/wallet/multisig/dkg/create.ts +++ b/ironfish-cli/src/commands/wallet/multisig/dkg/create.ts @@ -527,6 +527,7 @@ export class DkgCreateCommand extends IronfishCommand { }, version: ACCOUNT_SCHEMA_VERSION, name: accountName, + isLedger: true, createdAt: null, spendingKey: null, } diff --git a/ironfish-cli/src/commands/wallet/multisig/dkg/round3.ts b/ironfish-cli/src/commands/wallet/multisig/dkg/round3.ts index 15794f71c6..3499eebde8 100644 --- a/ironfish-cli/src/commands/wallet/multisig/dkg/round3.ts +++ b/ironfish-cli/src/commands/wallet/multisig/dkg/round3.ts @@ -235,6 +235,7 @@ export class DkgRound3Command extends IronfishCommand { }, version: ACCOUNT_SCHEMA_VERSION, name: participantName, + isLedger: true, spendingKey: null, createdAt: null, } diff --git a/ironfish-cli/src/commands/wallet/multisig/sign.ts b/ironfish-cli/src/commands/wallet/multisig/sign.ts index b9a29622d5..4621aa78eb 100644 --- a/ironfish-cli/src/commands/wallet/multisig/sign.ts +++ b/ironfish-cli/src/commands/wallet/multisig/sign.ts @@ -44,10 +44,6 @@ export class SignMultisigTransactionCommand extends IronfishCommand { char: 'a', description: 'Name of the account to use for signing the transaction', }), - ledger: Flags.boolean({ - default: false, - description: 'Perform operation with a ledger device', - }), server: Flags.boolean({ description: 'connect to a multisig broker server', }), @@ -78,12 +74,6 @@ export class SignMultisigTransactionCommand extends IronfishCommand { const client = await this.connectRpc() await ui.checkWalletUnlocked(client) - let ledger: LedgerMultiSigner | undefined = undefined - - if (flags.ledger) { - ledger = new LedgerMultiSigner() - } - let multisigAccountName: string if (!flags.account) { multisigAccountName = await ui.accountPrompt(client) @@ -97,6 +87,18 @@ export class SignMultisigTransactionCommand extends IronfishCommand { } } + const accountStatus = ( + await client.wallet.getAccountStatus({ + account: multisigAccountName, + }) + ).content.account + + let ledger: LedgerMultiSigner | undefined = undefined + + if (accountStatus.isLedger) { + ledger = new LedgerMultiSigner() + } + const accountIdentities = ( await client.wallet.multisig.getAccountIdentities({ account: multisigAccountName }) ).content.identities @@ -149,7 +151,10 @@ export class SignMultisigTransactionCommand extends IronfishCommand { ) // Prompt for confirmation before broker automates signing - if (!flags.ledger && sessionManager instanceof MultisigClientSigningSessionManager) { + if ( + !accountStatus.isLedger && + sessionManager instanceof MultisigClientSigningSessionManager + ) { await ui.confirmOrQuit('Sign this transaction?') } diff --git a/ironfish-cli/src/commands/wallet/send.ts b/ironfish-cli/src/commands/wallet/send.ts index e7cc1a26f2..052a03cff5 100644 --- a/ironfish-cli/src/commands/wallet/send.ts +++ b/ironfish-cli/src/commands/wallet/send.ts @@ -103,10 +103,6 @@ export class Send extends IronfishCommand { description: 'The note hashes to include in the transaction', multiple: true, }), - ledger: Flags.boolean({ - default: false, - description: 'Send a transaction using a Ledger device', - }), } async start(): Promise { @@ -128,6 +124,8 @@ export class Send extends IronfishCommand { } const from = await useAccount(client, flags.account, 'Select an account to send from') + const accountStatus = (await client.wallet.getAccountStatus({ account: from })).content + .account if (assetId == null) { const asset = await ui.assetPrompt(client, from, { @@ -255,7 +253,7 @@ export class Send extends IronfishCommand { this.exit(0) } - if (flags.ledger) { + if (accountStatus.isLedger) { await ui.sendTransactionWithLedger( client, raw, diff --git a/ironfish-cli/src/ledger/ledgerMultiSigner.ts b/ironfish-cli/src/ledger/ledgerMultiSigner.ts index 6595cfd48e..6b8720cfb8 100644 --- a/ironfish-cli/src/ledger/ledgerMultiSigner.ts +++ b/ironfish-cli/src/ledger/ledgerMultiSigner.ts @@ -178,6 +178,7 @@ export class LedgerMultiSigner extends Ledger { publicKeyPackage: publicKeyPackage.toString('hex'), identity: identity.toString('hex'), }, + isLedger: true, version: ACCOUNT_SCHEMA_VERSION, spendingKey: null, createdAt: null, diff --git a/ironfish-cli/src/ledger/ledgerSingleSigner.ts b/ironfish-cli/src/ledger/ledgerSingleSigner.ts index 8dc313a3a7..4e228270d8 100644 --- a/ironfish-cli/src/ledger/ledgerSingleSigner.ts +++ b/ironfish-cli/src/ledger/ledgerSingleSigner.ts @@ -50,6 +50,7 @@ export class LedgerSingleSigner extends Ledger { outgoingViewKey: responseViewKey.ovk.toString('hex'), proofAuthorizingKey: responsePGK.nsk.toString('hex'), spendingKey: null, + isLedger: true, createdAt: null, } diff --git a/ironfish/src/rpc/routes/wallet/importAccount.test.ts b/ironfish/src/rpc/routes/wallet/importAccount.test.ts index b7be8c5be5..7babdb55b6 100644 --- a/ironfish/src/rpc/routes/wallet/importAccount.test.ts +++ b/ironfish/src/rpc/routes/wallet/importAccount.test.ts @@ -43,6 +43,7 @@ describe('Route wallet/importAccount', () => { proofAuthorizingKey: null, version: 1, createdAt: null, + isLedger: false, } const response = await routeTest.client.wallet.importAccount({ @@ -69,6 +70,7 @@ describe('Route wallet/importAccount', () => { publicAddress: trustedDealerPackages.publicAddress, spendingKey: null, createdAt: null, + isLedger: false, proofAuthorizingKey: trustedDealerPackages.proofAuthorizingKey, multisigKeys: { publicKeyPackage: trustedDealerPackages.publicKeyPackage, @@ -102,6 +104,7 @@ describe('Route wallet/importAccount', () => { proofAuthorizingKey: null, version: 1, createdAt: null, + isLedger: false, }), rescan: false, }) @@ -129,6 +132,7 @@ describe('Route wallet/importAccount', () => { proofAuthorizingKey: null, version: 1, createdAt: null, + isLedger: false, }), name: overriddenAccountName, rescan: false, @@ -172,6 +176,7 @@ describe('Route wallet/importAccount', () => { proofAuthorizingKey: null, version: 1, createdAt: null, + isLedger: false, } const response = await routeTest.client.wallet.importAccount({ @@ -203,6 +208,7 @@ describe('Route wallet/importAccount', () => { version: 1, createdAt: null, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } } @@ -500,6 +506,7 @@ describe('Route wallet/importAccount', () => { keyPackage: trustedDealerPackages.keyPackages[1].keyPackage.toString(), secret: secrets[1].serialize().toString('hex'), }, + isLedger: false, } try { @@ -582,6 +589,7 @@ describe('Route wallet/importAccount', () => { publicKeyPackage: trustedDealerPackages.publicKeyPackage, identity: nextIdentity, }, + isLedger: false, } try { @@ -625,6 +633,7 @@ describe('Route wallet/importAccount', () => { publicKeyPackage: trustedDealerPackages.publicKeyPackage, identity: identity, }, + isLedger: false, } const response = await routeTest.client.wallet.importAccount({ diff --git a/ironfish/src/rpc/routes/wallet/multisig/createSignatureShare.test.ts b/ironfish/src/rpc/routes/wallet/multisig/createSignatureShare.test.ts index 1091ab900c..0914d59932 100644 --- a/ironfish/src/rpc/routes/wallet/multisig/createSignatureShare.test.ts +++ b/ironfish/src/rpc/routes/wallet/multisig/createSignatureShare.test.ts @@ -34,6 +34,7 @@ describe('Route wallt/multisig/createSignatureShare', () => { version: ACCOUNT_SCHEMA_VERSION, spendingKey: null, createdAt: null, + isLedger: false, } const account = await routeTest.wallet.importAccount(accountImport) diff --git a/ironfish/src/rpc/routes/wallet/multisig/createSigningCommitment.test.ts b/ironfish/src/rpc/routes/wallet/multisig/createSigningCommitment.test.ts index dcdf723c84..05be1d79de 100644 --- a/ironfish/src/rpc/routes/wallet/multisig/createSigningCommitment.test.ts +++ b/ironfish/src/rpc/routes/wallet/multisig/createSigningCommitment.test.ts @@ -53,6 +53,7 @@ describe('Route wallet/multisig/createSigningCommitment', () => { publicKeyPackage: trustedDealerPackage.publicKeyPackage, }, proofAuthorizingKey: null, + isLedger: false, } const importAccountRequest = { diff --git a/ironfish/src/rpc/routes/wallet/multisig/createTrustedDealerKeyPackage.ts b/ironfish/src/rpc/routes/wallet/multisig/createTrustedDealerKeyPackage.ts index 7b7bd170f8..7850637cac 100644 --- a/ironfish/src/rpc/routes/wallet/multisig/createTrustedDealerKeyPackage.ts +++ b/ironfish/src/rpc/routes/wallet/multisig/createTrustedDealerKeyPackage.ts @@ -101,6 +101,7 @@ routes.register< keyPackage, publicKeyPackage, }, + isLedger: false, } const encoder = new JsonEncoder() diff --git a/ironfish/src/rpc/routes/wallet/multisig/dkg/round3.ts b/ironfish/src/rpc/routes/wallet/multisig/dkg/round3.ts index 448ec7fe44..ad81be0a57 100644 --- a/ironfish/src/rpc/routes/wallet/multisig/dkg/round3.ts +++ b/ironfish/src/rpc/routes/wallet/multisig/dkg/round3.ts @@ -92,6 +92,7 @@ routes.register( keyPackage, publicKeyPackage, }, + isLedger: false, } const account = await node.wallet.importAccount(accountImport, { diff --git a/ironfish/src/rpc/routes/wallet/multisig/integration.test.slow.ts b/ironfish/src/rpc/routes/wallet/multisig/integration.test.slow.ts index 190d083e6a..35e9c99faf 100644 --- a/ironfish/src/rpc/routes/wallet/multisig/integration.test.slow.ts +++ b/ironfish/src/rpc/routes/wallet/multisig/integration.test.slow.ts @@ -159,6 +159,7 @@ describe('multisig RPC integration', () => { publicKeyPackage: trustedDealerPackage.publicKeyPackage, }, ...trustedDealerPackage, + isLedger: false, } // import an account to serve as the coordinator diff --git a/ironfish/src/rpc/routes/wallet/serializers.ts b/ironfish/src/rpc/routes/wallet/serializers.ts index 67ea68bba4..00eda4178d 100644 --- a/ironfish/src/rpc/routes/wallet/serializers.ts +++ b/ironfish/src/rpc/routes/wallet/serializers.ts @@ -161,6 +161,7 @@ export async function serializeRpcAccountStatus( return { name: account.name, id: account.id, + isLedger: account.isLedger, head: head ? { hash: head.hash.toString('hex'), diff --git a/ironfish/src/rpc/routes/wallet/types.ts b/ironfish/src/rpc/routes/wallet/types.ts index a692840702..05acedb054 100644 --- a/ironfish/src/rpc/routes/wallet/types.ts +++ b/ironfish/src/rpc/routes/wallet/types.ts @@ -165,6 +165,7 @@ export type RpcMultisigKeys = { export type RpcAccountStatus = { name: string id: string + isLedger: boolean head: { hash: string sequence: number @@ -179,6 +180,7 @@ export const RpcAccountStatusSchema: yup.ObjectSchema = yup .object({ name: yup.string().defined(), id: yup.string().defined(), + isLedger: yup.boolean().defined(), head: yup .object({ hash: yup.string().defined(), diff --git a/ironfish/src/wallet/account/account.ts b/ironfish/src/wallet/account/account.ts index 1450468c79..e56bc7ee34 100644 --- a/ironfish/src/wallet/account/account.ts +++ b/ironfish/src/wallet/account/account.ts @@ -76,7 +76,7 @@ export class Account { readonly prefixRange: DatabaseKeyRange readonly multisigKeys?: MultisigKeys readonly proofAuthorizingKey: string | null - + readonly isLedger: boolean constructor({ accountValue, walletDb, @@ -103,6 +103,7 @@ export class Account { this.scanningEnabled = accountValue.scanningEnabled this.multisigKeys = accountValue.multisigKeys this.proofAuthorizingKey = accountValue.proofAuthorizingKey + this.isLedger = accountValue.isLedger } isSpendingAccount(): this is SpendingAccount { @@ -124,6 +125,7 @@ export class Account { scanningEnabled: this.scanningEnabled, multisigKeys: this.multisigKeys, proofAuthorizingKey: this.proofAuthorizingKey, + isLedger: this.isLedger, } } diff --git a/ironfish/src/wallet/exporter/accountImport.ts b/ironfish/src/wallet/exporter/accountImport.ts index 3652cc0f47..ca3f060a68 100644 --- a/ironfish/src/wallet/exporter/accountImport.ts +++ b/ironfish/src/wallet/exporter/accountImport.ts @@ -29,6 +29,7 @@ export type AccountImport = { } | null multisigKeys?: MultisigKeysImport proofAuthorizingKey: string | null + isLedger: boolean } export function toAccountImport( @@ -54,6 +55,7 @@ export function toAccountImport( createdAt, multisigKeys: account.multisigKeys, proofAuthorizingKey: account.proofAuthorizingKey, + isLedger: account.isLedger, } if (viewOnly) { diff --git a/ironfish/src/wallet/exporter/encoders/base64json.test.ts b/ironfish/src/wallet/exporter/encoders/base64json.test.ts index 745b71ab66..f477f2fd48 100644 --- a/ironfish/src/wallet/exporter/encoders/base64json.test.ts +++ b/ironfish/src/wallet/exporter/encoders/base64json.test.ts @@ -22,6 +22,7 @@ describe('Base64JsonEncoder', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -40,6 +41,7 @@ describe('Base64JsonEncoder', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -58,6 +60,7 @@ describe('Base64JsonEncoder', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -84,6 +87,7 @@ describe('Base64JsonEncoder', () => { sequence: 1, }, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -104,6 +108,7 @@ describe('Base64JsonEncoder', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -127,6 +132,7 @@ describe('Base64JsonEncoder', () => { publicKeyPackage: 'abcdef0000', }, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -152,6 +158,7 @@ describe('Base64JsonEncoder', () => { keyPackage: 'bbbb', }, proofAuthorizingKey: null, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -172,6 +179,7 @@ describe('Base64JsonEncoder', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: null, + isLedger: false, } const encoded = encoder.encode(accountImport) diff --git a/ironfish/src/wallet/exporter/encoders/bech32.test.ts b/ironfish/src/wallet/exporter/encoders/bech32.test.ts index 92b6819ff1..d078807be1 100644 --- a/ironfish/src/wallet/exporter/encoders/bech32.test.ts +++ b/ironfish/src/wallet/exporter/encoders/bech32.test.ts @@ -22,6 +22,7 @@ describe('Bech32AccountEncoder', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -42,6 +43,7 @@ describe('Bech32AccountEncoder', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, }) const decoded = encoder.decode(encoded, { name: 'foo' }) @@ -65,6 +67,7 @@ describe('Bech32AccountEncoder', () => { sequence: 1, }, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -85,6 +88,7 @@ describe('Bech32AccountEncoder', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -108,6 +112,7 @@ describe('Bech32AccountEncoder', () => { publicKeyPackage: 'abcdef0000', }, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -133,6 +138,7 @@ describe('Bech32AccountEncoder', () => { keyPackage: 'bbbb', }, proofAuthorizingKey: null, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -153,6 +159,7 @@ describe('Bech32AccountEncoder', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: null, + isLedger: false, } const encoded = encoder.encode(accountImport) @@ -185,6 +192,7 @@ describe('Bech32AccountEncoder', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } encoder.VERSION = 0 diff --git a/ironfish/src/wallet/exporter/encoders/bech32.ts b/ironfish/src/wallet/exporter/encoders/bech32.ts index 07961220ec..dbcb623528 100644 --- a/ironfish/src/wallet/exporter/encoders/bech32.ts +++ b/ironfish/src/wallet/exporter/encoders/bech32.ts @@ -164,6 +164,7 @@ function decoderV1( publicAddress, createdAt, proofAuthorizingKey: null, + isLedger: false, } } diff --git a/ironfish/src/wallet/exporter/encoders/json.test.ts b/ironfish/src/wallet/exporter/encoders/json.test.ts index 69a83ae260..6cbee1df3d 100644 --- a/ironfish/src/wallet/exporter/encoders/json.test.ts +++ b/ironfish/src/wallet/exporter/encoders/json.test.ts @@ -70,7 +70,7 @@ describe('JsonEncoder', () => { version: ACCOUNT_SCHEMA_VERSION, name: 'test', spendingKey: null, - viewKey: key.viewKey, + viewKey: key.viewKey, // viewKey is required incomingViewKey: key.incomingViewKey, outgoingViewKey: key.outgoingViewKey, publicAddress: key.publicAddress, @@ -79,6 +79,7 @@ describe('JsonEncoder', () => { publicKeyPackage: 'cccc', }, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoder = new JsonEncoder() @@ -107,6 +108,7 @@ describe('JsonEncoder', () => { keyPackage: 'bbbb', }, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const encoder = new JsonEncoder() diff --git a/ironfish/src/wallet/exporter/encoders/json.ts b/ironfish/src/wallet/exporter/encoders/json.ts index 6f36d24be3..04e83c1495 100644 --- a/ironfish/src/wallet/exporter/encoders/json.ts +++ b/ironfish/src/wallet/exporter/encoders/json.ts @@ -66,6 +66,7 @@ type AccountEncodedJSON = { publicKeyPackage: string } proofAuthorizingKey?: string | null + isLedger?: boolean } const AccountEncodedJSONSchema: yup.ObjectSchema = yup @@ -96,6 +97,7 @@ const AccountEncodedJSONSchema: yup.ObjectSchema = yup .optional() .default(undefined), proofAuthorizingKey: yup.string().nullable().optional(), + isLedger: yup.boolean().optional(), }) .defined() @@ -118,6 +120,7 @@ const serializeAccountEncodedJSON = (accountImport: AccountImport): AccountEncod spendingKey: accountImport.spendingKey, multisigKeys: accountImport.multisigKeys, proofAuthorizingKey: accountImport.proofAuthorizingKey, + isLedger: accountImport.isLedger, createdAt: createdAt, } } @@ -150,5 +153,6 @@ function deserializeAccountEncodedJSON(raw: AccountEncodedJSON): AccountImport { multisigKeys: raw.multisigKeys ? deserializeRpcAccountMultisigKeys(raw.multisigKeys) : undefined, + isLedger: raw.isLedger ?? false, } } diff --git a/ironfish/src/wallet/exporter/encoders/mnemonic.ts b/ironfish/src/wallet/exporter/encoders/mnemonic.ts index 633afd105d..18a7b3890b 100644 --- a/ironfish/src/wallet/exporter/encoders/mnemonic.ts +++ b/ironfish/src/wallet/exporter/encoders/mnemonic.ts @@ -61,6 +61,7 @@ export class MnemonicEncoder implements AccountEncoder { createdAt: null, version: ACCOUNT_SCHEMA_VERSION, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } } } diff --git a/ironfish/src/wallet/exporter/encoders/spendingKey.ts b/ironfish/src/wallet/exporter/encoders/spendingKey.ts index 7b27badf65..953e2a95ad 100644 --- a/ironfish/src/wallet/exporter/encoders/spendingKey.ts +++ b/ironfish/src/wallet/exporter/encoders/spendingKey.ts @@ -44,6 +44,7 @@ export class SpendingKeyEncoder implements AccountEncoder { createdAt: null, version: ACCOUNT_SCHEMA_VERSION, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } } } diff --git a/ironfish/src/wallet/exporter/encryption.test.ts b/ironfish/src/wallet/exporter/encryption.test.ts index 69be117b51..e2553a9d15 100644 --- a/ironfish/src/wallet/exporter/encryption.test.ts +++ b/ironfish/src/wallet/exporter/encryption.test.ts @@ -27,6 +27,7 @@ describe('Wallet Export Encryption', () => { publicAddress: key.publicAddress, createdAt: null, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const secret = multisig.ParticipantSecret.random() diff --git a/ironfish/src/wallet/wallet.test.slow.ts b/ironfish/src/wallet/wallet.test.slow.ts index cae2f9263b..9ba4e2dbc6 100644 --- a/ironfish/src/wallet/wallet.test.slow.ts +++ b/ironfish/src/wallet/wallet.test.slow.ts @@ -636,6 +636,7 @@ describe('Wallet', () => { incomingViewKey: account.incomingViewKey, createdAt: null, proofAuthorizingKey: account.proofAuthorizingKey, + isLedger: false, } const viewOnlyAccount = await viewOnlyNode.wallet.importAccount(accountValue) @@ -1167,6 +1168,7 @@ describe('Wallet', () => { name: trustedDealerPackage.keyPackages[0].identity, spendingKey: null, createdAt: null, + isLedger: false, multisigKeys: getMultisigKeys(0), ...trustedDealerPackage, }) @@ -1175,6 +1177,7 @@ describe('Wallet', () => { name: trustedDealerPackage.keyPackages[1].identity, spendingKey: null, createdAt: null, + isLedger: false, multisigKeys: getMultisigKeys(1), ...trustedDealerPackage, }) @@ -1183,6 +1186,7 @@ describe('Wallet', () => { name: trustedDealerPackage.keyPackages[2].identity, spendingKey: null, createdAt: null, + isLedger: false, multisigKeys: getMultisigKeys(2), ...trustedDealerPackage, }) @@ -1194,6 +1198,7 @@ describe('Wallet', () => { name: 'coordinator', spendingKey: null, createdAt: null, + isLedger: false, multisigKeys: { publicKeyPackage: trustedDealerPackage.publicKeyPackage, }, @@ -1360,6 +1365,7 @@ describe('Wallet', () => { identity: trustedDealerPackage.keyPackages[0].identity, keyPackage: trustedDealerPackage.keyPackages[0].keyPackage, }, + isLedger: false, ...trustedDealerPackage, }) diff --git a/ironfish/src/wallet/wallet.test.ts b/ironfish/src/wallet/wallet.test.ts index 3398ce23d0..79683c7dbb 100644 --- a/ironfish/src/wallet/wallet.test.ts +++ b/ironfish/src/wallet/wallet.test.ts @@ -533,6 +533,7 @@ describe('Wallet', () => { version: 1, spendingKey: null, createdAt: null, + isLedger: false, ...key, } const viewonlyAccount = await node.wallet.importAccount(accountValue) @@ -554,6 +555,7 @@ describe('Wallet', () => { version: 1, spendingKey: null, createdAt: null, + isLedger: false, ...key, } const accountImport1 = await node.wallet.importAccount(accountValue) @@ -669,6 +671,7 @@ describe('Wallet', () => { version: 1, createdAt: null, scanningEnabled: false, + isLedger: false, ...key, } @@ -689,6 +692,7 @@ describe('Wallet', () => { name: 'new-account', version: 1, createdAt: null, + isLedger: false, scanningEnabled: false, ...key, } diff --git a/ironfish/src/wallet/wallet.ts b/ironfish/src/wallet/wallet.ts index 84f1529fea..3e90a6b045 100644 --- a/ironfish/src/wallet/wallet.ts +++ b/ironfish/src/wallet/wallet.ts @@ -40,8 +40,11 @@ import { TransactionUtils, } from '../utils' import { WorkerPool } from '../workerPool' -import { DecryptedNote, DecryptNotesItem } from '../workerPool/tasks/decryptNotes' -import { DecryptNotesOptions } from '../workerPool/tasks/decryptNotes' +import { + DecryptedNote, + DecryptNotesItem, + DecryptNotesOptions, +} from '../workerPool/tasks/decryptNotes' import { Account, ACCOUNT_SCHEMA_VERSION } from './account/account' import { EncryptedAccount } from './account/encryptedAccount' import { AssetBalances } from './assetBalances' @@ -1398,6 +1401,7 @@ export class Wallet { spendingKey: key.spendingKey, viewKey: key.viewKey, scanningEnabled: true, + isLedger: false, createdAt, }, walletDb: this.walletDb, diff --git a/ironfish/src/wallet/walletdb/accountValue.test.ts b/ironfish/src/wallet/walletdb/accountValue.test.ts index ee716a96b5..c5581f9ee2 100644 --- a/ironfish/src/wallet/walletdb/accountValue.test.ts +++ b/ironfish/src/wallet/walletdb/accountValue.test.ts @@ -30,6 +30,7 @@ describe('AccountValueEncoding', () => { }, scanningEnabled: true, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const buffer = encoder.serialize(value) const deserializedValue = encoder.deserialize(buffer) @@ -59,6 +60,7 @@ describe('AccountValueEncoding', () => { keyPackage: 'beef', }, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: false, } const buffer = encoder.serialize(value) const deserializedValue = encoder.deserialize(buffer) @@ -87,6 +89,7 @@ describe('AccountValueEncoding', () => { keyPackage: 'beef', }, proofAuthorizingKey: key.proofAuthorizingKey, + isLedger: true, } const passphrase = 'foobarbaz' diff --git a/ironfish/src/wallet/walletdb/accountValue.ts b/ironfish/src/wallet/walletdb/accountValue.ts index 50dc2be1ca..c00971abc6 100644 --- a/ironfish/src/wallet/walletdb/accountValue.ts +++ b/ironfish/src/wallet/walletdb/accountValue.ts @@ -20,6 +20,7 @@ export type EncryptedAccountValue = { export type DecryptedAccountValue = { encrypted: false + isLedger: boolean version: number id: string name: string @@ -66,6 +67,7 @@ export class AccountValueEncoding implements IDatabaseEncoding { flags |= Number(!!value.proofAuthorizingKey) << 3 flags |= Number(!!value.scanningEnabled) << 4 flags |= Number(!!value.encrypted) << 5 + flags |= Number(!!value.isLedger) << 6 bw.writeU8(flags) bw.writeU16(value.version) @@ -137,6 +139,7 @@ export class AccountValueEncoding implements IDatabaseEncoding { const hasMultisigKeys = flags & (1 << 2) const hasProofAuthorizingKey = flags & (1 << 3) const scanningEnabled = Boolean(flags & (1 << 4)) + const isLedger = Boolean(flags & (1 << 6)) const id = reader.readVarString('utf8') const name = reader.readVarString('utf8') const spendingKey = hasSpendingKey ? reader.readBytes(KEY_LENGTH).toString('hex') : null @@ -176,6 +179,7 @@ export class AccountValueEncoding implements IDatabaseEncoding { scanningEnabled, multisigKeys, proofAuthorizingKey, + isLedger, } } diff --git a/ironfish/src/wallet/walletdb/walletdb.test.ts b/ironfish/src/wallet/walletdb/walletdb.test.ts index d24515d7e9..ff9cf354bb 100644 --- a/ironfish/src/wallet/walletdb/walletdb.test.ts +++ b/ironfish/src/wallet/walletdb/walletdb.test.ts @@ -638,6 +638,7 @@ describe('WalletDB', () => { version: 1, createdAt: null, scanningEnabled: false, + isLedger: false, ...key, } const account = new Account({ accountValue, walletDb }) @@ -657,6 +658,7 @@ describe('WalletDB', () => { version: 1, createdAt: null, scanningEnabled: false, + isLedger: false, ...key, } const account = new Account({ accountValue, walletDb }) @@ -687,6 +689,7 @@ describe('WalletDB', () => { version: 1, createdAt: null, scanningEnabled: false, + isLedger: false, ...key, } const account = new Account({ accountValue, walletDb }) @@ -710,6 +713,7 @@ describe('WalletDB', () => { version: 1, createdAt: null, scanningEnabled: false, + isLedger: false, ...key, } const account = new Account({ accountValue, walletDb })