@solana-mobile/dapp-store-cli 0.15.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/bin/dapp-store.js +3 -1
  2. package/lib/CliSetup.js +304 -505
  3. package/lib/CliUtils.js +6 -376
  4. package/lib/__tests__/CliSetupTest.js +484 -74
  5. package/lib/cli/__tests__/parseErrors.test.js +25 -0
  6. package/lib/cli/__tests__/signer.test.js +436 -0
  7. package/lib/cli/constants.js +23 -0
  8. package/lib/cli/messages.js +21 -0
  9. package/lib/cli/parseErrors.js +41 -0
  10. package/lib/{commands/publish/PublishCliSupport.js → cli/selfUpdate.js} +72 -38
  11. package/lib/{commands/publish/PublishCliRemove.js → cli/signer.js} +35 -56
  12. package/lib/index.js +96 -5
  13. package/lib/package.json +5 -24
  14. package/lib/portal/__tests__/releaseMetadata.test.js +647 -0
  15. package/lib/portal/__tests__/translators.test.js +76 -0
  16. package/lib/portal/__tests__/workflowClient.test.js +457 -0
  17. package/lib/portal/attestationClient.js +143 -0
  18. package/lib/portal/files.js +64 -0
  19. package/lib/portal/http.js +364 -0
  20. package/lib/portal/records.js +64 -0
  21. package/lib/portal/releaseMetadata.js +748 -0
  22. package/lib/portal/translators.js +460 -0
  23. package/lib/portal/types.js +1 -0
  24. package/lib/portal/workflowClient.js +704 -0
  25. package/lib/publication/PublicationProgressReporter.js +1051 -0
  26. package/lib/publication/__tests__/PublicationProgressReporter.test.js +174 -0
  27. package/lib/{commands/ValidateCommand.js → publication/__tests__/fundingPreflight.test.js} +90 -66
  28. package/lib/publication/__tests__/publicationSummary.test.js +26 -0
  29. package/lib/publication/cliValidation.js +482 -0
  30. package/lib/publication/fundingPreflight.js +246 -0
  31. package/lib/publication/publicationSummary.js +99 -0
  32. package/lib/{commands/utils.js → publication/runPublicationWorkflow.js} +16 -46
  33. package/package.json +5 -24
  34. package/src/CliSetup.ts +370 -505
  35. package/src/CliUtils.ts +9 -233
  36. package/src/__tests__/CliSetupTest.ts +272 -120
  37. package/src/cli/__tests__/parseErrors.test.ts +34 -0
  38. package/src/cli/__tests__/signer.test.ts +359 -0
  39. package/src/cli/constants.ts +3 -0
  40. package/src/cli/messages.ts +27 -0
  41. package/src/cli/parseErrors.ts +62 -0
  42. package/src/cli/selfUpdate.ts +59 -0
  43. package/src/cli/signer.ts +38 -0
  44. package/src/index.ts +31 -4
  45. package/src/portal/__tests__/releaseMetadata.test.ts +508 -0
  46. package/src/portal/__tests__/translators.test.ts +82 -0
  47. package/src/portal/__tests__/workflowClient.test.ts +278 -0
  48. package/src/portal/attestationClient.ts +19 -0
  49. package/src/portal/files.ts +73 -0
  50. package/src/portal/http.ts +170 -0
  51. package/src/portal/records.ts +38 -0
  52. package/src/portal/releaseMetadata.ts +489 -0
  53. package/src/portal/translators.ts +750 -0
  54. package/src/portal/types.ts +27 -0
  55. package/src/portal/workflowClient.ts +575 -0
  56. package/src/publication/PublicationProgressReporter.ts +1026 -0
  57. package/src/publication/__tests__/PublicationProgressReporter.test.ts +210 -0
  58. package/src/publication/__tests__/fundingPreflight.test.ts +78 -0
  59. package/src/publication/__tests__/publicationSummary.test.ts +30 -0
  60. package/src/publication/cliValidation.ts +264 -0
  61. package/src/publication/fundingPreflight.ts +123 -0
  62. package/src/publication/publicationSummary.ts +26 -0
  63. package/src/publication/runPublicationWorkflow.ts +46 -0
  64. package/lib/commands/create/CreateCliApp.js +0 -223
  65. package/lib/commands/create/CreateCliRelease.js +0 -290
  66. package/lib/commands/create/index.js +0 -40
  67. package/lib/commands/index.js +0 -3
  68. package/lib/commands/publish/PublishCliSubmit.js +0 -208
  69. package/lib/commands/publish/PublishCliUpdate.js +0 -211
  70. package/lib/commands/publish/index.js +0 -22
  71. package/lib/commands/scaffolding/ScaffoldInit.js +0 -15
  72. package/lib/commands/scaffolding/index.js +0 -1
  73. package/lib/config/EnvVariables.js +0 -59
  74. package/lib/config/PublishDetails.js +0 -915
  75. package/lib/config/S3StorageManager.js +0 -93
  76. package/lib/config/index.js +0 -2
  77. package/lib/generated/config_obj.json +0 -1
  78. package/lib/generated/config_schema.json +0 -1
  79. package/lib/prebuild_schema/publishing_source.yaml +0 -64
  80. package/lib/prebuild_schema/schemagen.js +0 -25
  81. package/lib/upload/CachedStorageDriver.js +0 -293
  82. package/lib/upload/TurboStorageDriver.js +0 -718
  83. package/lib/upload/index.js +0 -2
  84. package/src/commands/ValidateCommand.ts +0 -82
  85. package/src/commands/create/CreateCliApp.ts +0 -93
  86. package/src/commands/create/CreateCliRelease.ts +0 -149
  87. package/src/commands/create/index.ts +0 -47
  88. package/src/commands/index.ts +0 -3
  89. package/src/commands/publish/PublishCliRemove.ts +0 -66
  90. package/src/commands/publish/PublishCliSubmit.ts +0 -93
  91. package/src/commands/publish/PublishCliSupport.ts +0 -66
  92. package/src/commands/publish/PublishCliUpdate.ts +0 -101
  93. package/src/commands/publish/index.ts +0 -29
  94. package/src/commands/scaffolding/ScaffoldInit.ts +0 -20
  95. package/src/commands/scaffolding/index.ts +0 -1
  96. package/src/commands/utils.ts +0 -33
  97. package/src/config/EnvVariables.ts +0 -39
  98. package/src/config/PublishDetails.ts +0 -456
  99. package/src/config/S3StorageManager.ts +0 -47
  100. package/src/config/index.ts +0 -2
  101. package/src/prebuild_schema/publishing_source.yaml +0 -64
  102. package/src/prebuild_schema/schemagen.js +0 -31
  103. package/src/upload/CachedStorageDriver.ts +0 -99
  104. package/src/upload/TurboStorageDriver.ts +0 -277
  105. package/src/upload/index.ts +0 -2
@@ -1,2 +0,0 @@
1
- export * from "./CachedStorageDriver.js";
2
- export * from "./TurboStorageDriver.js";
@@ -1,82 +0,0 @@
1
- import {
2
- createAppJson,
3
- createReleaseJson,
4
- validateApp,
5
- validateRelease,
6
- metaplexFileReplacer,
7
- } from "@solana-mobile/dapp-store-publishing-tools";
8
- import { debug, showMessage } from "../CliUtils.js";
9
-
10
- import type { Keypair } from "@solana/web3.js";
11
- import type { MetaplexFile } from "@metaplex-foundation/js";
12
- import { loadPublishDetailsWithChecks } from "../config/PublishDetails.js";
13
-
14
- export const validateCommand = async ({
15
- signer,
16
- buildToolsPath,
17
- }: {
18
- signer: Keypair;
19
- buildToolsPath?: string;
20
- }) => {
21
- const {
22
- publisher: publisherDetails,
23
- app: appDetails,
24
- release: releaseDetails,
25
- } = await loadPublishDetailsWithChecks(buildToolsPath);
26
-
27
- debug({ publisherDetails, appDetails, releaseDetails });
28
-
29
- const appJson = createAppJson(appDetails, signer.publicKey);
30
- if (typeof appJson.image !== "string") {
31
- appJson.image = (appJson.image as MetaplexFile)?.fileName;
32
- }
33
- debug("appJson=", JSON.stringify({ appJson }, metaplexFileReplacer, 2));
34
-
35
- try {
36
- validateApp(appJson);
37
- } catch (e) {
38
- const errorMsg = (e as Error | null)?.message ?? "";
39
- showMessage(
40
- "App JSON invalid",
41
- errorMsg,
42
- "error"
43
- )
44
- return
45
- }
46
-
47
- const releaseJson = await createReleaseJson(
48
- { releaseDetails, appDetails, publisherDetails },
49
- signer.publicKey
50
- );
51
-
52
-
53
- if (appDetails.android_package != releaseDetails.android_details.android_package) {
54
- showMessage(
55
- "App package name and release package name do not match",
56
- "App release specifies " + appDetails.android_package + " while release specifies " + releaseDetails.android_details.android_package,
57
- "error"
58
- )
59
- return
60
- }
61
-
62
- const objStringified = JSON.stringify(releaseJson, metaplexFileReplacer, 2);
63
- debug("releaseJson=", objStringified);
64
-
65
- try {
66
- validateRelease(JSON.parse(objStringified));
67
- } catch (e) {
68
- const errorMsg = (e as Error | null)?.message ?? "";
69
- showMessage(
70
- "Release JSON invalid",
71
- errorMsg,
72
- "error"
73
- )
74
- return
75
- }
76
-
77
- showMessage(
78
- "Json is Valid",
79
- "Input data is valid",
80
- "standard"
81
- )
82
- };
@@ -1,93 +0,0 @@
1
- import type { App } from "@solana-mobile/dapp-store-publishing-tools";
2
- import { createApp } from "@solana-mobile/dapp-store-publishing-tools";
3
- import {
4
- Connection,
5
- Keypair,
6
- } from "@solana/web3.js";
7
-
8
- import {
9
- Constants,
10
- getMetaplexInstance,
11
- } from "../../CliUtils.js";
12
- import { loadPublishDetailsWithChecks, writeToPublishDetails } from "../../config/PublishDetails.js";
13
- import { sendAndConfirmTransaction } from "../utils.js";
14
-
15
- const createAppNft = async (
16
- {
17
- appDetails,
18
- connection,
19
- publisher,
20
- storageParams,
21
- priorityFeeLamports,
22
- }: {
23
- appDetails: App;
24
- connection: Connection;
25
- publisher: Keypair;
26
- storageParams: string;
27
- priorityFeeLamports: number;
28
- },
29
- ) => {
30
- console.info(`Creating App NFT`);
31
-
32
- const mintAddress = Keypair.generate();
33
- const metaplex = getMetaplexInstance(connection, publisher, storageParams);
34
- const txBuilder = await createApp(
35
- {
36
- mintAddress,
37
- appDetails,
38
- priorityFeeLamports
39
- },
40
- { metaplex, publisher }
41
- );
42
-
43
- console.info(`App NFT data upload complete\nSigning transaction now`);
44
-
45
- const { response } = await sendAndConfirmTransaction(metaplex, txBuilder);
46
-
47
- return {
48
- appAddress: mintAddress.publicKey.toBase58(),
49
- transactionSignature: response.signature,
50
- };
51
- };
52
-
53
- type CreateAppCommandInput = {
54
- signer: Keypair;
55
- url: string;
56
- dryRun?: boolean;
57
- storageParams: string;
58
- priorityFeeLamports: number;
59
- };
60
-
61
- export const createAppCommand = async ({
62
- signer,
63
- url,
64
- dryRun,
65
- storageParams,
66
- priorityFeeLamports = Constants.DEFAULT_PRIORITY_FEE,
67
- }: CreateAppCommandInput) => {
68
- const connection = new Connection(
69
- url,
70
- {
71
- commitment: "confirmed",
72
- }
73
- );
74
-
75
- const { app: appDetails } =
76
- await loadPublishDetailsWithChecks();
77
-
78
- if (!dryRun) {
79
- const { appAddress, transactionSignature } = await createAppNft(
80
- {
81
- connection,
82
- publisher: signer,
83
- appDetails,
84
- storageParams,
85
- priorityFeeLamports
86
- },
87
- );
88
-
89
- await writeToPublishDetails({ app: { address: appAddress } });
90
-
91
- return { appAddress, transactionSignature };
92
- }
93
- };
@@ -1,149 +0,0 @@
1
- import type {
2
- App,
3
- Publisher,
4
- Release,
5
- } from "@solana-mobile/dapp-store-publishing-tools";
6
- import { createRelease } from "@solana-mobile/dapp-store-publishing-tools";
7
- import {
8
- Connection,
9
- Keypair,
10
- PublicKey,
11
- } from "@solana/web3.js";
12
- import fs from "fs";
13
- import { createHash } from "crypto";
14
- import {
15
- Constants,
16
- getMetaplexInstance,
17
- } from "../../CliUtils.js";
18
- import { PublishDetails, loadPublishDetailsWithChecks, writeToPublishDetails } from "../../config/PublishDetails.js";
19
- import { sendAndConfirmTransaction } from "../utils.js";
20
-
21
- type CreateReleaseCommandInput = {
22
- appMintAddress: string;
23
- buildToolsPath: string;
24
- signer: Keypair;
25
- url: string;
26
- dryRun?: boolean;
27
- storageParams: string;
28
- priorityFeeLamports: number;
29
- };
30
-
31
- const createReleaseNft = async ({
32
- appMintAddress,
33
- releaseDetails,
34
- appDetails,
35
- publisherDetails,
36
- connection,
37
- publisher,
38
- storageParams,
39
- priorityFeeLamports,
40
- }: {
41
- appMintAddress: string;
42
- releaseDetails: Release;
43
- appDetails: App;
44
- publisherDetails: Publisher;
45
- connection: Connection;
46
- publisher: Keypair;
47
- storageParams: string;
48
- priorityFeeLamports: number;
49
- }) => {
50
- console.info(`Creating Release NFT`);
51
-
52
- const releaseMintAddress = Keypair.generate();
53
-
54
- const metaplex = getMetaplexInstance(connection, publisher, storageParams);
55
-
56
- const { txBuilder } = await createRelease(
57
- {
58
- appMintAddress: new PublicKey(appMintAddress),
59
- releaseMintAddress,
60
- releaseDetails,
61
- appDetails,
62
- publisherDetails,
63
- priorityFeeLamports
64
- },
65
- { metaplex, publisher }
66
- );
67
-
68
- console.info(`Release NFT data upload complete\nSigning transaction now`);
69
-
70
- const { response } = await sendAndConfirmTransaction(metaplex, txBuilder);
71
-
72
- return {
73
- releaseAddress: releaseMintAddress.publicKey.toBase58(),
74
- transactionSignature: response.signature,
75
- };
76
- };
77
-
78
- export const createReleaseCommand = async ({
79
- appMintAddress,
80
- buildToolsPath,
81
- signer,
82
- url,
83
- dryRun = false,
84
- storageParams,
85
- priorityFeeLamports = Constants.DEFAULT_PRIORITY_FEE,
86
- }: CreateReleaseCommandInput) => {
87
- const connection = new Connection(
88
- url,
89
- {
90
- commitment: "confirmed",
91
- }
92
- );
93
-
94
- const config = await loadPublishDetailsWithChecks(buildToolsPath);
95
-
96
- const apkEntry = config.release.files.find(
97
- (asset: PublishDetails["release"]["files"][0]) => asset.purpose === "install"
98
- )!;
99
- const mediaBuffer = await fs.promises.readFile(apkEntry.uri);
100
- const hash = createHash("sha256").update(mediaBuffer).digest("base64");
101
-
102
- if (config.lastSubmittedVersionOnChain != null && hash === config.lastSubmittedVersionOnChain.apk_hash) {
103
- throw new Error(`The last created release used the same apk file.`);
104
- }
105
-
106
- if (config.lastSubmittedVersionOnChain != null && config.release.android_details.version_code <= config.lastSubmittedVersionOnChain.version_code) {
107
- throw new Error(`Each release NFT should have higher version code than previous minted release NFT.\nLast released version code is ${config.lastSubmittedVersionOnChain.version_code}.\nCurrent version code from apk file is ${config.release.android_details.version_code}`);
108
- }
109
-
110
- if (config.app.android_package != config.release.android_details.android_package) {
111
- throw new Error("App package name and release package name do not match.\nApp release specifies " + config.app.android_package + " while release specifies " + config.release.android_details.android_package)
112
- }
113
-
114
- if (!dryRun) {
115
- const { releaseAddress, transactionSignature } = await createReleaseNft({
116
- appMintAddress: config.app.address ?? appMintAddress,
117
- connection,
118
- publisher: signer,
119
- releaseDetails: {
120
- ...config.release,
121
- },
122
- appDetails: config.app,
123
- publisherDetails: config.publisher,
124
- storageParams: storageParams,
125
- priorityFeeLamports: priorityFeeLamports,
126
- });
127
-
128
- await writeToPublishDetails(
129
- {
130
- release: {
131
- address: releaseAddress,
132
- android_details: {
133
- cert_fingerprint: config.release.android_details.cert_fingerprint,
134
- min_sdk: config.release.android_details.min_sdk,
135
- version: config.release.android_details.version,
136
- version_code: config.release.android_details.version_code,
137
- locales: config.release.android_details.locales
138
- }
139
- },
140
- lastSubmittedVersionOnChain: {
141
- address: releaseAddress,
142
- version_code: config.release.android_details.version_code,
143
- apk_hash: hash,
144
- }
145
- });
146
-
147
- return { releaseAddress, transactionSignature };
148
- }
149
- };
@@ -1,47 +0,0 @@
1
- export * from "./CreateCliApp.js";
2
- export * from "./CreateCliRelease.js";
3
-
4
- /*
5
- * Module responsible for creating publishers, apps, and releases (in that order)
6
- * Anything that is out-of-order will be prompted back into order
7
- * And steps that happen more than once will do their best to remember as much information as possible.
8
- * We will ask questions and do our best to answer anything that's already been configured, and prompt for anything that's not
9
- */
10
-
11
- // We'll never ask for private keys or seed phrases
12
- // You can use a burner signer to publish; all NFTs require verification from the publisher signer
13
- // You can use a multisig or Ledger for that purpose
14
-
15
- // Publisher
16
- // Public key attached to a publisher must also verify applications and releases
17
- // Most information here can be be edited after the fact
18
- // Only required fields are name, address, publisher website, and contact email
19
- // Optional fields are: description, image_url (need dimensions!)
20
-
21
- // App
22
- // Publisher creator key required
23
- // Most information can be edited after the fact
24
- // Required: name, description, `android_package`
25
- // Optional: Any additional creator keys
26
- // TODO(jon): Probably okay to capture more information here like:
27
- // - `license_url`
28
- // - `copyright_url`
29
- // - `privacy_policy_url`
30
- // Release
31
- // Publisher creator key required
32
- // Immutable; information cannot be edited after publishing.
33
- // Change based on the review process must result in a new release
34
- // Required:
35
- // - version (automatically prompt with semver + 1)
36
- // - release notes (description)
37
- // - publisher creator key
38
- // - path to the APK
39
- // Optional:
40
- // - Media related to the release
41
- // - New permissions (prompted)
42
- // - New languages (prompted)
43
- // Handles uploads of all files, sha'ing them
44
- // Handles i18n (later)
45
-
46
- // We'll attempt to read as much as possible from a provided `.yml` file
47
- // If there are provided folders that are well-structured, we'll opt to use that too.
@@ -1,3 +0,0 @@
1
- export * from "./create/index.js";
2
- export * from "./publish/index.js";
3
- export * from "./ValidateCommand.js";
@@ -1,66 +0,0 @@
1
- import { Connection, Keypair } from "@solana/web3.js";
2
- import type { SignWithPublisherKeypair } from "@solana-mobile/dapp-store-publishing-tools";
3
- import { publishRemove } from "@solana-mobile/dapp-store-publishing-tools";
4
- import { checkMintedStatus } from "../../CliUtils.js";
5
- import nacl from "tweetnacl";
6
- import { loadPublishDetailsWithChecks } from "../../config/PublishDetails.js";
7
-
8
- type PublishRemoveCommandInput = {
9
- appMintAddress: string;
10
- releaseMintAddress: string;
11
- signer: Keypair;
12
- url: string;
13
- dryRun: boolean;
14
- requestorIsAuthorized: boolean;
15
- critical: boolean;
16
- };
17
-
18
- export const publishRemoveCommand = async ({
19
- appMintAddress,
20
- releaseMintAddress,
21
- signer,
22
- url,
23
- dryRun = false,
24
- requestorIsAuthorized = false,
25
- critical = false,
26
- }: PublishRemoveCommandInput) => {
27
- if (!requestorIsAuthorized) {
28
- console.error(
29
- "ERROR: Cannot submit a request for which the requestor does not attest they are authorized to do so"
30
- );
31
- return;
32
- }
33
-
34
- const connection = new Connection(
35
- url,
36
- {
37
- commitment: "confirmed",
38
- }
39
- );
40
-
41
- const {
42
- publisher: publisherDetails,
43
- app: appDetails,
44
- release: releaseDetails,
45
- } = await loadPublishDetailsWithChecks();
46
-
47
- const sign = ((buf: Buffer) =>
48
- nacl.sign(buf, signer.secretKey)) as SignWithPublisherKeypair;
49
-
50
- const appAddr = appMintAddress ?? appDetails.address;
51
- const releaseAddr = releaseMintAddress ?? releaseDetails.address;
52
-
53
- await checkMintedStatus(connection, appAddr, releaseAddr);
54
-
55
- await publishRemove(
56
- { connection, sign },
57
- {
58
- appMintAddress: appMintAddress ?? appDetails.address,
59
- releaseMintAddress: releaseMintAddress ?? releaseDetails.address,
60
- publisherDetails,
61
- requestorIsAuthorized,
62
- criticalUpdate: critical,
63
- },
64
- dryRun
65
- );
66
- };
@@ -1,93 +0,0 @@
1
- import { AccountInfo, Connection, Keypair, PublicKey } from "@solana/web3.js";
2
- import type { SignWithPublisherKeypair } from "@solana-mobile/dapp-store-publishing-tools";
3
- import { publishSubmit } from "@solana-mobile/dapp-store-publishing-tools";
4
- import nacl from "tweetnacl";
5
- import { checkMintedStatus, showMessage } from "../../CliUtils.js";
6
- import { Buffer } from "buffer";
7
- import { loadPublishDetailsWithChecks, writeToPublishDetails } from "../../config/PublishDetails.js";
8
-
9
- type PublishSubmitCommandInput = {
10
- appMintAddress: string;
11
- releaseMintAddress: string;
12
- signer: Keypair;
13
- url: string;
14
- dryRun: boolean;
15
- compliesWithSolanaDappStorePolicies: boolean;
16
- requestorIsAuthorized: boolean;
17
- alphaTest?: boolean;
18
- };
19
-
20
- export const publishSubmitCommand = async ({
21
- appMintAddress,
22
- releaseMintAddress,
23
- signer,
24
- url,
25
- dryRun = false,
26
- compliesWithSolanaDappStorePolicies = false,
27
- requestorIsAuthorized = false,
28
- alphaTest
29
- }: PublishSubmitCommandInput) => {
30
- showMessage(
31
- `Publishing Estimates`,
32
- "New app submissions take around 3-4 business days for review.",
33
- "warning"
34
- );
35
-
36
- if (!compliesWithSolanaDappStorePolicies) {
37
- console.error(
38
- "ERROR: Cannot submit a request for which the requestor does not attest that it complies with Solana dApp Store policies"
39
- );
40
- return;
41
- } else if (!requestorIsAuthorized) {
42
- console.error(
43
- "ERROR: Cannot submit a request for which the requestor does not attest they are authorized to do so"
44
- );
45
- return;
46
- }
47
-
48
- const connection = new Connection(url);
49
- const {
50
- publisher: publisherDetails,
51
- app: appDetails,
52
- release: releaseDetails,
53
- solana_mobile_dapp_publisher_portal: solanaMobileDappPublisherPortalDetails,
54
- lastUpdatedVersionOnStore: lastUpdatedVersionOnStore,
55
- } = await loadPublishDetailsWithChecks();
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
-
61
- const sign = ((buf: Buffer) =>
62
- nacl.sign(buf, signer.secretKey)) as SignWithPublisherKeypair;
63
-
64
- const appAddr = appMintAddress ?? appDetails.address;
65
- const releaseAddr = releaseMintAddress ?? releaseDetails.address;
66
-
67
- if (lastUpdatedVersionOnStore != null && releaseAddr === lastUpdatedVersionOnStore.address) {
68
- throw new Error(`You've already submitted this version for review.`);
69
- }
70
-
71
- await checkMintedStatus(connection, appAddr, releaseAddr);
72
-
73
- await publishSubmit(
74
- { connection, sign },
75
- {
76
- appMintAddress: appAddr,
77
- releaseMintAddress: releaseAddr,
78
- publisherDetails,
79
- solanaMobileDappPublisherPortalDetails,
80
- compliesWithSolanaDappStorePolicies,
81
- requestorIsAuthorized,
82
- alphaTest,
83
- },
84
- dryRun
85
- );
86
-
87
- if (!alphaTest) {
88
- await writeToPublishDetails(
89
- {
90
- lastUpdatedVersionOnStore: { address: releaseAddr }
91
- });
92
- }
93
- };
@@ -1,66 +0,0 @@
1
- import { Connection, Keypair } from "@solana/web3.js";
2
- import type { SignWithPublisherKeypair } from "@solana-mobile/dapp-store-publishing-tools";
3
- import { publishSupport } from "@solana-mobile/dapp-store-publishing-tools";
4
- import { checkMintedStatus } from "../../CliUtils.js";
5
- import nacl from "tweetnacl";
6
- import { loadPublishDetailsWithChecks } from "../../config/PublishDetails.js";
7
-
8
- type PublishSupportCommandInput = {
9
- appMintAddress: string;
10
- releaseMintAddress: string;
11
- signer: Keypair;
12
- url: string;
13
- dryRun: boolean;
14
- requestorIsAuthorized: boolean;
15
- requestDetails: string;
16
- };
17
-
18
- export const publishSupportCommand = async ({
19
- appMintAddress,
20
- releaseMintAddress,
21
- signer,
22
- url,
23
- dryRun = false,
24
- requestorIsAuthorized = false,
25
- requestDetails,
26
- }: PublishSupportCommandInput) => {
27
- if (!requestorIsAuthorized) {
28
- console.error(
29
- "ERROR: Cannot submit a request for which the requestor does not attest they are authorized to do so"
30
- );
31
- return;
32
- }
33
-
34
- const connection = new Connection(
35
- url,
36
- {
37
- commitment: "confirmed",
38
- }
39
- );
40
-
41
- const {
42
- publisher: publisherDetails,
43
- app: appDetails,
44
- release: releaseDetails,
45
- } = await loadPublishDetailsWithChecks();
46
-
47
- const sign = ((buf: Buffer) =>
48
- nacl.sign(buf, signer.secretKey)) as SignWithPublisherKeypair;
49
-
50
- const appAddr = appMintAddress ?? appDetails.address;
51
- const releaseAddr = releaseMintAddress ?? releaseDetails.address;
52
-
53
- await checkMintedStatus(connection, appAddr, releaseAddr);
54
-
55
- await publishSupport(
56
- { connection, sign },
57
- {
58
- appMintAddress: appMintAddress ?? appDetails.address,
59
- releaseMintAddress: releaseMintAddress ?? releaseDetails.address,
60
- publisherDetails,
61
- requestorIsAuthorized,
62
- requestDetails,
63
- },
64
- dryRun
65
- );
66
- };