@solana-mobile/dapp-store-publishing-tools 0.16.0 → 1.0.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.
Files changed (53) hide show
  1. package/lib/CoreUtils.js +0 -3
  2. package/lib/index.js +1 -0
  3. package/lib/portal/attestation.js +189 -0
  4. package/lib/portal/compat.js +3 -0
  5. package/lib/portal/index.js +5 -0
  6. package/lib/portal/signer.js +432 -0
  7. package/lib/portal/types.js +1 -0
  8. package/lib/portal/workflow/contracts.js +1 -0
  9. package/lib/portal/workflow/execution.js +493 -0
  10. package/lib/portal/workflow/ingestion.js +265 -0
  11. package/lib/portal/workflow/lifecycle.js +616 -0
  12. package/lib/portal/workflow/logging.js +8 -0
  13. package/lib/portal/workflow/source/files.js +304 -0
  14. package/lib/portal/workflow/source/preparation.js +318 -0
  15. package/lib/portal/workflow/state/bundle.js +260 -0
  16. package/lib/portal/workflow/state/checkpoints.js +53 -0
  17. package/lib/portal/workflow/state/session.js +100 -0
  18. package/lib/portal/workflow.js +1 -0
  19. package/lib/publish/PublishCoreAttestation.js +18 -17
  20. package/lib/publish/PublishCoreRemove.js +7 -89
  21. package/lib/publish/PublishCoreSubmit.js +7 -117
  22. package/lib/publish/PublishCoreSupport.js +7 -86
  23. package/lib/publish/PublishCoreUpdate.js +7 -117
  24. package/lib/publish/index.js +1 -0
  25. package/lib/schemas/releaseJsonMetadata.json +1 -2
  26. package/package.json +2 -4
  27. package/src/CoreUtils.ts +0 -6
  28. package/src/index.ts +1 -0
  29. package/src/portal/attestation.ts +76 -0
  30. package/src/portal/compat.ts +5 -0
  31. package/src/portal/index.ts +5 -0
  32. package/src/portal/signer.ts +327 -0
  33. package/src/portal/types.ts +447 -0
  34. package/src/portal/workflow/contracts.ts +108 -0
  35. package/src/portal/workflow/execution.ts +412 -0
  36. package/src/portal/workflow/ingestion.ts +187 -0
  37. package/src/portal/workflow/lifecycle.ts +435 -0
  38. package/src/portal/workflow/logging.ts +17 -0
  39. package/src/portal/workflow/source/files.ts +49 -0
  40. package/src/portal/workflow/source/preparation.ts +189 -0
  41. package/src/portal/workflow/state/bundle.ts +193 -0
  42. package/src/portal/workflow/state/checkpoints.ts +70 -0
  43. package/src/portal/workflow/state/session.ts +87 -0
  44. package/src/portal/workflow.ts +9 -0
  45. package/src/publish/PublishCoreAttestation.ts +21 -26
  46. package/src/publish/PublishCoreRemove.ts +13 -109
  47. package/src/publish/PublishCoreSubmit.ts +18 -150
  48. package/src/publish/PublishCoreSupport.ts +13 -102
  49. package/src/publish/PublishCoreUpdate.ts +17 -155
  50. package/src/publish/index.ts +2 -1
  51. package/src/schemas/releaseJsonMetadata.json +1 -2
  52. package/lib/publish/dapp_publisher_portal.js +0 -206
  53. package/src/publish/dapp_publisher_portal.ts +0 -81
@@ -0,0 +1,447 @@
1
+ import type { Transaction } from '@solana/web3.js';
2
+
3
+ export type PublicationSource =
4
+ | {
5
+ kind: 'portalUpload';
6
+ releaseFileUrl: string;
7
+ releaseFileName: string;
8
+ releaseFileSize: number;
9
+ releaseFileHash?: string;
10
+ contentType?: string;
11
+ }
12
+ | {
13
+ kind: 'externalUrl';
14
+ apkUrl: string;
15
+ releaseFileName?: string;
16
+ }
17
+ | {
18
+ kind: 'existingRelease';
19
+ sourceReleaseId: string;
20
+ }
21
+ | {
22
+ kind: 'apk-file';
23
+ fileName: string;
24
+ filePath: string;
25
+ mimeType?: string;
26
+ size?: number;
27
+ sha256?: string;
28
+ }
29
+ | {
30
+ kind: 'apk-url';
31
+ url: string;
32
+ fileName?: string;
33
+ mimeType?: string;
34
+ size?: number;
35
+ sha256?: string;
36
+ canonicalUrl?: string;
37
+ };
38
+
39
+ export type PublicationCreateUploadTargetInput = {
40
+ fileHash: string;
41
+ fileExtension: string;
42
+ contentType: string;
43
+ };
44
+
45
+ export type PublicationCreateUploadTargetResult = {
46
+ uploadUrl: string;
47
+ key: string;
48
+ providerId: string;
49
+ publicUrl: string;
50
+ };
51
+
52
+ export type PublicationInstallFile = {
53
+ uri: string;
54
+ mimeType: string;
55
+ size: number;
56
+ sha256?: string | null;
57
+ fileName?: string;
58
+ canonicalUrl?: string;
59
+ url?: string;
60
+ origin?: 'portal' | 'external';
61
+ };
62
+
63
+ export type PublicationMediaAsset = {
64
+ purpose: 'icon' | 'screenshot' | 'banner' | 'featureGraphic';
65
+ uri: string;
66
+ mimeType?: string;
67
+ fileName?: string;
68
+ size?: number;
69
+ sha256?: string;
70
+ width?: number;
71
+ height?: number;
72
+ };
73
+
74
+ export type PublicationLegalBundle = {
75
+ licenseUrl?: string | null;
76
+ copyrightUrl?: string | null;
77
+ privacyPolicyUrl?: string | null;
78
+ };
79
+
80
+ export type PublicationLocalizedStrings = {
81
+ locale: string;
82
+ name: string;
83
+ shortDescription: string;
84
+ longDescription: string;
85
+ newInVersion: string;
86
+ };
87
+
88
+ export type PublicationMetadataBundle = {
89
+ localizedName: string;
90
+ shortDescription: string;
91
+ longDescription: string;
92
+ newInVersion: string;
93
+ publisherWebsite?: string | null;
94
+ supportEmail?: string | null;
95
+ website?: string | null;
96
+ locales: string[];
97
+ legal: PublicationLegalBundle;
98
+ media: PublicationMediaAsset[];
99
+ installFile: PublicationInstallFile;
100
+ localizedStrings: PublicationLocalizedStrings[];
101
+ releaseMetadataUri?: string | null;
102
+ };
103
+
104
+ export type PublicationSignerAuthorityBundle = {
105
+ dappWalletAddress: string;
106
+ collectionAuthority: string;
107
+ appMintAddress: string;
108
+ sameSignerRequired: boolean;
109
+ acceptedSignerRoles: Array<'publisher' | 'payer'>;
110
+ dappId?: string;
111
+ requiredSigner?: string;
112
+ mintSigner?: string | null;
113
+ feePayer?: string | null;
114
+ };
115
+
116
+ export type PublicationIngestionSessionStatus =
117
+ | 'Created'
118
+ | 'Processing'
119
+ | 'Ready'
120
+ | 'Failed'
121
+ | 'created'
122
+ | 'queued'
123
+ | 'processing'
124
+ | 'ready'
125
+ | 'failed';
126
+
127
+ export type PublicationCheckpoint =
128
+ | 'created'
129
+ | 'bundle-ready'
130
+ | 'mint-submitted'
131
+ | 'mint-saved'
132
+ | 'verification-submitted'
133
+ | 'verified'
134
+ | 'attested'
135
+ | 'submitted'
136
+ | 'completed';
137
+
138
+ export type PublicationSessionStage =
139
+ | 'PreparedForMint'
140
+ | 'MintSubmitted'
141
+ | 'MintSaved'
142
+ | 'VerificationSubmitted'
143
+ | 'Verified'
144
+ | 'Attested'
145
+ | 'Submitted'
146
+ | 'Failed';
147
+
148
+ export type PublicationSessionStatus =
149
+ | 'pending'
150
+ | 'running'
151
+ | 'failed'
152
+ | 'completed';
153
+
154
+ export type PublicationIngestionSession = {
155
+ id: string;
156
+ publisherUserJoinId?: string | null;
157
+ sourceKind?: 'portalUpload' | 'externalUrl' | 'existingRelease';
158
+ source?: PublicationSource;
159
+ dappId?: string | null;
160
+ status: PublicationIngestionSessionStatus;
161
+ idempotencyKey: string;
162
+ whatsNew: string;
163
+ sourceUrl?: string | null;
164
+ canonicalSourceUrl?: string | null;
165
+ releaseFileName?: string | null;
166
+ releaseFileSize?: number | null;
167
+ releaseFileHash?: string | null;
168
+ androidPackage?: string | null;
169
+ versionName?: string | null;
170
+ versionCode?: number | null;
171
+ processingError?: string | null;
172
+ processingProgress?: number | null;
173
+ processingStage?: string | null;
174
+ processingDetail?: string | null;
175
+ releaseId?: string | null;
176
+ publicationSessionId?: string | null;
177
+ bundle?: PublicationBundle;
178
+ publicationSession?: PublicationSession;
179
+ created?: string;
180
+ updated?: string;
181
+ createdAt?: string;
182
+ updatedAt?: string;
183
+ error?: string | null;
184
+ };
185
+
186
+ export type PublicationSession = {
187
+ id: string;
188
+ releaseId: string;
189
+ ingestionSessionId?: string | null;
190
+ stage?: PublicationSessionStage;
191
+ expectedMintAddress?: string | null;
192
+ metadataUri?: string | null;
193
+ signerAddress?: string | null;
194
+ mintTransactionSignature?: string | null;
195
+ verificationTransactionSignature?: string | null;
196
+ attestationRequestUniqueId?: string | null;
197
+ hubspotTicketId?: string | null;
198
+ lastError?: string | null;
199
+ created: string;
200
+ updated: string;
201
+ checkpoint?: PublicationCheckpoint;
202
+ status?: PublicationSessionStatus;
203
+ releaseMintAddress?: string | null;
204
+ collectionMintAddress?: string | null;
205
+ verifyTransactionSignature?: string | null;
206
+ attestationPayload?: string | null;
207
+ error?: string | null;
208
+ createdAt?: string;
209
+ updatedAt?: string;
210
+ };
211
+
212
+ export type PublicationBundle = {
213
+ ingestionSessionId: string;
214
+ publicationSessionId: string;
215
+ releaseId: string;
216
+ dapp: {
217
+ id: string;
218
+ dappName: string;
219
+ subtitle?: string | null;
220
+ description?: string | null;
221
+ androidPackage: string;
222
+ dappIconUrl?: string | null;
223
+ dappPreviewUrls?: string[];
224
+ bannerUrl?: string | null;
225
+ featureGraphicUrl?: string | null;
226
+ editorsChoiceGraphicUrl?: string | null;
227
+ appWebsite?: string | null;
228
+ contactEmail?: string | null;
229
+ supportEmail?: string | null;
230
+ languages?: string[];
231
+ licenseUrl?: string | null;
232
+ copyrightUrl?: string | null;
233
+ privacyPolicyUrl?: string | null;
234
+ walletAddress?: string | null;
235
+ nftMintAddress?: string | null;
236
+ lastApprovedReleaseId?: string | null;
237
+ website?: string | null;
238
+ };
239
+ publisher: {
240
+ id: string;
241
+ type: 'organization' | 'individual';
242
+ name: string;
243
+ website: string;
244
+ email: string;
245
+ supportEmail?: string | null;
246
+ };
247
+ installFile: PublicationInstallFile;
248
+ signerAuthority: PublicationSignerAuthorityBundle;
249
+ release: {
250
+ id?: string;
251
+ dappId?: string;
252
+ releaseFileUrl?: string;
253
+ releaseFileName?: string;
254
+ releaseFileSize?: number;
255
+ releaseFileHash?: string | null;
256
+ androidPackage: string;
257
+ versionName: string;
258
+ versionCode: number;
259
+ minSdkVersion?: number | null;
260
+ targetSdkVersion?: number | null;
261
+ permissions?: string[];
262
+ locales?: string[];
263
+ certificateFingerprint?: string | null;
264
+ shortDescription?: string | null;
265
+ longDescription?: string | null;
266
+ newInVersion: string;
267
+ sagaFeatures?: string | null;
268
+ localizedName: string;
269
+ status?: string;
270
+ processingError?: string | null;
271
+ processedAt?: string | null;
272
+ releaseMintAddress?: string | null;
273
+ releaseMetadataUri?: string | null;
274
+ nftMintAddress?: string | null;
275
+ nftTransactionSignature?: string | null;
276
+ nftMetadataUri?: string | null;
277
+ nftCluster?: string | null;
278
+ isCollectionVerified?: boolean;
279
+ uploadProvider?: 'Arweave' | 'S3' | 'R2' | 'IPFS' | null;
280
+ uploadProviderId?: string | null;
281
+ publishedAt?: string | null;
282
+ rejectedAt?: string | null;
283
+ rejectionReason?: string | null;
284
+ submissionStatus?: string;
285
+ hubspotTicketId?: string | null;
286
+ submittedAt?: string | null;
287
+ reviewStartedAt?: string | null;
288
+ reviewCompletedAt?: string | null;
289
+ source?: 'Portal' | 'Hubspot';
290
+ created?: string;
291
+ updated?: string;
292
+ isLive?: boolean;
293
+ liveVersionComparison?: string;
294
+ releaseName?: string;
295
+ };
296
+ metadata?: PublicationMetadataBundle;
297
+ };
298
+
299
+ export type PublicationPreparedReleaseTransaction = {
300
+ transaction: string;
301
+ blockhash: string;
302
+ lastValidBlockHeight: number;
303
+ mintAddress: string;
304
+ metadataUri: string;
305
+ };
306
+
307
+ export type PublicationPreparedVerifyCollectionTransaction = {
308
+ transaction: string;
309
+ blockhash: string;
310
+ lastValidBlockHeight: number;
311
+ };
312
+
313
+ export type PublicationSubmitSignedTransactionResult = {
314
+ transactionSignature: string;
315
+ };
316
+
317
+ export type PublicationSaveReleaseNftDataResult = {
318
+ success: boolean;
319
+ releaseId: string;
320
+ mintAddress: string;
321
+ };
322
+
323
+ export type PublicationMarkReleaseCollectionAsVerifiedResult = {
324
+ success: boolean;
325
+ releaseId: string;
326
+ };
327
+
328
+ export type PublicationSubmitToStoreResult = {
329
+ success: boolean;
330
+ hubspotTicketId?: string;
331
+ message: string;
332
+ };
333
+
334
+ export type PublicationCreateIngestionSessionInput = {
335
+ source: PublicationSource;
336
+ whatsNew: string;
337
+ idempotencyKey: string;
338
+ dappId?: string;
339
+ };
340
+
341
+ export type PublicationGetIngestionSessionInput =
342
+ | {
343
+ sessionId: string;
344
+ ingestionSessionId?: string;
345
+ }
346
+ | {
347
+ sessionId?: string;
348
+ ingestionSessionId: string;
349
+ };
350
+
351
+ export type PublicationGetBundleInput = {
352
+ releaseId: string;
353
+ };
354
+
355
+ export type PublicationGetSessionInput = {
356
+ publicationSessionId?: string;
357
+ releaseId?: string;
358
+ };
359
+
360
+ export type PublicationCleanupReleaseInput = {
361
+ releaseId: string;
362
+ };
363
+
364
+ export type PublicationCleanupReleaseResult = {
365
+ success: boolean;
366
+ releaseId: string;
367
+ action: 'deleted' | 'preservedSubmitted';
368
+ message: string;
369
+ };
370
+
371
+ export type PublicationPrepareReleaseNftTransactionInput = {
372
+ releaseId: string;
373
+ releaseName: string;
374
+ releaseMetadataUri: string;
375
+ appMintAddress: string;
376
+ publisherAddress: string;
377
+ payerAddress: string;
378
+ };
379
+
380
+ export type PublicationPrepareVerifyCollectionTransactionInput = {
381
+ dappId: string;
382
+ nftMintAddress: string;
383
+ collectionMintAddress: string;
384
+ collectionAuthority: string;
385
+ payerAddress: string;
386
+ };
387
+
388
+ export type PublicationSaveReleaseNftDataInput = {
389
+ releaseId: string;
390
+ mintAddress: string;
391
+ transactionSignature: string;
392
+ metadataUri: string;
393
+ ownerAddress: string;
394
+ releaseName: string;
395
+ releaseVersion: string;
396
+ androidPackage: string;
397
+ appMintAddress: string;
398
+ uploadProvider?: 'Arweave' | 'S3' | 'R2' | 'IPFS';
399
+ uploadProviderId?: string;
400
+ };
401
+
402
+ export type PublicationSubmitToStoreInput = {
403
+ releaseId: string;
404
+ whatsNew?: string;
405
+ criticalUpdate?: boolean;
406
+ testingInstructions?: string;
407
+ attestation: {
408
+ payload: string;
409
+ requestUniqueId: string;
410
+ };
411
+ isResubmission?: boolean;
412
+ };
413
+
414
+ export type PublicationSigner = {
415
+ publicKey: string;
416
+ signTransaction(transaction: Transaction): Promise<Transaction>;
417
+ signMessage(message: Uint8Array): Promise<Uint8Array>;
418
+ };
419
+
420
+ export type PublicationAttestationBlockData = {
421
+ slot: number;
422
+ blockhash: string;
423
+ };
424
+
425
+ export type PublicationAttestationClient = {
426
+ getBlockData(): Promise<PublicationAttestationBlockData>;
427
+ };
428
+
429
+ export type PublicationWorkflowResult = {
430
+ ingestionSessionId: string;
431
+ publicationSessionId: string;
432
+ releaseId: string;
433
+ releaseMintAddress: string;
434
+ collectionMintAddress: string;
435
+ releaseTransactionSignature?: string;
436
+ collectionTransactionSignature?: string;
437
+ attestationRequestUniqueId?: string;
438
+ hubspotTicketId?: string;
439
+ publicationBundle: PublicationBundle;
440
+ publicationSession: PublicationSession;
441
+ };
442
+
443
+ export type PublicationWorkflowLogger = {
444
+ debug?: (message: string, metadata?: Record<string, unknown>) => void;
445
+ info?: (message: string, metadata?: Record<string, unknown>) => void;
446
+ warn?: (message: string, metadata?: Record<string, unknown>) => void;
447
+ };
@@ -0,0 +1,108 @@
1
+ import type {
2
+ PublicationAttestationClient,
3
+ PublicationBundle,
4
+ PublicationCleanupReleaseInput,
5
+ PublicationCleanupReleaseResult,
6
+ PublicationCreateIngestionSessionInput,
7
+ PublicationCreateUploadTargetInput,
8
+ PublicationCreateUploadTargetResult,
9
+ PublicationGetBundleInput,
10
+ PublicationGetIngestionSessionInput,
11
+ PublicationGetSessionInput,
12
+ PublicationIngestionSession,
13
+ PublicationMarkReleaseCollectionAsVerifiedResult,
14
+ PublicationPreparedReleaseTransaction,
15
+ PublicationPreparedVerifyCollectionTransaction,
16
+ PublicationSaveReleaseNftDataInput,
17
+ PublicationSaveReleaseNftDataResult,
18
+ PublicationSession,
19
+ PublicationSigner,
20
+ PublicationSource,
21
+ PublicationSubmitSignedTransactionResult,
22
+ PublicationSubmitToStoreInput,
23
+ PublicationSubmitToStoreResult,
24
+ PublicationWorkflowLogger,
25
+ } from "../types.js";
26
+
27
+ export type PublicationWorkflowClient = {
28
+ createUploadTarget?(
29
+ input: PublicationCreateUploadTargetInput
30
+ ): Promise<PublicationCreateUploadTargetResult>;
31
+ createIngestionSession(
32
+ input: PublicationCreateIngestionSessionInput
33
+ ): Promise<PublicationIngestionSession>;
34
+ getIngestionSession(
35
+ input: PublicationGetIngestionSessionInput
36
+ ): Promise<PublicationIngestionSession>;
37
+ getPublicationBundle(
38
+ input: PublicationGetBundleInput
39
+ ): Promise<PublicationBundle>;
40
+ getPublicationSession(
41
+ input: PublicationGetSessionInput
42
+ ): Promise<PublicationSession>;
43
+ prepareReleaseNftTransaction(
44
+ input: PublicationWorkflowPrepareReleaseTransactionInput
45
+ ): Promise<PublicationPreparedReleaseTransaction>;
46
+ submitSignedTransaction(input: {
47
+ signedTransaction: string;
48
+ publicationSessionId?: string;
49
+ }): Promise<PublicationSubmitSignedTransactionResult>;
50
+ saveReleaseNftData(
51
+ input: PublicationSaveReleaseNftDataInput
52
+ ): Promise<PublicationSaveReleaseNftDataResult>;
53
+ prepareVerifyCollectionTransaction(
54
+ input: PublicationWorkflowPrepareVerifyTransactionInput
55
+ ): Promise<PublicationPreparedVerifyCollectionTransaction>;
56
+ markReleaseCollectionAsVerified(input: {
57
+ releaseId: string;
58
+ }): Promise<PublicationMarkReleaseCollectionAsVerifiedResult>;
59
+ cleanupRelease?(
60
+ input: PublicationCleanupReleaseInput
61
+ ): Promise<PublicationCleanupReleaseResult>;
62
+ submitToStore(
63
+ input: PublicationSubmitToStoreInput
64
+ ): Promise<PublicationSubmitToStoreResult>;
65
+ };
66
+
67
+ export type PublicationWorkflowPrepareReleaseTransactionInput = {
68
+ releaseId: string;
69
+ releaseName: string;
70
+ releaseMetadataUri: string;
71
+ appMintAddress: string;
72
+ publisherAddress: string;
73
+ payerAddress: string;
74
+ };
75
+
76
+ export type PublicationWorkflowPrepareVerifyTransactionInput = {
77
+ dappId: string;
78
+ nftMintAddress: string;
79
+ collectionMintAddress: string;
80
+ collectionAuthority: string;
81
+ payerAddress: string;
82
+ };
83
+
84
+ export type PublicationWorkflowOptions = {
85
+ pollIntervalMs?: number;
86
+ maxPollAttempts?: number;
87
+ logger?: PublicationWorkflowLogger;
88
+ };
89
+
90
+ export type PublicationWorkflowInput = {
91
+ dappId?: string;
92
+ source: PublicationSource;
93
+ whatsNew: string;
94
+ idempotencyKey?: string;
95
+ signer: PublicationSigner;
96
+ attestationClient: PublicationAttestationClient;
97
+ };
98
+
99
+ export type PublicationResumeInput = {
100
+ publicationSessionId?: string;
101
+ releaseId?: string;
102
+ signer: PublicationSigner;
103
+ attestationClient: PublicationAttestationClient;
104
+ };
105
+
106
+ export type PublicationWorkflowPollOptions = Required<
107
+ Pick<PublicationWorkflowOptions, "pollIntervalMs" | "maxPollAttempts">
108
+ >;