@devtion/devcli 0.0.0-9c50f66 → 0.0.0-a7b749e

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.
Files changed (42) hide show
  1. package/README.md +1 -1
  2. package/dist/.env +55 -0
  3. package/dist/index.js +549 -120
  4. package/dist/public/mini-semaphore.wasm +0 -0
  5. package/dist/public/mini-semaphore.zkey +0 -0
  6. package/dist/types/commands/authBandada.d.ts +2 -0
  7. package/dist/types/commands/authSIWE.d.ts +7 -0
  8. package/dist/types/commands/ceremony/index.d.ts +3 -0
  9. package/dist/types/commands/ceremony/listParticipants.d.ts +2 -0
  10. package/dist/types/commands/contribute.d.ts +1 -1
  11. package/dist/types/commands/finalize.d.ts +4 -3
  12. package/dist/types/commands/index.d.ts +2 -0
  13. package/dist/types/commands/observe.d.ts +1 -1
  14. package/dist/types/commands/setup.d.ts +4 -4
  15. package/dist/types/lib/bandada.d.ts +6 -0
  16. package/dist/types/lib/files.d.ts +1 -0
  17. package/dist/types/lib/localConfigs.d.ts +38 -0
  18. package/dist/types/lib/prompts.d.ts +7 -7
  19. package/dist/types/lib/utils.d.ts +3 -2
  20. package/dist/types/types/index.d.ts +69 -0
  21. package/package.json +10 -3
  22. package/src/commands/auth.ts +25 -9
  23. package/src/commands/authBandada.ts +120 -0
  24. package/src/commands/authSIWE.ts +185 -0
  25. package/src/commands/ceremony/index.ts +20 -0
  26. package/src/commands/ceremony/listParticipants.ts +56 -0
  27. package/src/commands/contribute.ts +56 -29
  28. package/src/commands/finalize.ts +27 -14
  29. package/src/commands/index.ts +3 -1
  30. package/src/commands/listCeremonies.ts +2 -3
  31. package/src/commands/logout.ts +3 -1
  32. package/src/commands/observe.ts +8 -4
  33. package/src/commands/setup.ts +59 -48
  34. package/src/commands/validate.ts +2 -3
  35. package/src/index.ts +35 -13
  36. package/src/lib/bandada.ts +51 -0
  37. package/src/lib/errors.ts +2 -2
  38. package/src/lib/localConfigs.ts +55 -1
  39. package/src/lib/prompts.ts +23 -26
  40. package/src/lib/services.ts +39 -16
  41. package/src/lib/utils.ts +49 -13
  42. package/src/types/index.ts +75 -0
@@ -2,17 +2,22 @@ import {
2
2
  getCurrentFirebaseAuthUser,
3
3
  initializeFirebaseCoreServices,
4
4
  signInToFirebaseWithCredentials
5
- } from "@p0tion/actions"
5
+ } from "@devtion/actions"
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 { checkLocalAccessToken, deleteLocalAccessToken, getLocalAccessToken } from "./localConfigs.js"
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
 
@@ -117,8 +122,6 @@ export const signInToFirebase = async (firebaseApp: FirebaseApp, credentials: OA
117
122
  }
118
123
  }
119
124
 
120
-
121
-
122
125
  /**
123
126
  * Ensure that the callee is an authenticated user.
124
127
  * @notice The token will be passed as parameter.
@@ -166,22 +169,42 @@ export const checkAuth = async (firebaseApp: FirebaseApp): Promise<AuthUser> =>
166
169
  // Retrieve local access token.
167
170
  const token = String(getLocalAccessToken())
168
171
 
169
- // Get credentials.
170
- const credentials = exchangeGithubTokenForCredentials(token)
171
-
172
- // Sign in to Firebase using credentials.
173
- await signInToFirebase(firebaseApp, credentials)
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
+ }
174
202
 
175
203
  // Get current authenticated user.
176
204
  const user = getCurrentFirebaseAuthUser(firebaseApp)
177
205
 
178
- // Get Github unique identifier (handle-id).
179
- const providerUserId = await getGithubProviderUserId(String(token))
180
-
181
206
  // Greet the user.
182
- console.log(
183
- `Greetings, @${theme.text.bold(getUserHandleFromProviderUserId(providerUserId))} ${theme.emojis.wave}\n`
184
- )
207
+ console.log(`Greetings, @${theme.text.bold(username)} ${theme.emojis.wave}\n`)
185
208
 
186
209
  return {
187
210
  user,
package/src/lib/utils.ts CHANGED
@@ -18,8 +18,9 @@ import {
18
18
  ParticipantContributionStep,
19
19
  permanentlyStoreCurrentContributionTimeAndHash,
20
20
  progressToNextContributionStep,
21
- verifyContribution
22
- } from "@p0tion/actions"
21
+ verifyContribution,
22
+ contribHashRegex
23
+ } from "@devtion/actions"
23
24
  import { Presets, SingleBar } from "cli-progress"
24
25
  import dotenv from "dotenv"
25
26
  import { GithubAuthProvider, OAuthCredential } from "firebase/auth"
@@ -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) showError(THIRD_PARTY_SERVICES_ERRORS.GITHUB_GET_GITHUB_ACCOUNT_INFO, true)
159
+ if (providerUserId.indexOf("-") === -1) {
160
+ return providerUserId
161
+ }
159
162
 
160
- return providerUserId.split("-")[0]
163
+ return providerUserId.substring(0, providerUserId.lastIndexOf("-"))
161
164
  }
162
165
 
163
166
  /**
@@ -311,8 +314,22 @@ export const generateCustomUrlToTweetAboutParticipation = (
311
314
  isFinalizing: boolean
312
315
  ) =>
313
316
  isFinalizing
314
- ? `https://twitter.com/intent/tweet?text=I%20have%20finalized%20the%20${ceremonyName}%20Phase%202%20Trusted%20Setup%20ceremony!%20You%20can%20view%20my%20final%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP%20#PSE`
315
- : `https://twitter.com/intent/tweet?text=I%20contributed%20to%20the%20${ceremonyName}%20Phase%202%20Trusted%20Setup%20ceremony!%20You%20can%20contribute%20here:%20https://github.com/privacy-scaling-explorations/p0tion%20You%20can%20view%20my%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP`
317
+ ? `https://twitter.com/intent/tweet?text=I%20have%20finalized%20the%20${ceremonyName}${
318
+ ceremonyName.toLowerCase().includes("trusted") ||
319
+ ceremonyName.toLowerCase().includes("setup") ||
320
+ ceremonyName.toLowerCase().includes("phase2") ||
321
+ ceremonyName.toLowerCase().includes("ceremony")
322
+ ? "!"
323
+ : "%20Phase%202%20Trusted%20Setup%20ceremony!"
324
+ }%20You%20can%20view%20my%20final%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP%20#PSE`
325
+ : `https://twitter.com/intent/tweet?text=I%20contributed%20to%20the%20${ceremonyName}${
326
+ ceremonyName.toLowerCase().includes("trusted") ||
327
+ ceremonyName.toLowerCase().includes("setup") ||
328
+ ceremonyName.toLowerCase().includes("phase2") ||
329
+ ceremonyName.toLowerCase().includes("ceremony")
330
+ ? "!"
331
+ : "%20Phase%202%20Trusted%20Setup%20ceremony!"
332
+ }%20You%20can%20view%20the%20steps%20to%20contribute%20here:%20https://ceremony.pse.dev%20You%20can%20view%20my%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP`
316
333
 
317
334
  /**
318
335
  * Return a custom progress bar.
@@ -521,6 +538,7 @@ export const getLatestUpdatesFromParticipant = async (
521
538
  * @param entropyOrBeaconHash <string> - the entropy or beacon hash (only when finalizing) for the contribution.
522
539
  * @param contributorOrCoordinatorIdentifier <string> - the identifier of the contributor or coordinator (only when finalizing).
523
540
  * @param isFinalizing <boolean> - flag to discriminate between ceremony finalization (true) and contribution (false).
541
+ * @param circuitsLength <number> - the total number of circuits in the ceremony.
524
542
  */
525
543
  export const handleStartOrResumeContribution = async (
526
544
  cloudFunctions: Functions,
@@ -530,7 +548,8 @@ export const handleStartOrResumeContribution = async (
530
548
  participant: FirebaseDocumentInfo,
531
549
  entropyOrBeaconHash: any,
532
550
  contributorOrCoordinatorIdentifier: string,
533
- isFinalizing: boolean
551
+ isFinalizing: boolean,
552
+ circuitsLength: number
534
553
  ): Promise<void> => {
535
554
  // Extract data.
536
555
  const { prefix: ceremonyPrefix } = ceremony.data
@@ -538,7 +557,9 @@ export const handleStartOrResumeContribution = async (
538
557
  const { completedContributions } = waitingQueue // = current progress.
539
558
 
540
559
  console.log(
541
- `${theme.text.bold(`\n- Circuit # ${theme.colors.magenta(`${sequencePosition}`)}`)} (Contribution Steps)`
560
+ `${theme.text.bold(
561
+ `\n- Circuit # ${theme.colors.magenta(`${sequencePosition}/${circuitsLength}`)}`
562
+ )} (Contribution Steps)`
542
563
  )
543
564
 
544
565
  // Get most up-to-date data from the participant document.
@@ -607,6 +628,8 @@ export const handleStartOrResumeContribution = async (
607
628
  `${theme.symbols.success} Contribution ${theme.text.bold(`#${lastZkeyIndex}`)} correctly downloaded`
608
629
  )
609
630
 
631
+ await sleep(3000)
632
+
610
633
  // Advance to next contribution step (COMPUTING) if not finalizing.
611
634
  if (!isFinalizing) {
612
635
  spinner.text = `Preparing for contribution computation...`
@@ -642,7 +665,7 @@ export const handleStartOrResumeContribution = async (
642
665
 
643
666
  // Read local transcript file info to get the contribution hash.
644
667
  const transcriptContents = readFile(transcriptLocalFilePath)
645
- const matchContributionHash = transcriptContents.match(/Contribution.+Hash.+\n\t\t.+\n\t\t.+\n.+\n\t\t.+\n/)
668
+ const matchContributionHash = transcriptContents.match(contribHashRegex)
646
669
 
647
670
  if (!matchContributionHash)
648
671
  showError(COMMAND_ERRORS.COMMAND_CONTRIBUTE_FINALIZE_NO_TRANSCRIPT_CONTRIBUTION_HASH_MATCH, true)
@@ -650,6 +673,8 @@ export const handleStartOrResumeContribution = async (
650
673
  // Format contribution hash.
651
674
  const contributionHash = matchContributionHash?.at(0)?.replace("\n\t\t", "")!
652
675
 
676
+ await sleep(500)
677
+
653
678
  // Make request to cloud functions to permanently store the information.
654
679
  await permanentlyStoreCurrentContributionTimeAndHash(
655
680
  cloudFunctions,
@@ -675,6 +700,9 @@ export const handleStartOrResumeContribution = async (
675
700
  )}`
676
701
  )
677
702
 
703
+ // ensure the previous step is completed
704
+ await sleep(5000)
705
+
678
706
  // Advance to next contribution step (UPLOADING) if not finalizing.
679
707
  if (!isFinalizing) {
680
708
  spinner.text = `Preparing for uploading the contribution...`
@@ -696,10 +724,12 @@ export const handleStartOrResumeContribution = async (
696
724
  !isFinalizing ? theme.text.bold(`#${nextZkeyIndex}`) : ""
697
725
  } to storage.\n${
698
726
  theme.symbols.warning
699
- } This step may take a while based on circuit size and your contribution speed. Everything's fine, just be patient.`
727
+ } This step may take a while based on circuit size and your internet speed. Everything's fine, just be patient.`
700
728
  spinner.start()
701
729
 
702
- if (!isFinalizing)
730
+ const progressBar = customProgressBar(ProgressBarType.UPLOAD, `your contribution`)
731
+
732
+ if (!isFinalizing) {
703
733
  await multiPartUpload(
704
734
  cloudFunctions,
705
735
  bucketName,
@@ -707,9 +737,12 @@ export const handleStartOrResumeContribution = async (
707
737
  nextZkeyLocalFilePath,
708
738
  Number(process.env.CONFIG_STREAM_CHUNK_SIZE_IN_MB),
709
739
  ceremony.id,
710
- participantData.tempContributionData
740
+ participantData.tempContributionData,
741
+ progressBar
711
742
  )
712
- else
743
+
744
+ progressBar.stop()
745
+ } else
713
746
  await multiPartUpload(
714
747
  cloudFunctions,
715
748
  bucketName,
@@ -718,6 +751,9 @@ export const handleStartOrResumeContribution = async (
718
751
  Number(process.env.CONFIG_STREAM_CHUNK_SIZE_IN_MB)
719
752
  )
720
753
 
754
+ // small sleep to ensure the previous step is completed
755
+ await sleep(5000)
756
+
721
757
  spinner.succeed(
722
758
  `${
723
759
  isFinalizing ? `Contribution` : `Contribution ${theme.text.bold(`#${nextZkeyIndex}`)}`
@@ -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
+ }