@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.
- package/README.md +1 -1
- package/dist/.env +55 -0
- package/dist/index.js +549 -120
- 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/contribute.d.ts +1 -1
- package/dist/types/commands/finalize.d.ts +4 -3
- package/dist/types/commands/index.d.ts +2 -0
- package/dist/types/commands/observe.d.ts +1 -1
- package/dist/types/commands/setup.d.ts +4 -4
- package/dist/types/lib/bandada.d.ts +6 -0
- package/dist/types/lib/files.d.ts +1 -0
- package/dist/types/lib/localConfigs.d.ts +38 -0
- package/dist/types/lib/prompts.d.ts +7 -7
- package/dist/types/lib/utils.d.ts +3 -2
- package/dist/types/types/index.d.ts +69 -0
- package/package.json +10 -3
- package/src/commands/auth.ts +25 -9
- 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 +56 -29
- package/src/commands/finalize.ts +27 -14
- package/src/commands/index.ts +3 -1
- package/src/commands/listCeremonies.ts +2 -3
- package/src/commands/logout.ts +3 -1
- package/src/commands/observe.ts +8 -4
- package/src/commands/setup.ts +59 -48
- package/src/commands/validate.ts +2 -3
- package/src/index.ts +35 -13
- package/src/lib/bandada.ts +51 -0
- package/src/lib/errors.ts +2 -2
- package/src/lib/localConfigs.ts +55 -1
- package/src/lib/prompts.ts +23 -26
- package/src/lib/services.ts +39 -16
- package/src/lib/utils.ts +49 -13
- package/src/types/index.ts +75 -0
package/src/lib/services.ts
CHANGED
|
@@ -2,17 +2,22 @@ import {
|
|
|
2
2
|
getCurrentFirebaseAuthUser,
|
|
3
3
|
initializeFirebaseCoreServices,
|
|
4
4
|
signInToFirebaseWithCredentials
|
|
5
|
-
} from "@
|
|
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 {
|
|
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
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
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)
|
|
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
|
/**
|
|
@@ -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}
|
|
315
|
-
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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}`)}`
|
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
|
+
}
|