@solana-mobile/dapp-store-cli 0.9.3 → 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 +19 -10
- package/lib/CliUtils.js +36 -5
- package/lib/commands/publish/PublishCliRemove.js +3 -1
- package/lib/commands/publish/PublishCliSubmit.js +13 -3
- package/lib/commands/publish/PublishCliSupport.js +3 -1
- package/lib/commands/publish/PublishCliUpdate.js +16 -4
- package/lib/config/PublishDetails.js +32 -1
- package/lib/generated/config_obj.json +1 -1
- package/lib/generated/config_schema.json +1 -1
- package/lib/package.json +2 -2
- package/lib/prebuild_schema/publishing_source.yaml +6 -1
- package/package.json +2 -2
- package/src/CliSetup.ts +16 -0
- package/src/CliUtils.ts +48 -29
- package/src/commands/publish/PublishCliRemove.ts +7 -1
- package/src/commands/publish/PublishCliSubmit.ts +13 -4
- package/src/commands/publish/PublishCliSupport.ts +7 -1
- package/src/commands/publish/PublishCliUpdate.ts +20 -5
- package/src/config/PublishDetails.ts +16 -0
- package/src/prebuild_schema/publishing_source.yaml +6 -1
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.
|
|
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);
|
|
@@ -198,10 +198,17 @@ export var checkForSelfUpdate = function() {
|
|
|
198
198
|
}();
|
|
199
199
|
export var checkMintedStatus = function() {
|
|
200
200
|
var _ref = _async_to_generator(function(conn, pubAddr, appAddr, releaseAddr) {
|
|
201
|
-
var _results_, _results_1, _results_2, results, isPublisherMinted, isAppMinted, isReleaseMinted, errorMessage;
|
|
201
|
+
var i, _results_, _results_1, _results_2, results, isPublisherMinted, isAppMinted, isReleaseMinted, errorMessage;
|
|
202
202
|
return _ts_generator(this, function(_state) {
|
|
203
203
|
switch(_state.label){
|
|
204
204
|
case 0:
|
|
205
|
+
i = 0;
|
|
206
|
+
_state.label = 1;
|
|
207
|
+
case 1:
|
|
208
|
+
if (!(i < 5)) return [
|
|
209
|
+
3,
|
|
210
|
+
4
|
|
211
|
+
];
|
|
205
212
|
return [
|
|
206
213
|
4,
|
|
207
214
|
conn.getMultipleAccountsInfo([
|
|
@@ -210,12 +217,16 @@ export var checkMintedStatus = function() {
|
|
|
210
217
|
new PublicKey(releaseAddr)
|
|
211
218
|
])
|
|
212
219
|
];
|
|
213
|
-
case
|
|
220
|
+
case 2:
|
|
214
221
|
results = _state.sent();
|
|
215
222
|
isPublisherMinted = results[0] != undefined && ((_results_ = results[0]) === null || _results_ === void 0 ? void 0 : _results_.lamports) > 0;
|
|
216
223
|
isAppMinted = results[1] != undefined && ((_results_1 = results[1]) === null || _results_1 === void 0 ? void 0 : _results_1.lamports) > 0;
|
|
217
224
|
isReleaseMinted = results[2] != undefined && ((_results_2 = results[2]) === null || _results_2 === void 0 ? void 0 : _results_2.lamports) > 0;
|
|
218
|
-
if (
|
|
225
|
+
if (isPublisherMinted && isAppMinted && isReleaseMinted) {
|
|
226
|
+
return [
|
|
227
|
+
2
|
|
228
|
+
];
|
|
229
|
+
} else {
|
|
219
230
|
errorMessage = "";
|
|
220
231
|
if (!isPublisherMinted) {
|
|
221
232
|
errorMessage = errorMessage + "Publisher NFT fetch at address ".concat(pubAddr, " failed.\n");
|
|
@@ -226,8 +237,20 @@ export var checkMintedStatus = function() {
|
|
|
226
237
|
if (!isReleaseMinted) {
|
|
227
238
|
errorMessage = errorMessage + "Release NFT fetch at address ".concat(releaseAddr, " failed.\n");
|
|
228
239
|
}
|
|
229
|
-
|
|
240
|
+
if (i == 4) {
|
|
241
|
+
throw new Error("Expected Publisher :: ".concat(pubAddr, ", App :: ").concat(appAddr, " and Release :: ").concat(releaseAddr, " to be minted before submission.\n\n but ").concat(errorMessage, "\n\n Please ensure you have minted all of your NFTs before submitting to the Solana Mobile dApp publisher portal."));
|
|
242
|
+
} else {
|
|
243
|
+
sleep(2000);
|
|
244
|
+
}
|
|
230
245
|
}
|
|
246
|
+
_state.label = 3;
|
|
247
|
+
case 3:
|
|
248
|
+
i++;
|
|
249
|
+
return [
|
|
250
|
+
3,
|
|
251
|
+
1
|
|
252
|
+
];
|
|
253
|
+
case 4:
|
|
231
254
|
return [
|
|
232
255
|
2
|
|
233
256
|
];
|
|
@@ -238,6 +261,11 @@ export var checkMintedStatus = function() {
|
|
|
238
261
|
return _ref.apply(this, arguments);
|
|
239
262
|
};
|
|
240
263
|
}();
|
|
264
|
+
export var sleep = function(ms) {
|
|
265
|
+
return new Promise(function(resolve) {
|
|
266
|
+
return setTimeout(resolve, ms);
|
|
267
|
+
});
|
|
268
|
+
};
|
|
241
269
|
export var parseKeypair = function(pathToKeypairFile) {
|
|
242
270
|
try {
|
|
243
271
|
var keypairFile = fs.readFileSync(pathToKeypairFile, "utf-8");
|
|
@@ -271,6 +299,9 @@ export var generateNetworkSuffix = function(rpcUrl) {
|
|
|
271
299
|
export var dryRunSuccessMessage = function() {
|
|
272
300
|
showMessage("Dry run", "Dry run was successful", "standard");
|
|
273
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
|
+
};
|
|
274
305
|
export var showNetworkWarningIfApplicable = function(rpcUrl) {
|
|
275
306
|
if (isDevnet(rpcUrl)) {
|
|
276
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");
|
|
@@ -146,13 +146,18 @@ export var publishUpdateCommand = function() {
|
|
|
146
146
|
2
|
|
147
147
|
];
|
|
148
148
|
}
|
|
149
|
-
connection = new Connection(url
|
|
149
|
+
connection = new Connection(url, {
|
|
150
|
+
commitment: "confirmed"
|
|
151
|
+
});
|
|
150
152
|
return [
|
|
151
153
|
4,
|
|
152
154
|
loadPublishDetailsWithChecks()
|
|
153
155
|
];
|
|
154
156
|
case 1:
|
|
155
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
|
+
}
|
|
156
161
|
sign = function(buf) {
|
|
157
162
|
return nacl.sign(buf, signer.secretKey);
|
|
158
163
|
};
|
|
@@ -180,11 +185,16 @@ export var publishUpdateCommand = function() {
|
|
|
180
185
|
solanaMobileDappPublisherPortalDetails: solanaMobileDappPublisherPortalDetails,
|
|
181
186
|
compliesWithSolanaDappStorePolicies: compliesWithSolanaDappStorePolicies,
|
|
182
187
|
requestorIsAuthorized: requestorIsAuthorized,
|
|
183
|
-
criticalUpdate: critical
|
|
188
|
+
criticalUpdate: critical,
|
|
189
|
+
alphaTest: alphaTest
|
|
184
190
|
}, dryRun)
|
|
185
191
|
];
|
|
186
192
|
case 3:
|
|
187
193
|
_state.sent();
|
|
194
|
+
if (!!alphaTest) return [
|
|
195
|
+
3,
|
|
196
|
+
5
|
|
197
|
+
];
|
|
188
198
|
return [
|
|
189
199
|
4,
|
|
190
200
|
writeToPublishDetails({
|
|
@@ -195,6 +205,8 @@ export var publishUpdateCommand = function() {
|
|
|
195
205
|
];
|
|
196
206
|
case 4:
|
|
197
207
|
_state.sent();
|
|
208
|
+
_state.label = 5;
|
|
209
|
+
case 5:
|
|
198
210
|
return [
|
|
199
211
|
2
|
|
200
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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;
|
|
@@ -54,37 +54,47 @@ export const checkMintedStatus = async (
|
|
|
54
54
|
appAddr: string,
|
|
55
55
|
releaseAddr: string
|
|
56
56
|
) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
errorMessage =
|
|
57
|
+
for (let i = 0; i < 5; i++) {
|
|
58
|
+
const results = await conn.getMultipleAccountsInfo([
|
|
59
|
+
new PublicKey(pubAddr),
|
|
60
|
+
new PublicKey(appAddr),
|
|
61
|
+
new PublicKey(releaseAddr),
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
const isPublisherMinted = results[0] != undefined && results[0]?.lamports > 0
|
|
65
|
+
const isAppMinted = results[1] != undefined && results[1]?.lamports > 0
|
|
66
|
+
const isReleaseMinted = results[2] != undefined && results[2]?.lamports > 0
|
|
67
|
+
|
|
68
|
+
if (isPublisherMinted && isAppMinted && isReleaseMinted) {
|
|
69
|
+
return
|
|
70
|
+
} else {
|
|
71
|
+
let errorMessage = ``
|
|
72
|
+
if (!isPublisherMinted) {
|
|
73
|
+
errorMessage = errorMessage + `Publisher NFT fetch at address ${pubAddr} failed.\n`
|
|
74
|
+
}
|
|
75
|
+
if (!isAppMinted) {
|
|
76
|
+
errorMessage = errorMessage + `App NFT fetch at address ${appAddr} failed.\n`
|
|
77
|
+
}
|
|
78
|
+
if (!isReleaseMinted) {
|
|
79
|
+
errorMessage = errorMessage + `Release NFT fetch at address ${releaseAddr} failed.\n`
|
|
80
|
+
}
|
|
81
|
+
if (i == 4) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Expected Publisher :: ${pubAddr}, App :: ${appAddr} and Release :: ${releaseAddr} to be minted before submission.\n
|
|
84
|
+
but ${errorMessage}\n
|
|
85
|
+
Please ensure you have minted all of your NFTs before submitting to the Solana Mobile dApp publisher portal.`
|
|
86
|
+
);
|
|
87
|
+
} else {
|
|
88
|
+
sleep(2000)
|
|
89
|
+
}
|
|
72
90
|
}
|
|
73
|
-
if (!isAppMinted) {
|
|
74
|
-
errorMessage = errorMessage + `App NFT fetch at address ${appAddr} failed.\n`
|
|
75
|
-
}
|
|
76
|
-
if (!isReleaseMinted) {
|
|
77
|
-
errorMessage = errorMessage + `Release NFT fetch at address ${releaseAddr} failed.\n`
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
throw new Error(
|
|
81
|
-
`Expected Publisher :: ${pubAddr}, App :: ${appAddr} and Release :: ${releaseAddr} to be minted before submission.\n
|
|
82
|
-
but ${errorMessage}\n
|
|
83
|
-
Please ensure you have minted all of your NFTs before submitting to the Solana Mobile dApp publisher portal.`
|
|
84
|
-
);
|
|
85
91
|
}
|
|
86
92
|
};
|
|
87
93
|
|
|
94
|
+
export const sleep = (ms: number):Promise<void> => {
|
|
95
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
96
|
+
}
|
|
97
|
+
|
|
88
98
|
export const parseKeypair = (pathToKeypairFile: string) => {
|
|
89
99
|
try {
|
|
90
100
|
const keypairFile = fs.readFileSync(pathToKeypairFile, "utf-8");
|
|
@@ -93,7 +103,7 @@ export const parseKeypair = (pathToKeypairFile: string) => {
|
|
|
93
103
|
showMessage(
|
|
94
104
|
"KeyPair Error",
|
|
95
105
|
"Something went wrong when attempting to retrieve the keypair at " +
|
|
96
|
-
|
|
106
|
+
pathToKeypairFile,
|
|
97
107
|
"error"
|
|
98
108
|
);
|
|
99
109
|
}
|
|
@@ -133,6 +143,15 @@ export const dryRunSuccessMessage = () => {
|
|
|
133
143
|
showMessage("Dry run", "Dry run was successful", "standard")
|
|
134
144
|
}
|
|
135
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
|
+
|
|
136
155
|
export const showNetworkWarningIfApplicable = (rpcUrl: string) => {
|
|
137
156
|
if (isDevnet(rpcUrl)) {
|
|
138
157
|
showMessage("Devnet Mode", "Running on Devnet", "warning")
|
|
@@ -31,7 +31,13 @@ export const publishRemoveCommand = async ({
|
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const connection = new Connection(
|
|
34
|
+
const connection = new Connection(
|
|
35
|
+
url,
|
|
36
|
+
{
|
|
37
|
+
commitment: "confirmed",
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
35
41
|
const {
|
|
36
42
|
publisher: publisherDetails,
|
|
37
43
|
app: appDetails,
|
|
@@ -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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
if (!alphaTest) {
|
|
89
|
+
await writeToPublishDetails(
|
|
90
|
+
{
|
|
91
|
+
lastUpdatedVersionOnStore: { address: releaseAddr }
|
|
92
|
+
});
|
|
93
|
+
}
|
|
85
94
|
};
|
|
@@ -31,7 +31,13 @@ export const publishSupportCommand = async ({
|
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const connection = new Connection(
|
|
34
|
+
const connection = new Connection(
|
|
35
|
+
url,
|
|
36
|
+
{
|
|
37
|
+
commitment: "confirmed",
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
35
41
|
const {
|
|
36
42
|
publisher: publisherDetails,
|
|
37
43
|
app: appDetails,
|
|
@@ -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(
|
|
@@ -45,7 +47,13 @@ export const publishUpdateCommand = async ({
|
|
|
45
47
|
return;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
const connection = new Connection(
|
|
50
|
+
const connection = new Connection(
|
|
51
|
+
url,
|
|
52
|
+
{
|
|
53
|
+
commitment: "confirmed",
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
|
|
49
57
|
const {
|
|
50
58
|
publisher: publisherDetails,
|
|
51
59
|
app: appDetails,
|
|
@@ -54,6 +62,10 @@ export const publishUpdateCommand = async ({
|
|
|
54
62
|
lastUpdatedVersionOnStore: lastUpdatedVersionOnStore
|
|
55
63
|
} = await loadPublishDetailsWithChecks();
|
|
56
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
|
+
|
|
57
69
|
const sign = ((buf: Buffer) =>
|
|
58
70
|
nacl.sign(buf, signer.secretKey)) as SignWithPublisherKeypair;
|
|
59
71
|
|
|
@@ -77,11 +89,14 @@ export const publishUpdateCommand = async ({
|
|
|
77
89
|
compliesWithSolanaDappStorePolicies,
|
|
78
90
|
requestorIsAuthorized,
|
|
79
91
|
criticalUpdate: critical,
|
|
92
|
+
alphaTest,
|
|
80
93
|
},
|
|
81
94
|
dryRun
|
|
82
95
|
);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
96
|
+
if (!alphaTest) {
|
|
97
|
+
await writeToPublishDetails(
|
|
98
|
+
{
|
|
99
|
+
lastUpdatedVersionOnStore: { address: releaseAddr }
|
|
100
|
+
});
|
|
101
|
+
}
|
|
87
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>>
|