Phase Selection
-
-
-
+
+
+
+
+
+
+
+
+ {selectedPhase === "research" ? (
+
+ ) : (
+
+ )}
- {selectedPhase === "research" ? (
-
- ) : (
-
- )}
>
);
}
@@ -1394,6 +1766,9 @@ function DropForgeLaunchClaimActionsSection({
teamAirdrops,
runAirdropWrite,
subscriptionAirdropSections,
+ mintingClaimActionsByName,
+ mintingClaimActionPending,
+ onMintingClaimActionToggle,
claimId,
primaryStatus,
}: Readonly<{
@@ -1405,12 +1780,12 @@ function DropForgeLaunchClaimActionsSection({
isInitialized: boolean;
runMetadataLocationOnlyUpdate: () => void;
selectedPhase: "" | LaunchPhaseKey;
- onSelectedPhaseChange: (value: string) => void;
+ onSelectedPhaseChange: (value: LaunchPhaseKey) => void;
totalMinted: number;
researchTargetEditionSize: number;
onResearchTargetEditionSizeChange: (value: string) => void;
researchAirdropCount: number;
- runResearchAirdropWrite: () => void;
+ runResearchAirdropWrite: (mintingClaimAction: string | null) => void;
selectedPhaseDiffs: LaunchPhaseDiffsView;
changedFieldBoxClassName: string;
changedFieldBoxLabelClassName: string;
@@ -1435,6 +1810,12 @@ function DropForgeLaunchClaimActionsSection({
teamAirdrops: PhaseAirdrop[] | null;
runAirdropWrite: DropForgeLaunchClaimPageViewProps["runAirdropWrite"];
subscriptionAirdropSections: LaunchSubscriptionAirdropSectionView[];
+ mintingClaimActionsByName: Record
;
+ mintingClaimActionPending: string | null;
+ onMintingClaimActionToggle: (
+ action: string,
+ completed: boolean
+ ) => Promise;
claimId: number;
primaryStatus: LaunchClaimPrimaryStatus;
}>) {
@@ -1485,6 +1866,9 @@ function DropForgeLaunchClaimActionsSection({
artistAirdrops={artistAirdrops}
teamAirdrops={teamAirdrops}
runAirdropWrite={runAirdropWrite}
+ mintingClaimActionsByName={mintingClaimActionsByName}
+ mintingClaimActionPending={mintingClaimActionPending}
+ onMintingClaimActionToggle={onMintingClaimActionToggle}
subscriptionAirdropSections={subscriptionAirdropSections}
/>
)}
@@ -1549,6 +1933,9 @@ function DropForgeLaunchClaimContent({
teamAirdrops,
runAirdropWrite,
subscriptionAirdropSections,
+ mintingClaimActionsByName,
+ mintingClaimActionPending,
+ onMintingClaimActionToggle,
}: Readonly<
Omit<
DropForgeLaunchClaimPageViewProps,
@@ -1626,6 +2013,9 @@ function DropForgeLaunchClaimContent({
teamAirdrops={teamAirdrops}
runAirdropWrite={runAirdropWrite}
subscriptionAirdropSections={subscriptionAirdropSections}
+ mintingClaimActionsByName={mintingClaimActionsByName}
+ mintingClaimActionPending={mintingClaimActionPending}
+ onMintingClaimActionToggle={onMintingClaimActionToggle}
claimId={claimId}
primaryStatus={primaryStatus}
/>
diff --git a/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts b/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts
index 57d536301f..37bfc5bfa1 100644
--- a/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts
+++ b/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers.ts
@@ -176,6 +176,50 @@ export function getSubscriptionPhaseName(phaseKey: LaunchPhaseKey): string {
return "Public Phase";
}
+export function getAutoSelectedLaunchPhase({
+ hasPublishedMetadata,
+ isInitialized,
+ nowMs,
+ phases,
+}: Readonly<{
+ hasPublishedMetadata: boolean;
+ isInitialized: boolean;
+ nowMs: number;
+ phases: ReadonlyArray<{
+ key: Exclude;
+ schedule:
+ | {
+ startMs: number;
+ endMs: number;
+ }
+ | null
+ | undefined;
+ }>;
+}>): "" | LaunchPhaseKey {
+ if (!hasPublishedMetadata) {
+ return "";
+ }
+
+ if (!isInitialized) {
+ return "phase0";
+ }
+
+ if (phases.every((phase) => !phase.schedule)) {
+ return "phase0";
+ }
+
+ for (const phase of phases) {
+ if (!phase.schedule) {
+ continue;
+ }
+ if (nowMs <= phase.schedule.endMs) {
+ return phase.key;
+ }
+ }
+
+ return "research";
+}
+
function normalizeAirdropAmount(value: number | undefined): number {
const normalized = Number(value ?? 0);
if (!Number.isFinite(normalized)) return 0;
@@ -395,7 +439,9 @@ export function getAnimationMimeType(claim: MintingClaim): string | null {
}
if (isVideoUrl(animationUrl)) {
- return extension ? (VIDEO_EXTENSION_TO_MIME[extension] ?? "video/*") : "video/*";
+ return extension
+ ? (VIDEO_EXTENSION_TO_MIME[extension] ?? "video/*")
+ : "video/*";
}
return extension
diff --git a/components/waves/memes/submission/details/ArtworkDetails.tsx b/components/waves/memes/submission/details/ArtworkDetails.tsx
index 757b842d53..5c32cee456 100644
--- a/components/waves/memes/submission/details/ArtworkDetails.tsx
+++ b/components/waves/memes/submission/details/ArtworkDetails.tsx
@@ -35,9 +35,19 @@ const ArtworkDetails: React.FC = ({
const titleRef = useRef(null);
const descriptionRef = useRef(null);
+ const resizeDescriptionTextarea = useCallback(
+ (textarea: HTMLTextAreaElement | null) => {
+ if (!textarea) return;
+
+ textarea.style.height = "auto";
+ textarea.style.height = `${textarea.scrollHeight}px`;
+ },
+ []
+ );
+
// Sync refs with props when they change
React.useEffect(() => {
- if (titleRef.current && title && titleRef.current.value !== title) {
+ if (titleRef.current && titleRef.current.value !== title) {
titleRef.current.value = title;
}
}, [title]);
@@ -45,36 +55,43 @@ const ArtworkDetails: React.FC = ({
React.useEffect(() => {
if (
descriptionRef.current &&
- description &&
descriptionRef.current.value !== description
) {
descriptionRef.current.value = description;
}
- }, [description]);
+
+ resizeDescriptionTextarea(descriptionRef.current);
+ }, [description, resizeDescriptionTextarea]);
// Handle blur events - only update parent state when user finishes typing
const handleTitleBlur = useCallback(() => {
- if (titleRef.current && titleRef.current.value !== title) {
- onTitleChange(titleRef.current.value);
- }
// Call parent blur handler for validation
if (onTitleBlur) {
onTitleBlur();
}
- }, [onTitleChange, title, onTitleBlur]);
+ }, [onTitleBlur]);
const handleDescriptionBlur = useCallback(() => {
- if (
- descriptionRef.current &&
- descriptionRef.current.value !== description
- ) {
- onDescriptionChange(descriptionRef.current.value);
- }
// Call parent blur handler for validation
if (onDescriptionBlur) {
onDescriptionBlur();
}
- }, [onDescriptionChange, description, onDescriptionBlur]);
+ }, [onDescriptionBlur]);
+
+ const handleTitleInput = useCallback(
+ (event: React.FormEvent) => {
+ onTitleChange(event.currentTarget.value);
+ },
+ [onTitleChange]
+ );
+
+ const handleDescriptionInput = useCallback(
+ (event: React.FormEvent) => {
+ onDescriptionChange(event.currentTarget.value);
+ resizeDescriptionTextarea(event.currentTarget);
+ },
+ [onDescriptionChange, resizeDescriptionTextarea]
+ );
// Check if fields are filled
const isTitleFilled = useMemo(() => title.trim().length > 0, [title]);
@@ -93,12 +110,11 @@ const ArtworkDetails: React.FC = ({
@@ -111,25 +127,22 @@ const ArtworkDetails: React.FC
= ({
type="text"
maxLength={500}
defaultValue={title || ""}
+ onInput={handleTitleInput}
onBlur={handleTitleBlur}
aria-invalid={!!titleError}
aria-describedby={titleError ? "title-error" : undefined}
data-field="title"
- className={`tw-form-input tw-w-full tw-rounded-lg tw-px-4 tw-py-3.5 tw-text-sm tw-text-iron-100 tw-transition-all tw-duration-500 tw-ease-in-out
- tw-bg-iron-900 tw-border-0 tw-outline-none placeholder:tw-text-iron-500 tw-cursor-text tw-ring-1
- ${
- titleError
- ? "tw-ring-red"
- : "tw-ring-iron-700 desktop-hover:hover:tw-ring-iron-650 focus-visible:tw-ring-2 focus-visible:tw-ring-primary-400 focus-visible:hover:tw-ring-primary-400"
- }
- ${isTitleFilled && !titleError ? "tw-pr-10" : ""}
- `}
+ className={`tw-form-input tw-w-full tw-cursor-text tw-rounded-lg tw-border-0 tw-bg-iron-900 tw-px-4 tw-py-3.5 tw-text-sm tw-text-iron-100 tw-outline-none tw-ring-1 tw-transition-all tw-duration-500 tw-ease-in-out placeholder:tw-text-iron-500 ${
+ titleError
+ ? "tw-ring-red"
+ : "tw-ring-iron-700 focus-visible:tw-ring-2 focus-visible:tw-ring-primary-400 focus-visible:hover:tw-ring-primary-400 desktop-hover:hover:tw-ring-iron-650"
+ } ${isTitleFilled && !titleError ? "tw-pr-10" : ""} `}
/>
{/* Title checkmark */}
{isTitleFilled && !titleError && (
-
@@ -142,12 +155,11 @@ const ArtworkDetails: React.FC = ({
@@ -158,6 +170,7 @@ const ArtworkDetails: React.FC
= ({
id="field-description"
name="description"
defaultValue={description || ""}
+ onInput={handleDescriptionInput}
onBlur={handleDescriptionBlur}
rows={4}
maxLength={500}
@@ -166,21 +179,17 @@ const ArtworkDetails: React.FC = ({
descriptionError ? "description-error" : undefined
}
data-field="description"
- className={`tw-form-textarea tw-w-full tw-rounded-lg tw-px-4 tw-py-3.5 tw-text-sm tw-text-iron-100 tw-transition-all tw-duration-500 tw-ease-in-out
- tw-bg-iron-900 tw-border-0 tw-outline-none placeholder:tw-text-iron-500 tw-resize-none tw-cursor-text tw-ring-1
- ${
- descriptionError
- ? "tw-ring-red"
- : "tw-ring-iron-700 desktop-hover:hover:tw-ring-iron-650 focus-visible:tw-ring-2 focus-visible:tw-ring-primary-400 focus-visible:hover:tw-ring-primary-400"
- }
- ${isDescriptionFilled && !descriptionError ? "tw-pr-10" : ""}
- `}
+ className={`tw-form-textarea tw-w-full tw-cursor-text tw-overflow-hidden tw-rounded-lg tw-border-0 tw-bg-iron-900 tw-px-4 tw-py-3.5 tw-text-sm tw-text-iron-100 tw-outline-none tw-ring-1 tw-transition-all tw-duration-500 tw-ease-in-out placeholder:tw-text-iron-500 ${
+ descriptionError
+ ? "tw-ring-red"
+ : "tw-ring-iron-700 focus-visible:tw-ring-2 focus-visible:tw-ring-primary-400 focus-visible:hover:tw-ring-primary-400 desktop-hover:hover:tw-ring-iron-650"
+ } ${isDescriptionFilled && !descriptionError ? "tw-pr-10" : ""} `}
/>
{/* Description checkmark */}
{isDescriptionFilled && !descriptionError && (
-
diff --git a/generated/models/ApiDistributionAirdropsCsvUploadRequest.ts b/generated/models/ApiDistributionAirdropsCsvUploadRequest.ts
new file mode 100644
index 0000000000..845321fb60
--- /dev/null
+++ b/generated/models/ApiDistributionAirdropsCsvUploadRequest.ts
@@ -0,0 +1,40 @@
+// @ts-nocheck
+/**
+ * 6529.io API
+ * This is the API interface description. Brief terminology overview and an authentication example can be found at https://6529.io/about/api.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+import { HttpFile } from '../http/http';
+
+export class ApiDistributionAirdropsCsvUploadRequest {
+ /**
+ * CSV text with one `address,count` entry per line
+ */
+ 'csv': string;
+
+ static readonly discriminator: string | undefined = undefined;
+
+ static readonly mapping: {[index: string]: string} | undefined = undefined;
+
+ static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
+ {
+ "name": "csv",
+ "baseName": "csv",
+ "type": "string",
+ "format": ""
+ } ];
+
+ static getAttributeTypeMap() {
+ return ApiDistributionAirdropsCsvUploadRequest.attributeTypeMap;
+ }
+
+ public constructor() {
+ }
+}
diff --git a/generated/models/ApiDistributionAirdropsUploadResponse.ts b/generated/models/ApiDistributionAirdropsUploadResponse.ts
new file mode 100644
index 0000000000..3ca2ce8fea
--- /dev/null
+++ b/generated/models/ApiDistributionAirdropsUploadResponse.ts
@@ -0,0 +1,44 @@
+// @ts-nocheck
+/**
+ * 6529.io API
+ * This is the API interface description. Brief terminology overview and an authentication example can be found at https://6529.io/about/api.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+import { HttpFile } from '../http/http';
+
+export class ApiDistributionAirdropsUploadResponse {
+ 'success': boolean;
+ 'message': string;
+
+ static readonly discriminator: string | undefined = undefined;
+
+ static readonly mapping: {[index: string]: string} | undefined = undefined;
+
+ static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
+ {
+ "name": "success",
+ "baseName": "success",
+ "type": "boolean",
+ "format": ""
+ },
+ {
+ "name": "message",
+ "baseName": "message",
+ "type": "string",
+ "format": ""
+ } ];
+
+ static getAttributeTypeMap() {
+ return ApiDistributionAirdropsUploadResponse.attributeTypeMap;
+ }
+
+ public constructor() {
+ }
+}
diff --git a/generated/models/ApiDropWinningContext.ts b/generated/models/ApiDropWinningContext.ts
index 635ca80c0e..b8cb475f15 100644
--- a/generated/models/ApiDropWinningContext.ts
+++ b/generated/models/ApiDropWinningContext.ts
@@ -18,6 +18,9 @@ export class ApiDropWinningContext {
'place': number;
'awards': Array;
'decision_time': number;
+ 'sale_time'?: number | null;
+ 'sale_price'?: number | null;
+ 'sale_price_currency'?: string | null;
static readonly discriminator: string | undefined = undefined;
@@ -41,6 +44,24 @@ export class ApiDropWinningContext {
"baseName": "decision_time",
"type": "number",
"format": "int64"
+ },
+ {
+ "name": "sale_time",
+ "baseName": "sale_time",
+ "type": "number",
+ "format": "int64"
+ },
+ {
+ "name": "sale_price",
+ "baseName": "sale_price",
+ "type": "number",
+ "format": ""
+ },
+ {
+ "name": "sale_price_currency",
+ "baseName": "sale_price_currency",
+ "type": "string",
+ "format": ""
} ];
static getAttributeTypeMap() {
diff --git a/generated/models/ApiIdentityActivity.ts b/generated/models/ApiIdentityActivity.ts
new file mode 100644
index 0000000000..023efedfb5
--- /dev/null
+++ b/generated/models/ApiIdentityActivity.ts
@@ -0,0 +1,44 @@
+// @ts-nocheck
+/**
+ * 6529.io API
+ * This is the API interface description. Brief terminology overview and an authentication example can be found at https://6529.io/about/api.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+import { HttpFile } from '../http/http';
+
+export class ApiIdentityActivity {
+ 'last_date': string;
+ 'date_samples': Array;
+
+ static readonly discriminator: string | undefined = undefined;
+
+ static readonly mapping: {[index: string]: string} | undefined = undefined;
+
+ static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
+ {
+ "name": "last_date",
+ "baseName": "last_date",
+ "type": "string",
+ "format": ""
+ },
+ {
+ "name": "date_samples",
+ "baseName": "date_samples",
+ "type": "Array",
+ "format": "int64"
+ } ];
+
+ static getAttributeTypeMap() {
+ return ApiIdentityActivity.attributeTypeMap;
+ }
+
+ public constructor() {
+ }
+}
diff --git a/generated/models/ApiMintingClaimAction.ts b/generated/models/ApiMintingClaimAction.ts
new file mode 100644
index 0000000000..ec903b2743
--- /dev/null
+++ b/generated/models/ApiMintingClaimAction.ts
@@ -0,0 +1,81 @@
+// @ts-nocheck
+/**
+ * 6529.io API
+ * This is the API interface description. Brief terminology overview and an authentication example can be found at https://6529.io/about/api.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+import { HttpFile } from '../http/http';
+
+export class ApiMintingClaimAction {
+ /**
+ * Contract-specific minting claim action name
+ */
+ 'action': string;
+ 'completed': boolean;
+ /**
+ * Unix epoch milliseconds when this action record was created
+ */
+ 'created_at'?: number;
+ /**
+ * Unix epoch milliseconds when this action record was last updated
+ */
+ 'updated_at'?: number;
+ 'created_by_wallet'?: string;
+ 'updated_by_wallet'?: string;
+
+ static readonly discriminator: string | undefined = undefined;
+
+ static readonly mapping: {[index: string]: string} | undefined = undefined;
+
+ static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
+ {
+ "name": "action",
+ "baseName": "action",
+ "type": "string",
+ "format": ""
+ },
+ {
+ "name": "completed",
+ "baseName": "completed",
+ "type": "boolean",
+ "format": ""
+ },
+ {
+ "name": "created_at",
+ "baseName": "created_at",
+ "type": "number",
+ "format": "int64"
+ },
+ {
+ "name": "updated_at",
+ "baseName": "updated_at",
+ "type": "number",
+ "format": "int64"
+ },
+ {
+ "name": "created_by_wallet",
+ "baseName": "created_by_wallet",
+ "type": "string",
+ "format": ""
+ },
+ {
+ "name": "updated_by_wallet",
+ "baseName": "updated_by_wallet",
+ "type": "string",
+ "format": ""
+ } ];
+
+ static getAttributeTypeMap() {
+ return ApiMintingClaimAction.attributeTypeMap;
+ }
+
+ public constructor() {
+ }
+}
diff --git a/generated/models/ApiMintingClaimActionTypesResponse.ts b/generated/models/ApiMintingClaimActionTypesResponse.ts
new file mode 100644
index 0000000000..4eb0a4a9a0
--- /dev/null
+++ b/generated/models/ApiMintingClaimActionTypesResponse.ts
@@ -0,0 +1,44 @@
+// @ts-nocheck
+/**
+ * 6529.io API
+ * This is the API interface description. Brief terminology overview and an authentication example can be found at https://6529.io/about/api.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+import { HttpFile } from '../http/http';
+
+export class ApiMintingClaimActionTypesResponse {
+ 'contract': string;
+ 'action_types': Array;
+
+ static readonly discriminator: string | undefined = undefined;
+
+ static readonly mapping: {[index: string]: string} | undefined = undefined;
+
+ static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
+ {
+ "name": "contract",
+ "baseName": "contract",
+ "type": "string",
+ "format": ""
+ },
+ {
+ "name": "action_types",
+ "baseName": "action_types",
+ "type": "Array",
+ "format": ""
+ } ];
+
+ static getAttributeTypeMap() {
+ return ApiMintingClaimActionTypesResponse.attributeTypeMap;
+ }
+
+ public constructor() {
+ }
+}
diff --git a/generated/models/ApiMintingClaimActionUpdateRequest.ts b/generated/models/ApiMintingClaimActionUpdateRequest.ts
new file mode 100644
index 0000000000..3cd528498b
--- /dev/null
+++ b/generated/models/ApiMintingClaimActionUpdateRequest.ts
@@ -0,0 +1,47 @@
+// @ts-nocheck
+/**
+ * 6529.io API
+ * This is the API interface description. Brief terminology overview and an authentication example can be found at https://6529.io/about/api.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+import { HttpFile } from '../http/http';
+
+export class ApiMintingClaimActionUpdateRequest {
+ /**
+ * Contract-specific minting claim action name
+ */
+ 'action': string;
+ 'completed': boolean;
+
+ static readonly discriminator: string | undefined = undefined;
+
+ static readonly mapping: {[index: string]: string} | undefined = undefined;
+
+ static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
+ {
+ "name": "action",
+ "baseName": "action",
+ "type": "string",
+ "format": ""
+ },
+ {
+ "name": "completed",
+ "baseName": "completed",
+ "type": "boolean",
+ "format": ""
+ } ];
+
+ static getAttributeTypeMap() {
+ return ApiMintingClaimActionUpdateRequest.attributeTypeMap;
+ }
+
+ public constructor() {
+ }
+}
diff --git a/generated/models/ApiMintingClaimActionsResponse.ts b/generated/models/ApiMintingClaimActionsResponse.ts
new file mode 100644
index 0000000000..6b9524caa7
--- /dev/null
+++ b/generated/models/ApiMintingClaimActionsResponse.ts
@@ -0,0 +1,52 @@
+// @ts-nocheck
+/**
+ * 6529.io API
+ * This is the API interface description. Brief terminology overview and an authentication example can be found at https://6529.io/about/api.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+import { ApiMintingClaimAction } from '../models/ApiMintingClaimAction';
+import { HttpFile } from '../http/http';
+
+export class ApiMintingClaimActionsResponse {
+ 'contract': string;
+ 'claim_id': number;
+ 'actions': Array;
+
+ static readonly discriminator: string | undefined = undefined;
+
+ static readonly mapping: {[index: string]: string} | undefined = undefined;
+
+ static readonly attributeTypeMap: Array<{name: string, baseName: string, type: string, format: string}> = [
+ {
+ "name": "contract",
+ "baseName": "contract",
+ "type": "string",
+ "format": ""
+ },
+ {
+ "name": "claim_id",
+ "baseName": "claim_id",
+ "type": "number",
+ "format": "int64"
+ },
+ {
+ "name": "actions",
+ "baseName": "actions",
+ "type": "Array",
+ "format": ""
+ } ];
+
+ static getAttributeTypeMap() {
+ return ApiMintingClaimActionsResponse.attributeTypeMap;
+ }
+
+ public constructor() {
+ }
+}
diff --git a/generated/models/DistributionOverview.ts b/generated/models/DistributionOverview.ts
index 22b1b5c412..84fdc3580c 100644
--- a/generated/models/DistributionOverview.ts
+++ b/generated/models/DistributionOverview.ts
@@ -23,13 +23,21 @@ export class DistributionOverview {
*/
'is_normalized': boolean;
/**
- * Count of unique addresses with automatic airdrops
+ * Count of unique addresses in the Airdrop - Artist phase
*/
- 'automatic_airdrops_addresses': number;
+ 'artist_airdrops_addresses': number;
/**
- * Total count of automatic airdrops
+ * Total count in the Airdrop - Artist phase
*/
- 'automatic_airdrops_count': number;
+ 'artist_airdrops_count': number;
+ /**
+ * Count of unique addresses in the Airdrop - Team phase
+ */
+ 'team_airdrops_addresses': number;
+ /**
+ * Total count in the Airdrop - Team phase
+ */
+ 'team_airdrops_count': number;
static readonly discriminator: string | undefined = undefined;
@@ -49,14 +57,26 @@ export class DistributionOverview {
"format": ""
},
{
- "name": "automatic_airdrops_addresses",
- "baseName": "automatic_airdrops_addresses",
+ "name": "artist_airdrops_addresses",
+ "baseName": "artist_airdrops_addresses",
+ "type": "number",
+ "format": "int64"
+ },
+ {
+ "name": "artist_airdrops_count",
+ "baseName": "artist_airdrops_count",
+ "type": "number",
+ "format": "int64"
+ },
+ {
+ "name": "team_airdrops_addresses",
+ "baseName": "team_airdrops_addresses",
"type": "number",
"format": "int64"
},
{
- "name": "automatic_airdrops_count",
- "baseName": "automatic_airdrops_count",
+ "name": "team_airdrops_count",
+ "baseName": "team_airdrops_count",
"type": "number",
"format": "int64"
} ];
diff --git a/generated/models/ObjectSerializer.ts b/generated/models/ObjectSerializer.ts
index 4ffaeea605..371509e557 100644
--- a/generated/models/ObjectSerializer.ts
+++ b/generated/models/ObjectSerializer.ts
@@ -62,6 +62,8 @@ export * from '../models/ApiCreateWaveConfig';
export * from '../models/ApiCreateWaveDropRequest';
export * from '../models/ApiCreateWaveOutcome';
export * from '../models/ApiCreateWaveOutcomeDistributionItem';
+export * from '../models/ApiDistributionAirdropsCsvUploadRequest';
+export * from '../models/ApiDistributionAirdropsUploadResponse';
export * from '../models/ApiDrop';
export * from '../models/ApiDropAndDropVote';
export * from '../models/ApiDropBoost';
@@ -101,6 +103,7 @@ export * from '../models/ApiGroupRepFilter';
export * from '../models/ApiGroupTdhFilter';
export * from '../models/ApiGroupTdhInclusionStrategy';
export * from '../models/ApiIdentity';
+export * from '../models/ApiIdentityActivity';
export * from '../models/ApiIdentityAndSubscriptionActions';
export * from '../models/ApiIdentitySubscriptionActions';
export * from '../models/ApiIdentitySubscriptionTargetAction';
@@ -118,6 +121,10 @@ export * from '../models/ApiMemesMintStatsYearly';
export * from '../models/ApiMentionedWave';
export * from '../models/ApiMintMetrics';
export * from '../models/ApiMintMetricsPage';
+export * from '../models/ApiMintingClaimAction';
+export * from '../models/ApiMintingClaimActionTypesResponse';
+export * from '../models/ApiMintingClaimActionUpdateRequest';
+export * from '../models/ApiMintingClaimActionsResponse';
export * from '../models/ApiMintingClaimsPhaseTotalItem';
export * from '../models/ApiNft';
export * from '../models/ApiNftLinkData';
@@ -354,6 +361,8 @@ import { ApiCreateWaveConfig } from '../models/ApiCreateWaveConfig';
import { ApiCreateWaveDropRequest } from '../models/ApiCreateWaveDropRequest';
import { ApiCreateWaveOutcome } from '../models/ApiCreateWaveOutcome';
import { ApiCreateWaveOutcomeDistributionItem } from '../models/ApiCreateWaveOutcomeDistributionItem';
+import { ApiDistributionAirdropsCsvUploadRequest } from '../models/ApiDistributionAirdropsCsvUploadRequest';
+import { ApiDistributionAirdropsUploadResponse } from '../models/ApiDistributionAirdropsUploadResponse';
import { ApiDrop } from '../models/ApiDrop';
import { ApiDropAndDropVote } from '../models/ApiDropAndDropVote';
import { ApiDropBoost } from '../models/ApiDropBoost';
@@ -393,6 +402,7 @@ import { ApiGroupRepFilter } from '../models/ApiGroupRepFilter';
import { ApiGroupTdhFilter } from '../models/ApiGroupTdhFilter';
import { ApiGroupTdhInclusionStrategy } from '../models/ApiGroupTdhInclusionStrategy';
import { ApiIdentity } from '../models/ApiIdentity';
+import { ApiIdentityActivity } from '../models/ApiIdentityActivity';
import { ApiIdentityAndSubscriptionActions } from '../models/ApiIdentityAndSubscriptionActions';
import { ApiIdentitySubscriptionActions } from '../models/ApiIdentitySubscriptionActions';
import { ApiIdentitySubscriptionTargetAction } from '../models/ApiIdentitySubscriptionTargetAction';
@@ -410,6 +420,10 @@ import { ApiMemesMintStatsYearly } from '../models/ApiMemesMintStatsYearly';
import { ApiMentionedWave } from '../models/ApiMentionedWave';
import { ApiMintMetrics } from '../models/ApiMintMetrics';
import { ApiMintMetricsPage } from '../models/ApiMintMetricsPage';
+import { ApiMintingClaimAction } from '../models/ApiMintingClaimAction';
+import { ApiMintingClaimActionTypesResponse } from '../models/ApiMintingClaimActionTypesResponse';
+import { ApiMintingClaimActionUpdateRequest } from '../models/ApiMintingClaimActionUpdateRequest';
+import { ApiMintingClaimActionsResponse } from '../models/ApiMintingClaimActionsResponse';
import { ApiMintingClaimsPhaseTotalItem } from '../models/ApiMintingClaimsPhaseTotalItem';
import { ApiNft , ApiNftTokenTypeEnum } from '../models/ApiNft';
import { ApiNftLinkData } from '../models/ApiNftLinkData';
@@ -697,6 +711,8 @@ let typeMap: {[index: string]: any} = {
"ApiCreateWaveDropRequest": ApiCreateWaveDropRequest,
"ApiCreateWaveOutcome": ApiCreateWaveOutcome,
"ApiCreateWaveOutcomeDistributionItem": ApiCreateWaveOutcomeDistributionItem,
+ "ApiDistributionAirdropsCsvUploadRequest": ApiDistributionAirdropsCsvUploadRequest,
+ "ApiDistributionAirdropsUploadResponse": ApiDistributionAirdropsUploadResponse,
"ApiDrop": ApiDrop,
"ApiDropAndDropVote": ApiDropAndDropVote,
"ApiDropBoost": ApiDropBoost,
@@ -730,6 +746,7 @@ let typeMap: {[index: string]: any} = {
"ApiGroupRepFilter": ApiGroupRepFilter,
"ApiGroupTdhFilter": ApiGroupTdhFilter,
"ApiIdentity": ApiIdentity,
+ "ApiIdentityActivity": ApiIdentityActivity,
"ApiIdentityAndSubscriptionActions": ApiIdentityAndSubscriptionActions,
"ApiIdentitySubscriptionActions": ApiIdentitySubscriptionActions,
"ApiIncomingIdentitySubscriptionsPage": ApiIncomingIdentitySubscriptionsPage,
@@ -745,6 +762,10 @@ let typeMap: {[index: string]: any} = {
"ApiMentionedWave": ApiMentionedWave,
"ApiMintMetrics": ApiMintMetrics,
"ApiMintMetricsPage": ApiMintMetricsPage,
+ "ApiMintingClaimAction": ApiMintingClaimAction,
+ "ApiMintingClaimActionTypesResponse": ApiMintingClaimActionTypesResponse,
+ "ApiMintingClaimActionUpdateRequest": ApiMintingClaimActionUpdateRequest,
+ "ApiMintingClaimActionsResponse": ApiMintingClaimActionsResponse,
"ApiMintingClaimsPhaseTotalItem": ApiMintingClaimsPhaseTotalItem,
"ApiNft": ApiNft,
"ApiNftLinkData": ApiNftLinkData,
diff --git a/openapi.yaml b/openapi.yaml
index d18871e0fd..5d871fc5ab 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -771,12 +771,16 @@ paths:
description: Invalid request
"403":
description: Forbidden - not a Subscription Admin
- /distributions/{contract}/{id}/airdrops_artist:
+ /distributions/{contract}/{id}/artist-airdrops:
get:
tags:
- Distributions
summary: Get artist airdrops for a specific contract and card
- operationId: getDistributionAirdropsArtist
+ description: >-
+ Requires the user to be authenticated as a Subscription Admin. Returns
+ JSON by default, or CSV in `address,count` format when the client sends
+ `Accept: text/csv`.
+ operationId: getDistributionArtistAirdrops
parameters:
- name: contract
in: path
@@ -800,14 +804,66 @@ paths:
type: array
items:
$ref: "#/components/schemas/PhaseAirdrop"
+ text/csv:
+ schema:
+ type: string
+ format: binary
+ "400":
+ description: Invalid request
+ "403":
+ description: Forbidden - not a Subscription Admin
+ post:
+ tags:
+ - Distributions
+ summary: Upload artist airdrops for a specific contract and card
+ description: >-
+ Requires the user to be authenticated as a Subscription Admin. Replaces
+ any existing distribution rows for the Airdrop - Artist phase on the
+ given token. The request body must be `application/json` matching
+ `ApiDistributionAirdropsCsvUploadRequest`, with a `csv` property whose
+ value is CSV text in `address,count` format.
+ operationId: uploadDistributionArtistAirdrops
+ parameters:
+ - name: contract
+ in: path
+ description: Contract address
+ required: true
+ schema:
+ type: string
+ - name: id
+ in: path
+ description: Card ID
+ required: true
+ schema:
+ type: integer
+ format: int64
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ApiDistributionAirdropsCsvUploadRequest"
+ responses:
+ "200":
+ description: successful operation
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ApiDistributionAirdropsUploadResponse"
"400":
description: Invalid request
- /distributions/{contract}/{id}/airdrops_team:
+ "403":
+ description: Forbidden - not a Subscription Admin
+ /distributions/{contract}/{id}/team-airdrops:
get:
tags:
- Distributions
summary: Get team airdrops for a specific contract and card
- operationId: getDistributionAirdropsTeam
+ description: >-
+ Requires the user to be authenticated as a Subscription Admin. Returns
+ JSON by default, or CSV in `address,count` format when the client sends
+ `Accept: text/csv`.
+ operationId: getDistributionTeamAirdrops
parameters:
- name: contract
in: path
@@ -831,8 +887,56 @@ paths:
type: array
items:
$ref: "#/components/schemas/PhaseAirdrop"
+ text/csv:
+ schema:
+ type: string
+ format: binary
+ "400":
+ description: Invalid request
+ "403":
+ description: Forbidden - not a Subscription Admin
+ post:
+ tags:
+ - Distributions
+ summary: Upload team airdrops for a specific contract and card
+ description: >-
+ Requires the user to be authenticated as a Subscription Admin. Replaces
+ any existing distribution rows for the Airdrop - Team phase on the given
+ token. The request body must be `application/json` matching
+ `ApiDistributionAirdropsCsvUploadRequest`, with a `csv` property whose
+ value is CSV text in `address,count` format.
+ operationId: uploadDistributionTeamAirdrops
+ parameters:
+ - name: contract
+ in: path
+ description: Contract address
+ required: true
+ schema:
+ type: string
+ - name: id
+ in: path
+ description: Card ID
+ required: true
+ schema:
+ type: integer
+ format: int64
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ApiDistributionAirdropsCsvUploadRequest"
+ responses:
+ "200":
+ description: successful operation
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ApiDistributionAirdropsUploadResponse"
"400":
description: Invalid request
+ "403":
+ description: Forbidden - not a Subscription Admin
/light-drops:
get:
tags:
@@ -2029,6 +2133,27 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/ApiIdentitySubscriptionActions"
+ /identities/{id}/activity:
+ get:
+ tags:
+ - Identities
+ summary: Get daily public-wave drop activity for an identity.
+ operationId: getIdentityActivity
+ parameters:
+ - name: id
+ in: path
+ required: true
+ schema:
+ type: string
+ responses:
+ "200":
+ description: successful operation
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ApiIdentityActivity"
+ "404":
+ description: Identity not found
/memes-mint-stats:
get:
tags:
@@ -2339,6 +2464,7 @@ paths:
schema:
type: integer
format: int64
+ minimum: 1
responses:
"200":
description: successful operation
@@ -2374,6 +2500,7 @@ paths:
schema:
type: integer
format: int64
+ minimum: 1
requestBody:
content:
application/json:
@@ -2416,6 +2543,7 @@ paths:
schema:
type: integer
format: int64
+ minimum: 1
responses:
"202":
description: Accepted; work queued
@@ -2433,6 +2561,123 @@ paths:
description: Claim not found
"409":
description: Conflict - claim already synced or upload already in progress
+ /minting-claims/actions/{contract}/types:
+ get:
+ tags:
+ - Minting Claims
+ summary: >-
+ Get supported minting claim action types for a contract (claims admin
+ only)
+ description: >
+ Returns the supported minting claim action names for the given contract.
+ Only CLAIMS_ADMIN_WALLETS can call this. Unsupported contracts return
+ 400.
+ operationId: getMintingClaimActionTypes
+ parameters:
+ - name: contract
+ in: path
+ required: true
+ schema:
+ type: string
+ pattern: ^0x[a-fA-F0-9]{40}$
+ responses:
+ "200":
+ description: successful operation
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ApiMintingClaimActionTypesResponse"
+ "400":
+ description: Unsupported contract
+ "401":
+ description: Unauthorized - authentication required
+ "403":
+ description: Forbidden - only claims admins can access
+ /minting-claims/actions/{contract}/{claim_id}:
+ get:
+ tags:
+ - Minting Claims
+ summary: Get minting claim actions (claims admin only)
+ description: >
+ Returns the current action state for a minting claim. All supported
+ actions for the contract are always returned; missing records are
+ represented as completed=false. Only CLAIMS_ADMIN_WALLETS can call this.
+ Unsupported contracts return 400.
+ operationId: getMintingClaimActions
+ parameters:
+ - name: contract
+ in: path
+ required: true
+ schema:
+ type: string
+ pattern: ^0x[a-fA-F0-9]{40}$
+ - name: claim_id
+ in: path
+ required: true
+ schema:
+ type: integer
+ format: int64
+ minimum: 1
+ responses:
+ "200":
+ description: successful operation
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ApiMintingClaimActionsResponse"
+ "400":
+ description: Invalid request or unsupported contract
+ "401":
+ description: Unauthorized - authentication required
+ "403":
+ description: Forbidden - only claims admins can access
+ "404":
+ description: Claim not found
+ post:
+ tags:
+ - Minting Claims
+ summary: Upsert minting claim action state (claims admin only)
+ description: >
+ Creates or updates the current state of a minting claim action for the
+ given claim. The caller wallet is recorded as the actor. Only
+ CLAIMS_ADMIN_WALLETS can call this. Unsupported contracts or unsupported
+ action names for the given contract return 400.
+ operationId: postMintingClaimAction
+ parameters:
+ - name: contract
+ in: path
+ required: true
+ schema:
+ type: string
+ pattern: ^0x[a-fA-F0-9]{40}$
+ - name: claim_id
+ in: path
+ required: true
+ schema:
+ type: integer
+ format: int64
+ minimum: 1
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ApiMintingClaimActionUpdateRequest"
+ responses:
+ "200":
+ description: successful operation
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ApiMintingClaimActionsResponse"
+ "400":
+ description: Invalid request or unsupported contract
+ "401":
+ description: Unauthorized - authentication required
+ "403":
+ description: Forbidden - only claims admins can update
+ "404":
+ description: Claim not found
/nft-link:
get:
tags:
@@ -7912,6 +8157,27 @@ components:
description:
type: string
nullable: true
+ ApiDistributionAirdropsCsvUploadRequest:
+ type: object
+ required:
+ - csv
+ properties:
+ csv:
+ type: string
+ description: CSV text with one `address,count` entry per line
+ example: |-
+ 0x0000000000000000000000000000000000000001,2
+ 0x0000000000000000000000000000000000000002,1
+ ApiDistributionAirdropsUploadResponse:
+ type: object
+ required:
+ - success
+ - message
+ properties:
+ success:
+ type: boolean
+ message:
+ type: string
ApiDrop:
type: object
required:
@@ -8339,6 +8605,16 @@ components:
decision_time:
type: integer
format: int64
+ sale_time:
+ type: integer
+ format: int64
+ nullable: true
+ sale_price:
+ type: number
+ nullable: true
+ sale_price_currency:
+ type: string
+ nullable: true
ApiDropWithoutWave:
type: object
required:
@@ -8811,6 +9087,23 @@ components:
format: int64
is_wave_creator:
type: boolean
+ ApiIdentityActivity:
+ type: object
+ required:
+ - last_date
+ - date_samples
+ properties:
+ last_date:
+ type: string
+ example: 12.03.2026
+ date_samples:
+ type: array
+ minItems: 365
+ maxItems: 365
+ items:
+ type: integer
+ format: int64
+ minimum: 0
ApiIdentityAndSubscriptionActions:
type: object
required:
@@ -9058,6 +9351,76 @@ components:
type: string
wave:
$ref: "#/components/schemas/ApiWaveMin"
+ ApiMintingClaimAction:
+ type: object
+ required:
+ - action
+ - completed
+ properties:
+ action:
+ type: string
+ minLength: 1
+ pattern: ^[A-Z0-9_]+$
+ description: Contract-specific minting claim action name
+ completed:
+ type: boolean
+ created_at:
+ type: integer
+ format: int64
+ description: Unix epoch milliseconds when this action record was created
+ updated_at:
+ type: integer
+ format: int64
+ description: Unix epoch milliseconds when this action record was last updated
+ created_by_wallet:
+ $ref: "#/components/schemas/ApiEthereumAddress"
+ description: Wallet that first created this action record
+ updated_by_wallet:
+ $ref: "#/components/schemas/ApiEthereumAddress"
+ description: Wallet that last updated this action record
+ ApiMintingClaimActionsResponse:
+ type: object
+ required:
+ - contract
+ - claim_id
+ - actions
+ properties:
+ contract:
+ type: string
+ claim_id:
+ type: integer
+ format: int64
+ actions:
+ type: array
+ items:
+ $ref: "#/components/schemas/ApiMintingClaimAction"
+ ApiMintingClaimActionTypesResponse:
+ type: object
+ required:
+ - contract
+ - action_types
+ properties:
+ contract:
+ type: string
+ action_types:
+ type: array
+ items:
+ type: string
+ minLength: 1
+ description: Contract-specific minting claim action name
+ ApiMintingClaimActionUpdateRequest:
+ type: object
+ required:
+ - action
+ - completed
+ properties:
+ action:
+ type: string
+ minLength: 1
+ pattern: ^[A-Z0-9_]+$
+ description: Contract-specific minting claim action name
+ completed:
+ type: boolean
ApiMintingClaimsPhaseTotalItem:
type: object
required:
@@ -11855,8 +12218,10 @@ components:
required:
- photos_count
- is_normalized
- - automatic_airdrops_addresses
- - automatic_airdrops_count
+ - artist_airdrops_addresses
+ - artist_airdrops_count
+ - team_airdrops_addresses
+ - team_airdrops_count
properties:
photos_count:
type: integer
@@ -11865,14 +12230,22 @@ components:
is_normalized:
type: boolean
description: Whether the distribution has been normalized
- automatic_airdrops_addresses:
+ artist_airdrops_addresses:
+ type: integer
+ format: int64
+ description: Count of unique addresses in the Airdrop - Artist phase
+ artist_airdrops_count:
+ type: integer
+ format: int64
+ description: Total count in the Airdrop - Artist phase
+ team_airdrops_addresses:
type: integer
format: int64
- description: Count of unique addresses with automatic airdrops
- automatic_airdrops_count:
+ description: Count of unique addresses in the Airdrop - Team phase
+ team_airdrops_count:
type: integer
format: int64
- description: Total count of automatic airdrops
+ description: Total count in the Airdrop - Team phase
DistributionPhasesPage:
type: object
required:
diff --git a/services/api/memes-minting-claims-api.ts b/services/api/memes-minting-claims-api.ts
index cb8506a74b..485d9524d2 100644
--- a/services/api/memes-minting-claims-api.ts
+++ b/services/api/memes-minting-claims-api.ts
@@ -1,4 +1,7 @@
import { MEMES_CONTRACT } from "@/constants/constants";
+import type { ApiMintingClaimActionTypesResponse } from "@/generated/models/ApiMintingClaimActionTypesResponse";
+import type { ApiMintingClaimActionsResponse } from "@/generated/models/ApiMintingClaimActionsResponse";
+import type { ApiMintingClaimActionUpdateRequest } from "@/generated/models/ApiMintingClaimActionUpdateRequest";
import type { MintingClaim } from "@/generated/models/MintingClaim";
import type { MintingClaimsPageResponse } from "@/generated/models/MintingClaimsPageResponse";
import type { MintingClaimsProofsResponse } from "@/generated/models/MintingClaimsProofsResponse";
@@ -8,6 +11,7 @@ import type { PhaseAirdrop } from "@/generated/models/PhaseAirdrop";
import {
commonApiFetch,
commonApiPatch,
+ commonApiPost,
commonApiPostWithoutBodyAndResponse,
} from "@/services/api/common-api";
import { multipartUploadCore } from "@/services/uploads/multipartUploadCore";
@@ -73,6 +77,33 @@ export async function getClaim(claimId: number): Promise {
});
}
+export async function getMemesMintingClaimActionTypes(): Promise {
+ return commonApiFetch({
+ endpoint: `minting-claims/actions/${encodeURIComponent(MEMES_CONTRACT)}/types`,
+ });
+}
+
+export async function getMemesMintingClaimActions(
+ claimId: number
+): Promise {
+ return commonApiFetch({
+ endpoint: `minting-claims/actions/${encodeURIComponent(MEMES_CONTRACT)}/${claimId}`,
+ });
+}
+
+export async function upsertMemesMintingClaimAction(
+ claimId: number,
+ body: ApiMintingClaimActionUpdateRequest
+): Promise {
+ return commonApiPost<
+ ApiMintingClaimActionUpdateRequest,
+ ApiMintingClaimActionsResponse
+ >({
+ endpoint: `minting-claims/actions/${encodeURIComponent(MEMES_CONTRACT)}/${claimId}`,
+ body,
+ });
+}
+
export async function getMemesMintingRoots(
cardId: number
): Promise {
@@ -150,7 +181,7 @@ export async function getDistributionAirdropsArtist(
cardId: number
): Promise {
return commonApiFetch({
- endpoint: `distributions/${contract}/${cardId}/airdrops_artist`,
+ endpoint: `distributions/${contract}/${cardId}/artist-airdrops`,
});
}
@@ -159,7 +190,7 @@ export async function getDistributionAirdropsTeam(
cardId: number
): Promise {
return commonApiFetch({
- endpoint: `distributions/${contract}/${cardId}/airdrops_team`,
+ endpoint: `distributions/${contract}/${cardId}/team-airdrops`,
});
}