Skip to content

Commit

Permalink
Merge pull request #4752 from iron-fish/staging
Browse files Browse the repository at this point in the history
Staging -> Master
  • Loading branch information
danield9tqh authored Feb 20, 2024
2 parents 4fab80d + c979262 commit 83c9078
Show file tree
Hide file tree
Showing 173 changed files with 7,372 additions and 2,759 deletions.
19 changes: 11 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions ironfish-cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ironfish",
"version": "1.19.0",
"version": "1.20.0",
"description": "CLI for running and interacting with an Iron Fish node",
"author": "Iron Fish <[email protected]> (https://ironfish.network)",
"main": "build/src/index.js",
Expand Down Expand Up @@ -62,8 +62,8 @@
"@aws-sdk/client-s3": "3",
"@aws-sdk/client-secrets-manager": "3",
"@aws-sdk/s3-request-presigner": "3",
"@ironfish/rust-nodejs": "1.16.0",
"@ironfish/sdk": "1.19.0",
"@ironfish/rust-nodejs": "1.17.0",
"@ironfish/sdk": "1.20.0",
"@oclif/core": "1.23.1",
"@oclif/plugin-help": "5.1.12",
"@oclif/plugin-not-found": "2.3.1",
Expand Down
2 changes: 1 addition & 1 deletion ironfish-cli/src/commands/wallet/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class ExportCommand extends IronfishCommand {
? AccountFormat.Mnemonic
: flags.json
? AccountFormat.JSON
: AccountFormat.Bech32
: AccountFormat.Base64Json

const client = await this.sdk.connectRpc(local)
const response = await client.wallet.exportAccount({
Expand Down
53 changes: 39 additions & 14 deletions ironfish-cli/src/commands/wallet/import.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { PromiseUtils } from '@ironfish/sdk'
import { PromiseUtils, RPC_ERROR_CODES, RpcRequestError } from '@ironfish/sdk'
import { CliUx, Flags } from '@oclif/core'
import { IronfishCommand } from '../../command'
import { RemoteFlags } from '../../flags'
import { longPrompt } from '../../utils/longPrompt'

export class ImportCommand extends IronfishCommand {
static description = `Import an account`
Expand Down Expand Up @@ -78,11 +79,40 @@ export class ImportCommand extends IronfishCommand {
flags.name = name
}

const result = await client.wallet.importAccount({
account,
rescan: flags.rescan,
name: flags.name,
})
let result

while (!result) {
try {
result = await client.wallet.importAccount({
account,
rescan: flags.rescan,
name: flags.name,
})
} catch (e) {
if (
e instanceof RpcRequestError &&
(e.code === RPC_ERROR_CODES.DUPLICATE_ACCOUNT_NAME.toString() ||
e.code === RPC_ERROR_CODES.IMPORT_ACCOUNT_NAME_REQUIRED.toString())
) {
if (e.code === RPC_ERROR_CODES.DUPLICATE_ACCOUNT_NAME.toString()) {
this.log()
this.log(e.codeMessage)
}

const name = await CliUx.ux.prompt('Enter a name for the account', {
required: true,
})
if (name === flags.name) {
this.error(`Entered the same name: '${name}'`)
}

flags.name = name
continue
}

throw e
}
}

const { name, isDefaultAccount } = result.content
this.log(`Account ${name} imported.`)
Expand Down Expand Up @@ -120,13 +150,8 @@ export class ImportCommand extends IronfishCommand {
}

async importTTY(): Promise<string> {
const userInput = await CliUx.ux.prompt(
'Paste the output of wallet:export, or your spending key',
{
required: true,
},
)

return userInput.trim()
return await longPrompt('Paste the output of wallet:export, or your spending key: ', {
required: true,
})
}
}
2 changes: 1 addition & 1 deletion ironfish-cli/src/commands/wallet/mint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export class Mint extends IronfishCommand {
client: client,
required: true,
text: 'Enter the amount',
minimum: 1n,
minimum: 0n,
logger: this.logger,
})
}
Expand Down
136 changes: 136 additions & 0 deletions ironfish-cli/src/commands/wallet/multisig/account/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { ACCOUNT_SCHEMA_VERSION, Base64JsonEncoder } from '@ironfish/sdk'
import { CliUx, Flags } from '@oclif/core'
import { IronfishCommand } from '../../../../command'
import { RemoteFlags } from '../../../../flags'

export class MultisigCreate extends IronfishCommand {
static description = `Create a set of multisig accounts from identities`
static hidden = true

static flags = {
...RemoteFlags,
name: Flags.string({
char: 'n',
description: 'Name to use for the coordinator',
}),
identity: Flags.string({
char: 'i',
description: 'Identity of a participant',
multiple: true,
}),
minSigners: Flags.integer({
char: 'm',
description: 'Minimum number of signers to meet signing threshold',
}),
importCoordinator: Flags.boolean({
char: 'c',
default: true,
description: 'Import the coordinator as a view-only account after creating key packages',
}),
}

async start(): Promise<void> {
const { flags } = await this.parse(MultisigCreate)

let identities = flags.identity
if (!identities || identities.length < 2) {
const input = await CliUx.ux.prompt('Enter the identities separated by commas', {
required: true,
})
identities = input.split(',')

if (identities.length < 2) {
this.error('Minimum number of identities must be at least 2')
}
}
identities = identities.map((i) => i.trim())

let minSigners = flags.minSigners
if (!minSigners) {
const input = await CliUx.ux.prompt('Enter the number of minimum signers', {
required: true,
})
minSigners = parseInt(input)
if (isNaN(minSigners) || minSigners < 2) {
this.error('Minimum number of signers must be at least 2')
}
}

const name =
flags.name?.trim() ??
(await CliUx.ux.prompt('Enter the name for the coordinator', { required: true }))

const client = await this.sdk.connectRpc()

const response = await client.wallet.multisig.createTrustedDealerKeyPackage({
minSigners,
participants: identities.map((identity) => ({ identity })),
})

const chainResponse = await client.chain.getChainInfo()
const hash = Buffer.from(chainResponse.content.currentBlockIdentifier.hash, 'hex')
const sequence = Number(chainResponse.content.currentBlockIdentifier.index)
const createdAt = {
hash,
sequence,
}

if (flags.importCoordinator) {
this.log()
CliUx.ux.action.start('Importing the coordinator as a view-only account')

await client.wallet.importAccount({
account: {
name,
version: ACCOUNT_SCHEMA_VERSION,
createdAt: {
hash: createdAt.hash.toString('hex'),
sequence: createdAt.sequence,
},
spendingKey: null,
viewKey: response.content.viewKey,
incomingViewKey: response.content.incomingViewKey,
outgoingViewKey: response.content.outgoingViewKey,
publicAddress: response.content.publicAddress,
proofAuthorizingKey: response.content.proofAuthorizingKey,
multisigKeys: {
publicKeyPackage: response.content.publicKeyPackage,
},
},
})

CliUx.ux.action.stop()
}

const encoder = new Base64JsonEncoder()

for (const [i, keyPackage] of response.content.keyPackages.entries()) {
this.log('\n')
this.log(`Account ${i + 1}`)
this.log(`Identity ${keyPackage.identity}`)
this.log('----------------')
const accountStr = encoder.encode({
name: `${name}-${i}`,
version: ACCOUNT_SCHEMA_VERSION,
createdAt,
spendingKey: null,
viewKey: response.content.viewKey,
incomingViewKey: response.content.incomingViewKey,
outgoingViewKey: response.content.outgoingViewKey,
publicAddress: response.content.publicAddress,
proofAuthorizingKey: response.content.proofAuthorizingKey,
multisigKeys: {
identity: keyPackage.identity,
keyPackage: keyPackage.keyPackage,
publicKeyPackage: response.content.publicKeyPackage,
},
})
this.log(accountStr)
}

this.log()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import { CliUx, Flags } from '@oclif/core'
import { IronfishCommand } from '../../../command'
import { RemoteFlags } from '../../../flags'
import { longPrompt } from '../../../utils/longPrompt'

export class CreateSignatureShareCommand extends IronfishCommand {
static description = `Creates a signature share for a participant for a given transaction`
static hidden = true

static flags = {
...RemoteFlags,
account: Flags.string({
char: 'f',
description: 'The account from which the signature share will be created',
required: false,
}),
signingPackage: Flags.string({
char: 's',
description: 'The signing package for which the signature share will be created',
required: false,
}),
signerIdentity: Flags.string({
char: 'i',
description:
'The identity of the participants that will sign the transaction (may be specified multiple times to add multiple signers)',
required: true,
multiple: true,
}),
confirm: Flags.boolean({
default: false,
description: 'Confirm creating signature share without confirming',
}),
}

async start(): Promise<void> {
const { flags } = await this.parse(CreateSignatureShareCommand)
let signingPackage = flags.signingPackage?.trim()

if (!signingPackage) {
signingPackage = await longPrompt('Enter the signing package: ')
}

if (!flags.confirm) {
const confirmed = await CliUx.ux.confirm('Confirm new signature share creation (Y/N)')
if (!confirmed) {
this.error('Creating signature share aborted')
}
}

const client = await this.sdk.connectRpc()
const signatureShareResponse = await client.wallet.multisig.createSignatureShare({
account: flags.account,
signingPackage,
})

this.log('Signing Share:\n')
this.log(signatureShareResponse.content.signatureShare)
}
}
Loading

0 comments on commit 83c9078

Please sign in to comment.