@devtion/devcli 0.0.0-b499eaf → 0.0.0-c1f4cbe
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/dist/.env +14 -0
- package/dist/index.js +388 -29
- 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/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/types/index.d.ts +63 -0
- package/package.json +10 -3
- package/src/commands/auth.ts +7 -1
- package/src/commands/authBandada.ts +120 -0
- package/src/commands/authSIWE.ts +178 -0
- package/src/commands/ceremony/index.ts +20 -0
- package/src/commands/ceremony/listParticipants.ts +30 -0
- package/src/commands/contribute.ts +16 -11
- package/src/commands/finalize.ts +3 -3
- package/src/commands/index.ts +2 -0
- package/src/commands/logout.ts +3 -1
- package/src/index.ts +18 -5
- package/src/lib/bandada.ts +51 -0
- package/src/lib/errors.ts +1 -1
- package/src/lib/localConfigs.ts +54 -0
- package/src/lib/services.ts +38 -13
- package/src/lib/utils.ts +3 -1
- package/src/types/index.ts +68 -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.`,
|
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/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
|
@@ -155,7 +155,9 @@ export const getPublicAttestationGist = async (
|
|
|
155
155
|
* @returns <string> - the third-party provider handle of the user.
|
|
156
156
|
*/
|
|
157
157
|
export const getUserHandleFromProviderUserId = (providerUserId: string): string => {
|
|
158
|
-
if (providerUserId.indexOf("-") === -1)
|
|
158
|
+
if (providerUserId.indexOf("-") === -1) {
|
|
159
|
+
return providerUserId
|
|
160
|
+
}
|
|
159
161
|
|
|
160
162
|
return providerUserId.split("-")[0]
|
|
161
163
|
}
|
package/src/types/index.ts
CHANGED
|
@@ -68,3 +68,71 @@ 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
|
+
*/
|
|
95
|
+
export type OAuthDeviceCodeResponse = {
|
|
96
|
+
device_code: string
|
|
97
|
+
user_code: string
|
|
98
|
+
verification_uri: string
|
|
99
|
+
expires_in: number
|
|
100
|
+
interval: number
|
|
101
|
+
verification_uri_complete: string
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Define the return object of the polling endpoint
|
|
106
|
+
* @typedef {Object} OAuthTokenResponse
|
|
107
|
+
* @property {string} access_token - the resulting device flow token
|
|
108
|
+
* @property {string} token_type - token type
|
|
109
|
+
* @property {number} expires_in - when does the token expires
|
|
110
|
+
* @property {string} scope - the scope requested by the initial device flow endpoint
|
|
111
|
+
* @property {string} refresh_token - refresh token
|
|
112
|
+
* @property {string} id_token - id token
|
|
113
|
+
* @property {string} error - in case there was an error
|
|
114
|
+
* @property {string} error_description - error details
|
|
115
|
+
*/
|
|
116
|
+
export type OAuthTokenResponse = {
|
|
117
|
+
access_token: string
|
|
118
|
+
token_type: string
|
|
119
|
+
expires_in: number
|
|
120
|
+
scope: string
|
|
121
|
+
refresh_token: string
|
|
122
|
+
id_token: string
|
|
123
|
+
// error response should contain
|
|
124
|
+
error?: string
|
|
125
|
+
error_description?: string
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @typedef {Object} CheckNonceOfSIWEAddressResponse
|
|
130
|
+
* @property {boolean} valid - if the checking was valid or not
|
|
131
|
+
* @property {string} message - more information about the validity
|
|
132
|
+
* @property {string} token - token to sign into Firebase
|
|
133
|
+
*/
|
|
134
|
+
export type CheckNonceOfSIWEAddressResponse = {
|
|
135
|
+
valid: boolean
|
|
136
|
+
message: string
|
|
137
|
+
token: string
|
|
138
|
+
}
|