@solana-mobile/dapp-store-cli 0.7.2 → 0.8.0
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 +74 -46
- package/lib/CliUtils.js +5 -1
- package/lib/__tests__/CliSetupTest.js +3 -3
- package/lib/commands/ValidateCommand.js +27 -5
- package/lib/commands/create/CreateCliApp.js +68 -32
- package/lib/commands/create/CreateCliPublisher.js +68 -28
- package/lib/commands/create/CreateCliRelease.js +21 -16
- package/lib/config/PublishDetails.js +9 -3
- package/lib/package.json +2 -2
- package/lib/upload/CachedStorageDriver.js +1 -10
- package/package.json +2 -2
- package/src/CliSetup.ts +62 -32
- package/src/CliUtils.ts +6 -1
- package/src/__tests__/CliSetupTest.ts +15 -12
- package/src/commands/ValidateCommand.ts +38 -4
- package/src/commands/create/CreateCliApp.ts +46 -27
- package/src/commands/create/CreateCliPublisher.ts +45 -30
- package/src/commands/create/CreateCliRelease.ts +20 -9
- package/src/config/PublishDetails.ts +18 -6
- package/src/upload/CachedStorageDriver.ts +1 -10
|
@@ -175,11 +175,12 @@ Commands:
|
|
|
175
175
|
Create a publisher
|
|
176
176
|
|
|
177
177
|
Options:
|
|
178
|
-
-k, --keypair <path-to-keypair-file>
|
|
179
|
-
-u, --url <url>
|
|
180
|
-
-d, --dry-run
|
|
181
|
-
-s, --storage-config <storage-config>
|
|
182
|
-
-
|
|
178
|
+
-k, --keypair <path-to-keypair-file> Path to keypair file
|
|
179
|
+
-u, --url <url> RPC URL (default: "https://api.devnet.solana.com")
|
|
180
|
+
-d, --dry-run Flag for dry run. Doesn't mint an NFT
|
|
181
|
+
-s, --storage-config <storage-config> Provide alternative storage configuration details
|
|
182
|
+
-p, --priority-fee-lamports <priority-fee-lamports> Priority Fee lamports
|
|
183
|
+
-h, --help display help for command
|
|
183
184
|
`;
|
|
184
185
|
|
|
185
186
|
const createAppHelp = `Usage: dapp-store create app [options]
|
|
@@ -192,6 +193,7 @@ Options:
|
|
|
192
193
|
-u, --url <url> RPC URL (default: "https://api.devnet.solana.com")
|
|
193
194
|
-d, --dry-run Flag for dry run. Doesn't mint an NFT
|
|
194
195
|
-s, --storage-config <storage-config> Provide alternative storage configuration details
|
|
196
|
+
-p, --priority-fee-lamports <priority-fee-lamports> Priority Fee lamports
|
|
195
197
|
-h, --help display help for command
|
|
196
198
|
`;
|
|
197
199
|
|
|
@@ -200,13 +202,14 @@ Options:
|
|
|
200
202
|
Create a release
|
|
201
203
|
|
|
202
204
|
Options:
|
|
203
|
-
-k, --keypair <path-to-keypair-file>
|
|
204
|
-
-a, --app-mint-address <app-mint-address>
|
|
205
|
-
-u, --url <url>
|
|
206
|
-
-d, --dry-run
|
|
207
|
-
-b, --build-tools-path <build-tools-path>
|
|
208
|
-
-s, --storage-config <storage-config>
|
|
209
|
-
-
|
|
205
|
+
-k, --keypair <path-to-keypair-file> Path to keypair file
|
|
206
|
+
-a, --app-mint-address <app-mint-address> The mint address of the app NFT
|
|
207
|
+
-u, --url <url> RPC URL (default: "https://api.devnet.solana.com")
|
|
208
|
+
-d, --dry-run Flag for dry run. Doesn't mint an NFT
|
|
209
|
+
-b, --build-tools-path <build-tools-path> Path to Android build tools which contains AAPT2
|
|
210
|
+
-s, --storage-config <storage-config> Provide alternative storage configuration details
|
|
211
|
+
-p, --priority-fee-lamports <priority-fee-lamports> Priority Fee lamports
|
|
212
|
+
-h, --help display help for command
|
|
210
213
|
`;
|
|
211
214
|
|
|
212
215
|
});
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
validateRelease,
|
|
8
8
|
metaplexFileReplacer,
|
|
9
9
|
} from "@solana-mobile/dapp-store-publishing-tools";
|
|
10
|
-
import { debug } from "../CliUtils.js";
|
|
10
|
+
import { debug, showMessage } from "../CliUtils.js";
|
|
11
11
|
|
|
12
12
|
import type { Keypair } from "@solana/web3.js";
|
|
13
13
|
import type { MetaplexFile } from "@metaplex-foundation/js";
|
|
@@ -39,7 +39,13 @@ export const validateCommand = async ({
|
|
|
39
39
|
validatePublisher(publisherJson);
|
|
40
40
|
console.info(`Publisher JSON valid!`);
|
|
41
41
|
} catch (e) {
|
|
42
|
-
|
|
42
|
+
const errorMsg = (e as Error | null)?.message ?? "";
|
|
43
|
+
showMessage(
|
|
44
|
+
"Publisher JSON invalid",
|
|
45
|
+
errorMsg,
|
|
46
|
+
"error"
|
|
47
|
+
)
|
|
48
|
+
return
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
const appJson = createAppJson(appDetails, signer.publicKey);
|
|
@@ -52,7 +58,13 @@ export const validateCommand = async ({
|
|
|
52
58
|
validateApp(appJson);
|
|
53
59
|
console.info(`App JSON valid!`);
|
|
54
60
|
} catch (e) {
|
|
55
|
-
|
|
61
|
+
const errorMsg = (e as Error | null)?.message ?? "";
|
|
62
|
+
showMessage(
|
|
63
|
+
"App JSON invalid",
|
|
64
|
+
errorMsg,
|
|
65
|
+
"error"
|
|
66
|
+
)
|
|
67
|
+
return
|
|
56
68
|
}
|
|
57
69
|
|
|
58
70
|
const releaseJson = await createReleaseJson(
|
|
@@ -60,6 +72,16 @@ export const validateCommand = async ({
|
|
|
60
72
|
signer.publicKey
|
|
61
73
|
);
|
|
62
74
|
|
|
75
|
+
|
|
76
|
+
if (appDetails.android_package != releaseDetails.android_details.android_package) {
|
|
77
|
+
showMessage(
|
|
78
|
+
"App package name and release package name do not match",
|
|
79
|
+
"App release specifies " + appDetails.android_package + " while release specifies " + releaseDetails.android_details.android_package,
|
|
80
|
+
"error"
|
|
81
|
+
)
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
63
85
|
const objStringified = JSON.stringify(releaseJson, metaplexFileReplacer, 2);
|
|
64
86
|
debug("releaseJson=", objStringified);
|
|
65
87
|
|
|
@@ -67,6 +89,18 @@ export const validateCommand = async ({
|
|
|
67
89
|
validateRelease(JSON.parse(objStringified));
|
|
68
90
|
console.info(`Release JSON valid!`);
|
|
69
91
|
} catch (e) {
|
|
70
|
-
|
|
92
|
+
const errorMsg = (e as Error | null)?.message ?? "";
|
|
93
|
+
showMessage(
|
|
94
|
+
"Release JSON invalid",
|
|
95
|
+
errorMsg,
|
|
96
|
+
"error"
|
|
97
|
+
)
|
|
98
|
+
return
|
|
71
99
|
}
|
|
100
|
+
|
|
101
|
+
showMessage(
|
|
102
|
+
"Json is Valid",
|
|
103
|
+
"Input data is valid",
|
|
104
|
+
"standard"
|
|
105
|
+
)
|
|
72
106
|
};
|
|
@@ -8,7 +8,9 @@ import {
|
|
|
8
8
|
} from "@solana/web3.js";
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
|
+
Constants,
|
|
11
12
|
getMetaplexInstance,
|
|
13
|
+
showMessage,
|
|
12
14
|
} from "../../CliUtils.js";
|
|
13
15
|
import { loadPublishDetailsWithChecks, writeToPublishDetails } from "../../config/PublishDetails.js";
|
|
14
16
|
|
|
@@ -19,15 +21,18 @@ const createAppNft = async (
|
|
|
19
21
|
publisherMintAddress,
|
|
20
22
|
publisher,
|
|
21
23
|
storageParams,
|
|
24
|
+
priorityFeeLamports,
|
|
22
25
|
}: {
|
|
23
26
|
appDetails: App;
|
|
24
27
|
connection: Connection;
|
|
25
28
|
publisherMintAddress: string;
|
|
26
29
|
publisher: Keypair;
|
|
27
30
|
storageParams: string;
|
|
31
|
+
priorityFeeLamports: number;
|
|
28
32
|
},
|
|
29
|
-
{ dryRun }: { dryRun?: boolean }
|
|
30
33
|
) => {
|
|
34
|
+
console.info(`Creating App NFT`);
|
|
35
|
+
|
|
31
36
|
const mintAddress = Keypair.generate();
|
|
32
37
|
const metaplex = getMetaplexInstance(connection, publisher, storageParams);
|
|
33
38
|
const txBuilder = await createApp(
|
|
@@ -35,25 +40,37 @@ const createAppNft = async (
|
|
|
35
40
|
publisherMintAddress: new PublicKey(publisherMintAddress),
|
|
36
41
|
mintAddress,
|
|
37
42
|
appDetails,
|
|
43
|
+
priorityFeeLamports
|
|
38
44
|
},
|
|
39
45
|
{ metaplex, publisher }
|
|
40
46
|
);
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
48
|
+
console.info(`App NFT data upload complete\nSigning transaction now`);
|
|
49
|
+
const maxTries = 8;
|
|
50
|
+
for (let i = 1; i <= maxTries; i++) {
|
|
51
|
+
try {
|
|
52
|
+
const blockhash = await connection.getLatestBlockhashAndContext();
|
|
53
|
+
const tx = txBuilder.toTransaction(blockhash.value);
|
|
54
|
+
tx.sign(mintAddress, publisher);
|
|
45
55
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
const txSig = await sendAndConfirmTransaction(connection, tx, [
|
|
57
|
+
publisher,
|
|
58
|
+
mintAddress,
|
|
59
|
+
], {
|
|
60
|
+
minContextSlot: blockhash.context.slot
|
|
61
|
+
});
|
|
62
|
+
return { appAddress: mintAddress.publicKey.toBase58(), transactionSignature: txSig };
|
|
63
|
+
} catch (e) {
|
|
64
|
+
const errorMsg = (e as Error | null)?.message ?? "";
|
|
65
|
+
if (i == maxTries) {
|
|
66
|
+
showMessage("Transaction Failure", errorMsg, "error");
|
|
67
|
+
process.exit(-1)
|
|
68
|
+
} else {
|
|
69
|
+
const retryMsg = errorMsg + "\nWill Retry minting app NFT."
|
|
70
|
+
showMessage("Transaction Failure", retryMsg, "standard");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
54
73
|
}
|
|
55
|
-
|
|
56
|
-
return { appAddress: mintAddress.publicKey.toBase58() };
|
|
57
74
|
};
|
|
58
75
|
|
|
59
76
|
type CreateAppCommandInput = {
|
|
@@ -62,6 +79,7 @@ type CreateAppCommandInput = {
|
|
|
62
79
|
url: string;
|
|
63
80
|
dryRun?: boolean;
|
|
64
81
|
storageParams: string;
|
|
82
|
+
priorityFeeLamports: number;
|
|
65
83
|
};
|
|
66
84
|
|
|
67
85
|
export const createAppCommand = async ({
|
|
@@ -70,26 +88,27 @@ export const createAppCommand = async ({
|
|
|
70
88
|
dryRun,
|
|
71
89
|
publisherMintAddress,
|
|
72
90
|
storageParams,
|
|
91
|
+
priorityFeeLamports = Constants.DEFAULT_PRIORITY_FEE,
|
|
73
92
|
}: CreateAppCommandInput) => {
|
|
74
93
|
const connection = new Connection(url);
|
|
75
94
|
|
|
76
95
|
const { app: appDetails, publisher: publisherDetails } =
|
|
77
96
|
await loadPublishDetailsWithChecks();
|
|
78
97
|
|
|
79
|
-
const { appAddress } = await createAppNft(
|
|
80
|
-
{
|
|
81
|
-
connection,
|
|
82
|
-
publisher: signer,
|
|
83
|
-
publisherMintAddress: publisherDetails.address ?? publisherMintAddress,
|
|
84
|
-
appDetails,
|
|
85
|
-
storageParams,
|
|
86
|
-
},
|
|
87
|
-
{ dryRun }
|
|
88
|
-
);
|
|
89
|
-
|
|
90
98
|
if (!dryRun) {
|
|
99
|
+
const { appAddress, transactionSignature } = await createAppNft(
|
|
100
|
+
{
|
|
101
|
+
connection,
|
|
102
|
+
publisher: signer,
|
|
103
|
+
publisherMintAddress: publisherDetails.address ?? publisherMintAddress,
|
|
104
|
+
appDetails,
|
|
105
|
+
storageParams,
|
|
106
|
+
priorityFeeLamports
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
|
|
91
110
|
await writeToPublishDetails({ app: { address: appAddress } });
|
|
92
|
-
}
|
|
93
111
|
|
|
94
|
-
|
|
112
|
+
return { appAddress, transactionSignature };
|
|
113
|
+
}
|
|
95
114
|
};
|
|
@@ -7,7 +7,9 @@ import {
|
|
|
7
7
|
} from "@solana/web3.js";
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
|
+
Constants,
|
|
10
11
|
getMetaplexInstance,
|
|
12
|
+
showMessage,
|
|
11
13
|
} from "../../CliUtils.js";
|
|
12
14
|
import { loadPublishDetailsWithChecks, writeToPublishDetails } from "../../config/PublishDetails.js";
|
|
13
15
|
|
|
@@ -17,39 +19,49 @@ const createPublisherNft = async (
|
|
|
17
19
|
publisher,
|
|
18
20
|
publisherDetails,
|
|
19
21
|
storageParams,
|
|
22
|
+
priorityFeeLamports,
|
|
20
23
|
}: {
|
|
21
24
|
connection: Connection;
|
|
22
25
|
publisher: Keypair;
|
|
23
26
|
publisherDetails: Publisher;
|
|
24
27
|
storageParams: string;
|
|
28
|
+
priorityFeeLamports: number;
|
|
25
29
|
},
|
|
26
|
-
{ dryRun }: { dryRun: boolean }
|
|
27
30
|
) => {
|
|
31
|
+
console.info(`Creating Publisher NFT`);
|
|
28
32
|
const mintAddress = Keypair.generate();
|
|
29
33
|
const metaplex = getMetaplexInstance(connection, publisher, storageParams);
|
|
30
|
-
console.info(
|
|
31
|
-
`Creating publisher at address: ${mintAddress.publicKey.toBase58()}`
|
|
32
|
-
);
|
|
33
34
|
const txBuilder = await createPublisher(
|
|
34
|
-
{ mintAddress, publisherDetails },
|
|
35
|
+
{ mintAddress, publisherDetails, priorityFeeLamports },
|
|
35
36
|
{ metaplex, publisher }
|
|
36
37
|
);
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
39
|
+
console.info(`Publisher NFT data upload complete\nSigning transaction now`);
|
|
40
|
+
const maxTries = 8;
|
|
41
|
+
for (let i = 1; i <= maxTries; i++) {
|
|
42
|
+
try {
|
|
43
|
+
const blockhash = await connection.getLatestBlockhashAndContext();
|
|
44
|
+
const tx = txBuilder.toTransaction(blockhash.value);
|
|
45
|
+
tx.sign(mintAddress, publisher);
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
const txSig = await sendAndConfirmTransaction(connection, tx, [
|
|
48
|
+
publisher,
|
|
49
|
+
mintAddress,
|
|
50
|
+
], {
|
|
51
|
+
minContextSlot: blockhash.context.slot
|
|
52
|
+
});
|
|
53
|
+
return { publisherAddress: mintAddress.publicKey.toBase58(), transactionSignature: txSig};
|
|
54
|
+
} catch (e) {
|
|
55
|
+
const errorMsg = (e as Error | null)?.message ?? "";
|
|
56
|
+
if (i == maxTries) {
|
|
57
|
+
showMessage("Transaction Failure", errorMsg, "error");
|
|
58
|
+
process.exit(-1)
|
|
59
|
+
} else {
|
|
60
|
+
const retryMsg = errorMsg + "\nWill Retry minting publisher."
|
|
61
|
+
showMessage("Transaction Failure", retryMsg, "standard");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
50
64
|
}
|
|
51
|
-
|
|
52
|
-
return { publisherAddress: mintAddress.publicKey.toBase58() };
|
|
53
65
|
};
|
|
54
66
|
|
|
55
67
|
export const createPublisherCommand = async ({
|
|
@@ -57,28 +69,31 @@ export const createPublisherCommand = async ({
|
|
|
57
69
|
url,
|
|
58
70
|
dryRun,
|
|
59
71
|
storageParams,
|
|
72
|
+
priorityFeeLamports = Constants.DEFAULT_PRIORITY_FEE,
|
|
60
73
|
}: {
|
|
61
74
|
signer: Keypair;
|
|
62
75
|
url: string;
|
|
63
76
|
dryRun: boolean;
|
|
64
77
|
storageParams: string;
|
|
78
|
+
priorityFeeLamports: number;
|
|
65
79
|
}) => {
|
|
66
80
|
const connection = new Connection(url);
|
|
67
81
|
|
|
68
82
|
const { publisher: publisherDetails } = await loadPublishDetailsWithChecks();
|
|
69
83
|
|
|
70
|
-
|
|
71
|
-
{
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
84
|
+
if (!dryRun) {
|
|
85
|
+
const { publisherAddress, transactionSignature } = await createPublisherNft(
|
|
86
|
+
{
|
|
87
|
+
connection,
|
|
88
|
+
publisher: signer,
|
|
89
|
+
publisherDetails,
|
|
90
|
+
storageParams: storageParams,
|
|
91
|
+
priorityFeeLamports: priorityFeeLamports,
|
|
92
|
+
},
|
|
93
|
+
);
|
|
79
94
|
|
|
80
|
-
|
|
81
|
-
await writeToPublishDetails({ publisher: { address: publisherAddress } });
|
|
95
|
+
await writeToPublishDetails({ publisher: { address: publisherAddress } });
|
|
82
96
|
|
|
83
|
-
|
|
97
|
+
return { publisherAddress, transactionSignature };
|
|
98
|
+
}
|
|
84
99
|
};
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
sendAndConfirmTransaction,
|
|
12
12
|
} from "@solana/web3.js";
|
|
13
13
|
import {
|
|
14
|
+
Constants,
|
|
14
15
|
getMetaplexInstance,
|
|
15
16
|
showMessage
|
|
16
17
|
} from "../../CliUtils.js";
|
|
@@ -23,6 +24,7 @@ type CreateReleaseCommandInput = {
|
|
|
23
24
|
url: string;
|
|
24
25
|
dryRun?: boolean;
|
|
25
26
|
storageParams: string;
|
|
27
|
+
priorityFeeLamports: number;
|
|
26
28
|
};
|
|
27
29
|
|
|
28
30
|
const createReleaseNft = async ({
|
|
@@ -33,6 +35,7 @@ const createReleaseNft = async ({
|
|
|
33
35
|
connection,
|
|
34
36
|
publisher,
|
|
35
37
|
storageParams,
|
|
38
|
+
priorityFeeLamports,
|
|
36
39
|
}: {
|
|
37
40
|
appMintAddress: string;
|
|
38
41
|
releaseDetails: Release;
|
|
@@ -41,7 +44,10 @@ const createReleaseNft = async ({
|
|
|
41
44
|
connection: Connection;
|
|
42
45
|
publisher: Keypair;
|
|
43
46
|
storageParams: string;
|
|
47
|
+
priorityFeeLamports: number;
|
|
44
48
|
}) => {
|
|
49
|
+
console.info(`Creating Release NFT`);
|
|
50
|
+
|
|
45
51
|
const releaseMintAddress = Keypair.generate();
|
|
46
52
|
|
|
47
53
|
const metaplex = getMetaplexInstance(connection, publisher, storageParams);
|
|
@@ -53,11 +59,13 @@ const createReleaseNft = async ({
|
|
|
53
59
|
releaseDetails,
|
|
54
60
|
appDetails,
|
|
55
61
|
publisherDetails,
|
|
62
|
+
priorityFeeLamports
|
|
56
63
|
},
|
|
57
64
|
{ metaplex, publisher }
|
|
58
65
|
);
|
|
59
66
|
|
|
60
|
-
|
|
67
|
+
console.info(`Release NFT data upload complete\nSigning transaction now`);
|
|
68
|
+
const maxTries = 8;
|
|
61
69
|
for (let i = 1; i <= maxTries; i++) {
|
|
62
70
|
try {
|
|
63
71
|
const blockhash = await connection.getLatestBlockhashAndContext();
|
|
@@ -69,18 +77,14 @@ const createReleaseNft = async ({
|
|
|
69
77
|
], {
|
|
70
78
|
minContextSlot: blockhash.context.slot,
|
|
71
79
|
});
|
|
72
|
-
|
|
73
|
-
txSig,
|
|
74
|
-
releaseMintAddress: releaseMintAddress.publicKey.toBase58(),
|
|
75
|
-
});
|
|
76
|
-
return { releaseAddress: releaseMintAddress.publicKey.toBase58() };
|
|
80
|
+
return { releaseAddress: releaseMintAddress.publicKey.toBase58(), transactionSignature: txSig };
|
|
77
81
|
} catch (e) {
|
|
78
82
|
const errorMsg = (e as Error | null)?.message ?? "";
|
|
79
83
|
if (i == maxTries) {
|
|
80
84
|
showMessage("Transaction Failure", errorMsg, "error");
|
|
81
85
|
process.exit(-1)
|
|
82
86
|
} else {
|
|
83
|
-
const retryMsg = errorMsg + "\nWill Retry minting release"
|
|
87
|
+
const retryMsg = errorMsg + "\nWill Retry minting release NFT"
|
|
84
88
|
showMessage("Transaction Failure", retryMsg, "standard");
|
|
85
89
|
}
|
|
86
90
|
}
|
|
@@ -94,13 +98,19 @@ export const createReleaseCommand = async ({
|
|
|
94
98
|
url,
|
|
95
99
|
dryRun = false,
|
|
96
100
|
storageParams,
|
|
101
|
+
priorityFeeLamports = Constants.DEFAULT_PRIORITY_FEE,
|
|
97
102
|
}: CreateReleaseCommandInput) => {
|
|
98
103
|
const connection = new Connection(url);
|
|
99
104
|
|
|
100
105
|
const { release, app, publisher } = await loadPublishDetailsWithChecks(buildToolsPath);
|
|
101
106
|
|
|
107
|
+
|
|
108
|
+
if (app.android_package != release.android_details.android_package) {
|
|
109
|
+
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)
|
|
110
|
+
}
|
|
111
|
+
|
|
102
112
|
if (!dryRun) {
|
|
103
|
-
const { releaseAddress } = await createReleaseNft({
|
|
113
|
+
const { releaseAddress, transactionSignature } = await createReleaseNft({
|
|
104
114
|
appMintAddress: app.address ?? appMintAddress,
|
|
105
115
|
connection,
|
|
106
116
|
publisher: signer,
|
|
@@ -110,10 +120,11 @@ export const createReleaseCommand = async ({
|
|
|
110
120
|
appDetails: app,
|
|
111
121
|
publisherDetails: publisher,
|
|
112
122
|
storageParams: storageParams,
|
|
123
|
+
priorityFeeLamports: priorityFeeLamports,
|
|
113
124
|
});
|
|
114
125
|
|
|
115
126
|
await writeToPublishDetails({ release: { address: releaseAddress }, });
|
|
116
127
|
|
|
117
|
-
return { releaseAddress };
|
|
128
|
+
return { releaseAddress, transactionSignature };
|
|
118
129
|
}
|
|
119
130
|
};
|
|
@@ -119,13 +119,25 @@ export const loadPublishDetailsWithChecks = async (
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
config.release.media.forEach((item: PublishDetails["release"]["media"][0]) => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
122
|
+
const imagePath = path.join(process.cwd(), item.uri);
|
|
123
|
+
if (!fs.existsSync(imagePath) || !checkImageExtension(imagePath)) {
|
|
124
|
+
throw new Error(`Invalid media path or file type: ${item.uri}. Please ensure the file is a jpeg, png, or webp file.`);
|
|
126
125
|
}
|
|
126
|
+
}
|
|
127
127
|
);
|
|
128
128
|
|
|
129
|
+
const screenshots = config.release.media?.filter(
|
|
130
|
+
(asset: any) => asset.purpose === "screenshot"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if (screenshots.length < 4) {
|
|
134
|
+
showMessage(
|
|
135
|
+
"Screenshots requirements changing in version 0.9.0",
|
|
136
|
+
`At least 4 screenshots are required for publishing a new release. Found only ${screenshots.length}`,
|
|
137
|
+
"warning"
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
129
141
|
validateLocalizableResources(config);
|
|
130
142
|
|
|
131
143
|
const googlePkg = config.solana_mobile_dapp_publisher_portal.google_store_package;
|
|
@@ -146,7 +158,7 @@ const checkIconCompatibility = async (path: string, typeString: string) => {
|
|
|
146
158
|
}
|
|
147
159
|
|
|
148
160
|
if (await checkIconDimensions(path)) {
|
|
149
|
-
throw new Error("Icons must
|
|
161
|
+
throw new Error("Icons must be 512px by 512px.");
|
|
150
162
|
}
|
|
151
163
|
};
|
|
152
164
|
|
|
@@ -189,7 +201,7 @@ const validateLocalizableResources = (config: PublishDetails) => {
|
|
|
189
201
|
const checkIconDimensions = async (iconPath: string): Promise<boolean> => {
|
|
190
202
|
const size = await runImgSize(iconPath);
|
|
191
203
|
|
|
192
|
-
return size?.width != size?.height || (size?.width ?? 0)
|
|
204
|
+
return size?.width != size?.height || (size?.width ?? 0) != 512;
|
|
193
205
|
};
|
|
194
206
|
|
|
195
207
|
const getAndroidDetails = async (
|
|
@@ -32,7 +32,6 @@ export class CachedStorageDriver implements StorageDriver {
|
|
|
32
32
|
{ assetManifestPath }: { assetManifestPath: string }
|
|
33
33
|
) {
|
|
34
34
|
this.assetManifestPath = assetManifestPath;
|
|
35
|
-
console.info({ loading: true });
|
|
36
35
|
this.assetManifest = this.loadAssetManifest(assetManifestPath) ?? {
|
|
37
36
|
schema_version: CachedStorageDriver.SCHEMA_VERSION,
|
|
38
37
|
assets: {},
|
|
@@ -69,15 +68,6 @@ export class CachedStorageDriver implements StorageDriver {
|
|
|
69
68
|
}
|
|
70
69
|
const hash = createHash("sha256").update(file.buffer).digest("base64");
|
|
71
70
|
|
|
72
|
-
console.info(
|
|
73
|
-
JSON.stringify({
|
|
74
|
-
file: {
|
|
75
|
-
name: file.fileName,
|
|
76
|
-
disn: file.displayName,
|
|
77
|
-
un: file.uniqueName,
|
|
78
|
-
},
|
|
79
|
-
})
|
|
80
|
-
);
|
|
81
71
|
const uploadedAsset = this.uploadedAsset(file.fileName, { sha256: hash });
|
|
82
72
|
if (uploadedAsset) {
|
|
83
73
|
console.log(
|
|
@@ -101,6 +91,7 @@ export class CachedStorageDriver implements StorageDriver {
|
|
|
101
91
|
JSON.stringify({ assets: { ...this.assetManifest.assets } }, null, 2),
|
|
102
92
|
"utf-8"
|
|
103
93
|
);
|
|
94
|
+
console.log(`${file.fileName} uploaded at ${uri}`)
|
|
104
95
|
|
|
105
96
|
return uri;
|
|
106
97
|
}
|