@devtion/devcli 0.0.0-3df1645 → 0.0.0-477457c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/.env +14 -0
- package/dist/index.js +487 -82
- package/dist/public/mini-semaphore.wasm +0 -0
- package/dist/public/mini-semaphore.zkey +0 -0
- package/dist/types/commands/authBandada.d.ts +2 -0
- package/dist/types/commands/authSIWE.d.ts +7 -0
- package/dist/types/commands/ceremony/index.d.ts +3 -0
- package/dist/types/commands/ceremony/listParticipants.d.ts +2 -0
- package/dist/types/commands/index.d.ts +2 -0
- package/dist/types/commands/setup.d.ts +3 -3
- package/dist/types/lib/bandada.d.ts +6 -0
- package/dist/types/lib/files.d.ts +0 -1
- package/dist/types/lib/localConfigs.d.ts +38 -0
- package/dist/types/lib/prompts.d.ts +6 -6
- package/dist/types/types/index.d.ts +69 -0
- package/package.json +12 -5
- package/src/commands/auth.ts +18 -8
- package/src/commands/authBandada.ts +120 -0
- package/src/commands/authSIWE.ts +185 -0
- package/src/commands/ceremony/index.ts +20 -0
- package/src/commands/ceremony/listParticipants.ts +56 -0
- package/src/commands/contribute.ts +48 -25
- package/src/commands/finalize.ts +9 -5
- package/src/commands/index.ts +2 -0
- package/src/commands/logout.ts +3 -1
- package/src/commands/observe.ts +6 -2
- package/src/commands/setup.ts +32 -18
- package/src/index.ts +18 -5
- package/src/lib/bandada.ts +51 -0
- package/src/lib/errors.ts +2 -2
- package/src/lib/localConfigs.ts +54 -0
- package/src/lib/prompts.ts +11 -15
- package/src/lib/services.ts +38 -13
- package/src/lib/utils.ts +13 -9
- package/src/types/index.ts +75 -0
package/src/index.ts
CHANGED
|
@@ -7,6 +7,8 @@ import { fileURLToPath } from "url"
|
|
|
7
7
|
import {
|
|
8
8
|
setup,
|
|
9
9
|
auth,
|
|
10
|
+
authSIWE,
|
|
11
|
+
authBandada,
|
|
10
12
|
contribute,
|
|
11
13
|
observe,
|
|
12
14
|
finalize,
|
|
@@ -15,6 +17,7 @@ import {
|
|
|
15
17
|
validate,
|
|
16
18
|
listCeremonies
|
|
17
19
|
} from "./commands/index.js"
|
|
20
|
+
import setCeremonyCommands from "./commands/ceremony/index.js"
|
|
18
21
|
|
|
19
22
|
// Get pkg info (e.g., name, version).
|
|
20
23
|
const packagePath = `${dirname(fileURLToPath(import.meta.url))}/..`
|
|
@@ -26,6 +29,14 @@ program.name(name).description(description).version(version)
|
|
|
26
29
|
|
|
27
30
|
// User commands.
|
|
28
31
|
program.command("auth").description("authenticate yourself using your Github account (OAuth 2.0)").action(auth)
|
|
32
|
+
program
|
|
33
|
+
.command("auth-bandada")
|
|
34
|
+
.description("authenticate yourself in a privacy-perserving manner using Bandada")
|
|
35
|
+
.action(authBandada)
|
|
36
|
+
program
|
|
37
|
+
.command("auth-siwe")
|
|
38
|
+
.description("authenticate yourself using your Ethereum account (Sign In With Ethereum - SIWE)")
|
|
39
|
+
.action(authSIWE)
|
|
29
40
|
program
|
|
30
41
|
.command("contribute")
|
|
31
42
|
.description("compute contributions for a Phase2 Trusted Setup ceremony circuits")
|
|
@@ -44,27 +55,27 @@ program
|
|
|
44
55
|
.action(logout)
|
|
45
56
|
program
|
|
46
57
|
.command("validate")
|
|
47
|
-
.description("
|
|
58
|
+
.description("validate that a Ceremony Setup file is correct")
|
|
48
59
|
.requiredOption("-t, --template <path>", "The path to the ceremony setup template", "")
|
|
49
60
|
.option("-c, --constraints <number>", "The number of constraints to check against")
|
|
50
61
|
.action(validate)
|
|
51
62
|
|
|
52
63
|
// Only coordinator commands.
|
|
53
|
-
const
|
|
64
|
+
const coordinate = program.command("coordinate").description("commands for coordinating a ceremony")
|
|
54
65
|
|
|
55
|
-
|
|
66
|
+
coordinate
|
|
56
67
|
.command("setup")
|
|
57
68
|
.description("setup a Groth16 Phase 2 Trusted Setup ceremony for zk-SNARK circuits")
|
|
58
69
|
.option("-t, --template <path>", "The path to the ceremony setup template", "")
|
|
59
70
|
.option("-a, --auth <string>", "The Github OAuth 2.0 token", "")
|
|
60
71
|
.action(setup)
|
|
61
72
|
|
|
62
|
-
|
|
73
|
+
coordinate
|
|
63
74
|
.command("observe")
|
|
64
75
|
.description("observe in real-time the waiting queue of each ceremony circuit")
|
|
65
76
|
.action(observe)
|
|
66
77
|
|
|
67
|
-
|
|
78
|
+
coordinate
|
|
68
79
|
.command("finalize")
|
|
69
80
|
.description(
|
|
70
81
|
"finalize a Phase2 Trusted Setup ceremony by applying a beacon, exporting verification key and verifier contract"
|
|
@@ -72,4 +83,6 @@ ceremony
|
|
|
72
83
|
.option("-a, --auth <string>", "the Github OAuth 2.0 token", "")
|
|
73
84
|
.action(finalize)
|
|
74
85
|
|
|
86
|
+
setCeremonyCommands(program)
|
|
87
|
+
|
|
75
88
|
program.parseAsync(process.argv)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ApiSdk, GroupResponse } from "@bandada/api-sdk"
|
|
2
|
+
import { Identity } from "@semaphore-protocol/identity"
|
|
3
|
+
import open from "open"
|
|
4
|
+
|
|
5
|
+
import { askForConfirmation } from "../lib/prompts.js"
|
|
6
|
+
import { showError } from "./errors.js"
|
|
7
|
+
import theme from "../lib/theme.js"
|
|
8
|
+
|
|
9
|
+
const { BANDADA_API_URL } = process.env
|
|
10
|
+
|
|
11
|
+
const bandadaApi = new ApiSdk(BANDADA_API_URL)
|
|
12
|
+
|
|
13
|
+
export const getGroup = async (groupId: string): Promise<GroupResponse | null> => {
|
|
14
|
+
try {
|
|
15
|
+
const group = await bandadaApi.getGroup(groupId)
|
|
16
|
+
return group
|
|
17
|
+
} catch (error: any) {
|
|
18
|
+
showError(`Bandada getGroup error: ${error}`, true)
|
|
19
|
+
return null
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const getMembersOfGroup = async (groupId: string): Promise<string[] | null> => {
|
|
24
|
+
try {
|
|
25
|
+
const group = await bandadaApi.getGroup(groupId)
|
|
26
|
+
return group.members
|
|
27
|
+
} catch (error: any) {
|
|
28
|
+
showError(`Bandada getMembersOfGroup error: ${error}`, true)
|
|
29
|
+
return null
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const addMemberToGroup = async (groupId: string, dashboardUrl: string, identity: Identity) => {
|
|
34
|
+
const commitment = identity.commitment.toString()
|
|
35
|
+
const group = await bandadaApi.getGroup(groupId)
|
|
36
|
+
const providerName = group.credentials.id.split("_")[0].toLowerCase()
|
|
37
|
+
|
|
38
|
+
// 6. open a new window with the url:
|
|
39
|
+
const url = `${dashboardUrl}credentials?group=${groupId}&member=${commitment}&provider=${providerName}`
|
|
40
|
+
console.log(`${theme.text.bold(`Verification URL:`)} ${theme.text.underlined(url)}`)
|
|
41
|
+
open(url)
|
|
42
|
+
|
|
43
|
+
const { confirmation } = await askForConfirmation("Did you join the Bandada group in the browser?")
|
|
44
|
+
if (!confirmation) showError("You must join the Bandada group to continue the login process", true)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const isGroupMember = async (groupId: string, identity: Identity): Promise<boolean> => {
|
|
48
|
+
const commitment = identity.commitment.toString()
|
|
49
|
+
const isMember: boolean = await bandadaApi.isGroupMember(groupId, commitment)
|
|
50
|
+
return isMember
|
|
51
|
+
}
|
package/src/lib/errors.ts
CHANGED
|
@@ -6,7 +6,7 @@ export const CORE_SERVICES_ERRORS = {
|
|
|
6
6
|
FIREBASE_TOKEN_EXPIRED_REMOVED_PERMISSIONS: `The Github authorization has failed due to lack of association between your account and the CLI`,
|
|
7
7
|
FIREBASE_USER_DISABLED: `The Github account has been suspended by the ceremony coordinator(s), blocking the possibility of contribution. Please, contact them to understand the motivation behind it.`,
|
|
8
8
|
FIREBASE_FAILED_CREDENTIALS_VERIFICATION: `Firebase cannot verify your Github credentials due to network errors. Please, try once again later.`,
|
|
9
|
-
FIREBASE_NETWORK_ERROR: `Unable to reach Firebase due to network
|
|
9
|
+
FIREBASE_NETWORK_ERROR: `Unable to reach Firebase due to network errors. Please, try once again later and make sure your Internet connection is stable.`,
|
|
10
10
|
FIREBASE_CEREMONY_NOT_OPENED: `There are no ceremonies opened to contributions`,
|
|
11
11
|
FIREBASE_CEREMONY_NOT_CLOSED: `There are no ceremonies ready to finalization`,
|
|
12
12
|
AWS_CEREMONY_BUCKET_CREATION: `Unable to create a new bucket for the ceremony. Something went wrong during the creation. Please, repeat the process by providing a new ceremony name of the ceremony.`,
|
|
@@ -34,7 +34,7 @@ export const COMMAND_ERRORS = {
|
|
|
34
34
|
COMMAND_SETUP_NO_R1CS: `Unable to retrieve R1CS files from current working directory. Please, run this command from a working directory where the R1CS files are located to continue with the setup process. We kindly ask you to run the command from an empty directory containing only the R1CS and WASM files.`,
|
|
35
35
|
COMMAND_SETUP_NO_WASM: `Unable to retrieve WASM files from current working directory. Please, run this command from a working directory where the WASM files are located to continue with the setup process. We kindly ask you to run the command from an empty directory containing only the WASM and R1CS files.`,
|
|
36
36
|
COMMAND_SETUP_MISMATCH_R1CS_WASM: `The folder contains more R1CS files than WASM files (or vice versa). Please, run this command from a working directory where each R1CS is paired with its corresponding file WASM.`,
|
|
37
|
-
COMMAND_SETUP_DOWNLOAD_PTAU: `Unable to download Powers of Tau file from
|
|
37
|
+
COMMAND_SETUP_DOWNLOAD_PTAU: `Unable to download Powers of Tau file from PPoT Phase 1 Trusted Setup. Possible causes may involve an error while making the request (be sure to have a stable internet connection). Please, we kindly ask you to terminate the current session and repeat the process.`,
|
|
38
38
|
COMMAND_SETUP_ABORT: `You chose to abort the setup process.`,
|
|
39
39
|
COMMAND_CONTRIBUTE_NO_OPENED_CEREMONIES: `Unfortunately, there is no ceremony for which you can make a contribution at this time. Please, try again later.`,
|
|
40
40
|
COMMAND_CONTRIBUTE_NO_PARTICIPANT_DATA: `Unable to retrieve your data as ceremony participant. Please, terminate the current session and try again later. If the error persists, please contact the ceremony coordinator.`,
|
package/src/lib/localConfigs.ts
CHANGED
|
@@ -24,6 +24,14 @@ const config = new Conf({
|
|
|
24
24
|
accessToken: {
|
|
25
25
|
type: "string",
|
|
26
26
|
default: ""
|
|
27
|
+
},
|
|
28
|
+
bandadaIdentity: {
|
|
29
|
+
type: "string",
|
|
30
|
+
default: ""
|
|
31
|
+
},
|
|
32
|
+
authMethod: {
|
|
33
|
+
type: "string",
|
|
34
|
+
default: ""
|
|
27
35
|
}
|
|
28
36
|
}
|
|
29
37
|
})
|
|
@@ -91,6 +99,52 @@ export const setLocalAccessToken = (token: string) => config.set("accessToken",
|
|
|
91
99
|
*/
|
|
92
100
|
export const deleteLocalAccessToken = () => config.delete("accessToken")
|
|
93
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Return the Bandada identity, if present.
|
|
104
|
+
* @returns <string | undefined> - the Bandada identity if present, otherwise undefined.
|
|
105
|
+
*/
|
|
106
|
+
export const getLocalBandadaIdentity = (): string | unknown => config.get("bandadaIdentity")
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Check if the Bandada identity exists in the local storage.
|
|
110
|
+
* @returns <boolean>
|
|
111
|
+
*/
|
|
112
|
+
export const checkLocalBandadaIdentity = (): boolean => config.has("bandadaIdentity") && !!config.get("bandadaIdentity")
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Set the Bandada identity.
|
|
116
|
+
* @param identity <string> - the Bandada identity to be stored.
|
|
117
|
+
*/
|
|
118
|
+
export const setLocalBandadaIdentity = (identity: string) => config.set("bandadaIdentity", identity)
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Delete the stored Bandada identity.
|
|
122
|
+
*/
|
|
123
|
+
export const deleteLocalBandadaIdentity = () => config.delete("bandadaIdentity")
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Return the authentication method, if present.
|
|
127
|
+
* @returns <string | undefined> - the authentication method if present, otherwise undefined.
|
|
128
|
+
*/
|
|
129
|
+
export const getLocalAuthMethod = (): string | unknown => config.get("authMethod")
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Check if the authentication method exists in the local storage.
|
|
133
|
+
* @returns <boolean>
|
|
134
|
+
*/
|
|
135
|
+
export const checkLocalAuthMethod = (): boolean => config.has("authMethod") && !!config.get("authMethod")
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Set the authentication method.
|
|
139
|
+
* @param method <string> - the authentication method to be stored.
|
|
140
|
+
*/
|
|
141
|
+
export const setLocalAuthMethod = (method: string) => config.set("authMethod", method)
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Delete the stored authentication method.
|
|
145
|
+
*/
|
|
146
|
+
export const deleteLocalAuthMethod = () => config.delete("authMethod")
|
|
147
|
+
|
|
94
148
|
/**
|
|
95
149
|
* Get the complete local file path.
|
|
96
150
|
* @param cwd <string> - the current working directory path.
|
package/src/lib/prompts.ts
CHANGED
|
@@ -203,7 +203,7 @@ export const promptCircomCompiler = async (): Promise<CircomCompilerData> => {
|
|
|
203
203
|
* Shows a list of circuits for a single option selection.
|
|
204
204
|
* @dev the circuit names are derived from local R1CS files.
|
|
205
205
|
* @param options <Array<string>> - an array of circuits names.
|
|
206
|
-
* @returns Promise<string> - the name of the
|
|
206
|
+
* @returns Promise<string> - the name of the chosen circuit.
|
|
207
207
|
*/
|
|
208
208
|
export const promptCircuitSelector = async (options: Array<string>): Promise<string> => {
|
|
209
209
|
const { circuitFilename } = await prompts({
|
|
@@ -223,7 +223,7 @@ export const promptCircuitSelector = async (options: Array<string>): Promise<str
|
|
|
223
223
|
* Shows a list of standard EC2 VM instance types for a single option selection.
|
|
224
224
|
* @notice the suggested VM configuration type is calculated based on circuit constraint size.
|
|
225
225
|
* @param constraintSize <number> - the amount of circuit constraints
|
|
226
|
-
* @returns Promise<string> - the name of the
|
|
226
|
+
* @returns Promise<string> - the name of the chosen VM type.
|
|
227
227
|
*/
|
|
228
228
|
export const promptVMTypeSelector = async (constraintSize): Promise<string> => {
|
|
229
229
|
let suggestedConfiguration: number = 0
|
|
@@ -325,7 +325,7 @@ export const promptVMDiskTypeSelector = async (): Promise<DiskTypeForVM> => {
|
|
|
325
325
|
/**
|
|
326
326
|
* Show a series of questions about the circuits.
|
|
327
327
|
* @param constraintSize <number> - the amount of circuit constraints.
|
|
328
|
-
* @param timeoutMechanismType <CeremonyTimeoutType> - the
|
|
328
|
+
* @param timeoutMechanismType <CeremonyTimeoutType> - the chosen timeout mechanism type for the ceremony.
|
|
329
329
|
* @param needPromptCircomCompiler <boolean> - a boolean value indicating if the questions related to the Circom compiler version and commit hash must be asked.
|
|
330
330
|
* @param enforceVM <boolean> - a boolean value indicating if the contribution verification could be supported by VM-only approach or not.
|
|
331
331
|
* @returns Promise<Array<Circuit>> - circuit info prompted by the coordinator.
|
|
@@ -422,7 +422,7 @@ export const promptCircuitInputData = async (
|
|
|
422
422
|
circomCommitHash = commitHash
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
// Ask for
|
|
425
|
+
// Ask for preferred contribution verification method (CF vs VM).
|
|
426
426
|
if (!enforceVM) {
|
|
427
427
|
const { confirmation } = await askForConfirmation(
|
|
428
428
|
`The contribution verification can be performed using Cloud Functions (CF, cheaper for small contributions but limited to 1M constraints) or custom virtual machines (expensive but could scale up to 30M constraints). Be aware about VM costs and if you wanna learn more, please visit the documentation to have a complete overview about cost estimation of the two mechanisms.\nChoose the contribution verification mechanism`,
|
|
@@ -432,7 +432,6 @@ export const promptCircuitInputData = async (
|
|
|
432
432
|
cfOrVm = confirmation
|
|
433
433
|
? CircuitContributionVerificationMechanism.CF
|
|
434
434
|
: CircuitContributionVerificationMechanism.VM
|
|
435
|
-
|
|
436
435
|
} else {
|
|
437
436
|
cfOrVm = CircuitContributionVerificationMechanism.VM
|
|
438
437
|
}
|
|
@@ -587,7 +586,7 @@ export const promptCircuitAddition = async (): Promise<boolean> => {
|
|
|
587
586
|
* Shows a list of pre-computed zKeys for a single option selection.
|
|
588
587
|
* @dev the names are derived from local zKeys files.
|
|
589
588
|
* @param options <Array<string>> - an array of pre-computed zKeys names.
|
|
590
|
-
* @returns Promise<string> - the name of the
|
|
589
|
+
* @returns Promise<string> - the name of the chosen pre-computed zKey.
|
|
591
590
|
*/
|
|
592
591
|
export const promptPreComputedZkeySelector = async (options: Array<string>): Promise<string> => {
|
|
593
592
|
const { preComputedZkeyFilename } = await prompts({
|
|
@@ -634,13 +633,13 @@ export const promptNeededPowersForCircuit = async (suggestedSmallestNeededPowers
|
|
|
634
633
|
* Shows a list of PoT files for a single option selection.
|
|
635
634
|
* @dev the names are derived from local PoT files.
|
|
636
635
|
* @param options <Array<string>> - an array of PoT file names.
|
|
637
|
-
* @returns Promise<string> - the name of the
|
|
636
|
+
* @returns Promise<string> - the name of the chosen PoT.
|
|
638
637
|
*/
|
|
639
638
|
export const promptPotSelector = async (options: Array<string>): Promise<string> => {
|
|
640
639
|
const { potFilename } = await prompts({
|
|
641
640
|
type: "select",
|
|
642
641
|
name: "potFilename",
|
|
643
|
-
message: theme.text.bold("Select the Powers of Tau file
|
|
642
|
+
message: theme.text.bold("Select the Powers of Tau file chosen for the circuit"),
|
|
644
643
|
choices: options.map((option: string) => {
|
|
645
644
|
console.log(option)
|
|
646
645
|
return { title: option, value: option }
|
|
@@ -662,7 +661,8 @@ export const promptPotSelector = async (options: Array<string>): Promise<string>
|
|
|
662
661
|
*/
|
|
663
662
|
export const promptForCeremonySelection = async (
|
|
664
663
|
ceremoniesDocuments: Array<FirebaseDocumentInfo>,
|
|
665
|
-
isFinalizing: boolean
|
|
664
|
+
isFinalizing: boolean,
|
|
665
|
+
messageToDisplay?: string
|
|
666
666
|
): Promise<FirebaseDocumentInfo> => {
|
|
667
667
|
// Prepare state.
|
|
668
668
|
const choices: Array<Choice> = []
|
|
@@ -687,11 +687,7 @@ export const promptForCeremonySelection = async (
|
|
|
687
687
|
const { ceremony } = await prompts({
|
|
688
688
|
type: "select",
|
|
689
689
|
name: "ceremony",
|
|
690
|
-
message: theme.text.bold(
|
|
691
|
-
!isFinalizing
|
|
692
|
-
? "Which ceremony would you like to contribute to?"
|
|
693
|
-
: "Which ceremony would you like to finalize?"
|
|
694
|
-
),
|
|
690
|
+
message: theme.text.bold(messageToDisplay),
|
|
695
691
|
choices,
|
|
696
692
|
initial: 0
|
|
697
693
|
})
|
|
@@ -732,7 +728,7 @@ export const promptToTypeEntropyOrBeacon = async (isEntropy = true): Promise<str
|
|
|
732
728
|
* @return <Promise<string>> - the entropy.
|
|
733
729
|
*/
|
|
734
730
|
export const promptForEntropy = async (): Promise<string> => {
|
|
735
|
-
// Prompt for entropy generation
|
|
731
|
+
// Prompt for entropy generation preferred method.
|
|
736
732
|
const { confirmation } = await askForConfirmation(
|
|
737
733
|
`Do you prefer to type your entropy or generate it randomly?`,
|
|
738
734
|
"Manually",
|
package/src/lib/services.ts
CHANGED
|
@@ -6,13 +6,18 @@ import {
|
|
|
6
6
|
import clear from "clear"
|
|
7
7
|
import figlet from "figlet"
|
|
8
8
|
import { FirebaseApp } from "firebase/app"
|
|
9
|
-
import { OAuthCredential } from "firebase/auth"
|
|
9
|
+
import { OAuthCredential, getAuth, signInWithCustomToken } from "firebase/auth"
|
|
10
10
|
import dotenv from "dotenv"
|
|
11
11
|
import { fileURLToPath } from "url"
|
|
12
12
|
import { dirname } from "path"
|
|
13
13
|
import { AuthUser } from "../types/index.js"
|
|
14
14
|
import { CONFIG_ERRORS, CORE_SERVICES_ERRORS, showError, THIRD_PARTY_SERVICES_ERRORS } from "./errors.js"
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
checkLocalAccessToken,
|
|
17
|
+
deleteLocalAccessToken,
|
|
18
|
+
getLocalAccessToken,
|
|
19
|
+
getLocalAuthMethod
|
|
20
|
+
} from "./localConfigs.js"
|
|
16
21
|
import theme from "./theme.js"
|
|
17
22
|
import { exchangeGithubTokenForCredentials, getGithubProviderUserId, getUserHandleFromProviderUserId } from "./utils.js"
|
|
18
23
|
|
|
@@ -164,22 +169,42 @@ export const checkAuth = async (firebaseApp: FirebaseApp): Promise<AuthUser> =>
|
|
|
164
169
|
// Retrieve local access token.
|
|
165
170
|
const token = String(getLocalAccessToken())
|
|
166
171
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
+
let providerUserId: string
|
|
173
|
+
let username: string
|
|
174
|
+
const authMethod = getLocalAuthMethod()
|
|
175
|
+
switch (authMethod) {
|
|
176
|
+
case "github": {
|
|
177
|
+
// Get credentials.
|
|
178
|
+
const credentials = exchangeGithubTokenForCredentials(token)
|
|
179
|
+
// Sign in to Firebase using credentials.
|
|
180
|
+
await signInToFirebase(firebaseApp, credentials)
|
|
181
|
+
// Get Github unique identifier (handle-id).
|
|
182
|
+
providerUserId = await getGithubProviderUserId(String(token))
|
|
183
|
+
username = getUserHandleFromProviderUserId(providerUserId)
|
|
184
|
+
break
|
|
185
|
+
}
|
|
186
|
+
case "bandada": {
|
|
187
|
+
const userCredentials = await signInWithCustomToken(getAuth(), token)
|
|
188
|
+
providerUserId = userCredentials.user.uid
|
|
189
|
+
username = providerUserId
|
|
190
|
+
break
|
|
191
|
+
}
|
|
192
|
+
case "siwe": {
|
|
193
|
+
const userCredentials = await signInWithCustomToken(getAuth(), token)
|
|
194
|
+
providerUserId = userCredentials.user.uid
|
|
195
|
+
username = providerUserId
|
|
196
|
+
break
|
|
197
|
+
}
|
|
198
|
+
default: {
|
|
199
|
+
break
|
|
200
|
+
}
|
|
201
|
+
}
|
|
172
202
|
|
|
173
203
|
// Get current authenticated user.
|
|
174
204
|
const user = getCurrentFirebaseAuthUser(firebaseApp)
|
|
175
205
|
|
|
176
|
-
// Get Github unique identifier (handle-id).
|
|
177
|
-
const providerUserId = await getGithubProviderUserId(String(token))
|
|
178
|
-
|
|
179
206
|
// Greet the user.
|
|
180
|
-
console.log(
|
|
181
|
-
`Greetings, @${theme.text.bold(getUserHandleFromProviderUserId(providerUserId))} ${theme.emojis.wave}\n`
|
|
182
|
-
)
|
|
207
|
+
console.log(`Greetings, @${theme.text.bold(username)} ${theme.emojis.wave}\n`)
|
|
183
208
|
|
|
184
209
|
return {
|
|
185
210
|
user,
|
package/src/lib/utils.ts
CHANGED
|
@@ -18,7 +18,8 @@ import {
|
|
|
18
18
|
ParticipantContributionStep,
|
|
19
19
|
permanentlyStoreCurrentContributionTimeAndHash,
|
|
20
20
|
progressToNextContributionStep,
|
|
21
|
-
verifyContribution
|
|
21
|
+
verifyContribution,
|
|
22
|
+
contribHashRegex
|
|
22
23
|
} from "@devtion/actions"
|
|
23
24
|
import { Presets, SingleBar } from "cli-progress"
|
|
24
25
|
import dotenv from "dotenv"
|
|
@@ -155,9 +156,11 @@ export const getPublicAttestationGist = async (
|
|
|
155
156
|
* @returns <string> - the third-party provider handle of the user.
|
|
156
157
|
*/
|
|
157
158
|
export const getUserHandleFromProviderUserId = (providerUserId: string): string => {
|
|
158
|
-
if (providerUserId.indexOf("-") === -1)
|
|
159
|
+
if (providerUserId.indexOf("-") === -1) {
|
|
160
|
+
return providerUserId
|
|
161
|
+
}
|
|
159
162
|
|
|
160
|
-
return providerUserId.
|
|
163
|
+
return providerUserId.substring(0, providerUserId.lastIndexOf("-"))
|
|
161
164
|
}
|
|
162
165
|
|
|
163
166
|
/**
|
|
@@ -309,8 +312,9 @@ export const generateCustomUrlToTweetAboutParticipation = (
|
|
|
309
312
|
ceremonyName: string,
|
|
310
313
|
gistUrl: string,
|
|
311
314
|
isFinalizing: boolean
|
|
312
|
-
) =>
|
|
313
|
-
|
|
315
|
+
) => {
|
|
316
|
+
ceremonyName = ceremonyName.replace(/ /g, "%20")
|
|
317
|
+
return isFinalizing
|
|
314
318
|
? `https://twitter.com/intent/tweet?text=I%20have%20finalized%20the%20${ceremonyName}${
|
|
315
319
|
ceremonyName.toLowerCase().includes("trusted") ||
|
|
316
320
|
ceremonyName.toLowerCase().includes("setup") ||
|
|
@@ -327,6 +331,7 @@ export const generateCustomUrlToTweetAboutParticipation = (
|
|
|
327
331
|
? "!"
|
|
328
332
|
: "%20Phase%202%20Trusted%20Setup%20ceremony!"
|
|
329
333
|
}%20You%20can%20view%20the%20steps%20to%20contribute%20here:%20https://ceremony.pse.dev%20You%20can%20view%20my%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP`
|
|
334
|
+
}
|
|
330
335
|
|
|
331
336
|
/**
|
|
332
337
|
* Return a custom progress bar.
|
|
@@ -662,7 +667,7 @@ export const handleStartOrResumeContribution = async (
|
|
|
662
667
|
|
|
663
668
|
// Read local transcript file info to get the contribution hash.
|
|
664
669
|
const transcriptContents = readFile(transcriptLocalFilePath)
|
|
665
|
-
const matchContributionHash = transcriptContents.match(
|
|
670
|
+
const matchContributionHash = transcriptContents.match(contribHashRegex)
|
|
666
671
|
|
|
667
672
|
if (!matchContributionHash)
|
|
668
673
|
showError(COMMAND_ERRORS.COMMAND_CONTRIBUTE_FINALIZE_NO_TRANSCRIPT_CONTRIBUTION_HASH_MATCH, true)
|
|
@@ -739,8 +744,7 @@ export const handleStartOrResumeContribution = async (
|
|
|
739
744
|
)
|
|
740
745
|
|
|
741
746
|
progressBar.stop()
|
|
742
|
-
}
|
|
743
|
-
else
|
|
747
|
+
} else
|
|
744
748
|
await multiPartUpload(
|
|
745
749
|
cloudFunctions,
|
|
746
750
|
bucketName,
|
|
@@ -751,7 +755,7 @@ export const handleStartOrResumeContribution = async (
|
|
|
751
755
|
|
|
752
756
|
// small sleep to ensure the previous step is completed
|
|
753
757
|
await sleep(5000)
|
|
754
|
-
|
|
758
|
+
|
|
755
759
|
spinner.succeed(
|
|
756
760
|
`${
|
|
757
761
|
isFinalizing ? `Contribution` : `Contribution ${theme.text.bold(`#${nextZkeyIndex}`)}`
|
package/src/types/index.ts
CHANGED
|
@@ -68,3 +68,78 @@ export type GithubGistFile = {
|
|
|
68
68
|
raw_url: string
|
|
69
69
|
size: number
|
|
70
70
|
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Define the return object of the function that verifies the Bandada membership and proof.
|
|
74
|
+
* @typedef {Object} VerifiedBandadaResponse
|
|
75
|
+
* @property {boolean} valid - true if the proof is valid and the user is a member of the group; otherwise false.
|
|
76
|
+
* @property {string} message - a message describing the result of the verification.
|
|
77
|
+
* @property {string} token - the custom access token.
|
|
78
|
+
*/
|
|
79
|
+
export type VerifiedBandadaResponse = {
|
|
80
|
+
valid: boolean
|
|
81
|
+
message: string
|
|
82
|
+
token: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Define the return object of the device code uri request.
|
|
87
|
+
* @typedef {Object} OAuthDeviceCodeResponse
|
|
88
|
+
* @property {string} device_code - the device code.
|
|
89
|
+
* @property {string} user_code - the user code.
|
|
90
|
+
* @property {string} verification_uri - the verification uri.
|
|
91
|
+
* @property {number} expires_in - the expiration time in seconds.
|
|
92
|
+
* @property {number} interval - the interval time in seconds.
|
|
93
|
+
* @property {string} verification_uri_complete - the complete verification uri.
|
|
94
|
+
* @property {string} error - in case there was an error, show the code
|
|
95
|
+
* @property {string} error_description - error details.
|
|
96
|
+
* @property {string} error_uri - error uri.
|
|
97
|
+
*/
|
|
98
|
+
export type OAuthDeviceCodeResponse = {
|
|
99
|
+
device_code: string
|
|
100
|
+
user_code: string
|
|
101
|
+
verification_uri: string
|
|
102
|
+
expires_in: number
|
|
103
|
+
interval: number
|
|
104
|
+
verification_uri_complete: string
|
|
105
|
+
// error response should contain
|
|
106
|
+
error?: string
|
|
107
|
+
error_description?: string
|
|
108
|
+
error_uri?: string
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Define the return object of the polling endpoint
|
|
113
|
+
* @typedef {Object} OAuthTokenResponse
|
|
114
|
+
* @property {string} access_token - the resulting device flow token
|
|
115
|
+
* @property {string} token_type - token type
|
|
116
|
+
* @property {number} expires_in - when does the token expires
|
|
117
|
+
* @property {string} scope - the scope requested by the initial device flow endpoint
|
|
118
|
+
* @property {string} refresh_token - refresh token
|
|
119
|
+
* @property {string} id_token - id token
|
|
120
|
+
* @property {string} error - in case there was an error, show the code
|
|
121
|
+
* @property {string} error_description - error details
|
|
122
|
+
*/
|
|
123
|
+
export type OAuthTokenResponse = {
|
|
124
|
+
access_token: string
|
|
125
|
+
token_type: string
|
|
126
|
+
expires_in: number
|
|
127
|
+
scope: string
|
|
128
|
+
refresh_token: string
|
|
129
|
+
id_token: string
|
|
130
|
+
// error response should contain
|
|
131
|
+
error?: string
|
|
132
|
+
error_description?: string
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @typedef {Object} CheckNonceOfSIWEAddressResponse
|
|
137
|
+
* @property {boolean} valid - if the checking was valid or not
|
|
138
|
+
* @property {string} message - more information about the validity
|
|
139
|
+
* @property {string} token - token to sign into Firebase
|
|
140
|
+
*/
|
|
141
|
+
export type CheckNonceOfSIWEAddressResponse = {
|
|
142
|
+
valid: boolean
|
|
143
|
+
message: string
|
|
144
|
+
token: string
|
|
145
|
+
}
|