@solana-mobile/dapp-store-cli 0.9.4 → 0.9.5

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/lib/CliSetup.js CHANGED
@@ -126,7 +126,7 @@ import { Command } from "commander";
126
126
  import { validateCommand } from "./commands/index.js";
127
127
  import { createAppCommand, createPublisherCommand, createReleaseCommand } from "./commands/create/index.js";
128
128
  import { publishRemoveCommand, publishSubmitCommand, publishSupportCommand, publishUpdateCommand } from "./commands/publish/index.js";
129
- import { checkForSelfUpdate, checkSubmissionNetwork, Constants, dryRunSuccessMessage, generateNetworkSuffix, parseKeypair, showMessage, showNetworkWarningIfApplicable } from "./CliUtils.js";
129
+ import { checkForSelfUpdate, checkSubmissionNetwork, Constants, alphaAppSubmissionMessage, dryRunSuccessMessage, generateNetworkSuffix, parseKeypair, showMessage, showNetworkWarningIfApplicable } from "./CliUtils.js";
130
130
  import { LAMPORTS_PER_SOL } from "@solana/web3.js";
131
131
  import * as dotenv from "dotenv";
132
132
  import { initScaffold } from "./commands/scaffolding/index.js";
@@ -520,13 +520,13 @@ mainCli.command("validate").description("Validates details prior to publishing")
520
520
  };
521
521
  }());
522
522
  var publishCommand = mainCli.command("publish").description("Submit a publishing request (`submit`, `update`, `remove`, or `support`) to the Solana Mobile dApp publisher portal");
523
- publishCommand.command("submit").description("Submit a new app to the Solana Mobile dApp publisher portal").requiredOption("-k, --keypair <path-to-keypair-file>", "Path to keypair file").requiredOption("--complies-with-solana-dapp-store-policies", "An attestation that the app complies with the Solana dApp Store policies").requiredOption("--requestor-is-authorized", "An attestation that the party making this Solana dApp publisher portal request is authorized to do so").option("-a, --app-mint-address <app-mint-address>", "The mint address of the app NFT. If not specified, the value from your config file will be used.").option("-r, --release-mint-address <release-mint-address>", "The mint address of the release NFT. If not specified, the value from your config file will be used.").option("-u, --url <url>", "RPC URL", Constants.DEFAULT_RPC_DEVNET).option("-d, --dry-run", "Flag for dry run. Doesn't submit the request to the publisher portal.").action(function() {
523
+ publishCommand.command("submit").description("Submit a new app to the Solana Mobile dApp publisher portal").requiredOption("-k, --keypair <path-to-keypair-file>", "Path to keypair file").requiredOption("--complies-with-solana-dapp-store-policies", "An attestation that the app complies with the Solana dApp Store policies").requiredOption("--requestor-is-authorized", "An attestation that the party making this Solana dApp publisher portal request is authorized to do so").option("-a, --app-mint-address <app-mint-address>", "The mint address of the app NFT. If not specified, the value from your config file will be used.").option("-r, --release-mint-address <release-mint-address>", "The mint address of the release NFT. If not specified, the value from your config file will be used.").option("-u, --url <url>", "RPC URL", Constants.DEFAULT_RPC_DEVNET).option("-d, --dry-run", "Flag for dry run. Doesn't submit the request to the publisher portal.").option("-l, --alpha", "Flag to mark the submission as alpha test.").action(function() {
524
524
  var _ref = _async_to_generator(function(param) {
525
- var appMintAddress, releaseMintAddress, keypair, url, compliesWithSolanaDappStorePolicies, requestorIsAuthorized, dryRun;
525
+ var appMintAddress, releaseMintAddress, keypair, url, compliesWithSolanaDappStorePolicies, requestorIsAuthorized, dryRun, alpha;
526
526
  return _ts_generator(this, function(_state) {
527
527
  switch(_state.label){
528
528
  case 0:
529
- appMintAddress = param.appMintAddress, releaseMintAddress = param.releaseMintAddress, keypair = param.keypair, url = param.url, compliesWithSolanaDappStorePolicies = param.compliesWithSolanaDappStorePolicies, requestorIsAuthorized = param.requestorIsAuthorized, dryRun = param.dryRun;
529
+ appMintAddress = param.appMintAddress, releaseMintAddress = param.releaseMintAddress, keypair = param.keypair, url = param.url, compliesWithSolanaDappStorePolicies = param.compliesWithSolanaDappStorePolicies, requestorIsAuthorized = param.requestorIsAuthorized, dryRun = param.dryRun, alpha = param.alpha;
530
530
  return [
531
531
  4,
532
532
  tryWithErrorMessage(/*#__PURE__*/ _async_to_generator(function() {
@@ -550,6 +550,9 @@ publishCommand.command("submit").description("Submit a new app to the Solana Mob
550
550
  if (!hasAddressInConfig(config.release) && !releaseMintAddress) {
551
551
  throw new Error("Either specify a release mint address in the config file or specify as a CLI argument to this command.");
552
552
  }
553
+ if (alpha) {
554
+ alphaAppSubmissionMessage();
555
+ }
553
556
  signer = parseKeypair(keypair);
554
557
  if (!signer) return [
555
558
  3,
@@ -569,7 +572,8 @@ publishCommand.command("submit").description("Submit a new app to the Solana Mob
569
572
  dryRun: dryRun,
570
573
  compliesWithSolanaDappStorePolicies: compliesWithSolanaDappStorePolicies,
571
574
  requestorIsAuthorized: requestorIsAuthorized,
572
- critical: false
575
+ critical: false,
576
+ alphaTest: alpha
573
577
  })
574
578
  ];
575
579
  case 3:
@@ -588,7 +592,8 @@ publishCommand.command("submit").description("Submit a new app to the Solana Mob
588
592
  url: url,
589
593
  dryRun: dryRun,
590
594
  compliesWithSolanaDappStorePolicies: compliesWithSolanaDappStorePolicies,
591
- requestorIsAuthorized: requestorIsAuthorized
595
+ requestorIsAuthorized: requestorIsAuthorized,
596
+ alphaTest: alpha
592
597
  })
593
598
  ];
594
599
  case 5:
@@ -621,13 +626,13 @@ publishCommand.command("submit").description("Submit a new app to the Solana Mob
621
626
  return _ref.apply(this, arguments);
622
627
  };
623
628
  }());
624
- publishCommand.command("update").description("Update an existing app on the Solana Mobile dApp publisher portal").requiredOption("-k, --keypair <path-to-keypair-file>", "Path to keypair file").requiredOption("--complies-with-solana-dapp-store-policies", "An attestation that the app complies with the Solana dApp Store policies").requiredOption("--requestor-is-authorized", "An attestation that the party making this Solana dApp publisher portal request is authorized to do so").option("-a, --app-mint-address <app-mint-address>", "The mint address of the app NFT. If not specified, the value from your config file will be used.").option("-r, --release-mint-address <release-mint-address>", "The mint address of the release NFT. If not specified, the value from your config file will be used.").option("-c, --critical", "Flag for a critical app update request").option("-u, --url <url>", "RPC URL", Constants.DEFAULT_RPC_DEVNET).option("-d, --dry-run", "Flag for dry run. Doesn't submit the request to the publisher portal.").action(function() {
629
+ publishCommand.command("update").description("Update an existing app on the Solana Mobile dApp publisher portal").requiredOption("-k, --keypair <path-to-keypair-file>", "Path to keypair file").requiredOption("--complies-with-solana-dapp-store-policies", "An attestation that the app complies with the Solana dApp Store policies").requiredOption("--requestor-is-authorized", "An attestation that the party making this Solana dApp publisher portal request is authorized to do so").option("-a, --app-mint-address <app-mint-address>", "The mint address of the app NFT. If not specified, the value from your config file will be used.").option("-r, --release-mint-address <release-mint-address>", "The mint address of the release NFT. If not specified, the value from your config file will be used.").option("-c, --critical", "Flag for a critical app update request").option("-u, --url <url>", "RPC URL", Constants.DEFAULT_RPC_DEVNET).option("-d, --dry-run", "Flag for dry run. Doesn't submit the request to the publisher portal.").option("-l, --alpha", "Flag to mark the submission as alpha test.").action(function() {
625
630
  var _ref = _async_to_generator(function(param) {
626
- var appMintAddress, releaseMintAddress, keypair, url, compliesWithSolanaDappStorePolicies, requestorIsAuthorized, critical, dryRun;
631
+ var appMintAddress, releaseMintAddress, keypair, url, compliesWithSolanaDappStorePolicies, requestorIsAuthorized, critical, dryRun, alpha;
627
632
  return _ts_generator(this, function(_state) {
628
633
  switch(_state.label){
629
634
  case 0:
630
- appMintAddress = param.appMintAddress, releaseMintAddress = param.releaseMintAddress, keypair = param.keypair, url = param.url, compliesWithSolanaDappStorePolicies = param.compliesWithSolanaDappStorePolicies, requestorIsAuthorized = param.requestorIsAuthorized, critical = param.critical, dryRun = param.dryRun;
635
+ appMintAddress = param.appMintAddress, releaseMintAddress = param.releaseMintAddress, keypair = param.keypair, url = param.url, compliesWithSolanaDappStorePolicies = param.compliesWithSolanaDappStorePolicies, requestorIsAuthorized = param.requestorIsAuthorized, critical = param.critical, dryRun = param.dryRun, alpha = param.alpha;
631
636
  return [
632
637
  4,
633
638
  tryWithErrorMessage(/*#__PURE__*/ _async_to_generator(function() {
@@ -651,6 +656,9 @@ publishCommand.command("update").description("Update an existing app on the Sola
651
656
  if (!hasAddressInConfig(config.release) && !releaseMintAddress) {
652
657
  throw new Error("Either specify a release mint address in the config file or specify as a CLI argument to this command.");
653
658
  }
659
+ if (alpha) {
660
+ alphaAppSubmissionMessage();
661
+ }
654
662
  signer = parseKeypair(keypair);
655
663
  if (!signer) return [
656
664
  3,
@@ -666,7 +674,8 @@ publishCommand.command("update").description("Update an existing app on the Sola
666
674
  dryRun: dryRun,
667
675
  compliesWithSolanaDappStorePolicies: compliesWithSolanaDappStorePolicies,
668
676
  requestorIsAuthorized: requestorIsAuthorized,
669
- critical: critical
677
+ critical: critical,
678
+ alphaTest: alpha
670
679
  })
671
680
  ];
672
681
  case 3:
package/lib/CliUtils.js CHANGED
@@ -158,7 +158,7 @@ export var Constants = function Constants() {
158
158
  "use strict";
159
159
  _class_call_check(this, Constants);
160
160
  };
161
- _define_property(Constants, "CLI_VERSION", "0.9.4");
161
+ _define_property(Constants, "CLI_VERSION", "0.9.5");
162
162
  _define_property(Constants, "CONFIG_FILE_NAME", "config.yaml");
163
163
  _define_property(Constants, "DEFAULT_RPC_DEVNET", "https://api.devnet.solana.com");
164
164
  _define_property(Constants, "DEFAULT_PRIORITY_FEE", 500000);
@@ -299,6 +299,9 @@ export var generateNetworkSuffix = function(rpcUrl) {
299
299
  export var dryRunSuccessMessage = function() {
300
300
  showMessage("Dry run", "Dry run was successful", "standard");
301
301
  };
302
+ export var alphaAppSubmissionMessage = function() {
303
+ showMessage("Alpha release", "Alpha releases are not reviewed on dApp store and are meant for internal testing only.\n" + "Run the `npx dapp-store publish submit ...` command again without the `--alpha` param to publish the app", "warning");
304
+ };
302
305
  export var showNetworkWarningIfApplicable = function(rpcUrl) {
303
306
  if (isDevnet(rpcUrl)) {
304
307
  showMessage("Devnet Mode", "Running on Devnet", "warning");
@@ -129,11 +129,11 @@ import { checkMintedStatus, showMessage } from "../../CliUtils.js";
129
129
  import { loadPublishDetailsWithChecks, writeToPublishDetails } from "../../config/PublishDetails.js";
130
130
  export var publishSubmitCommand = function() {
131
131
  var _ref = _async_to_generator(function(param) {
132
- var appMintAddress, releaseMintAddress, signer, url, _param_dryRun, dryRun, _param_compliesWithSolanaDappStorePolicies, compliesWithSolanaDappStorePolicies, _param_requestorIsAuthorized, requestorIsAuthorized, connection, _ref, publisherDetails, appDetails, releaseDetails, solanaMobileDappPublisherPortalDetails, lastUpdatedVersionOnStore, sign, pubAddr, appAddr, releaseAddr;
132
+ var appMintAddress, releaseMintAddress, signer, url, _param_dryRun, dryRun, _param_compliesWithSolanaDappStorePolicies, compliesWithSolanaDappStorePolicies, _param_requestorIsAuthorized, requestorIsAuthorized, alphaTest, connection, _ref, publisherDetails, appDetails, releaseDetails, solanaMobileDappPublisherPortalDetails, lastUpdatedVersionOnStore, sign, pubAddr, appAddr, releaseAddr;
133
133
  return _ts_generator(this, function(_state) {
134
134
  switch(_state.label){
135
135
  case 0:
136
- appMintAddress = param.appMintAddress, releaseMintAddress = param.releaseMintAddress, signer = param.signer, url = param.url, _param_dryRun = param.dryRun, dryRun = _param_dryRun === void 0 ? false : _param_dryRun, _param_compliesWithSolanaDappStorePolicies = param.compliesWithSolanaDappStorePolicies, compliesWithSolanaDappStorePolicies = _param_compliesWithSolanaDappStorePolicies === void 0 ? false : _param_compliesWithSolanaDappStorePolicies, _param_requestorIsAuthorized = param.requestorIsAuthorized, requestorIsAuthorized = _param_requestorIsAuthorized === void 0 ? false : _param_requestorIsAuthorized;
136
+ appMintAddress = param.appMintAddress, releaseMintAddress = param.releaseMintAddress, signer = param.signer, url = param.url, _param_dryRun = param.dryRun, dryRun = _param_dryRun === void 0 ? false : _param_dryRun, _param_compliesWithSolanaDappStorePolicies = param.compliesWithSolanaDappStorePolicies, compliesWithSolanaDappStorePolicies = _param_compliesWithSolanaDappStorePolicies === void 0 ? false : _param_compliesWithSolanaDappStorePolicies, _param_requestorIsAuthorized = param.requestorIsAuthorized, requestorIsAuthorized = _param_requestorIsAuthorized === void 0 ? false : _param_requestorIsAuthorized, alphaTest = param.alphaTest;
137
137
  showMessage("Publishing Estimates", "New app submissions take around 3-4 business days for review.", "warning");
138
138
  if (!compliesWithSolanaDappStorePolicies) {
139
139
  console.error("ERROR: Cannot submit a request for which the requestor does not attest that it complies with Solana dApp Store policies");
@@ -153,6 +153,9 @@ export var publishSubmitCommand = function() {
153
153
  ];
154
154
  case 1:
155
155
  _ref = _state.sent(), publisherDetails = _ref.publisher, appDetails = _ref.app, releaseDetails = _ref.release, solanaMobileDappPublisherPortalDetails = _ref.solana_mobile_dapp_publisher_portal, lastUpdatedVersionOnStore = _ref.lastUpdatedVersionOnStore;
156
+ if (alphaTest && solanaMobileDappPublisherPortalDetails.alpha_testers == undefined) {
157
+ throw new Error("Alpha test submission without specifying any testers.\nAdd field alpha_testers in your 'config.yaml' file.");
158
+ }
156
159
  sign = function(buf) {
157
160
  return nacl.sign(buf, signer.secretKey);
158
161
  };
@@ -179,11 +182,16 @@ export var publishSubmitCommand = function() {
179
182
  publisherDetails: publisherDetails,
180
183
  solanaMobileDappPublisherPortalDetails: solanaMobileDappPublisherPortalDetails,
181
184
  compliesWithSolanaDappStorePolicies: compliesWithSolanaDappStorePolicies,
182
- requestorIsAuthorized: requestorIsAuthorized
185
+ requestorIsAuthorized: requestorIsAuthorized,
186
+ alphaTest: alphaTest
183
187
  }, dryRun)
184
188
  ];
185
189
  case 3:
186
190
  _state.sent();
191
+ if (!!alphaTest) return [
192
+ 3,
193
+ 5
194
+ ];
187
195
  return [
188
196
  4,
189
197
  writeToPublishDetails({
@@ -194,6 +202,8 @@ export var publishSubmitCommand = function() {
194
202
  ];
195
203
  case 4:
196
204
  _state.sent();
205
+ _state.label = 5;
206
+ case 5:
197
207
  return [
198
208
  2
199
209
  ];
@@ -129,11 +129,11 @@ import nacl from "tweetnacl";
129
129
  import { loadPublishDetailsWithChecks, writeToPublishDetails } from "../../config/PublishDetails.js";
130
130
  export var publishUpdateCommand = function() {
131
131
  var _ref = _async_to_generator(function(param) {
132
- var appMintAddress, releaseMintAddress, signer, url, _param_dryRun, dryRun, _param_compliesWithSolanaDappStorePolicies, compliesWithSolanaDappStorePolicies, _param_requestorIsAuthorized, requestorIsAuthorized, _param_critical, critical, connection, _ref, publisherDetails, appDetails, releaseDetails, solanaMobileDappPublisherPortalDetails, lastUpdatedVersionOnStore, sign, pubAddr, appAddr, releaseAddr;
132
+ var appMintAddress, releaseMintAddress, signer, url, _param_dryRun, dryRun, _param_compliesWithSolanaDappStorePolicies, compliesWithSolanaDappStorePolicies, _param_requestorIsAuthorized, requestorIsAuthorized, _param_critical, critical, alphaTest, connection, _ref, publisherDetails, appDetails, releaseDetails, solanaMobileDappPublisherPortalDetails, lastUpdatedVersionOnStore, sign, pubAddr, appAddr, releaseAddr;
133
133
  return _ts_generator(this, function(_state) {
134
134
  switch(_state.label){
135
135
  case 0:
136
- appMintAddress = param.appMintAddress, releaseMintAddress = param.releaseMintAddress, signer = param.signer, url = param.url, _param_dryRun = param.dryRun, dryRun = _param_dryRun === void 0 ? false : _param_dryRun, _param_compliesWithSolanaDappStorePolicies = param.compliesWithSolanaDappStorePolicies, compliesWithSolanaDappStorePolicies = _param_compliesWithSolanaDappStorePolicies === void 0 ? false : _param_compliesWithSolanaDappStorePolicies, _param_requestorIsAuthorized = param.requestorIsAuthorized, requestorIsAuthorized = _param_requestorIsAuthorized === void 0 ? false : _param_requestorIsAuthorized, _param_critical = param.critical, critical = _param_critical === void 0 ? false : _param_critical;
136
+ appMintAddress = param.appMintAddress, releaseMintAddress = param.releaseMintAddress, signer = param.signer, url = param.url, _param_dryRun = param.dryRun, dryRun = _param_dryRun === void 0 ? false : _param_dryRun, _param_compliesWithSolanaDappStorePolicies = param.compliesWithSolanaDappStorePolicies, compliesWithSolanaDappStorePolicies = _param_compliesWithSolanaDappStorePolicies === void 0 ? false : _param_compliesWithSolanaDappStorePolicies, _param_requestorIsAuthorized = param.requestorIsAuthorized, requestorIsAuthorized = _param_requestorIsAuthorized === void 0 ? false : _param_requestorIsAuthorized, _param_critical = param.critical, critical = _param_critical === void 0 ? false : _param_critical, alphaTest = param.alphaTest;
137
137
  showMessage("Publishing Estimates", "App update approvals take around 1-2 business days for review.", "warning");
138
138
  if (!compliesWithSolanaDappStorePolicies) {
139
139
  console.error("ERROR: Cannot submit a request for which the requestor does not attest that it complies with Solana dApp Store policies");
@@ -155,6 +155,9 @@ export var publishUpdateCommand = function() {
155
155
  ];
156
156
  case 1:
157
157
  _ref = _state.sent(), publisherDetails = _ref.publisher, appDetails = _ref.app, releaseDetails = _ref.release, solanaMobileDappPublisherPortalDetails = _ref.solana_mobile_dapp_publisher_portal, lastUpdatedVersionOnStore = _ref.lastUpdatedVersionOnStore;
158
+ if (alphaTest && solanaMobileDappPublisherPortalDetails.alpha_testers == undefined) {
159
+ throw new Error("Alpha test submission without specifying any testers.\nAdd field alpha_testers in your 'config.yaml' file.");
160
+ }
158
161
  sign = function(buf) {
159
162
  return nacl.sign(buf, signer.secretKey);
160
163
  };
@@ -182,11 +185,16 @@ export var publishUpdateCommand = function() {
182
185
  solanaMobileDappPublisherPortalDetails: solanaMobileDappPublisherPortalDetails,
183
186
  compliesWithSolanaDappStorePolicies: compliesWithSolanaDappStorePolicies,
184
187
  requestorIsAuthorized: requestorIsAuthorized,
185
- criticalUpdate: critical
188
+ criticalUpdate: critical,
189
+ alphaTest: alphaTest
186
190
  }, dryRun)
187
191
  ];
188
192
  case 3:
189
193
  _state.sent();
194
+ if (!!alphaTest) return [
195
+ 3,
196
+ 5
197
+ ];
190
198
  return [
191
199
  4,
192
200
  writeToPublishDetails({
@@ -197,6 +205,8 @@ export var publishUpdateCommand = function() {
197
205
  ];
198
206
  case 4:
199
207
  _state.sent();
208
+ _state.label = 5;
209
+ case 5:
200
210
  return [
201
211
  2
202
212
  ];
@@ -219,6 +219,7 @@ import util from "util";
219
219
  import { imageSize } from "image-size";
220
220
  import { exec } from "child_process";
221
221
  import getVideoDimensions from "get-video-dimensions";
222
+ import { PublicKey } from "@solana/web3.js";
222
223
  var runImgSize = util.promisify(imageSize);
223
224
  var runExec = util.promisify(exec);
224
225
  var AaptPrefixes = {
@@ -265,7 +266,7 @@ export var loadPublishDetails = function() {
265
266
  }();
266
267
  export var loadPublishDetailsWithChecks = function() {
267
268
  var _ref = _async_to_generator(function() {
268
- var buildToolsDir, _config_publisher_media_find, _config_publisher_media, _config_app_media_find, _config_app_media, _config_release_media_find, _config_release_media, _config_release_media1, _config_release_media2, config, apkEntry, apkPath, _, publisherIcon, iconPath, iconBuffer, appIcon, iconPath1, iconBuffer1, releaseIcon, iconPath2, screenshots, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, item, mediaPath, err, videos, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, video, mediaPath1, err, googlePkg, pkgCompare;
269
+ var buildToolsDir, _config_publisher_media_find, _config_publisher_media, _config_app_media_find, _config_app_media, _config_release_media_find, _config_release_media, _config_release_media1, _config_release_media2, config, apkEntry, apkPath, _, publisherIcon, iconPath, iconBuffer, appIcon, iconPath1, iconBuffer1, releaseIcon, iconPath2, screenshots, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, item, mediaPath, err, videos, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, video, mediaPath1, err, googlePkg, pkgCompare, alpha_testers, _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, wallet;
269
270
  var _arguments = arguments;
270
271
  return _ts_generator(this, function(_state) {
271
272
  switch(_state.label){
@@ -511,6 +512,36 @@ export var loadPublishDetailsWithChecks = function() {
511
512
  throw new Error("Please provide a valid Google store package name in the Publisher Portal section of your configuration file.");
512
513
  }
513
514
  }
515
+ alpha_testers = config.solana_mobile_dapp_publisher_portal.alpha_testers;
516
+ if (alpha_testers !== undefined) {
517
+ _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = undefined;
518
+ try {
519
+ for(_iterator2 = alpha_testers[Symbol.iterator](); !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true){
520
+ wallet = _step2.value;
521
+ try {
522
+ void new PublicKey(wallet.address);
523
+ } catch (e) {
524
+ throw new Error("invalid alpha tester wallet address <".concat(wallet, ">"));
525
+ }
526
+ }
527
+ } catch (err) {
528
+ _didIteratorError2 = true;
529
+ _iteratorError2 = err;
530
+ } finally{
531
+ try {
532
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
533
+ _iterator2.return();
534
+ }
535
+ } finally{
536
+ if (_didIteratorError2) {
537
+ throw _iteratorError2;
538
+ }
539
+ }
540
+ }
541
+ if (alpha_testers.size > 10) {
542
+ throw new Error("Alpha testers are limited to 10 per app submission");
543
+ }
544
+ }
514
545
  return [
515
546
  2,
516
547
  config
@@ -1 +1 @@
1
- {"publisher":{"name":"<<YOUR_PUBLISHER_NAME>>","address":"","website":"<<URL_OF_PUBLISHER_WEBSITE>>","email":"<<EMAIL_ADDRESS_TO_CONTACT_PUBLISHER>>","media":[{"purpose":"icon","uri":"<<RELATIVE_PATH_TO_PUBLISHER_ICON>>"}]},"app":{"name":"<<APP_NAME>>","address":"","android_package":"<<ANDROID_PACKAGE_NAME>>","urls":{"license_url":"<<URL_OF_APP_LICENSE_OR_TERMS_OF_SERVICE>>","copyright_url":"<<URL_OF_COPYRIGHT_DETAILS_FOR_APP>>","privacy_policy_url":"<<URL_OF_APP_PRIVACY_POLICY>>","website":"<<URL_OF_APP_WEBSITE>>"},"media":[{"purpose":"icon","uri":"<<RELATIVE_PATH_TO_APP_ICON>>"}]},"release":{"address":"","media":[{"purpose":"icon","uri":"<<RELATIVE_PATH_TO_RELEASE_ICON>>"},{"purpose":"screenshot","uri":"<<RELATIVE_PATH_TO_SCREENSHOT1>>"},{"purpose":"screenshot","uri":"<<RELATIVE_PATH_TO_SCREENSHOT2>>"},{"purpose":"screenshot","uri":"<<RELATIVE_PATH_TO_SCREENSHOT3>>"},{"purpose":"screenshot","uri":"<<RELATIVE_PATH_TO_SCREENSHOT4>>"},{"purpose":"video","uri":"<<RELATIVE_PATH_TO_VIDEO1>>"}],"files":[{"purpose":"install","uri":"<<RELATIVE_PATH_TO_APK>>"}],"catalog":{"en-US":{"name":"<<APP_NAME>>","short_description":"<<SHORT_APP_DESCRIPTION>>","long_description":"<<LONG_APP_DESCRIPTION>>","new_in_version":"<<WHATS_NEW_IN_THIS_VERSION>>","saga_features":"<<ANY_FEATURES_ONLY_AVAILBLE_WHEN_RUNNING_ON_SAGA>>"}}},"solana_mobile_dapp_publisher_portal":{"google_store_package":"<<ANDROID_PACKAGE_NAME_OF_GOOGLE_PLAY_STORE_VERSION_IF_DIFFERENT>>","testing_instructions":"<<TESTING_INSTRUCTIONS>>"}}
1
+ {"publisher":{"name":"<<YOUR_PUBLISHER_NAME>>","address":"","website":"<<URL_OF_PUBLISHER_WEBSITE>>","email":"<<EMAIL_ADDRESS_TO_CONTACT_PUBLISHER>>","media":[{"purpose":"icon","uri":"<<RELATIVE_PATH_TO_PUBLISHER_ICON>>"}]},"app":{"name":"<<APP_NAME>>","address":"","android_package":"<<ANDROID_PACKAGE_NAME>>","urls":{"license_url":"<<URL_OF_APP_LICENSE_OR_TERMS_OF_SERVICE>>","copyright_url":"<<URL_OF_COPYRIGHT_DETAILS_FOR_APP>>","privacy_policy_url":"<<URL_OF_APP_PRIVACY_POLICY>>","website":"<<URL_OF_APP_WEBSITE>>"},"media":[{"purpose":"icon","uri":"<<RELATIVE_PATH_TO_APP_ICON>>"}]},"release":{"address":"","media":[{"purpose":"icon","uri":"<<RELATIVE_PATH_TO_RELEASE_ICON>>"},{"purpose":"screenshot","uri":"<<RELATIVE_PATH_TO_SCREENSHOT1>>"},{"purpose":"screenshot","uri":"<<RELATIVE_PATH_TO_SCREENSHOT2>>"},{"purpose":"screenshot","uri":"<<RELATIVE_PATH_TO_SCREENSHOT3>>"},{"purpose":"screenshot","uri":"<<RELATIVE_PATH_TO_SCREENSHOT4>>"},{"purpose":"video","uri":"<<RELATIVE_PATH_TO_VIDEO1>>"}],"files":[{"purpose":"install","uri":"<<RELATIVE_PATH_TO_APK>>"}],"catalog":{"en-US":{"name":"<<APP_NAME>>","short_description":"<<SHORT_APP_DESCRIPTION>>","long_description":"<<LONG_APP_DESCRIPTION>>","new_in_version":"<<WHATS_NEW_IN_THIS_VERSION>>","saga_features":"<<ANY_FEATURES_ONLY_AVAILBLE_WHEN_RUNNING_ON_SAGA>>"}}},"solana_mobile_dapp_publisher_portal":{"google_store_package":"<<ANDROID_PACKAGE_NAME_OF_GOOGLE_PLAY_STORE_VERSION_IF_DIFFERENT>>","testing_instructions":"<<TESTING_INSTRUCTIONS>>","alpha_testers":[{"address":"<<genesis token wallet address>>","comment":"<<Optional. For internal use only>>"},{"address":"<<genesis token wallet address>>","comment":"<<Optional. For internal use only>>"}]}}
@@ -1 +1 @@
1
- {"type":"object","properties":{"publisher":{"type":"object","properties":{"name":{"type":"string"},"address":{"type":"string"},"website":{"type":"string"},"email":{"type":"string"},"media":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}}}}}},"app":{"type":"object","properties":{"name":{"type":"string"},"address":{"type":"string"},"android_package":{"type":"string"},"urls":{"type":"object","properties":{"license_url":{"type":"string"},"copyright_url":{"type":"string"},"privacy_policy_url":{"type":"string"},"website":{"type":"string"}}},"media":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}}}}}},"release":{"type":"object","properties":{"address":{"type":"string"},"media":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}},"required":["purpose","uri"]}},"files":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}}}},"catalog":{"type":"object","properties":{"en-US":{"type":"object","properties":{"name":{"type":"string"},"short_description":{"type":"string"},"long_description":{"type":"string"},"new_in_version":{"type":"string"},"saga_features":{"type":"string"}},"required":["short_description"]}}}}},"solana_mobile_dapp_publisher_portal":{"type":"object","properties":{"google_store_package":{"type":"string"},"testing_instructions":{"type":"string"}}}}}
1
+ {"type":"object","properties":{"publisher":{"type":"object","properties":{"name":{"type":"string"},"address":{"type":"string"},"website":{"type":"string"},"email":{"type":"string"},"media":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}}}}}},"app":{"type":"object","properties":{"name":{"type":"string"},"address":{"type":"string"},"android_package":{"type":"string"},"urls":{"type":"object","properties":{"license_url":{"type":"string"},"copyright_url":{"type":"string"},"privacy_policy_url":{"type":"string"},"website":{"type":"string"}}},"media":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}}}}}},"release":{"type":"object","properties":{"address":{"type":"string"},"media":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}},"required":["purpose","uri"]}},"files":{"type":"array","items":{"type":"object","properties":{"purpose":{"type":"string"},"uri":{"type":"string"}}}},"catalog":{"type":"object","properties":{"en-US":{"type":"object","properties":{"name":{"type":"string"},"short_description":{"type":"string"},"long_description":{"type":"string"},"new_in_version":{"type":"string"},"saga_features":{"type":"string"}},"required":["short_description"]}}}}},"solana_mobile_dapp_publisher_portal":{"type":"object","properties":{"google_store_package":{"type":"string"},"testing_instructions":{"type":"string"},"alpha_testers":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"comment":{"type":"string"}},"required":["address","comment"]}}}}}}
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solana-mobile/dapp-store-cli",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -53,7 +53,7 @@
53
53
  "dependencies": {
54
54
  "@aws-sdk/client-s3": "^3.321.1",
55
55
  "@metaplex-foundation/js-plugin-aws": "^0.20.0",
56
- "@solana-mobile/dapp-store-publishing-tools": "workspace:0.9.4",
56
+ "@solana-mobile/dapp-store-publishing-tools": "workspace:0.9.5",
57
57
  "@solana/web3.js": "1.92.1",
58
58
  "@types/semver": "^7.3.13",
59
59
  "ajv": "^8.11.0",
@@ -51,4 +51,9 @@ release:
51
51
  solana_mobile_dapp_publisher_portal:
52
52
  google_store_package: <<ANDROID_PACKAGE_NAME_OF_GOOGLE_PLAY_STORE_VERSION_IF_DIFFERENT>>
53
53
  testing_instructions: >-
54
- <<TESTING_INSTRUCTIONS>>
54
+ <<TESTING_INSTRUCTIONS>>
55
+ alpha_testers:
56
+ - address: <<genesis token wallet address>>
57
+ comment: <<Optional. For internal use only>>
58
+ - address: <<genesis token wallet address>>
59
+ comment: <<Optional. For internal use only>>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solana-mobile/dapp-store-cli",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -46,7 +46,7 @@
46
46
  "dependencies": {
47
47
  "@aws-sdk/client-s3": "^3.321.1",
48
48
  "@metaplex-foundation/js-plugin-aws": "^0.20.0",
49
- "@solana-mobile/dapp-store-publishing-tools": "0.9.4",
49
+ "@solana-mobile/dapp-store-publishing-tools": "0.9.5",
50
50
  "@solana/web3.js": "1.92.1",
51
51
  "@types/semver": "^7.3.13",
52
52
  "ajv": "^8.11.0",
package/src/CliSetup.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
11
  checkForSelfUpdate,
12
12
  checkSubmissionNetwork,
13
13
  Constants,
14
+ alphaAppSubmissionMessage,
14
15
  dryRunSuccessMessage,
15
16
  generateNetworkSuffix,
16
17
  parseKeypair,
@@ -303,6 +304,7 @@ publishCommand
303
304
  "-d, --dry-run",
304
305
  "Flag for dry run. Doesn't submit the request to the publisher portal."
305
306
  )
307
+ .option("-l, --alpha", "Flag to mark the submission as alpha test.")
306
308
  .action(
307
309
  async ({
308
310
  appMintAddress,
@@ -312,6 +314,7 @@ publishCommand
312
314
  compliesWithSolanaDappStorePolicies,
313
315
  requestorIsAuthorized,
314
316
  dryRun,
317
+ alpha,
315
318
  }) => {
316
319
  await tryWithErrorMessage(async () => {
317
320
  await checkForSelfUpdate();
@@ -323,6 +326,10 @@ publishCommand
323
326
  throw new Error("Either specify a release mint address in the config file or specify as a CLI argument to this command.")
324
327
  }
325
328
 
329
+ if (alpha) {
330
+ alphaAppSubmissionMessage()
331
+ }
332
+
326
333
  const signer = parseKeypair(keypair);
327
334
  if (signer) {
328
335
  if (config.lastUpdatedVersionOnStore != null && config.lastSubmittedVersionOnChain.address != null) {
@@ -335,6 +342,7 @@ publishCommand
335
342
  compliesWithSolanaDappStorePolicies: compliesWithSolanaDappStorePolicies,
336
343
  requestorIsAuthorized: requestorIsAuthorized,
337
344
  critical: false,
345
+ alphaTest: alpha,
338
346
  });
339
347
  } else {
340
348
  await publishSubmitCommand({
@@ -345,6 +353,7 @@ publishCommand
345
353
  dryRun: dryRun,
346
354
  compliesWithSolanaDappStorePolicies: compliesWithSolanaDappStorePolicies,
347
355
  requestorIsAuthorized: requestorIsAuthorized,
356
+ alphaTest: alpha,
348
357
  });
349
358
  }
350
359
 
@@ -389,6 +398,7 @@ publishCommand
389
398
  "-d, --dry-run",
390
399
  "Flag for dry run. Doesn't submit the request to the publisher portal."
391
400
  )
401
+ .option("-l, --alpha", "Flag to mark the submission as alpha test.")
392
402
  .action(
393
403
  async ({
394
404
  appMintAddress,
@@ -399,6 +409,7 @@ publishCommand
399
409
  requestorIsAuthorized,
400
410
  critical,
401
411
  dryRun,
412
+ alpha,
402
413
  }) => {
403
414
  await tryWithErrorMessage(async () => {
404
415
  await checkForSelfUpdate();
@@ -410,6 +421,10 @@ publishCommand
410
421
  throw new Error("Either specify a release mint address in the config file or specify as a CLI argument to this command.")
411
422
  }
412
423
 
424
+ if (alpha) {
425
+ alphaAppSubmissionMessage()
426
+ }
427
+
413
428
  const signer = parseKeypair(keypair);
414
429
  if (signer) {
415
430
  await publishUpdateCommand({
@@ -421,6 +436,7 @@ publishCommand
421
436
  compliesWithSolanaDappStorePolicies,
422
437
  requestorIsAuthorized,
423
438
  critical,
439
+ alphaTest: alpha,
424
440
  });
425
441
 
426
442
  if (dryRun) {
package/src/CliUtils.ts CHANGED
@@ -19,7 +19,7 @@ import { awsStorage } from "@metaplex-foundation/js-plugin-aws";
19
19
  import { S3StorageManager } from "./config/index.js";
20
20
 
21
21
  export class Constants {
22
- static CLI_VERSION = "0.9.4";
22
+ static CLI_VERSION = "0.9.5";
23
23
  static CONFIG_FILE_NAME = "config.yaml";
24
24
  static DEFAULT_RPC_DEVNET = "https://api.devnet.solana.com";
25
25
  static DEFAULT_PRIORITY_FEE = 500000;
@@ -143,6 +143,15 @@ export const dryRunSuccessMessage = () => {
143
143
  showMessage("Dry run", "Dry run was successful", "standard")
144
144
  }
145
145
 
146
+ export const alphaAppSubmissionMessage = () => {
147
+ showMessage(
148
+ "Alpha release",
149
+ "Alpha releases are not reviewed on dApp store and are meant for internal testing only.\n" +
150
+ "Run the `npx dapp-store publish submit ...` command again without the `--alpha` param to publish the app",
151
+ "warning"
152
+ )
153
+ }
154
+
146
155
  export const showNetworkWarningIfApplicable = (rpcUrl: string) => {
147
156
  if (isDevnet(rpcUrl)) {
148
157
  showMessage("Devnet Mode", "Running on Devnet", "warning")
@@ -14,6 +14,7 @@ type PublishSubmitCommandInput = {
14
14
  dryRun: boolean;
15
15
  compliesWithSolanaDappStorePolicies: boolean;
16
16
  requestorIsAuthorized: boolean;
17
+ alphaTest?: boolean;
17
18
  };
18
19
 
19
20
  export const publishSubmitCommand = async ({
@@ -24,6 +25,7 @@ export const publishSubmitCommand = async ({
24
25
  dryRun = false,
25
26
  compliesWithSolanaDappStorePolicies = false,
26
27
  requestorIsAuthorized = false,
28
+ alphaTest
27
29
  }: PublishSubmitCommandInput) => {
28
30
  showMessage(
29
31
  `Publishing Estimates`,
@@ -52,6 +54,10 @@ export const publishSubmitCommand = async ({
52
54
  lastUpdatedVersionOnStore: lastUpdatedVersionOnStore,
53
55
  } = await loadPublishDetailsWithChecks();
54
56
 
57
+ if (alphaTest && solanaMobileDappPublisherPortalDetails.alpha_testers == undefined) {
58
+ throw new Error(`Alpha test submission without specifying any testers.\nAdd field alpha_testers in your 'config.yaml' file.`)
59
+ }
60
+
55
61
  const sign = ((buf: Buffer) =>
56
62
  nacl.sign(buf, signer.secretKey)) as SignWithPublisherKeypair;
57
63
 
@@ -74,12 +80,15 @@ export const publishSubmitCommand = async ({
74
80
  solanaMobileDappPublisherPortalDetails,
75
81
  compliesWithSolanaDappStorePolicies,
76
82
  requestorIsAuthorized,
83
+ alphaTest,
77
84
  },
78
85
  dryRun
79
86
  );
80
87
 
81
- await writeToPublishDetails(
82
- {
83
- lastUpdatedVersionOnStore: { address: releaseAddr }
84
- });
88
+ if (!alphaTest) {
89
+ await writeToPublishDetails(
90
+ {
91
+ lastUpdatedVersionOnStore: { address: releaseAddr }
92
+ });
93
+ }
85
94
  };
@@ -14,6 +14,7 @@ type PublishUpdateCommandInput = {
14
14
  compliesWithSolanaDappStorePolicies: boolean;
15
15
  requestorIsAuthorized: boolean;
16
16
  critical: boolean;
17
+ alphaTest?: boolean;
17
18
  };
18
19
 
19
20
  export const publishUpdateCommand = async ({
@@ -25,6 +26,7 @@ export const publishUpdateCommand = async ({
25
26
  compliesWithSolanaDappStorePolicies = false,
26
27
  requestorIsAuthorized = false,
27
28
  critical = false,
29
+ alphaTest,
28
30
  }: PublishUpdateCommandInput) => {
29
31
 
30
32
  showMessage(
@@ -60,6 +62,10 @@ export const publishUpdateCommand = async ({
60
62
  lastUpdatedVersionOnStore: lastUpdatedVersionOnStore
61
63
  } = await loadPublishDetailsWithChecks();
62
64
 
65
+ if (alphaTest && solanaMobileDappPublisherPortalDetails.alpha_testers == undefined) {
66
+ throw new Error(`Alpha test submission without specifying any testers.\nAdd field alpha_testers in your 'config.yaml' file.`)
67
+ }
68
+
63
69
  const sign = ((buf: Buffer) =>
64
70
  nacl.sign(buf, signer.secretKey)) as SignWithPublisherKeypair;
65
71
 
@@ -83,11 +89,14 @@ export const publishUpdateCommand = async ({
83
89
  compliesWithSolanaDappStorePolicies,
84
90
  requestorIsAuthorized,
85
91
  criticalUpdate: critical,
92
+ alphaTest,
86
93
  },
87
94
  dryRun
88
95
  );
89
- await writeToPublishDetails(
90
- {
91
- lastUpdatedVersionOnStore: { address: releaseAddr }
92
- });
96
+ if (!alphaTest) {
97
+ await writeToPublishDetails(
98
+ {
99
+ lastUpdatedVersionOnStore: { address: releaseAddr }
100
+ });
101
+ }
93
102
  };
@@ -20,6 +20,7 @@ import util from "util";
20
20
  import { imageSize } from "image-size";
21
21
  import { exec } from "child_process";
22
22
  import getVideoDimensions from "get-video-dimensions";
23
+ import { PublicKey } from "@solana/web3.js";
23
24
 
24
25
  const runImgSize = util.promisify(imageSize);
25
26
  const runExec = util.promisify(exec);
@@ -179,6 +180,21 @@ export const loadPublishDetailsWithChecks = async (
179
180
  }
180
181
  }
181
182
 
183
+ const alpha_testers = config.solana_mobile_dapp_publisher_portal.alpha_testers;
184
+ if (alpha_testers !== undefined) {
185
+ for (const wallet of alpha_testers) {
186
+ try {
187
+ void new PublicKey(wallet.address);
188
+ } catch (e: unknown) {
189
+ throw new Error(`invalid alpha tester wallet address <${wallet}>`);
190
+ }
191
+ }
192
+
193
+ if (alpha_testers.size > 10) {
194
+ throw new Error(`Alpha testers are limited to 10 per app submission`);
195
+ }
196
+ }
197
+
182
198
  return config;
183
199
  };
184
200
 
@@ -51,4 +51,9 @@ release:
51
51
  solana_mobile_dapp_publisher_portal:
52
52
  google_store_package: <<ANDROID_PACKAGE_NAME_OF_GOOGLE_PLAY_STORE_VERSION_IF_DIFFERENT>>
53
53
  testing_instructions: >-
54
- <<TESTING_INSTRUCTIONS>>
54
+ <<TESTING_INSTRUCTIONS>>
55
+ alpha_testers:
56
+ - address: <<genesis token wallet address>>
57
+ comment: <<Optional. For internal use only>>
58
+ - address: <<genesis token wallet address>>
59
+ comment: <<Optional. For internal use only>>