ani-ads-sdk 1.0.1 → 1.0.2
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/dist/index.d.mts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +13 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -58
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -2
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -29,7 +29,6 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
29
29
|
var AniAds = ({
|
|
30
30
|
creator_code,
|
|
31
31
|
user_wallet_address,
|
|
32
|
-
ad_format,
|
|
33
32
|
api_url = "https://ani-ads.vercel.app",
|
|
34
33
|
// Replace with your Ani Ads API domain
|
|
35
34
|
onAdClick
|
|
@@ -37,51 +36,9 @@ var AniAds = ({
|
|
|
37
36
|
const [ad, setAd] = (0, import_react.useState)(null);
|
|
38
37
|
const [loading, setLoading] = (0, import_react.useState)(true);
|
|
39
38
|
const [error, setError] = (0, import_react.useState)(null);
|
|
40
|
-
const
|
|
41
|
-
return
|
|
42
|
-
}, [ad_format]);
|
|
43
|
-
const getImageUrl = (ad2, format) => {
|
|
44
|
-
const normalizedFormat = format.toLowerCase().replace(/[:\s]/g, "");
|
|
45
|
-
if (normalizedFormat === "11" || normalizedFormat === "1:1") {
|
|
46
|
-
return ad2.image_square || null;
|
|
47
|
-
} else if (normalizedFormat === "916" || normalizedFormat === "9:16") {
|
|
48
|
-
return ad2.image_portrait || null;
|
|
49
|
-
} else if (normalizedFormat === "169" || normalizedFormat === "16:9") {
|
|
50
|
-
return ad2.image_landscape || null;
|
|
51
|
-
}
|
|
52
|
-
return null;
|
|
39
|
+
const getImageUrl = (ad2) => {
|
|
40
|
+
return ad2.image_square || null;
|
|
53
41
|
};
|
|
54
|
-
const fetchAd = (0, import_react.useCallback)(async () => {
|
|
55
|
-
try {
|
|
56
|
-
setLoading(true);
|
|
57
|
-
setError(null);
|
|
58
|
-
const response = await fetch(`${api_url}/api/ads/sdk`, {
|
|
59
|
-
method: "POST",
|
|
60
|
-
headers: {
|
|
61
|
-
"Content-Type": "application/json"
|
|
62
|
-
},
|
|
63
|
-
body: JSON.stringify({
|
|
64
|
-
creator_code,
|
|
65
|
-
formats
|
|
66
|
-
})
|
|
67
|
-
});
|
|
68
|
-
if (!response.ok) {
|
|
69
|
-
throw new Error("Failed to fetch ads");
|
|
70
|
-
}
|
|
71
|
-
const data = await response.json();
|
|
72
|
-
if (data.ad) {
|
|
73
|
-
setAd(data.ad);
|
|
74
|
-
} else {
|
|
75
|
-
setAd(null);
|
|
76
|
-
}
|
|
77
|
-
} catch (err) {
|
|
78
|
-
console.error("Error fetching ad:", err);
|
|
79
|
-
setError(err instanceof Error ? err.message : "Failed to load ad");
|
|
80
|
-
setAd(null);
|
|
81
|
-
} finally {
|
|
82
|
-
setLoading(false);
|
|
83
|
-
}
|
|
84
|
-
}, [creator_code, formats, api_url]);
|
|
85
42
|
const handleClick = (0, import_react.useCallback)(async () => {
|
|
86
43
|
if (!ad || !user_wallet_address) return;
|
|
87
44
|
try {
|
|
@@ -106,18 +63,14 @@ var AniAds = ({
|
|
|
106
63
|
console.error("Error tracking click:", err);
|
|
107
64
|
window.open(ad.destination_url, "_blank", "noopener,noreferrer");
|
|
108
65
|
}
|
|
109
|
-
}, [ad, creator_code, user_wallet_address, api_url, onAdClick
|
|
66
|
+
}, [ad, creator_code, user_wallet_address, api_url, onAdClick]);
|
|
110
67
|
const getBestImage = (ad2) => {
|
|
111
|
-
|
|
112
|
-
const imageUrl2 = getImageUrl(ad2, format);
|
|
113
|
-
if (imageUrl2) return imageUrl2;
|
|
114
|
-
}
|
|
115
|
-
return ad2.image_square || ad2.image_portrait || ad2.image_landscape || null;
|
|
68
|
+
return getImageUrl(ad2);
|
|
116
69
|
};
|
|
117
70
|
(0, import_react.useEffect)(() => {
|
|
118
71
|
let cancelled = false;
|
|
119
72
|
const loadAd = async () => {
|
|
120
|
-
if (!creator_code
|
|
73
|
+
if (!creator_code) {
|
|
121
74
|
setLoading(false);
|
|
122
75
|
return;
|
|
123
76
|
}
|
|
@@ -130,25 +83,28 @@ var AniAds = ({
|
|
|
130
83
|
"Content-Type": "application/json"
|
|
131
84
|
},
|
|
132
85
|
body: JSON.stringify({
|
|
133
|
-
creator_code
|
|
134
|
-
formats
|
|
86
|
+
creator_code
|
|
135
87
|
})
|
|
136
88
|
});
|
|
137
89
|
if (cancelled) return;
|
|
138
90
|
if (!response.ok) {
|
|
139
|
-
|
|
91
|
+
const errorData = await response.json().catch(() => ({}));
|
|
92
|
+
throw new Error(errorData.error || `HTTP ${response.status}: Failed to fetch ads`);
|
|
140
93
|
}
|
|
141
94
|
const data = await response.json();
|
|
142
95
|
if (cancelled) return;
|
|
143
96
|
if (data.ad) {
|
|
144
97
|
setAd(data.ad);
|
|
98
|
+
setError(null);
|
|
145
99
|
} else {
|
|
146
100
|
setAd(null);
|
|
101
|
+
setError(null);
|
|
147
102
|
}
|
|
148
103
|
} catch (err) {
|
|
149
104
|
if (cancelled) return;
|
|
150
105
|
console.error("Error fetching ad:", err);
|
|
151
|
-
|
|
106
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to load ad";
|
|
107
|
+
setError(errorMessage);
|
|
152
108
|
setAd(null);
|
|
153
109
|
} finally {
|
|
154
110
|
if (!cancelled) {
|
|
@@ -160,7 +116,7 @@ var AniAds = ({
|
|
|
160
116
|
return () => {
|
|
161
117
|
cancelled = true;
|
|
162
118
|
};
|
|
163
|
-
}, [creator_code,
|
|
119
|
+
}, [creator_code, api_url]);
|
|
164
120
|
if (loading) {
|
|
165
121
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
166
122
|
display: "flex",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback, useMemo } from 'react'\r\n\r\nexport interface AniAdsProps {\r\n creator_code: string\r\n user_wallet_address: string\r\n ad_format: string[] | string // Can be array like [\"16:9\", \"9:16\"] or string like \"16:9,9:16\"\r\n api_url?: string // Optional API URL, defaults to production\r\n onAdClick?: (adId: string, destinationUrl: string) => void // Optional click handler\r\n}\r\n\r\ninterface Ad {\r\n id: string\r\n title: string\r\n destination_url: string\r\n image_square: string\r\n image_portrait: string\r\n image_landscape: string\r\n status: 'active' | 'paused' | 'deleting'\r\n remaining_budget: number\r\n}\r\n\r\nexport const AniAds: React.FC<AniAdsProps> = ({\r\n creator_code,\r\n user_wallet_address,\r\n ad_format,\r\n api_url = 'https://ani-ads.vercel.app', // Replace with your Ani Ads API domain\r\n onAdClick,\r\n}) => {\r\n const [ad, setAd] = useState<Ad | null>(null)\r\n const [loading, setLoading] = useState(true)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n // Parse ad format - memoized to prevent unnecessary re-renders\r\n const formats = useMemo(() => {\r\n return Array.isArray(ad_format) \r\n ? ad_format \r\n : typeof ad_format === 'string' \r\n ? ad_format.split(',').map(f => f.trim())\r\n : []\r\n }, [ad_format])\r\n\r\n // Map format strings to image keys\r\n const getImageUrl = (ad: Ad, format: string): string | null => {\r\n const normalizedFormat = format.toLowerCase().replace(/[:\\s]/g, '')\r\n \r\n if (normalizedFormat === '11' || normalizedFormat === '1:1') {\r\n return ad.image_square || null\r\n } else if (normalizedFormat === '916' || normalizedFormat === '9:16') {\r\n return ad.image_portrait || null\r\n } else if (normalizedFormat === '169' || normalizedFormat === '16:9') {\r\n return ad.image_landscape || null\r\n }\r\n \r\n return null\r\n }\r\n\r\n // Fetch available ads\r\n const fetchAd = useCallback(async () => {\r\n try {\r\n setLoading(true)\r\n setError(null)\r\n\r\n const response = await fetch(`${api_url}/api/ads/sdk`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n creator_code,\r\n formats,\r\n }),\r\n })\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to fetch ads')\r\n }\r\n\r\n const data = await response.json()\r\n \r\n if (data.ad) {\r\n setAd(data.ad)\r\n } else {\r\n setAd(null)\r\n }\r\n } catch (err) {\r\n console.error('Error fetching ad:', err)\r\n setError(err instanceof Error ? err.message : 'Failed to load ad')\r\n setAd(null)\r\n } finally {\r\n setLoading(false)\r\n }\r\n }, [creator_code, formats, api_url]) // formats is memoized, so this is safe\r\n\r\n // Track ad click\r\n const handleClick = useCallback(async () => {\r\n if (!ad || !user_wallet_address) return\r\n\r\n try {\r\n // Track click on backend\r\n const response = await fetch(`${api_url}/api/ads/click`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n ad_id: ad.id,\r\n creator_code,\r\n user_wallet_address: user_wallet_address.toLowerCase(),\r\n }),\r\n })\r\n\r\n if (response.ok) {\r\n // Call optional click handler\r\n if (onAdClick) {\r\n onAdClick(ad.id, ad.destination_url)\r\n }\r\n\r\n // Open destination URL\r\n window.open(ad.destination_url, '_blank', 'noopener,noreferrer')\r\n\r\n // Don't fetch new ad after click - keep showing the same ad until page reload\r\n }\r\n } catch (err) {\r\n console.error('Error tracking click:', err)\r\n // Still open the URL even if tracking fails\r\n window.open(ad.destination_url, '_blank', 'noopener,noreferrer')\r\n }\r\n }, [ad, creator_code, user_wallet_address, api_url, onAdClick, fetchAd])\r\n\r\n // Find best matching image for formats\r\n const getBestImage = (ad: Ad): string | null => {\r\n for (const format of formats) {\r\n const imageUrl = getImageUrl(ad, format)\r\n if (imageUrl) return imageUrl\r\n }\r\n // Fallback to any available image\r\n return ad.image_square || ad.image_portrait || ad.image_landscape || null\r\n }\r\n\r\n // Fetch ad only once when component mounts or when creator_code/ad_format changes\r\n useEffect(() => {\r\n let cancelled = false\r\n \r\n const loadAd = async () => {\r\n if (!creator_code || formats.length === 0) {\r\n setLoading(false)\r\n return\r\n }\r\n\r\n try {\r\n setLoading(true)\r\n setError(null)\r\n\r\n const response = await fetch(`${api_url}/api/ads/sdk`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n creator_code,\r\n formats,\r\n }),\r\n })\r\n\r\n if (cancelled) return\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to fetch ads')\r\n }\r\n\r\n const data = await response.json()\r\n \r\n if (cancelled) return\r\n \r\n if (data.ad) {\r\n setAd(data.ad)\r\n } else {\r\n setAd(null)\r\n }\r\n } catch (err) {\r\n if (cancelled) return\r\n console.error('Error fetching ad:', err)\r\n setError(err instanceof Error ? err.message : 'Failed to load ad')\r\n setAd(null)\r\n } finally {\r\n if (!cancelled) {\r\n setLoading(false)\r\n }\r\n }\r\n }\r\n\r\n loadAd()\r\n\r\n return () => {\r\n cancelled = true\r\n }\r\n }, [creator_code, ad_format, api_url]) // Only depend on props, not derived values\r\n\r\n if (loading) {\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n width: '100%',\r\n minHeight: '100px',\r\n backgroundColor: '#f3f4f6',\r\n borderRadius: '8px',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n }}>\r\n <span style={{ color: '#6b7280' }}>Loading ad...</span>\r\n </div>\r\n )\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n width: '100%',\r\n minHeight: '100px',\r\n backgroundColor: '#fee2e2',\r\n borderRadius: '8px',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n padding: '12px',\r\n }}>\r\n <span style={{ color: '#dc2626', fontSize: '14px' }}>{error}</span>\r\n </div>\r\n )\r\n }\r\n\r\n if (!ad) {\r\n return null // Don't render anything if no ad available\r\n }\r\n\r\n const imageUrl = getBestImage(ad)\r\n\r\n if (!imageUrl) {\r\n return null\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n display: 'inline-block',\r\n width: '100%',\r\n cursor: 'pointer',\r\n borderRadius: '8px',\r\n overflow: 'hidden',\r\n transition: 'transform 0.2s, box-shadow 0.2s',\r\n }}\r\n onClick={handleClick}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.transform = 'scale(1.02)'\r\n e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)'\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.transform = 'scale(1)'\r\n e.currentTarget.style.boxShadow = 'none'\r\n }}\r\n >\r\n <img\r\n src={imageUrl}\r\n alt={ad.title}\r\n style={{\r\n width: '100%',\r\n height: 'auto',\r\n display: 'block',\r\n }}\r\n loading=\"lazy\"\r\n />\r\n </div>\r\n )\r\n}\r\n\r\nexport default AniAds\r\n\r\n"],"mappings":"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","names":["ad","imageUrl"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback, useMemo } from 'react'\r\n\r\nexport interface AniAdsProps {\r\n creator_code: string\r\n user_wallet_address: string\r\n api_url?: string // Optional API URL, defaults to production\r\n onAdClick?: (adId: string, destinationUrl: string) => void // Optional click handler\r\n}\r\n\r\ninterface Ad {\r\n id: string\r\n title: string\r\n destination_url: string\r\n image_square: string\r\n image_portrait: string\r\n image_landscape: string\r\n status: 'active' | 'paused' | 'deleting'\r\n remaining_budget: number\r\n}\r\n\r\nexport const AniAds: React.FC<AniAdsProps> = ({\r\n creator_code,\r\n user_wallet_address,\r\n api_url = 'https://ani-ads.vercel.app', // Replace with your Ani Ads API domain\r\n onAdClick,\r\n}) => {\r\n const [ad, setAd] = useState<Ad | null>(null)\r\n const [loading, setLoading] = useState(true)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n // Get image URL - always use image_square (380x90 banner format)\r\n const getImageUrl = (ad: Ad): string | null => {\r\n return ad.image_square || null\r\n }\r\n\r\n // Track ad click\r\n const handleClick = useCallback(async () => {\r\n if (!ad || !user_wallet_address) return\r\n\r\n try {\r\n // Track click on backend\r\n const response = await fetch(`${api_url}/api/ads/click`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n ad_id: ad.id,\r\n creator_code,\r\n user_wallet_address: user_wallet_address.toLowerCase(),\r\n }),\r\n })\r\n\r\n if (response.ok) {\r\n // Call optional click handler\r\n if (onAdClick) {\r\n onAdClick(ad.id, ad.destination_url)\r\n }\r\n\r\n // Open destination URL\r\n window.open(ad.destination_url, '_blank', 'noopener,noreferrer')\r\n\r\n // Don't fetch new ad after click - keep showing the same ad until page reload\r\n }\r\n } catch (err) {\r\n console.error('Error tracking click:', err)\r\n // Still open the URL even if tracking fails\r\n window.open(ad.destination_url, '_blank', 'noopener,noreferrer')\r\n }\r\n }, [ad, creator_code, user_wallet_address, api_url, onAdClick])\r\n\r\n // Get image - always use banner format (380x90)\r\n const getBestImage = (ad: Ad): string | null => {\r\n return getImageUrl(ad)\r\n }\r\n\r\n // Fetch ad only once when component mounts or when creator_code/ad_format changes\r\n useEffect(() => {\r\n let cancelled = false\r\n \r\n const loadAd = async () => {\r\n if (!creator_code) {\r\n setLoading(false)\r\n return\r\n }\r\n\r\n try {\r\n setLoading(true)\r\n setError(null)\r\n\r\n const response = await fetch(`${api_url}/api/ads/sdk`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n creator_code,\r\n }),\r\n })\r\n\r\n if (cancelled) return\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}))\r\n throw new Error(errorData.error || `HTTP ${response.status}: Failed to fetch ads`)\r\n }\r\n\r\n const data = await response.json()\r\n \r\n if (cancelled) return\r\n \r\n if (data.ad) {\r\n setAd(data.ad)\r\n setError(null) // Clear any previous errors\r\n } else {\r\n // No ad available, but not an error - just don't show anything\r\n setAd(null)\r\n setError(null)\r\n }\r\n } catch (err) {\r\n if (cancelled) return\r\n console.error('Error fetching ad:', err)\r\n const errorMessage = err instanceof Error ? err.message : 'Failed to load ad'\r\n setError(errorMessage)\r\n setAd(null)\r\n } finally {\r\n if (!cancelled) {\r\n setLoading(false)\r\n }\r\n }\r\n }\r\n\r\n loadAd()\r\n\r\n return () => {\r\n cancelled = true\r\n }\r\n }, [creator_code, api_url]) // Only depend on props, not derived values\r\n\r\n if (loading) {\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n width: '100%',\r\n minHeight: '100px',\r\n backgroundColor: '#f3f4f6',\r\n borderRadius: '8px',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n }}>\r\n <span style={{ color: '#6b7280' }}>Loading ad...</span>\r\n </div>\r\n )\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n width: '100%',\r\n minHeight: '100px',\r\n backgroundColor: '#fee2e2',\r\n borderRadius: '8px',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n padding: '12px',\r\n }}>\r\n <span style={{ color: '#dc2626', fontSize: '14px' }}>{error}</span>\r\n </div>\r\n )\r\n }\r\n\r\n if (!ad) {\r\n return null // Don't render anything if no ad available\r\n }\r\n\r\n const imageUrl = getBestImage(ad)\r\n\r\n if (!imageUrl) {\r\n return null\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n display: 'inline-block',\r\n width: '100%',\r\n cursor: 'pointer',\r\n borderRadius: '8px',\r\n overflow: 'hidden',\r\n transition: 'transform 0.2s, box-shadow 0.2s',\r\n }}\r\n onClick={handleClick}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.transform = 'scale(1.02)'\r\n e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)'\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.transform = 'scale(1)'\r\n e.currentTarget.style.boxShadow = 'none'\r\n }}\r\n >\r\n <img\r\n src={imageUrl}\r\n alt={ad.title}\r\n style={{\r\n width: '100%',\r\n height: 'auto',\r\n display: 'block',\r\n }}\r\n loading=\"lazy\"\r\n />\r\n </div>\r\n )\r\n}\r\n\r\nexport default AniAds\r\n\r\n"],"mappings":"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","names":["ad"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// src/index.tsx
|
|
2
|
-
import { useEffect, useState, useCallback
|
|
2
|
+
import { useEffect, useState, useCallback } from "react";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
var AniAds = ({
|
|
5
5
|
creator_code,
|
|
6
6
|
user_wallet_address,
|
|
7
|
-
ad_format,
|
|
8
7
|
api_url = "https://ani-ads.vercel.app",
|
|
9
8
|
// Replace with your Ani Ads API domain
|
|
10
9
|
onAdClick
|
|
@@ -12,51 +11,9 @@ var AniAds = ({
|
|
|
12
11
|
const [ad, setAd] = useState(null);
|
|
13
12
|
const [loading, setLoading] = useState(true);
|
|
14
13
|
const [error, setError] = useState(null);
|
|
15
|
-
const
|
|
16
|
-
return
|
|
17
|
-
}, [ad_format]);
|
|
18
|
-
const getImageUrl = (ad2, format) => {
|
|
19
|
-
const normalizedFormat = format.toLowerCase().replace(/[:\s]/g, "");
|
|
20
|
-
if (normalizedFormat === "11" || normalizedFormat === "1:1") {
|
|
21
|
-
return ad2.image_square || null;
|
|
22
|
-
} else if (normalizedFormat === "916" || normalizedFormat === "9:16") {
|
|
23
|
-
return ad2.image_portrait || null;
|
|
24
|
-
} else if (normalizedFormat === "169" || normalizedFormat === "16:9") {
|
|
25
|
-
return ad2.image_landscape || null;
|
|
26
|
-
}
|
|
27
|
-
return null;
|
|
14
|
+
const getImageUrl = (ad2) => {
|
|
15
|
+
return ad2.image_square || null;
|
|
28
16
|
};
|
|
29
|
-
const fetchAd = useCallback(async () => {
|
|
30
|
-
try {
|
|
31
|
-
setLoading(true);
|
|
32
|
-
setError(null);
|
|
33
|
-
const response = await fetch(`${api_url}/api/ads/sdk`, {
|
|
34
|
-
method: "POST",
|
|
35
|
-
headers: {
|
|
36
|
-
"Content-Type": "application/json"
|
|
37
|
-
},
|
|
38
|
-
body: JSON.stringify({
|
|
39
|
-
creator_code,
|
|
40
|
-
formats
|
|
41
|
-
})
|
|
42
|
-
});
|
|
43
|
-
if (!response.ok) {
|
|
44
|
-
throw new Error("Failed to fetch ads");
|
|
45
|
-
}
|
|
46
|
-
const data = await response.json();
|
|
47
|
-
if (data.ad) {
|
|
48
|
-
setAd(data.ad);
|
|
49
|
-
} else {
|
|
50
|
-
setAd(null);
|
|
51
|
-
}
|
|
52
|
-
} catch (err) {
|
|
53
|
-
console.error("Error fetching ad:", err);
|
|
54
|
-
setError(err instanceof Error ? err.message : "Failed to load ad");
|
|
55
|
-
setAd(null);
|
|
56
|
-
} finally {
|
|
57
|
-
setLoading(false);
|
|
58
|
-
}
|
|
59
|
-
}, [creator_code, formats, api_url]);
|
|
60
17
|
const handleClick = useCallback(async () => {
|
|
61
18
|
if (!ad || !user_wallet_address) return;
|
|
62
19
|
try {
|
|
@@ -81,18 +38,14 @@ var AniAds = ({
|
|
|
81
38
|
console.error("Error tracking click:", err);
|
|
82
39
|
window.open(ad.destination_url, "_blank", "noopener,noreferrer");
|
|
83
40
|
}
|
|
84
|
-
}, [ad, creator_code, user_wallet_address, api_url, onAdClick
|
|
41
|
+
}, [ad, creator_code, user_wallet_address, api_url, onAdClick]);
|
|
85
42
|
const getBestImage = (ad2) => {
|
|
86
|
-
|
|
87
|
-
const imageUrl2 = getImageUrl(ad2, format);
|
|
88
|
-
if (imageUrl2) return imageUrl2;
|
|
89
|
-
}
|
|
90
|
-
return ad2.image_square || ad2.image_portrait || ad2.image_landscape || null;
|
|
43
|
+
return getImageUrl(ad2);
|
|
91
44
|
};
|
|
92
45
|
useEffect(() => {
|
|
93
46
|
let cancelled = false;
|
|
94
47
|
const loadAd = async () => {
|
|
95
|
-
if (!creator_code
|
|
48
|
+
if (!creator_code) {
|
|
96
49
|
setLoading(false);
|
|
97
50
|
return;
|
|
98
51
|
}
|
|
@@ -105,25 +58,28 @@ var AniAds = ({
|
|
|
105
58
|
"Content-Type": "application/json"
|
|
106
59
|
},
|
|
107
60
|
body: JSON.stringify({
|
|
108
|
-
creator_code
|
|
109
|
-
formats
|
|
61
|
+
creator_code
|
|
110
62
|
})
|
|
111
63
|
});
|
|
112
64
|
if (cancelled) return;
|
|
113
65
|
if (!response.ok) {
|
|
114
|
-
|
|
66
|
+
const errorData = await response.json().catch(() => ({}));
|
|
67
|
+
throw new Error(errorData.error || `HTTP ${response.status}: Failed to fetch ads`);
|
|
115
68
|
}
|
|
116
69
|
const data = await response.json();
|
|
117
70
|
if (cancelled) return;
|
|
118
71
|
if (data.ad) {
|
|
119
72
|
setAd(data.ad);
|
|
73
|
+
setError(null);
|
|
120
74
|
} else {
|
|
121
75
|
setAd(null);
|
|
76
|
+
setError(null);
|
|
122
77
|
}
|
|
123
78
|
} catch (err) {
|
|
124
79
|
if (cancelled) return;
|
|
125
80
|
console.error("Error fetching ad:", err);
|
|
126
|
-
|
|
81
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to load ad";
|
|
82
|
+
setError(errorMessage);
|
|
127
83
|
setAd(null);
|
|
128
84
|
} finally {
|
|
129
85
|
if (!cancelled) {
|
|
@@ -135,7 +91,7 @@ var AniAds = ({
|
|
|
135
91
|
return () => {
|
|
136
92
|
cancelled = true;
|
|
137
93
|
};
|
|
138
|
-
}, [creator_code,
|
|
94
|
+
}, [creator_code, api_url]);
|
|
139
95
|
if (loading) {
|
|
140
96
|
return /* @__PURE__ */ jsx("div", { style: {
|
|
141
97
|
display: "flex",
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback, useMemo } from 'react'\r\n\r\nexport interface AniAdsProps {\r\n creator_code: string\r\n user_wallet_address: string\r\n ad_format: string[] | string // Can be array like [\"16:9\", \"9:16\"] or string like \"16:9,9:16\"\r\n api_url?: string // Optional API URL, defaults to production\r\n onAdClick?: (adId: string, destinationUrl: string) => void // Optional click handler\r\n}\r\n\r\ninterface Ad {\r\n id: string\r\n title: string\r\n destination_url: string\r\n image_square: string\r\n image_portrait: string\r\n image_landscape: string\r\n status: 'active' | 'paused' | 'deleting'\r\n remaining_budget: number\r\n}\r\n\r\nexport const AniAds: React.FC<AniAdsProps> = ({\r\n creator_code,\r\n user_wallet_address,\r\n ad_format,\r\n api_url = 'https://ani-ads.vercel.app', // Replace with your Ani Ads API domain\r\n onAdClick,\r\n}) => {\r\n const [ad, setAd] = useState<Ad | null>(null)\r\n const [loading, setLoading] = useState(true)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n // Parse ad format - memoized to prevent unnecessary re-renders\r\n const formats = useMemo(() => {\r\n return Array.isArray(ad_format) \r\n ? ad_format \r\n : typeof ad_format === 'string' \r\n ? ad_format.split(',').map(f => f.trim())\r\n : []\r\n }, [ad_format])\r\n\r\n // Map format strings to image keys\r\n const getImageUrl = (ad: Ad, format: string): string | null => {\r\n const normalizedFormat = format.toLowerCase().replace(/[:\\s]/g, '')\r\n \r\n if (normalizedFormat === '11' || normalizedFormat === '1:1') {\r\n return ad.image_square || null\r\n } else if (normalizedFormat === '916' || normalizedFormat === '9:16') {\r\n return ad.image_portrait || null\r\n } else if (normalizedFormat === '169' || normalizedFormat === '16:9') {\r\n return ad.image_landscape || null\r\n }\r\n \r\n return null\r\n }\r\n\r\n // Fetch available ads\r\n const fetchAd = useCallback(async () => {\r\n try {\r\n setLoading(true)\r\n setError(null)\r\n\r\n const response = await fetch(`${api_url}/api/ads/sdk`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n creator_code,\r\n formats,\r\n }),\r\n })\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to fetch ads')\r\n }\r\n\r\n const data = await response.json()\r\n \r\n if (data.ad) {\r\n setAd(data.ad)\r\n } else {\r\n setAd(null)\r\n }\r\n } catch (err) {\r\n console.error('Error fetching ad:', err)\r\n setError(err instanceof Error ? err.message : 'Failed to load ad')\r\n setAd(null)\r\n } finally {\r\n setLoading(false)\r\n }\r\n }, [creator_code, formats, api_url]) // formats is memoized, so this is safe\r\n\r\n // Track ad click\r\n const handleClick = useCallback(async () => {\r\n if (!ad || !user_wallet_address) return\r\n\r\n try {\r\n // Track click on backend\r\n const response = await fetch(`${api_url}/api/ads/click`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n ad_id: ad.id,\r\n creator_code,\r\n user_wallet_address: user_wallet_address.toLowerCase(),\r\n }),\r\n })\r\n\r\n if (response.ok) {\r\n // Call optional click handler\r\n if (onAdClick) {\r\n onAdClick(ad.id, ad.destination_url)\r\n }\r\n\r\n // Open destination URL\r\n window.open(ad.destination_url, '_blank', 'noopener,noreferrer')\r\n\r\n // Don't fetch new ad after click - keep showing the same ad until page reload\r\n }\r\n } catch (err) {\r\n console.error('Error tracking click:', err)\r\n // Still open the URL even if tracking fails\r\n window.open(ad.destination_url, '_blank', 'noopener,noreferrer')\r\n }\r\n }, [ad, creator_code, user_wallet_address, api_url, onAdClick, fetchAd])\r\n\r\n // Find best matching image for formats\r\n const getBestImage = (ad: Ad): string | null => {\r\n for (const format of formats) {\r\n const imageUrl = getImageUrl(ad, format)\r\n if (imageUrl) return imageUrl\r\n }\r\n // Fallback to any available image\r\n return ad.image_square || ad.image_portrait || ad.image_landscape || null\r\n }\r\n\r\n // Fetch ad only once when component mounts or when creator_code/ad_format changes\r\n useEffect(() => {\r\n let cancelled = false\r\n \r\n const loadAd = async () => {\r\n if (!creator_code || formats.length === 0) {\r\n setLoading(false)\r\n return\r\n }\r\n\r\n try {\r\n setLoading(true)\r\n setError(null)\r\n\r\n const response = await fetch(`${api_url}/api/ads/sdk`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n creator_code,\r\n formats,\r\n }),\r\n })\r\n\r\n if (cancelled) return\r\n\r\n if (!response.ok) {\r\n throw new Error('Failed to fetch ads')\r\n }\r\n\r\n const data = await response.json()\r\n \r\n if (cancelled) return\r\n \r\n if (data.ad) {\r\n setAd(data.ad)\r\n } else {\r\n setAd(null)\r\n }\r\n } catch (err) {\r\n if (cancelled) return\r\n console.error('Error fetching ad:', err)\r\n setError(err instanceof Error ? err.message : 'Failed to load ad')\r\n setAd(null)\r\n } finally {\r\n if (!cancelled) {\r\n setLoading(false)\r\n }\r\n }\r\n }\r\n\r\n loadAd()\r\n\r\n return () => {\r\n cancelled = true\r\n }\r\n }, [creator_code, ad_format, api_url]) // Only depend on props, not derived values\r\n\r\n if (loading) {\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n width: '100%',\r\n minHeight: '100px',\r\n backgroundColor: '#f3f4f6',\r\n borderRadius: '8px',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n }}>\r\n <span style={{ color: '#6b7280' }}>Loading ad...</span>\r\n </div>\r\n )\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n width: '100%',\r\n minHeight: '100px',\r\n backgroundColor: '#fee2e2',\r\n borderRadius: '8px',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n padding: '12px',\r\n }}>\r\n <span style={{ color: '#dc2626', fontSize: '14px' }}>{error}</span>\r\n </div>\r\n )\r\n }\r\n\r\n if (!ad) {\r\n return null // Don't render anything if no ad available\r\n }\r\n\r\n const imageUrl = getBestImage(ad)\r\n\r\n if (!imageUrl) {\r\n return null\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n display: 'inline-block',\r\n width: '100%',\r\n cursor: 'pointer',\r\n borderRadius: '8px',\r\n overflow: 'hidden',\r\n transition: 'transform 0.2s, box-shadow 0.2s',\r\n }}\r\n onClick={handleClick}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.transform = 'scale(1.02)'\r\n e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)'\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.transform = 'scale(1)'\r\n e.currentTarget.style.boxShadow = 'none'\r\n }}\r\n >\r\n <img\r\n src={imageUrl}\r\n alt={ad.title}\r\n style={{\r\n width: '100%',\r\n height: 'auto',\r\n display: 'block',\r\n }}\r\n loading=\"lazy\"\r\n />\r\n </div>\r\n )\r\n}\r\n\r\nexport default AniAds\r\n\r\n"],"mappings":"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","names":["ad","imageUrl"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import React, { useEffect, useState, useCallback, useMemo } from 'react'\r\n\r\nexport interface AniAdsProps {\r\n creator_code: string\r\n user_wallet_address: string\r\n api_url?: string // Optional API URL, defaults to production\r\n onAdClick?: (adId: string, destinationUrl: string) => void // Optional click handler\r\n}\r\n\r\ninterface Ad {\r\n id: string\r\n title: string\r\n destination_url: string\r\n image_square: string\r\n image_portrait: string\r\n image_landscape: string\r\n status: 'active' | 'paused' | 'deleting'\r\n remaining_budget: number\r\n}\r\n\r\nexport const AniAds: React.FC<AniAdsProps> = ({\r\n creator_code,\r\n user_wallet_address,\r\n api_url = 'https://ani-ads.vercel.app', // Replace with your Ani Ads API domain\r\n onAdClick,\r\n}) => {\r\n const [ad, setAd] = useState<Ad | null>(null)\r\n const [loading, setLoading] = useState(true)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n // Get image URL - always use image_square (380x90 banner format)\r\n const getImageUrl = (ad: Ad): string | null => {\r\n return ad.image_square || null\r\n }\r\n\r\n // Track ad click\r\n const handleClick = useCallback(async () => {\r\n if (!ad || !user_wallet_address) return\r\n\r\n try {\r\n // Track click on backend\r\n const response = await fetch(`${api_url}/api/ads/click`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n ad_id: ad.id,\r\n creator_code,\r\n user_wallet_address: user_wallet_address.toLowerCase(),\r\n }),\r\n })\r\n\r\n if (response.ok) {\r\n // Call optional click handler\r\n if (onAdClick) {\r\n onAdClick(ad.id, ad.destination_url)\r\n }\r\n\r\n // Open destination URL\r\n window.open(ad.destination_url, '_blank', 'noopener,noreferrer')\r\n\r\n // Don't fetch new ad after click - keep showing the same ad until page reload\r\n }\r\n } catch (err) {\r\n console.error('Error tracking click:', err)\r\n // Still open the URL even if tracking fails\r\n window.open(ad.destination_url, '_blank', 'noopener,noreferrer')\r\n }\r\n }, [ad, creator_code, user_wallet_address, api_url, onAdClick])\r\n\r\n // Get image - always use banner format (380x90)\r\n const getBestImage = (ad: Ad): string | null => {\r\n return getImageUrl(ad)\r\n }\r\n\r\n // Fetch ad only once when component mounts or when creator_code/ad_format changes\r\n useEffect(() => {\r\n let cancelled = false\r\n \r\n const loadAd = async () => {\r\n if (!creator_code) {\r\n setLoading(false)\r\n return\r\n }\r\n\r\n try {\r\n setLoading(true)\r\n setError(null)\r\n\r\n const response = await fetch(`${api_url}/api/ads/sdk`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n creator_code,\r\n }),\r\n })\r\n\r\n if (cancelled) return\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}))\r\n throw new Error(errorData.error || `HTTP ${response.status}: Failed to fetch ads`)\r\n }\r\n\r\n const data = await response.json()\r\n \r\n if (cancelled) return\r\n \r\n if (data.ad) {\r\n setAd(data.ad)\r\n setError(null) // Clear any previous errors\r\n } else {\r\n // No ad available, but not an error - just don't show anything\r\n setAd(null)\r\n setError(null)\r\n }\r\n } catch (err) {\r\n if (cancelled) return\r\n console.error('Error fetching ad:', err)\r\n const errorMessage = err instanceof Error ? err.message : 'Failed to load ad'\r\n setError(errorMessage)\r\n setAd(null)\r\n } finally {\r\n if (!cancelled) {\r\n setLoading(false)\r\n }\r\n }\r\n }\r\n\r\n loadAd()\r\n\r\n return () => {\r\n cancelled = true\r\n }\r\n }, [creator_code, api_url]) // Only depend on props, not derived values\r\n\r\n if (loading) {\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n width: '100%',\r\n minHeight: '100px',\r\n backgroundColor: '#f3f4f6',\r\n borderRadius: '8px',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n }}>\r\n <span style={{ color: '#6b7280' }}>Loading ad...</span>\r\n </div>\r\n )\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div style={{\r\n display: 'flex',\r\n width: '100%',\r\n minHeight: '100px',\r\n backgroundColor: '#fee2e2',\r\n borderRadius: '8px',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n padding: '12px',\r\n }}>\r\n <span style={{ color: '#dc2626', fontSize: '14px' }}>{error}</span>\r\n </div>\r\n )\r\n }\r\n\r\n if (!ad) {\r\n return null // Don't render anything if no ad available\r\n }\r\n\r\n const imageUrl = getBestImage(ad)\r\n\r\n if (!imageUrl) {\r\n return null\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n display: 'inline-block',\r\n width: '100%',\r\n cursor: 'pointer',\r\n borderRadius: '8px',\r\n overflow: 'hidden',\r\n transition: 'transform 0.2s, box-shadow 0.2s',\r\n }}\r\n onClick={handleClick}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.transform = 'scale(1.02)'\r\n e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)'\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.transform = 'scale(1)'\r\n e.currentTarget.style.boxShadow = 'none'\r\n }}\r\n >\r\n <img\r\n src={imageUrl}\r\n alt={ad.title}\r\n style={{\r\n width: '100%',\r\n height: 'auto',\r\n display: 'block',\r\n }}\r\n loading=\"lazy\"\r\n />\r\n </div>\r\n )\r\n}\r\n\r\nexport default AniAds\r\n\r\n"],"mappings":"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","names":["ad"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ani-ads-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Ani Ads SDK for Mini App Creators to display ads in their apps",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -35,4 +35,3 @@
|
|
|
35
35
|
"react-dom": "^19.2.0"
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
|