diff --git a/packages/cli/src/CliSetup.ts b/packages/cli/src/CliSetup.ts index 5b339f9..761fb88 100644 --- a/packages/cli/src/CliSetup.ts +++ b/packages/cli/src/CliSetup.ts @@ -48,7 +48,7 @@ function resolveBuildToolsPath(buildToolsPath: string | undefined) { function latestReleaseMessage() { showMessage( `Publishing Tools Version ${ Constants.CLI_VERSION }`, - "- priority fee has been updated to 500000 lamports = 0.0005 SOL. To adjust this value use param `-p or --priority-fee-lamports`", + "- priority fee has been updated to 500000 lamports = 0.0005 SOL. To adjust this value use param `-p or --priority-fee-lamports`\n\n- Icon dimensions are now fixed at 512x512", "warning" ); } @@ -104,10 +104,14 @@ export const createPublisherCliCmd = createCliCmd if (signer) { const result: { publisherAddress: string } = await createPublisherCommand({ signer, url, dryRun, storageParams: storageConfig, priorityFeeLamports }); - const displayUrl = `https://solscan.io/token/${result.publisherAddress}${generateNetworkSuffix(url)}`; - const resultText = `Publisher NFT successfully minted:\n${displayUrl}`; + if (dryRun) { + showMessage("Dry run", "dry run was a success") + } else { + const displayUrl = `https://solscan.io/token/${result.publisherAddress}${generateNetworkSuffix(url)}`; + const resultText = `Publisher NFT successfully minted:\n${displayUrl}`; - showMessage("Success", resultText); + showMessage("Success", resultText); + } } }); }); @@ -149,10 +153,13 @@ export const createAppCliCmd = createCliCmd priorityFeeLamports: priorityFeeLamports, }); - const displayUrl = `https://solscan.io/token/${result.appAddress}${generateNetworkSuffix(url)}`; - const resultText = `App NFT successfully minted:\n${displayUrl}`; - - showMessage("Success", resultText); + if (dryRun) { + showMessage("Dry run", "dry run was a success") + } else { + const displayUrl = `https://solscan.io/token/${result.appAddress}${generateNetworkSuffix(url)}`; + const resultText = `App NFT successfully minted:\n${displayUrl}`; + showMessage("Success", resultText); + } } }); }); @@ -203,10 +210,14 @@ export const createReleaseCliCmd = createCliCmd priorityFeeLamports: priorityFeeLamports }); - const displayUrl = `https://solscan.io/token/${result?.releaseAddress}${generateNetworkSuffix(url)}`; - const resultText = `Release NFT successfully minted:\n${displayUrl}`; + if (dryRun) { + showMessage("Dry run", "dry run was a success") + } else { + const displayUrl = `https://solscan.io/token/${result?.releaseAddress}${generateNetworkSuffix(url)}`; + const resultText = `Release NFT successfully minted:\n${displayUrl}`; - showMessage("Success", resultText); + showMessage("Success", resultText); + } } }); } @@ -309,8 +320,11 @@ publishCommand requestorIsAuthorized, }); - const resultText = "Successfully submitted to the Solana Mobile dApp publisher portal"; - showMessage("Success", resultText); + if (dryRun) { + showMessage("Dry run", "dry run was a success") + } else { + showMessage("Success", "Successfully submitted to the Solana Mobile dApp publisher portal"); + } } }); } @@ -381,8 +395,11 @@ publishCommand critical, }); - const resultText = "dApp successfully updated on the publisher portal"; - showMessage("Success", resultText); + if (dryRun) { + showMessage("Dry run", "dry run was a success") + } else { + showMessage("Success", "dApp successfully updated on the publisher portal"); + } } }); } @@ -447,8 +464,11 @@ publishCommand critical, }); - const resultText = "dApp successfully removed from the publisher portal"; - showMessage("Success", resultText); + if (dryRun) { + showMessage("Dry run", "dry run was a success") + } else { + showMessage("Success", "dApp successfully removed from the publisher portal"); + } } }) } @@ -507,8 +527,11 @@ publishCommand requestDetails, }); - const resultText = "Support request sent successfully"; - showMessage("Success", resultText); + if (dryRun) { + showMessage("Dry run", "dry run was a success") + } else { + showMessage("Success", "Support request sent successfully"); + } } }); } diff --git a/packages/cli/src/commands/ValidateCommand.ts b/packages/cli/src/commands/ValidateCommand.ts index 0643ee1..d7f12bb 100644 --- a/packages/cli/src/commands/ValidateCommand.ts +++ b/packages/cli/src/commands/ValidateCommand.ts @@ -7,7 +7,7 @@ import { validateRelease, metaplexFileReplacer, } from "@solana-mobile/dapp-store-publishing-tools"; -import { debug } from "../CliUtils.js"; +import { debug, showMessage } from "../CliUtils.js"; import type { Keypair } from "@solana/web3.js"; import type { MetaplexFile } from "@metaplex-foundation/js"; @@ -39,7 +39,13 @@ export const validateCommand = async ({ validatePublisher(publisherJson); console.info(`Publisher JSON valid!`); } catch (e) { - console.error(e); + const errorMsg = (e as Error | null)?.message ?? ""; + showMessage( + "Publisher JSON invalid", + errorMsg, + "error" + ) + return } const appJson = createAppJson(appDetails, signer.publicKey); @@ -52,7 +58,13 @@ export const validateCommand = async ({ validateApp(appJson); console.info(`App JSON valid!`); } catch (e) { - console.error(e); + const errorMsg = (e as Error | null)?.message ?? ""; + showMessage( + "App JSON invalid", + errorMsg, + "error" + ) + return } const releaseJson = await createReleaseJson( @@ -60,6 +72,16 @@ export const validateCommand = async ({ signer.publicKey ); + + if (appDetails.android_package != releaseDetails.android_details.android_package) { + showMessage( + "App package name and release package name do not match", + "App release specifies " + appDetails.android_package + " while release specifies " + releaseDetails.android_details.android_package, + "error" + ) + return + } + const objStringified = JSON.stringify(releaseJson, metaplexFileReplacer, 2); debug("releaseJson=", objStringified); @@ -67,6 +89,18 @@ export const validateCommand = async ({ validateRelease(JSON.parse(objStringified)); console.info(`Release JSON valid!`); } catch (e) { - console.error(e); + const errorMsg = (e as Error | null)?.message ?? ""; + showMessage( + "Release JSON invalid", + errorMsg, + "error" + ) + return } + + showMessage( + "Json is Valid", + "Input data is valid", + "standard" + ) }; diff --git a/packages/cli/src/commands/create/CreateCliApp.ts b/packages/cli/src/commands/create/CreateCliApp.ts index 55b1dfa..5a5d858 100644 --- a/packages/cli/src/commands/create/CreateCliApp.ts +++ b/packages/cli/src/commands/create/CreateCliApp.ts @@ -9,6 +9,7 @@ import { import { getMetaplexInstance, + showMessage, } from "../../CliUtils.js"; import { loadPublishDetailsWithChecks, writeToPublishDetails } from "../../config/PublishDetails.js"; @@ -42,21 +43,35 @@ const createAppNft = async ( { metaplex, publisher } ); - const blockhash = await connection.getLatestBlockhashAndContext(); - const tx = txBuilder.toTransaction(blockhash.value); - tx.sign(mintAddress, publisher); + const maxTries = 8; + for (let i = 1; i <= maxTries; i++) { + try { + const blockhash = await connection.getLatestBlockhashAndContext(); + const tx = txBuilder.toTransaction(blockhash.value); + tx.sign(mintAddress, publisher); - if (!dryRun) { - const txSig = await sendAndConfirmTransaction(connection, tx, [ - publisher, - mintAddress, - ], { - minContextSlot: blockhash.context.slot - }); - console.info({ txSig, mintAddress: mintAddress.publicKey.toBase58() }); - } + if (!dryRun) { + const txSig = await sendAndConfirmTransaction(connection, tx, [ + publisher, + mintAddress, + ], { + minContextSlot: blockhash.context.slot + }); + console.info({ txSig, mintAddress: mintAddress.publicKey.toBase58() }); + } - return { appAddress: mintAddress.publicKey.toBase58() }; + return { appAddress: mintAddress.publicKey.toBase58() }; + } catch (e) { + const errorMsg = (e as Error | null)?.message ?? ""; + if (i == maxTries) { + showMessage("Transaction Failure", errorMsg, "error"); + process.exit(-1) + } else { + const retryMsg = errorMsg + "\nWill Retry minting publisher." + showMessage("Transaction Failure", retryMsg, "standard"); + } + } + } }; type CreateAppCommandInput = { diff --git a/packages/cli/src/commands/create/CreateCliPublisher.ts b/packages/cli/src/commands/create/CreateCliPublisher.ts index ebf0a1e..46d25f4 100644 --- a/packages/cli/src/commands/create/CreateCliPublisher.ts +++ b/packages/cli/src/commands/create/CreateCliPublisher.ts @@ -8,6 +8,7 @@ import { import { getMetaplexInstance, + showMessage, } from "../../CliUtils.js"; import { loadPublishDetailsWithChecks, writeToPublishDetails } from "../../config/PublishDetails.js"; @@ -37,21 +38,34 @@ const createPublisherNft = async ( { metaplex, publisher } ); - const blockhash = await connection.getLatestBlockhashAndContext(); - const tx = txBuilder.toTransaction(blockhash.value); - tx.sign(mintAddress, publisher); + const maxTries = 8; + for (let i = 1; i <= maxTries; i++) { + try { + const blockhash = await connection.getLatestBlockhashAndContext(); + const tx = txBuilder.toTransaction(blockhash.value); + tx.sign(mintAddress, publisher); - if (!dryRun) { - const txSig = await sendAndConfirmTransaction(connection, tx, [ - publisher, - mintAddress, - ], { - minContextSlot: blockhash.context.slot - }); - console.info({ txSig, mintAddress: mintAddress.publicKey.toBase58() }); + if (!dryRun) { + const txSig = await sendAndConfirmTransaction(connection, tx, [ + publisher, + mintAddress, + ], { + minContextSlot: blockhash.context.slot + }); + console.info({ txSig, mintAddress: mintAddress.publicKey.toBase58() }); + } + return { publisherAddress: mintAddress.publicKey.toBase58() }; + } catch (e) { + const errorMsg = (e as Error | null)?.message ?? ""; + if (i == maxTries) { + showMessage("Transaction Failure", errorMsg, "error"); + process.exit(-1) + } else { + const retryMsg = errorMsg + "\nWill Retry minting publisher." + showMessage("Transaction Failure", retryMsg, "standard"); + } + } } - - return { publisherAddress: mintAddress.publicKey.toBase58() }; }; export const createPublisherCommand = async ({ diff --git a/packages/cli/src/commands/create/CreateCliRelease.ts b/packages/cli/src/commands/create/CreateCliRelease.ts index b16948f..45a0b92 100644 --- a/packages/cli/src/commands/create/CreateCliRelease.ts +++ b/packages/cli/src/commands/create/CreateCliRelease.ts @@ -104,6 +104,11 @@ export const createReleaseCommand = async ({ const { release, app, publisher } = await loadPublishDetailsWithChecks(buildToolsPath); + + if (app.android_package != release.android_details.android_package) { + throw new Error("App package name and release package name do not match.\nApp release specifies " + app.android_package + " while release specifies " + release.android_details.android_package) + } + if (!dryRun) { const { releaseAddress } = await createReleaseNft({ appMintAddress: app.address ?? appMintAddress, diff --git a/packages/cli/src/config/PublishDetails.ts b/packages/cli/src/config/PublishDetails.ts index f8061cd..4567c97 100644 --- a/packages/cli/src/config/PublishDetails.ts +++ b/packages/cli/src/config/PublishDetails.ts @@ -146,7 +146,7 @@ const checkIconCompatibility = async (path: string, typeString: string) => { } if (await checkIconDimensions(path)) { - throw new Error("Icons must have square dimensions and be no greater than 512px by 512px."); + throw new Error("Icons must be 512px by 512px."); } }; @@ -189,7 +189,7 @@ const validateLocalizableResources = (config: PublishDetails) => { const checkIconDimensions = async (iconPath: string): Promise => { const size = await runImgSize(iconPath); - return size?.width != size?.height || (size?.width ?? 0) > 512; + return size?.width != size?.height || (size?.width ?? 0) != 512; }; const getAndroidDetails = async (