@solana-mobile/dapp-store-cli 0.1.1-0

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 (86) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +142 -0
  3. package/bin/dapp-store.js +3 -0
  4. package/lib/esm/commands/create/app.js +37 -0
  5. package/lib/esm/commands/create/app.js.map +1 -0
  6. package/lib/esm/commands/create/index.js +44 -0
  7. package/lib/esm/commands/create/index.js.map +1 -0
  8. package/lib/esm/commands/create/publisher.js +33 -0
  9. package/lib/esm/commands/create/publisher.js.map +1 -0
  10. package/lib/esm/commands/create/release.js +48 -0
  11. package/lib/esm/commands/create/release.js.map +1 -0
  12. package/lib/esm/commands/index.js +4 -0
  13. package/lib/esm/commands/index.js.map +1 -0
  14. package/lib/esm/commands/publish/index.js +25 -0
  15. package/lib/esm/commands/publish/index.js.map +1 -0
  16. package/lib/esm/commands/publish/remove.js +20 -0
  17. package/lib/esm/commands/publish/remove.js.map +1 -0
  18. package/lib/esm/commands/publish/submit.js +25 -0
  19. package/lib/esm/commands/publish/submit.js.map +1 -0
  20. package/lib/esm/commands/publish/support.js +20 -0
  21. package/lib/esm/commands/publish/support.js.map +1 -0
  22. package/lib/esm/commands/publish/update.js +26 -0
  23. package/lib/esm/commands/publish/update.js.map +1 -0
  24. package/lib/esm/commands/validate.js +40 -0
  25. package/lib/esm/commands/validate.js.map +1 -0
  26. package/lib/esm/config/index.js +19 -0
  27. package/lib/esm/config/index.js.map +1 -0
  28. package/lib/esm/config/schema.json +228 -0
  29. package/lib/esm/index.js +259 -0
  30. package/lib/esm/index.js.map +1 -0
  31. package/lib/esm/upload/CachedStorageDriver.js +64 -0
  32. package/lib/esm/upload/CachedStorageDriver.js.map +1 -0
  33. package/lib/esm/upload/index.js +2 -0
  34. package/lib/esm/upload/index.js.map +1 -0
  35. package/lib/esm/utils.js +171 -0
  36. package/lib/esm/utils.js.map +1 -0
  37. package/lib/types/commands/create/app.d.ts +12 -0
  38. package/lib/types/commands/create/app.d.ts.map +1 -0
  39. package/lib/types/commands/create/index.d.ts +4 -0
  40. package/lib/types/commands/create/index.d.ts.map +1 -0
  41. package/lib/types/commands/create/publisher.d.ts +9 -0
  42. package/lib/types/commands/create/publisher.d.ts.map +1 -0
  43. package/lib/types/commands/create/release.d.ts +14 -0
  44. package/lib/types/commands/create/release.d.ts.map +1 -0
  45. package/lib/types/commands/index.d.ts +4 -0
  46. package/lib/types/commands/index.d.ts.map +1 -0
  47. package/lib/types/commands/publish/index.d.ts +5 -0
  48. package/lib/types/commands/publish/index.d.ts.map +1 -0
  49. package/lib/types/commands/publish/remove.d.ts +12 -0
  50. package/lib/types/commands/publish/remove.d.ts.map +1 -0
  51. package/lib/types/commands/publish/submit.d.ts +12 -0
  52. package/lib/types/commands/publish/submit.d.ts.map +1 -0
  53. package/lib/types/commands/publish/support.d.ts +12 -0
  54. package/lib/types/commands/publish/support.d.ts.map +1 -0
  55. package/lib/types/commands/publish/update.d.ts +13 -0
  56. package/lib/types/commands/publish/update.d.ts.map +1 -0
  57. package/lib/types/commands/validate.d.ts +6 -0
  58. package/lib/types/commands/validate.d.ts.map +1 -0
  59. package/lib/types/config/index.d.ts +10 -0
  60. package/lib/types/config/index.d.ts.map +1 -0
  61. package/lib/types/index.d.ts +2 -0
  62. package/lib/types/index.d.ts.map +1 -0
  63. package/lib/types/upload/CachedStorageDriver.d.ts +30 -0
  64. package/lib/types/upload/CachedStorageDriver.d.ts.map +1 -0
  65. package/lib/types/upload/index.d.ts +2 -0
  66. package/lib/types/upload/index.d.ts.map +1 -0
  67. package/lib/types/utils.d.ts +21 -0
  68. package/lib/types/utils.d.ts.map +1 -0
  69. package/package.json +49 -0
  70. package/src/commands/create/app.ts +88 -0
  71. package/src/commands/create/index.ts +48 -0
  72. package/src/commands/create/publisher.ts +78 -0
  73. package/src/commands/create/release.ts +107 -0
  74. package/src/commands/index.ts +3 -0
  75. package/src/commands/publish/index.ts +29 -0
  76. package/src/commands/publish/remove.ts +46 -0
  77. package/src/commands/publish/submit.ts +55 -0
  78. package/src/commands/publish/support.ts +46 -0
  79. package/src/commands/publish/update.ts +58 -0
  80. package/src/commands/validate.ts +67 -0
  81. package/src/config/index.ts +40 -0
  82. package/src/config/schema.json +228 -0
  83. package/src/index.ts +435 -0
  84. package/src/upload/CachedStorageDriver.ts +104 -0
  85. package/src/upload/index.ts +1 -0
  86. package/src/utils.ts +275 -0
@@ -0,0 +1,228 @@
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "publisher": {
5
+ "type": "object",
6
+ "properties": {
7
+ "name": {
8
+ "type": "string"
9
+ },
10
+ "address": {
11
+ "type": "string"
12
+ },
13
+ "website": {
14
+ "type": "string"
15
+ },
16
+ "email": {
17
+ "type": "string"
18
+ },
19
+ "media": {
20
+ "type": "array",
21
+ "items": [
22
+ {
23
+ "type": "object",
24
+ "properties": {
25
+ "purpose": {
26
+ "type": "string"
27
+ },
28
+ "uri": {
29
+ "type": "string"
30
+ },
31
+ "width": {
32
+ "type": "integer"
33
+ },
34
+ "height": {
35
+ "type": "integer"
36
+ }
37
+ },
38
+ "required": ["purpose", "uri", "width", "height"]
39
+ }
40
+ ]
41
+ }
42
+ },
43
+ "required": ["name", "website", "email", "media"]
44
+ },
45
+ "app": {
46
+ "type": "object",
47
+ "properties": {
48
+ "name": {
49
+ "type": "string"
50
+ },
51
+ "address": {
52
+ "type": "string"
53
+ },
54
+ "android_package": {
55
+ "type": "string"
56
+ },
57
+ "creators": {
58
+ "type": "array",
59
+ "items": [
60
+ {
61
+ "type": "string"
62
+ }
63
+ ]
64
+ },
65
+ "urls": {
66
+ "type": "object",
67
+ "properties": {
68
+ "license_url": {
69
+ "type": "string"
70
+ },
71
+ "copyright_url": {
72
+ "type": "string"
73
+ },
74
+ "privacy_policy_url": {
75
+ "type": "string"
76
+ },
77
+ "website": {
78
+ "type": "string"
79
+ }
80
+ },
81
+ "required": [
82
+ "license_url",
83
+ "copyright_url",
84
+ "privacy_policy_url",
85
+ "website"
86
+ ]
87
+ },
88
+ "media": {
89
+ "type": "array",
90
+ "items": [
91
+ {
92
+ "type": "object",
93
+ "properties": {
94
+ "purpose": {
95
+ "type": "string"
96
+ },
97
+ "uri": {
98
+ "type": "string"
99
+ },
100
+ "width": {
101
+ "type": "integer"
102
+ },
103
+ "height": {
104
+ "type": "integer"
105
+ }
106
+ },
107
+ "required": ["purpose", "uri", "width", "height"]
108
+ }
109
+ ]
110
+ }
111
+ },
112
+ "required": ["name", "android_package", "creators", "urls", "media"]
113
+ },
114
+ "release": {
115
+ "type": "object",
116
+ "properties": {
117
+ "version": {
118
+ "type": "string"
119
+ },
120
+ "address": {
121
+ "type": "string"
122
+ },
123
+ "media": {
124
+ "type": "array",
125
+ "items": [
126
+ {
127
+ "type": "object",
128
+ "properties": {
129
+ "purpose": {
130
+ "type": "string"
131
+ },
132
+ "uri": {
133
+ "type": "string"
134
+ },
135
+ "width": {
136
+ "type": "integer"
137
+ },
138
+ "height": {
139
+ "type": "integer"
140
+ }
141
+ },
142
+ "required": ["purpose", "uri", "width", "height"]
143
+ }
144
+ ]
145
+ },
146
+ "files": {
147
+ "type": "array",
148
+ "minItems": 1,
149
+ "contains": {
150
+ "type": "object",
151
+ "properties": {
152
+ "purpose": {
153
+ "type": "string",
154
+ "const": "install"
155
+ }
156
+ }
157
+ },
158
+ "items": [
159
+ {
160
+ "type": "object",
161
+ "properties": {
162
+ "purpose": {
163
+ "type": "string"
164
+ },
165
+ "uri": {
166
+ "type": "string"
167
+ }
168
+ },
169
+ "required": ["purpose", "uri"]
170
+ }
171
+ ]
172
+ },
173
+ "catalog": {
174
+ "type": "object",
175
+ "properties": {
176
+ "en-US": {
177
+ "type": "object",
178
+ "properties": {
179
+ "name": {
180
+ "type": "string"
181
+ },
182
+ "short_description": {
183
+ "type": "string"
184
+ },
185
+ "long_description": {
186
+ "type": "string"
187
+ },
188
+ "new_in_version": {
189
+ "type": "string"
190
+ },
191
+ "saga_features_localized": {
192
+ "type": "string"
193
+ }
194
+ },
195
+ "required": [
196
+ "name",
197
+ "short_description",
198
+ "long_description",
199
+ "new_in_version",
200
+ "saga_features_localized"
201
+ ]
202
+ }
203
+ },
204
+ "required": ["en-US"]
205
+ }
206
+ },
207
+ "required": ["version", "media", "files", "catalog"]
208
+ },
209
+ "solana_mobile_dapp_publisher_portal": {
210
+ "type": "object",
211
+ "properties": {
212
+ "google_store_package": {
213
+ "type": "string"
214
+ },
215
+ "testing_instructions": {
216
+ "type": "string"
217
+ }
218
+ },
219
+ "required": ["google_store_package", "testing_instructions"]
220
+ }
221
+ },
222
+ "required": [
223
+ "publisher",
224
+ "app",
225
+ "release",
226
+ "solana_mobile_dapp_publisher_portal"
227
+ ]
228
+ }
package/src/index.ts ADDED
@@ -0,0 +1,435 @@
1
+ import { Command } from "commander";
2
+ import { validateCommand } from "./commands/index.js";
3
+ import { createAppCommand, createPublisherCommand, createReleaseCommand } from "./commands/create/index.js";
4
+ import {
5
+ publishRemoveCommand,
6
+ publishSubmitCommand,
7
+ publishSupportCommand,
8
+ publishUpdateCommand
9
+ } from "./commands/publish/index.js";
10
+ import { getConfigFile, parseKeypair, showUserErrorMessage } from "./utils.js";
11
+
12
+ import * as dotenv from "dotenv";
13
+
14
+ dotenv.config();
15
+
16
+ const hasAddressInConfig = ({ address }: { address: string }) => {
17
+ return !!address;
18
+ };
19
+
20
+ const program = new Command();
21
+
22
+ function resolveBuildToolsPath(buildToolsPath: string | undefined) {
23
+ // If a path was specified on the command line, use that
24
+ if (buildToolsPath !== undefined) {
25
+ return buildToolsPath;
26
+ }
27
+
28
+ // If a path is specified in a .env file, use that
29
+ if (process.env.ANDROID_TOOLS_DIR !== undefined) {
30
+ return process.env.ANDROID_TOOLS_DIR;
31
+ }
32
+
33
+ // No path was specified
34
+ return;
35
+ }
36
+
37
+ async function main() {
38
+ program
39
+ .name("dapp-store")
40
+ .version("0.1.0")
41
+ .description("CLI to assist with publishing to the Saga Dapp Store");
42
+
43
+ const createCommand = program
44
+ .command("create")
45
+ .description("Create a `publisher`, `app`, or `release`");
46
+
47
+ createCommand
48
+ .command("publisher")
49
+ .description("Create a publisher")
50
+ .requiredOption(
51
+ "-k, --keypair <path-to-keypair-file>",
52
+ "Path to keypair file"
53
+ )
54
+ .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
55
+ .option("-d, --dry-run", "Flag for dry run. Doesn't mint an NFT")
56
+ .action(async ({ keypair, url, dryRun }) => {
57
+ const signer = parseKeypair(keypair);
58
+
59
+ if (signer) {
60
+ const result = await createPublisherCommand({ signer, url, dryRun });
61
+ }
62
+ });
63
+
64
+ createCommand
65
+ .command("app")
66
+ .description("Create a app")
67
+ .requiredOption(
68
+ "-k, --keypair <path-to-keypair-file>",
69
+ "Path to keypair file"
70
+ )
71
+ .option(
72
+ "-p, --publisher-mint-address <publisher-mint-address>",
73
+ "The mint address of the publisher NFT"
74
+ )
75
+ .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
76
+ .option("-d, --dry-run", "Flag for dry run. Doesn't mint an NFT")
77
+ .action(async ({ publisherMintAddress, keypair, url, dryRun }) => {
78
+ const config = await getConfigFile();
79
+ if (!config.isValid) return;
80
+
81
+ if (!hasAddressInConfig(config.publisher) && !publisherMintAddress) {
82
+ showUserErrorMessage(
83
+ "Either specify an publisher mint address in the config file, or specify as a CLI argument to this command."
84
+ );
85
+ createCommand.showHelpAfterError();
86
+ return;
87
+ }
88
+
89
+ const signer = parseKeypair(keypair);
90
+ if (signer) {
91
+ await createAppCommand({
92
+ publisherMintAddress: publisherMintAddress,
93
+ signer,
94
+ url,
95
+ dryRun,
96
+ });
97
+ }
98
+ });
99
+
100
+ createCommand
101
+ .command("release <version>")
102
+ .description("Create a release")
103
+ .requiredOption(
104
+ "-k, --keypair <path-to-keypair-file>",
105
+ "Path to keypair file"
106
+ )
107
+ .option(
108
+ "-a, --app-mint-address <app-mint-address>",
109
+ "The mint address of the app NFT"
110
+ )
111
+ .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
112
+ .option("-d, --dry-run", "Flag for dry run. Doesn't mint an NFT")
113
+ .option(
114
+ "-b, --build-tools-path <build-tools-path>",
115
+ "Path to Android build tools which contains AAPT2"
116
+ )
117
+ .action(
118
+ async (
119
+ version,
120
+ { appMintAddress, keypair, url, dryRun, buildToolsPath }
121
+ ) => {
122
+ const toolsEnvDir = process.env.ANDROID_TOOLS_DIR ?? "";
123
+
124
+ let buildTools = "";
125
+ if (toolsEnvDir && toolsEnvDir.length > 0) {
126
+ buildTools = toolsEnvDir;
127
+ } else if (buildToolsPath) {
128
+ buildTools = buildToolsPath;
129
+ } else {
130
+ showUserErrorMessage(
131
+ "\n\n::: Please specify an Android build tools directory in the .env file or via the command line argument. :::\n\n"
132
+ );
133
+ createCommand.showHelpAfterError();
134
+ return;
135
+ }
136
+
137
+ const config = await getConfigFile();
138
+ if (!config.isValid) return;
139
+
140
+ if (!hasAddressInConfig(config.app) && !appMintAddress) {
141
+ showUserErrorMessage(
142
+ "\n\n::: Either specify an app mint address in the config file, or specify as a CLI argument to this command. :::\n\n"
143
+ );
144
+ createCommand.showHelpAfterError();
145
+ return;
146
+ }
147
+
148
+ const signer = parseKeypair(keypair);
149
+
150
+ if (signer) {
151
+ const result = await createReleaseCommand({
152
+ appMintAddress: appMintAddress,
153
+ version,
154
+ buildToolsPath: buildTools,
155
+ signer,
156
+ url,
157
+ dryRun,
158
+ });
159
+ }
160
+ }
161
+ );
162
+
163
+ program
164
+ .command("validate")
165
+ .description("Validates details prior to publishing")
166
+ .requiredOption(
167
+ "-k, --keypair <path-to-keypair-file>",
168
+ "Path to keypair file"
169
+ )
170
+ .option(
171
+ "-b, --build-tools-path <build-tools-path>",
172
+ "Path to Android build tools which contains AAPT2"
173
+ )
174
+ .action(async ({ keypair, buildToolsPath }) => {
175
+ const resolvedBuildToolsPath = resolveBuildToolsPath(buildToolsPath);
176
+ if (resolvedBuildToolsPath === undefined) {
177
+ showUserErrorMessage(
178
+ "Please specify an Android build tools directory in the .env file or via the command line argument."
179
+ );
180
+ createCommand.showHelpAfterError();
181
+ return;
182
+ }
183
+
184
+ const signer = parseKeypair(keypair);
185
+
186
+ if (signer) {
187
+ await validateCommand({
188
+ signer,
189
+ buildToolsPath: resolvedBuildToolsPath,
190
+ });
191
+ }
192
+ });
193
+
194
+ const publishCommand = program
195
+ .command("publish")
196
+ .description(
197
+ "Submit a publishing request (`submit`, `update`, `remove`, or `support`) to the Solana Mobile dApp publisher portal"
198
+ );
199
+
200
+ publishCommand
201
+ .command("submit")
202
+ .description("Submit a new app to the Solana Mobile dApp publisher portal")
203
+ .requiredOption(
204
+ "-k, --keypair <path-to-keypair-file>",
205
+ "Path to keypair file"
206
+ )
207
+ .requiredOption(
208
+ "--complies-with-solana-dapp-store-policies",
209
+ "An attestation that the app complies with the Solana dApp Store policies"
210
+ )
211
+ .requiredOption(
212
+ "--requestor-is-authorized",
213
+ "An attestation that the party making this Solana dApp publisher portal request is authorized to do so"
214
+ )
215
+ .option(
216
+ "-r, --release-mint-address <release-mint-address>",
217
+ "The mint address of the release NFT"
218
+ )
219
+ .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
220
+ .option(
221
+ "-d, --dry-run",
222
+ "Flag for dry run. Doesn't submit the request to the publisher portal."
223
+ )
224
+ .action(
225
+ async ({
226
+ releaseMintAddress,
227
+ keypair,
228
+ url,
229
+ compliesWithSolanaDappStorePolicies,
230
+ requestorIsAuthorized,
231
+ dryRun,
232
+ }) => {
233
+ const config = await getConfigFile();
234
+ if (!config.isValid) return;
235
+
236
+ if (!hasAddressInConfig(config.publisher) && !releaseMintAddress) {
237
+ showUserErrorMessage(
238
+ "\n\n::: Either specify an release mint address in the config file, or specify as a CLI argument to this command. :::\n\n"
239
+ );
240
+ publishCommand.showHelpAfterError();
241
+ return;
242
+ }
243
+
244
+ const signer = parseKeypair(keypair);
245
+ if (signer) {
246
+ await publishSubmitCommand({
247
+ releaseMintAddress,
248
+ signer,
249
+ url,
250
+ dryRun,
251
+ compliesWithSolanaDappStorePolicies,
252
+ requestorIsAuthorized,
253
+ });
254
+ }
255
+ }
256
+ );
257
+
258
+ publishCommand
259
+ .command("update")
260
+ .description(
261
+ "Update an existing app on the Solana Mobile dApp publisher portal"
262
+ )
263
+ .requiredOption(
264
+ "-k, --keypair <path-to-keypair-file>",
265
+ "Path to keypair file"
266
+ )
267
+ .requiredOption(
268
+ "--complies-with-solana-dapp-store-policies",
269
+ "An attestation that the app complies with the Solana dApp Store policies"
270
+ )
271
+ .requiredOption(
272
+ "--requestor-is-authorized",
273
+ "An attestation that the party making this Solana dApp publisher portal request is authorized to do so"
274
+ )
275
+ .option(
276
+ "-r, --release-mint-address <release-mint-address>",
277
+ "The mint address of the release NFT"
278
+ )
279
+ .option("-c, --critical", "Flag for a critical app update request")
280
+ .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
281
+ .option(
282
+ "-d, --dry-run",
283
+ "Flag for dry run. Doesn't submit the request to the publisher portal."
284
+ )
285
+ .action(
286
+ async ({
287
+ releaseMintAddress,
288
+ keypair,
289
+ url,
290
+ compliesWithSolanaDappStorePolicies,
291
+ requestorIsAuthorized,
292
+ critical,
293
+ dryRun,
294
+ }) => {
295
+ const config = await getConfigFile();
296
+ if (!config.isValid) return;
297
+
298
+ if (!hasAddressInConfig(config.publisher) && !releaseMintAddress) {
299
+ showUserErrorMessage(
300
+ "\n\n::: Either specify an release mint address in the config file, or specify as a CLI argument to this command. :::\n\n"
301
+ );
302
+ publishCommand.showHelpAfterError();
303
+ return;
304
+ }
305
+
306
+ const signer = parseKeypair(keypair);
307
+
308
+ if (signer) {
309
+ await publishUpdateCommand({
310
+ releaseMintAddress,
311
+ signer,
312
+ url,
313
+ dryRun,
314
+ compliesWithSolanaDappStorePolicies,
315
+ requestorIsAuthorized,
316
+ critical,
317
+ });
318
+ }
319
+ }
320
+ );
321
+
322
+ publishCommand
323
+ .command("remove")
324
+ .description(
325
+ "Remove an existing app from the Solana Mobile dApp publisher portal"
326
+ )
327
+ .requiredOption(
328
+ "-k, --keypair <path-to-keypair-file>",
329
+ "Path to keypair file"
330
+ )
331
+ .requiredOption(
332
+ "--requestor-is-authorized",
333
+ "An attestation that the party making this Solana dApp publisher portal request is authorized to do so"
334
+ )
335
+ .option(
336
+ "-r, --release-mint-address <release-mint-address>",
337
+ "The mint address of the release NFT"
338
+ )
339
+ .option("-c, --critical", "Flag for a critical app removal request")
340
+ .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
341
+ .option(
342
+ "-d, --dry-run",
343
+ "Flag for dry run. Doesn't submit the request to the publisher portal."
344
+ )
345
+ .action(
346
+ async ({
347
+ releaseMintAddress,
348
+ keypair,
349
+ url,
350
+ requestorIsAuthorized,
351
+ critical,
352
+ dryRun,
353
+ }) => {
354
+ const config = await getConfigFile();
355
+ if (!config.isValid) return;
356
+
357
+ if (!hasAddressInConfig(config.publisher) && !releaseMintAddress) {
358
+ showUserErrorMessage(
359
+ "\n\n::: Either specify an release mint address in the config file, or specify as a CLI argument to this command. :::\n\n"
360
+ );
361
+ publishCommand.showHelpAfterError();
362
+ return;
363
+ }
364
+
365
+ const signer = parseKeypair(keypair);
366
+
367
+ if (signer) {
368
+ await publishRemoveCommand({
369
+ releaseMintAddress,
370
+ signer,
371
+ url,
372
+ dryRun,
373
+ requestorIsAuthorized,
374
+ critical,
375
+ });
376
+ }
377
+ }
378
+ );
379
+
380
+ publishCommand
381
+ .command("support <request_details>")
382
+ .description(
383
+ "Submit a support request for an existing app on the Solana Mobile dApp publisher portal"
384
+ )
385
+ .requiredOption(
386
+ "-k, --keypair <path-to-keypair-file>",
387
+ "Path to keypair file"
388
+ )
389
+ .requiredOption(
390
+ "--requestor-is-authorized",
391
+ "An attestation that the party making this Solana dApp publisher portal request is authorized to do so"
392
+ )
393
+ .option(
394
+ "-r, --release-mint-address <release-mint-address>",
395
+ "The mint address of the release NFT"
396
+ )
397
+ .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
398
+ .option(
399
+ "-d, --dry-run",
400
+ "Flag for dry run. Doesn't submit the request to the publisher portal."
401
+ )
402
+ .action(
403
+ async (
404
+ requestDetails,
405
+ { releaseMintAddress, keypair, url, requestorIsAuthorized, dryRun }
406
+ ) => {
407
+ const config = await getConfigFile();
408
+ if (!config.isValid) return;
409
+
410
+ if (!hasAddressInConfig(config.publisher) && !releaseMintAddress) {
411
+ showUserErrorMessage(
412
+ "\n\n::: Either specify an release mint address in the config file, or specify as a CLI argument to this command. :::\n\n"
413
+ );
414
+ publishCommand.showHelpAfterError();
415
+ return;
416
+ }
417
+
418
+ const signer = parseKeypair(keypair);
419
+
420
+ if (signer) {
421
+ await publishSupportCommand({
422
+ releaseMintAddress,
423
+ signer,
424
+ url,
425
+ dryRun,
426
+ requestorIsAuthorized,
427
+ requestDetails,
428
+ });
429
+ }
430
+ }
431
+ );
432
+
433
+ await program.parseAsync(process.argv);
434
+ }
435
+ main();