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

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 (43) hide show
  1. package/README.md +27 -25
  2. package/bin/dapp-store.js +1 -1
  3. package/lib/esm/commands/create/release.js +2 -3
  4. package/lib/esm/commands/create/release.js.map +1 -1
  5. package/lib/esm/commands/publish/remove.js +2 -2
  6. package/lib/esm/commands/publish/remove.js.map +1 -1
  7. package/lib/esm/commands/publish/submit.js +2 -2
  8. package/lib/esm/commands/publish/submit.js.map +1 -1
  9. package/lib/esm/commands/publish/support.js +2 -2
  10. package/lib/esm/commands/publish/support.js.map +1 -1
  11. package/lib/esm/commands/publish/update.js +2 -2
  12. package/lib/esm/commands/publish/update.js.map +1 -1
  13. package/lib/esm/config/index.js.map +1 -1
  14. package/lib/esm/config/schema.json +11 -40
  15. package/lib/esm/index.js +133 -123
  16. package/lib/esm/index.js.map +1 -1
  17. package/lib/esm/upload/CachedStorageDriver.js +3 -1
  18. package/lib/esm/upload/CachedStorageDriver.js.map +1 -1
  19. package/lib/esm/utils.js +16 -28
  20. package/lib/esm/utils.js.map +1 -1
  21. package/lib/types/commands/create/release.d.ts +1 -2
  22. package/lib/types/commands/create/release.d.ts.map +1 -1
  23. package/lib/types/commands/publish/remove.d.ts.map +1 -1
  24. package/lib/types/commands/publish/submit.d.ts.map +1 -1
  25. package/lib/types/commands/publish/support.d.ts.map +1 -1
  26. package/lib/types/commands/publish/update.d.ts.map +1 -1
  27. package/lib/types/config/index.d.ts +0 -1
  28. package/lib/types/config/index.d.ts.map +1 -1
  29. package/lib/types/upload/CachedStorageDriver.d.ts +1 -1
  30. package/lib/types/upload/CachedStorageDriver.d.ts.map +1 -1
  31. package/lib/types/utils.d.ts +2 -4
  32. package/lib/types/utils.d.ts.map +1 -1
  33. package/package.json +2 -2
  34. package/src/commands/create/release.ts +1 -4
  35. package/src/commands/publish/remove.ts +5 -2
  36. package/src/commands/publish/submit.ts +2 -1
  37. package/src/commands/publish/support.ts +5 -2
  38. package/src/commands/publish/update.ts +2 -1
  39. package/src/config/index.ts +1 -2
  40. package/src/config/schema.json +11 -40
  41. package/src/index.ts +162 -155
  42. package/src/upload/CachedStorageDriver.ts +4 -1
  43. package/src/utils.ts +21 -54
package/src/index.ts CHANGED
@@ -51,7 +51,7 @@ async function main() {
51
51
  "-k, --keypair <path-to-keypair-file>",
52
52
  "Path to keypair file"
53
53
  )
54
- .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
54
+ .option("-u, --url <url>", "RPC URL", "https://devnet.genesysgo.net")
55
55
  .option("-d, --dry-run", "Flag for dry run. Doesn't mint an NFT")
56
56
  .action(async ({ keypair, url, dryRun }) => {
57
57
  const signer = parseKeypair(keypair);
@@ -72,33 +72,36 @@ async function main() {
72
72
  "-p, --publisher-mint-address <publisher-mint-address>",
73
73
  "The mint address of the publisher NFT"
74
74
  )
75
- .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
75
+ .option("-u, --url <url>", "RPC URL", "https://devnet.genesysgo.net")
76
76
  .option("-d, --dry-run", "Flag for dry run. Doesn't mint an NFT")
77
77
  .action(async ({ publisherMintAddress, keypair, url, dryRun }) => {
78
- const config = await getConfigFile();
79
- if (!config.isValid) return;
78
+ try {
79
+ const config = await getConfigFile();
80
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
- }
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
88
 
89
- const signer = parseKeypair(keypair);
90
- if (signer) {
91
- await createAppCommand({
92
- publisherMintAddress: publisherMintAddress,
93
- signer,
94
- url,
95
- dryRun,
96
- });
89
+ const signer = parseKeypair(keypair);
90
+ if (signer) {
91
+ await createAppCommand({
92
+ publisherMintAddress: publisherMintAddress,
93
+ signer,
94
+ url,
95
+ dryRun,
96
+ });
97
+ }
98
+ } catch (e) {
99
+ showUserErrorMessage((e as Error | null)?.message ?? "");
97
100
  }
98
101
  });
99
102
 
100
103
  createCommand
101
- .command("release <version>")
104
+ .command("release")
102
105
  .description("Create a release")
103
106
  .requiredOption(
104
107
  "-k, --keypair <path-to-keypair-file>",
@@ -108,54 +111,46 @@ async function main() {
108
111
  "-a, --app-mint-address <app-mint-address>",
109
112
  "The mint address of the app NFT"
110
113
  )
111
- .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
114
+ .option("-u, --url <url>", "RPC URL", "https://devnet.genesysgo.net")
112
115
  .option("-d, --dry-run", "Flag for dry run. Doesn't mint an NFT")
113
116
  .option(
114
117
  "-b, --build-tools-path <build-tools-path>",
115
118
  "Path to Android build tools which contains AAPT2"
116
119
  )
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
- });
120
+ .action(async ({ appMintAddress, keypair, url, dryRun, buildToolsPath }) => {
121
+ try {
122
+ const resolvedBuildToolsPath = resolveBuildToolsPath(buildToolsPath);
123
+ if (resolvedBuildToolsPath === undefined) {
124
+ showUserErrorMessage(
125
+ "Please specify an Android build tools directory in the .env file or via the command line argument."
126
+ );
127
+ createCommand.showHelpAfterError();
128
+ return;
129
+ }
130
+
131
+ const config = await getConfigFile();
132
+
133
+ if (!hasAddressInConfig(config.app) && !appMintAddress) {
134
+ showUserErrorMessage(
135
+ "\n\n::: Either specify an app mint address in the config file, or specify as a CLI argument to this command. :::\n\n"
136
+ );
137
+ createCommand.showHelpAfterError();
138
+ return;
139
+ }
140
+
141
+ const signer = parseKeypair(keypair);
142
+
143
+ if (signer) {
144
+ const result = await createReleaseCommand({
145
+ appMintAddress: appMintAddress,
146
+ buildToolsPath: resolvedBuildToolsPath,
147
+ signer,
148
+ url,
149
+ dryRun,
150
+ });
151
+ }
152
+ } catch (e) {
153
+ showUserErrorMessage((e as Error | null)?.message ?? "");
159
154
  }
160
155
  }
161
156
  );
@@ -216,7 +211,7 @@ async function main() {
216
211
  "-r, --release-mint-address <release-mint-address>",
217
212
  "The mint address of the release NFT"
218
213
  )
219
- .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
214
+ .option("-u, --url <url>", "RPC URL", "https://devnet.genesysgo.net")
220
215
  .option(
221
216
  "-d, --dry-run",
222
217
  "Flag for dry run. Doesn't submit the request to the publisher portal."
@@ -230,27 +225,30 @@ async function main() {
230
225
  requestorIsAuthorized,
231
226
  dryRun,
232
227
  }) => {
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
- });
228
+ try {
229
+ const config = await getConfigFile();
230
+
231
+ if (!hasAddressInConfig(config.release) && !releaseMintAddress) {
232
+ showUserErrorMessage(
233
+ "\n\n::: Either specify an release mint address in the config file, or specify as a CLI argument to this command. :::\n\n"
234
+ );
235
+ publishCommand.showHelpAfterError();
236
+ return;
237
+ }
238
+
239
+ const signer = parseKeypair(keypair);
240
+ if (signer) {
241
+ await publishSubmitCommand({
242
+ releaseMintAddress,
243
+ signer,
244
+ url,
245
+ dryRun,
246
+ compliesWithSolanaDappStorePolicies,
247
+ requestorIsAuthorized,
248
+ });
249
+ }
250
+ } catch (e) {
251
+ showUserErrorMessage((e as Error | null)?.message ?? "");
254
252
  }
255
253
  }
256
254
  );
@@ -277,7 +275,7 @@ async function main() {
277
275
  "The mint address of the release NFT"
278
276
  )
279
277
  .option("-c, --critical", "Flag for a critical app update request")
280
- .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
278
+ .option("-u, --url <url>", "RPC URL", "https://devnet.genesysgo.net")
281
279
  .option(
282
280
  "-d, --dry-run",
283
281
  "Flag for dry run. Doesn't submit the request to the publisher portal."
@@ -292,29 +290,32 @@ async function main() {
292
290
  critical,
293
291
  dryRun,
294
292
  }) => {
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
- });
293
+ try {
294
+ const config = await getConfigFile();
295
+
296
+ if (!hasAddressInConfig(config.release) && !releaseMintAddress) {
297
+ showUserErrorMessage(
298
+ "\n\n::: Either specify an release mint address in the config file, or specify as a CLI argument to this command. :::\n\n"
299
+ );
300
+ publishCommand.showHelpAfterError();
301
+ return;
302
+ }
303
+
304
+ const signer = parseKeypair(keypair);
305
+
306
+ if (signer) {
307
+ await publishUpdateCommand({
308
+ releaseMintAddress,
309
+ signer,
310
+ url,
311
+ dryRun,
312
+ compliesWithSolanaDappStorePolicies,
313
+ requestorIsAuthorized,
314
+ critical,
315
+ });
316
+ }
317
+ } catch (e) {
318
+ showUserErrorMessage((e as Error | null)?.message ?? "");
318
319
  }
319
320
  }
320
321
  );
@@ -337,7 +338,7 @@ async function main() {
337
338
  "The mint address of the release NFT"
338
339
  )
339
340
  .option("-c, --critical", "Flag for a critical app removal request")
340
- .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
341
+ .option("-u, --url <url>", "RPC URL", "https://devnet.genesysgo.net")
341
342
  .option(
342
343
  "-d, --dry-run",
343
344
  "Flag for dry run. Doesn't submit the request to the publisher portal."
@@ -351,28 +352,31 @@ async function main() {
351
352
  critical,
352
353
  dryRun,
353
354
  }) => {
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
- });
355
+ try {
356
+ const config = await getConfigFile();
357
+
358
+ if (!hasAddressInConfig(config.release) && !releaseMintAddress) {
359
+ showUserErrorMessage(
360
+ "\n\n::: Either specify an release mint address in the config file, or specify as a CLI argument to this command. :::\n\n"
361
+ );
362
+ publishCommand.showHelpAfterError();
363
+ return;
364
+ }
365
+
366
+ const signer = parseKeypair(keypair);
367
+
368
+ if (signer) {
369
+ await publishRemoveCommand({
370
+ releaseMintAddress,
371
+ signer,
372
+ url,
373
+ dryRun,
374
+ requestorIsAuthorized,
375
+ critical,
376
+ });
377
+ }
378
+ } catch (e) {
379
+ showUserErrorMessage((e as Error | null)?.message ?? "");
376
380
  }
377
381
  }
378
382
  );
@@ -394,7 +398,7 @@ async function main() {
394
398
  "-r, --release-mint-address <release-mint-address>",
395
399
  "The mint address of the release NFT"
396
400
  )
397
- .option("-u, --url", "RPC URL", "https://devnet.genesysgo.net")
401
+ .option("-u, --url <url>", "RPC URL", "https://devnet.genesysgo.net")
398
402
  .option(
399
403
  "-d, --dry-run",
400
404
  "Flag for dry run. Doesn't submit the request to the publisher portal."
@@ -404,28 +408,31 @@ async function main() {
404
408
  requestDetails,
405
409
  { releaseMintAddress, keypair, url, requestorIsAuthorized, dryRun }
406
410
  ) => {
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
- });
411
+ try {
412
+ const config = await getConfigFile();
413
+
414
+ if (!hasAddressInConfig(config.release) && !releaseMintAddress) {
415
+ showUserErrorMessage(
416
+ "\n\n::: Either specify an release mint address in the config file, or specify as a CLI argument to this command. :::\n\n"
417
+ );
418
+ publishCommand.showHelpAfterError();
419
+ return;
420
+ }
421
+
422
+ const signer = parseKeypair(keypair);
423
+
424
+ if (signer) {
425
+ await publishSupportCommand({
426
+ releaseMintAddress,
427
+ signer,
428
+ url,
429
+ dryRun,
430
+ requestorIsAuthorized,
431
+ requestDetails,
432
+ });
433
+ }
434
+ } catch (e) {
435
+ showUserErrorMessage((e as Error | null)?.message ?? "");
429
436
  }
430
437
  }
431
438
  );
@@ -19,7 +19,10 @@ export type AssetManifestSchema = {
19
19
 
20
20
  // TODO(jon): We need to manage the removal / replacement of assets in the manifest
21
21
  export class CachedStorageDriver implements StorageDriver {
22
- static readonly SCHEMA_VERSION = "0.2.2";
22
+ // NOTE: this schema version is independent of the publishing JSON schema. It should be updated
23
+ // when the AssetManifestSchema or Asset types are updated.
24
+ static readonly SCHEMA_VERSION = "0.1";
25
+
23
26
  assetManifest: AssetManifestSchema;
24
27
  assetManifestPath: string;
25
28
  storageDriver: StorageDriver;
package/src/utils.ts CHANGED
@@ -1,10 +1,5 @@
1
1
  import fs from "fs";
2
- import type {
3
- AndroidDetails,
4
- App,
5
- Publisher,
6
- Release,
7
- } from "@solana-mobile/dapp-store-publishing-tools";
2
+ import type { AndroidDetails, App, Publisher, Release } from "@solana-mobile/dapp-store-publishing-tools";
8
3
  import type { Connection } from "@solana/web3.js";
9
4
  import { Keypair } from "@solana/web3.js";
10
5
  import type { CLIConfig } from "./config/index.js";
@@ -14,12 +9,7 @@ import { dump } from "js-yaml";
14
9
  import * as util from "util";
15
10
  import { exec } from "child_process";
16
11
  import * as path from "path";
17
- import {
18
- BundlrStorageDriver,
19
- keypairIdentity,
20
- Metaplex,
21
- toMetaplexFile,
22
- } from "@metaplex-foundation/js";
12
+ import { BundlrStorageDriver, keypairIdentity, Metaplex, toMetaplexFile } from "@metaplex-foundation/js";
23
13
  import { imageSize } from "image-size";
24
14
 
25
15
  import { CachedStorageDriver } from "./upload/CachedStorageDriver.js";
@@ -53,11 +43,10 @@ const AaptPrefixes = {
53
43
 
54
44
  export const getConfigFile = async (
55
45
  buildToolsDir: string | null = null
56
- ): Promise<CLIConfig & { isValid: boolean }> => {
46
+ ): Promise<CLIConfig> => {
57
47
  const configFilePath = `${process.cwd()}/config.yaml`;
58
48
 
59
49
  const config = await getConfig(configFilePath);
60
- config.isValid = true;
61
50
 
62
51
  console.info(`Pulling details from ${configFilePath}`);
63
52
 
@@ -68,9 +57,7 @@ export const getConfigFile = async (
68
57
  )!;
69
58
  const apkPath = path.join(process.cwd(), apkEntry?.uri);
70
59
  if (!fs.existsSync(apkPath)) {
71
- showUserErrorMessage("Invalid path to APK file.");
72
- config.isValid = false;
73
- return config;
60
+ throw new Error("Invalid path to APK file.");
74
61
  }
75
62
 
76
63
  config.release.android_details = await getAndroidDetails(
@@ -85,27 +72,16 @@ export const getConfigFile = async (
85
72
  if (publisherIcon) {
86
73
  const iconPath = path.join(process.cwd(), publisherIcon);
87
74
  if (!fs.existsSync(iconPath) || !checkImageExtension(iconPath)) {
88
- showUserErrorMessage(
89
- "Please check the path to your Publisher icon ensure the file is a jpeg, png, or webp file."
90
- );
91
- config.isValid = false;
92
- return config;
75
+ throw new Error("Please check the path to your Publisher icon and ensure the file is a jpeg, png, or webp file.");
93
76
  }
94
77
 
95
78
  const iconBuffer = await fs.promises.readFile(iconPath);
96
79
 
97
80
  if (await checkIconDimensions(iconPath)) {
98
- showUserErrorMessage(
99
- "Icons must have square dimensions and be no greater than 512px by 512px."
100
- );
101
- config.isValid = false;
102
- return config;
81
+ throw new Error("Icons must have square dimensions and be no greater than 512px by 512px.")
103
82
  }
104
83
 
105
- config.publisher.icon = toMetaplexFile(
106
- iconBuffer,
107
- path.join("media", publisherIcon)
108
- );
84
+ config.publisher.icon = toMetaplexFile(iconBuffer, publisherIcon);
109
85
  }
110
86
 
111
87
  const appIcon = config.app.media?.find(
@@ -114,34 +90,22 @@ export const getConfigFile = async (
114
90
  if (appIcon) {
115
91
  const iconPath = path.join(process.cwd(), appIcon);
116
92
  if (!fs.existsSync(iconPath) || !checkImageExtension(iconPath)) {
117
- showUserErrorMessage(
118
- "Please check the path to your App icon ensure the file is a jpeg, png, or webp file."
119
- );
120
- config.isValid = false;
121
- return config;
93
+ throw new Error("Please check the path to your App icon and ensure the file is a jpeg, png, or webp file.")
122
94
  }
123
95
 
124
96
  const iconBuffer = await fs.promises.readFile(iconPath);
125
97
 
126
98
  if (await checkIconDimensions(iconPath)) {
127
- showUserErrorMessage(
128
- "Icons must have square dimensions and be no greater than 512px by 512px."
129
- );
130
- config.isValid = false;
131
- return config;
99
+ throw new Error("Icons must have square dimensions and be no greater than 512px by 512px.")
132
100
  }
133
101
 
134
- config.app.icon = toMetaplexFile(iconBuffer, path.join("media", appIcon));
102
+ config.app.icon = toMetaplexFile(iconBuffer, appIcon);
135
103
  }
136
104
 
137
105
  config.release.media.forEach((item: CLIConfig["release"]["media"][0]) => {
138
106
  const imagePath = path.join(process.cwd(), item.uri);
139
107
  if (!fs.existsSync(imagePath) || !checkImageExtension(imagePath)) {
140
- showUserErrorMessage(
141
- `Invalid media path or file type: ${item.uri}. Please ensure the file is a jpeg, png, or webp file.`
142
- );
143
- config.isValid = false;
144
- return config;
108
+ throw new Error(`Invalid media path or file type: ${item.uri}. Please ensure the file is a jpeg, png, or webp file.`)
145
109
  }
146
110
  });
147
111
 
@@ -182,8 +146,9 @@ const getAndroidDetails = async (
182
146
  const versionCode = new RegExp(
183
147
  AaptPrefixes.verCodePrefix + AaptPrefixes.quoteRegex
184
148
  ).exec(stdout);
185
- //TODO: Return this and use automatically replacing command line arg
186
- //const versionName = new RegExp(prefixes.verNamePrefix + prefixes.quoteRegex).exec(stdout);
149
+ const versionName = new RegExp(
150
+ AaptPrefixes.verNamePrefix + AaptPrefixes.quoteRegex
151
+ ).exec(stdout);
187
152
  const minSdk = new RegExp(
188
153
  AaptPrefixes.sdkPrefix + AaptPrefixes.quoteRegex
189
154
  ).exec(stdout);
@@ -209,6 +174,7 @@ const getAndroidDetails = async (
209
174
  android_package: appPackage?.[1] ?? "",
210
175
  min_sdk: parseInt(minSdk?.[1] ?? "0", 10),
211
176
  version_code: parseInt(versionCode?.[1] ?? "0", 10),
177
+ version: versionName?.[1] ?? "0",
212
178
  permissions: permissionArray,
213
179
  locales: localeArray,
214
180
  };
@@ -217,7 +183,7 @@ const getAndroidDetails = async (
217
183
  type SaveToConfigArgs = {
218
184
  publisher?: Pick<Publisher, "address">;
219
185
  app?: Pick<App, "address">;
220
- release?: Pick<Release, "address" | "version">;
186
+ release?: Pick<Release, "address">;
221
187
  };
222
188
 
223
189
  export const saveToConfig = async ({
@@ -242,11 +208,9 @@ export const saveToConfig = async ({
242
208
  release: {
243
209
  ...currentConfig.release,
244
210
  address: release?.address ?? currentConfig.release.address,
245
- version: release?.version ?? currentConfig.release.version,
246
211
  },
247
212
  solana_mobile_dapp_publisher_portal:
248
213
  currentConfig.solana_mobile_dapp_publisher_portal,
249
- isValid: currentConfig.isValid,
250
214
  };
251
215
 
252
216
  // TODO(jon): Verify the contents of the YAML file
@@ -258,8 +222,9 @@ export const getMetaplexInstance = (
258
222
  keypair: Keypair
259
223
  ) => {
260
224
  const metaplex = Metaplex.make(connection).use(keypairIdentity(keypair));
225
+ const isDevnet = connection.rpcEndpoint.includes("devnet");
261
226
 
262
- const bundlrStorageDriver = connection.rpcEndpoint.includes("devnet")
227
+ const bundlrStorageDriver = isDevnet
263
228
  ? new BundlrStorageDriver(metaplex, {
264
229
  address: "https://devnet.bundlr.network",
265
230
  providerUrl: "https://api.devnet.solana.com",
@@ -268,7 +233,9 @@ export const getMetaplexInstance = (
268
233
 
269
234
  metaplex.storage().setDriver(
270
235
  new CachedStorageDriver(bundlrStorageDriver, {
271
- assetManifestPath: "./.asset-manifest.json",
236
+ assetManifestPath: isDevnet
237
+ ? "./.asset-manifest-devnet.json"
238
+ : "./.asset-manifest.json",
272
239
  })
273
240
  );
274
241
  return metaplex;