Skip to content

Commit 04d3678

Browse files
authored
Merge pull request #4848 from iron-fish/staging
STAGING -> MASTER
2 parents f996f89 + 264df7b commit 04d3678

File tree

88 files changed

+1569
-504
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+1569
-504
lines changed

.github/pull_request_template.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ related documentation pull request for the website.
1414

1515
## Breaking Change
1616

17-
Is this a breaking change? If yes, add notes below on why this is breaking and
18-
what additional work is required, if any.
17+
Is this a breaking change? If yes, add notes below on why this is breaking and label it with `breaking-change-rpc` or `breaking-change-sdk`.
1918

2019
```
2120
[ ] Yes

Cargo.lock

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ironfish-cli/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ironfish",
3-
"version": "2.0.0",
3+
"version": "2.1.0",
44
"description": "CLI for running and interacting with an Iron Fish node",
55
"author": "Iron Fish <[email protected]> (https://ironfish.network)",
66
"main": "build/src/index.js",
@@ -62,8 +62,8 @@
6262
"@aws-sdk/client-s3": "3",
6363
"@aws-sdk/client-secrets-manager": "3",
6464
"@aws-sdk/s3-request-presigner": "3",
65-
"@ironfish/rust-nodejs": "2.0.0",
66-
"@ironfish/sdk": "2.0.0",
65+
"@ironfish/rust-nodejs": "2.1.0",
66+
"@ironfish/sdk": "2.1.0",
6767
"@oclif/core": "1.23.1",
6868
"@oclif/plugin-help": "5.1.12",
6969
"@oclif/plugin-not-found": "2.3.1",

ironfish-cli/src/commands/wallet/import.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,20 +92,15 @@ export class ImportCommand extends IronfishCommand {
9292
if (
9393
e instanceof RpcRequestError &&
9494
(e.code === RPC_ERROR_CODES.DUPLICATE_ACCOUNT_NAME.toString() ||
95-
e.code === RPC_ERROR_CODES.IMPORT_ACCOUNT_NAME_REQUIRED.toString() ||
96-
e.code === RPC_ERROR_CODES.MULTISIG_SECRET_NAME_REQUIRED.toString())
95+
e.code === RPC_ERROR_CODES.IMPORT_ACCOUNT_NAME_REQUIRED.toString())
9796
) {
98-
let message = 'Enter a name for the account'
97+
const message = 'Enter a name for the account'
9998

10099
if (e.code === RPC_ERROR_CODES.DUPLICATE_ACCOUNT_NAME.toString()) {
101100
this.log()
102101
this.log(e.codeMessage)
103102
}
104103

105-
if (e.code === RPC_ERROR_CODES.MULTISIG_SECRET_NAME_REQUIRED.toString()) {
106-
message = 'Enter the name of the multisig secret'
107-
}
108-
109104
const name = await CliUx.ux.prompt(message, {
110105
required: true,
111106
})

ironfish-cli/src/commands/wallet/multisig/commitment/aggregate.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import { Flags } from '@oclif/core'
66
import { IronfishCommand } from '../../../../command'
77
import { RemoteFlags } from '../../../../flags'
88
import { longPrompt } from '../../../../utils/longPrompt'
9+
import { MultisigTransactionJson } from '../../../../utils/multisig'
910

1011
export class CreateSigningPackage extends IronfishCommand {
1112
static description = `Creates a signing package for a given transaction for a multisig account`
12-
static hidden = true
1313

1414
static flags = {
1515
...RemoteFlags,
@@ -28,20 +28,25 @@ export class CreateSigningPackage extends IronfishCommand {
2828
'The signing commitments from participants to be used for creating the signing package',
2929
multiple: true,
3030
}),
31+
path: Flags.string({
32+
description: 'Path to a JSON file containing multisig transaction data',
33+
}),
3134
}
3235

3336
async start(): Promise<void> {
3437
const { flags } = await this.parse(CreateSigningPackage)
3538

36-
let unsignedTransaction = flags.unsignedTransaction?.trim()
39+
const loaded = await MultisigTransactionJson.load(this.sdk.fileSystem, flags.path)
40+
const options = MultisigTransactionJson.resolveFlags(flags, loaded)
3741

42+
let unsignedTransaction = options.unsignedTransaction
3843
if (!unsignedTransaction) {
3944
unsignedTransaction = await longPrompt('Enter the unsigned transaction', {
4045
required: true,
4146
})
4247
}
4348

44-
let commitments = flags.commitment
49+
let commitments = options.commitment
4550
if (!commitments) {
4651
const input = await longPrompt('Enter the signing commitments separated by commas', {
4752
required: true,
@@ -60,5 +65,9 @@ export class CreateSigningPackage extends IronfishCommand {
6065

6166
this.log(`Signing Package for commitments from ${commitments.length} participants:\n`)
6267
this.log(signingPackageResponse.content.signingPackage)
68+
69+
this.log()
70+
this.log('Next step:')
71+
this.log('Send the signing package to all of the participants who provided a commitment.')
6372
}
6473
}

ironfish-cli/src/commands/wallet/multisig/commitment/create.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import { CliUx, Flags } from '@oclif/core'
66
import { IronfishCommand } from '../../../../command'
77
import { RemoteFlags } from '../../../../flags'
88
import { longPrompt } from '../../../../utils/longPrompt'
9+
import { MultisigTransactionJson } from '../../../../utils/multisig'
910
import { renderUnsignedTransactionDetails } from '../../../../utils/transaction'
1011

1112
export class CreateSigningCommitmentCommand extends IronfishCommand {
1213
static description = 'Create a signing commitment from a participant for a given transaction'
13-
static hidden = true
1414

1515
static flags = {
1616
...RemoteFlags,
@@ -34,12 +34,18 @@ export class CreateSigningCommitmentCommand extends IronfishCommand {
3434
default: false,
3535
description: 'Confirm creating signing commitment without confirming',
3636
}),
37+
path: Flags.string({
38+
description: 'Path to a JSON file containing multisig transaction data',
39+
}),
3740
}
3841

3942
async start(): Promise<void> {
4043
const { flags } = await this.parse(CreateSigningCommitmentCommand)
4144

42-
let identities = flags.identity
45+
const loaded = await MultisigTransactionJson.load(this.sdk.fileSystem, flags.path)
46+
const options = MultisigTransactionJson.resolveFlags(flags, loaded)
47+
48+
let identities = options.identity
4349
if (!identities || identities.length < 2) {
4450
const input = await longPrompt('Enter the identities separated by commas', {
4551
required: true,
@@ -52,7 +58,7 @@ export class CreateSigningCommitmentCommand extends IronfishCommand {
5258
}
5359
identities = identities.map((i) => i.trim())
5460

55-
let unsignedTransactionInput = flags.unsignedTransaction?.trim()
61+
let unsignedTransactionInput = options.unsignedTransaction
5662
if (!unsignedTransactionInput) {
5763
unsignedTransactionInput = await longPrompt('Enter the unsigned transaction', {
5864
required: true,
@@ -86,5 +92,9 @@ export class CreateSigningCommitmentCommand extends IronfishCommand {
8692

8793
this.log('\nCommitment:\n')
8894
this.log(response.content.commitment)
95+
96+
this.log()
97+
this.log('Next step:')
98+
this.log('Send the commitment to the multisig account coordinator.')
8999
}
90100
}

ironfish-cli/src/commands/wallet/multisig/dealer/create.ts

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
/* This Source Code Form is subject to the terms of the Mozilla Public
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4-
import { ACCOUNT_SCHEMA_VERSION } from '@ironfish/sdk'
4+
import { ACCOUNT_SCHEMA_VERSION, RpcClient } from '@ironfish/sdk'
55
import { CliUx, Flags } from '@oclif/core'
66
import { IronfishCommand } from '../../../../command'
77
import { RemoteFlags } from '../../../../flags'
8+
import { longPrompt } from '../../../../utils/longPrompt'
89

910
export class MultisigCreateDealer extends IronfishCommand {
1011
static description = `Create a set of multisig accounts from participant identities`
@@ -37,7 +38,7 @@ export class MultisigCreateDealer extends IronfishCommand {
3738

3839
let identities = flags.identity
3940
if (!identities || identities.length < 2) {
40-
const input = await CliUx.ux.prompt('Enter the identities separated by commas', {
41+
const input = await longPrompt('Enter the identities separated by commas', {
4142
required: true,
4243
})
4344
identities = input.split(',')
@@ -59,12 +60,10 @@ export class MultisigCreateDealer extends IronfishCommand {
5960
}
6061
}
6162

62-
const name =
63-
flags.name?.trim() ??
64-
(await CliUx.ux.prompt('Enter the name for the coordinator', { required: true }))
65-
6663
const client = await this.sdk.connectRpc()
6764

65+
const name = await this.getCoordinatorName(client, flags.name?.trim())
66+
6867
const response = await client.wallet.multisig.createTrustedDealerKeyPackage({
6968
minSigners,
7069
participants: identities.map((identity) => ({ identity })),
@@ -114,5 +113,33 @@ export class MultisigCreateDealer extends IronfishCommand {
114113
}
115114

116115
this.log()
116+
this.log('Next step:')
117+
this.log('Send the account imports to the participant with the corresponding identity.')
118+
}
119+
120+
async getCoordinatorName(client: RpcClient, inputName?: string): Promise<string> {
121+
const accountsResponse = await client.wallet.getAccounts()
122+
const accountNames = new Set(accountsResponse.content.accounts)
123+
124+
const identitiesResponse = await client.wallet.multisig.getIdentities()
125+
const secretNames = new Set(identitiesResponse.content.identities.map((i) => i.name))
126+
127+
let name = inputName
128+
do {
129+
name =
130+
name ?? (await CliUx.ux.prompt('Enter a name for the coordinator', { required: true }))
131+
132+
if (accountNames.has(name)) {
133+
this.log(`Account with name ${name} already exists`)
134+
this.log('')
135+
name = undefined
136+
} else if (secretNames.has(name)) {
137+
this.log(`Multisig identity with name ${name} already exists`)
138+
this.log('')
139+
name = undefined
140+
}
141+
} while (name === undefined)
142+
143+
return name
117144
}
118145
}

ironfish-cli/src/commands/wallet/multisig/participant/create.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { RemoteFlags } from '../../../../flags'
88

99
export class MultisigIdentityCreate extends IronfishCommand {
1010
static description = `Create a multisig participant identity`
11-
static hidden = true
1211

1312
static flags = {
1413
...RemoteFlags,
@@ -39,15 +38,20 @@ export class MultisigIdentityCreate extends IronfishCommand {
3938
) {
4039
this.log()
4140
this.log(e.codeMessage)
41+
name = await CliUx.ux.prompt('Enter a new name for the identity', {
42+
required: true,
43+
})
44+
} else {
45+
throw e
4246
}
43-
44-
name = await CliUx.ux.prompt('Enter a new name for the identity', {
45-
required: true,
46-
})
4747
}
4848
}
4949

5050
this.log('Identity:')
5151
this.log(response.content.identity)
52+
53+
this.log()
54+
this.log('Next step:')
55+
this.log('Send the identity to the multisig account dealer.')
5256
}
5357
}

ironfish-cli/src/commands/wallet/multisig/participant/index.ts

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,18 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
44
import { Flags } from '@oclif/core'
5+
import inquirer from 'inquirer'
56
import { IronfishCommand } from '../../../../command'
67
import { RemoteFlags } from '../../../../flags'
78

89
export class MultisigIdentity extends IronfishCommand {
910
static description = `Retrieve a multisig participant identity from a name`
10-
static hidden = true
1111

1212
static flags = {
1313
...RemoteFlags,
1414
name: Flags.string({
1515
char: 'n',
1616
description: 'Name of the participant identity',
17-
required: true,
1817
}),
1918
}
2019

@@ -23,9 +22,38 @@ export class MultisigIdentity extends IronfishCommand {
2322

2423
const client = await this.sdk.connectRpc()
2524

26-
const response = await client.wallet.multisig.getIdentity({ name: flags.name })
25+
if (flags.name) {
26+
const response = await client.wallet.multisig.getIdentity({ name: flags.name })
2727

28-
this.log('Identity:')
29-
this.log(response.content.identity)
28+
this.log('Identity:')
29+
this.log(response.content.identity)
30+
} else {
31+
const response = await client.wallet.multisig.getIdentities()
32+
33+
const choices = []
34+
for (const { name, identity } of response.content.identities) {
35+
choices.push({
36+
name,
37+
value: identity,
38+
})
39+
}
40+
41+
// sort identities by name
42+
choices.sort((a, b) => a.name.localeCompare(b.name))
43+
44+
const selection = await inquirer.prompt<{
45+
identity: string
46+
}>([
47+
{
48+
name: 'identity',
49+
message: 'Select participant name to view identity',
50+
type: 'list',
51+
choices,
52+
},
53+
])
54+
55+
this.log('Identity:')
56+
this.log(selection.identity)
57+
}
3058
}
3159
}

ironfish-cli/src/commands/wallet/multisig/participants/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { RemoteFlags } from '../../../../flags'
77

88
export class MultisigAccountParticipants extends IronfishCommand {
99
static description = `List the participant identities for a multisig account`
10-
static hidden = true
1110

1211
static flags = {
1312
...RemoteFlags,

0 commit comments

Comments
 (0)