algomintx 2.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.
- package/README.md +381 -0
- package/dist/algomintx.js +2 -0
- package/dist/algomintx.js.LICENSE.txt +52 -0
- package/dist/node/index.cjs +2 -0
- package/dist/node/index.cjs.LICENSE.txt +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
# AlgoMintX SDK
|
|
2
|
+
|
|
3
|
+
**Launch a beautiful, full-featured NFT / FT marketplace on Algorand in minutes.**
|
|
4
|
+
Plug-and-play JavaScript SDK: just drop it in, connect wallets, mint, list, unlist, buy, and earn revenueβno backend required.
|
|
5
|
+
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://algorand.com)
|
|
8
|
+
|
|
9
|
+
## β¨ Features
|
|
10
|
+
|
|
11
|
+
- π **Wallet integration** (Pera Wallet & Defly Wallet)
|
|
12
|
+
- π¨ **NFT minting** via IPFS (Pinata)
|
|
13
|
+
- πͺ **Fungible Token (FT / Algorand ASA) minting** with a dedicated "Mint FT" tab
|
|
14
|
+
- π·οΈ **Configurable `marketplaceType`** (`"NFT"` or `"FT"`) that gates what can be listed, discovered, and purchased
|
|
15
|
+
- π§ **Marketplace discovery** (`getMarketplaces()`) to power dashboards and explorers
|
|
16
|
+
- π **NFT / FT Marketplace Analytics Dashboard** (standalone Vite/React app, see `NFT Marketplace Analytics Dashboard/`)
|
|
17
|
+
- π¦ **Listing NFTs / FTs** for sale
|
|
18
|
+
- ποΈ **Unlisting NFTs / FTs** from the marketplace
|
|
19
|
+
- π **Buying NFTs / FTs** from the marketplace
|
|
20
|
+
- π° **Revenue mechanism** for marketplace owners
|
|
21
|
+
- πΈ **Customizable marketplace fees** (minting, listing, buying, unlisting)
|
|
22
|
+
- π **IPFS metadata storage** and retrieval
|
|
23
|
+
- π₯ **Multi-media support** for NFTs (Images, Videos, Audio)
|
|
24
|
+
- π§ͺ **No smart contract writing required** β pre-audited smart contract ready to use
|
|
25
|
+
- π **No blockchain expertise required**
|
|
26
|
+
- β
Works on **Testnet** and **Mainnet**
|
|
27
|
+
- π§ **Minimal, user-friendly UI** with SDK minimization support
|
|
28
|
+
- β‘ **Real-time event emitter** for frontend event handling
|
|
29
|
+
- π **Customizable toast notifications**
|
|
30
|
+
- π¨ **Customizable UI** with logo support
|
|
31
|
+
- π **Light/Dark theme support**
|
|
32
|
+
- π± **Mobile-friendly, responsive UI**
|
|
33
|
+
- π **No backend required**βall logic runs in the browser
|
|
34
|
+
- β³ **UI feedbacks with loaders and toast messages**
|
|
35
|
+
- π‘οΈ **Robust input validation** for all user and config parameters
|
|
36
|
+
- π **Open source & actively maintained**
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## π Quick Start (For SDK Users)
|
|
41
|
+
|
|
42
|
+
### 1. Import the SDK in your HTML
|
|
43
|
+
|
|
44
|
+
Add the following `<script>` tag to your HTML `<head>` (see demo HTML for reference):
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<!-- Import AlgoMintX SDK -->
|
|
48
|
+
<script
|
|
49
|
+
defer
|
|
50
|
+
src="https://cdn.jsdelivr.net/gh/IBHAGYESH/AlgoMintX@latest/dist/algomintx.js"
|
|
51
|
+
></script>
|
|
52
|
+
<!-- Or use your local build during development -->
|
|
53
|
+
<!-- <script defer src="./dist/algomintx.js"></script> -->
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. Initialize the SDK in your frontend
|
|
57
|
+
|
|
58
|
+
Add this to your main JS file or a `<script>` tag after the SDK import:
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
window.algoMintXClient = new window.AlgoMintX({
|
|
62
|
+
pinata_ipfs_server_key: "<YOUR_PINATA_API_KEY>",
|
|
63
|
+
pinata_ipfs_gateway_url: "YOUR_PINATA_GATEWAY.mypinata.cloud",
|
|
64
|
+
env: "testnet", // "testnet" or "mainnet"
|
|
65
|
+
namespace: "ABCDE", // Unique 5-character uppercase string
|
|
66
|
+
revenueWalletAddress: "<YOUR_ALGORAND_WALLET_ADDRESS>",
|
|
67
|
+
// Optional:
|
|
68
|
+
marketplaceType: "NFT", // "NFT" (default) or "FT" β only this asset type can be listed/discovered/bought
|
|
69
|
+
mintFee: 0.1, // in Algos
|
|
70
|
+
listingFee: 0.1, // in Algos
|
|
71
|
+
buyingFee: 0.5, // in Algos
|
|
72
|
+
unListingFee: 0.1, // in Algos
|
|
73
|
+
disableToast: false,
|
|
74
|
+
toastLocation: "TOP_RIGHT", // "TOP_LEFT" or "TOP_RIGHT"
|
|
75
|
+
minimizeUILocation: "right", // "left" or "right"
|
|
76
|
+
logo: "./logo.png", // URL or path to your logo
|
|
77
|
+
supportedMediaFormats: ["IMAGE", "VIDEO", "AUDIO"],
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 3. See the SDK UI
|
|
82
|
+
|
|
83
|
+
After initialization, the AlgoMintX UI will automatically appear on your frontend. Users can connect their wallet, mint, list, buy, and manage NFTs / FTs with no further setup.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## π§ Advanced Configuration
|
|
88
|
+
|
|
89
|
+
### UI Customization
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
// UI customization (relevant options only)
|
|
93
|
+
disableToast: false;
|
|
94
|
+
toastLocation: "TOP_RIGHT";
|
|
95
|
+
minimizeUILocation: "right";
|
|
96
|
+
logo: "https://myapp.com/logo.png";
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Marketplace Type (`marketplaceType`)
|
|
100
|
+
|
|
101
|
+
`marketplaceType` controls which kind of Algorand asset your marketplace deals in:
|
|
102
|
+
|
|
103
|
+
| Value | Behavior |
|
|
104
|
+
| ----------------- | ------------------------------------------------------------------------------------------------- |
|
|
105
|
+
| `"NFT"` (default) | Only non-fungible assets (`total === 1`, `decimals === 0`) can be listed, discovered, and bought. |
|
|
106
|
+
| `"FT"` | Only fungible assets (`total > 1` or `decimals > 0`) can be listed, discovered, and bought. |
|
|
107
|
+
|
|
108
|
+
The UI always shows **both** the "Mint NFT" and "Mint FT" tabs (you can mint either asset type), but the listing, discovery (`getListedNFTs`), and purchase flows are restricted to the configured `marketplaceType`. Attempting to list or buy a mismatched asset type throws a clear error.
|
|
109
|
+
|
|
110
|
+
### Fungible Token (FT) Minting
|
|
111
|
+
|
|
112
|
+
The "Mint FT" tab creates an Algorand ASA with a configurable supply and divisibility, following the same ARC-3 + IPFS flow as NFT minting. The form fields are:
|
|
113
|
+
|
|
114
|
+
- **Token Name** (required)
|
|
115
|
+
- **Token Description** (required)
|
|
116
|
+
- **Decimals** (required, `0`β`19`) β how divisible the token is
|
|
117
|
+
- **Total Supply** (required, `>= 1`)
|
|
118
|
+
- **Token Icon** (optional image, reuses the existing IPFS pipeline)
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## π§ͺ How to Run the Demos
|
|
123
|
+
|
|
124
|
+
### HTML/CSS/JS Demo
|
|
125
|
+
|
|
126
|
+
- **Location:** `testing/html-css-js/`
|
|
127
|
+
- **Config file:** `testing/html-css-js/index.js`
|
|
128
|
+
|
|
129
|
+
#### Run with Live Deployed SDK (Recommended for most users)
|
|
130
|
+
|
|
131
|
+
1. Configure the SDK in `index.js` as shown above.
|
|
132
|
+
2. Start a local server:
|
|
133
|
+
```bash
|
|
134
|
+
npx http-server .
|
|
135
|
+
```
|
|
136
|
+
3. Open the demo in your browser:
|
|
137
|
+
```
|
|
138
|
+
http://127.0.0.1:8080/testing/html-css-js/index.html
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### Run with Local Development Build of SDK (For SDK Developers)
|
|
142
|
+
|
|
143
|
+
1. Configure the SDK in `index.js` as above.
|
|
144
|
+
2. Install dependencies and build the SDK:
|
|
145
|
+
```bash
|
|
146
|
+
npm install
|
|
147
|
+
npm run build
|
|
148
|
+
```
|
|
149
|
+
3. Change the `<script src=...>` in your HTML files to point to your local build (e.g., `../../dist/algomintx.js`).
|
|
150
|
+
4. Start a local server:
|
|
151
|
+
```bash
|
|
152
|
+
npx http-server .
|
|
153
|
+
```
|
|
154
|
+
5. Open the demo:
|
|
155
|
+
```
|
|
156
|
+
http://127.0.0.1:8080/testing/html-css-js/index.html
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### React Demo
|
|
160
|
+
|
|
161
|
+
- **Location:** `testing/react/`
|
|
162
|
+
- **Config file:** `testing/react/src/hooks/useSDK.js`
|
|
163
|
+
|
|
164
|
+
1. Configure the SDK in `hooks/useSDK.js` as shown above.
|
|
165
|
+
2. In the terminal:
|
|
166
|
+
```bash
|
|
167
|
+
cd testing/react
|
|
168
|
+
npm install
|
|
169
|
+
npm run build
|
|
170
|
+
npm run preview
|
|
171
|
+
```
|
|
172
|
+
3. Open the demo:
|
|
173
|
+
```
|
|
174
|
+
http://localhost:4173
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## π¦ SDK API
|
|
180
|
+
|
|
181
|
+
### NFT Type Schema
|
|
182
|
+
|
|
183
|
+
The SDK returns NFT objects with the following structure:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
type NFT = {
|
|
187
|
+
assetId: number; // Algorand asset ID
|
|
188
|
+
name: string; // NFT name
|
|
189
|
+
unitName?: string; // Asset unit name (e.g., AMXDEMO)
|
|
190
|
+
creator?: string; // Wallet address of the creator
|
|
191
|
+
url?: string; // IPFS metadata URL (ipfs://...)
|
|
192
|
+
clawback?: string; // On-chain clawback address if set (not required for listing)
|
|
193
|
+
decimals: number; // Always 0 for NFTs
|
|
194
|
+
total: number; // Always 1 for NFTs
|
|
195
|
+
metadata?: {
|
|
196
|
+
name: string; // NFT name (from metadata)
|
|
197
|
+
description: string; // NFT description
|
|
198
|
+
image: string; // IPFS gateway URL to image/media
|
|
199
|
+
image_integrity: string; // SHA-256 hash of the image/media
|
|
200
|
+
image_mimetype: string; // MIME type (e.g., image/png, video/mp4)
|
|
201
|
+
decimals: number; // Always 0
|
|
202
|
+
standard: string; // e.g., "arc3"
|
|
203
|
+
minted_by: string; // SDK identifier
|
|
204
|
+
marketplace: string; // Marketplace namespace
|
|
205
|
+
};
|
|
206
|
+
currentHolder?: string; // Wallet address of current holder
|
|
207
|
+
listing?: {
|
|
208
|
+
seller: string; // Wallet address of seller
|
|
209
|
+
price: number; // Price in ALGOs
|
|
210
|
+
marketplace: string; // Marketplace namespace
|
|
211
|
+
};
|
|
212
|
+
transactionId?: string; // Asset creation or last relevant transaction ID
|
|
213
|
+
};
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### FT Type Schema
|
|
217
|
+
|
|
218
|
+
In an `"FT"` marketplace the same object shape is returned, but `total` reflects the chosen supply and `decimals` the chosen divisibility. The IPFS `metadata` follows ARC-3 with `decimals` set to the divisibility and `image`/integrity fields optional (an icon is optional for FTs):
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
type FT = {
|
|
222
|
+
assetId: number; // Algorand asset ID
|
|
223
|
+
name: string; // Token name
|
|
224
|
+
unitName?: string; // Asset unit name (e.g., AMXDEMO)
|
|
225
|
+
decimals: number; // Chosen divisibility (0-19)
|
|
226
|
+
total: number; // Chosen total supply (>= 1)
|
|
227
|
+
metadata?: {
|
|
228
|
+
name: string;
|
|
229
|
+
description: string;
|
|
230
|
+
decimals: number; // Chosen divisibility
|
|
231
|
+
standard: string; // e.g., "arc3"
|
|
232
|
+
minted_by: string; // SDK identifier
|
|
233
|
+
marketplace: string; // Marketplace namespace
|
|
234
|
+
image?: string; // Optional icon (IPFS gateway URL)
|
|
235
|
+
image_integrity?: string;
|
|
236
|
+
image_mimetype?: string;
|
|
237
|
+
};
|
|
238
|
+
listing?: {
|
|
239
|
+
seller: string;
|
|
240
|
+
price: number; // Price in ALGOs
|
|
241
|
+
marketplace: string;
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Marketplace Discovery Type Schema
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
type Marketplace = {
|
|
250
|
+
marketplace: string; // e.g., "AMXDEMO" (= AMX + namespace)
|
|
251
|
+
namespace: string; // e.g., "DEMO"
|
|
252
|
+
listingCount: number;
|
|
253
|
+
uniqueSellers: number;
|
|
254
|
+
totalListedValue: number; // total of listed prices (ALGO)
|
|
255
|
+
floorPrice: number; // lowest listed price (ALGO)
|
|
256
|
+
avgPrice: number; // average listed price (ALGO)
|
|
257
|
+
assetIds: string[];
|
|
258
|
+
isCurrentMarketplace: boolean; // true if it matches this SDK instance's namespace
|
|
259
|
+
};
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Exposed Variables
|
|
263
|
+
|
|
264
|
+
| Variable | Type | Description |
|
|
265
|
+
| ------------- | ------- | -------------------------------------------------------- |
|
|
266
|
+
| `account` | string | Wallet address of the currently connected user |
|
|
267
|
+
| `events` | object | Event emitter for subscribing to SDK lifecycle events |
|
|
268
|
+
| `isMinimized` | boolean | If the SDK UI is currently minimized |
|
|
269
|
+
| `network` | string | Current configured network (`"testnet"` or `"mainnet"`) |
|
|
270
|
+
| `processing` | boolean | If an operation (e.g., minting, buying, etc.) is ongoing |
|
|
271
|
+
| `theme` | string | Current theme of the SDK UI (`"light"` or `"dark"`) |
|
|
272
|
+
|
|
273
|
+
#### Exposed Methods
|
|
274
|
+
|
|
275
|
+
| Method & Signature | Description |
|
|
276
|
+
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
277
|
+
| `mintNFT({ name, description, file })` | Mint an NFT programmatically (headless or custom UI). `file` accepts browser `File`/`Blob` or Node `{ data, name, type }`. |
|
|
278
|
+
| `mintFT({ name, description, decimals, totalSupply, file? })` | Mint a fungible token programmatically (headless or custom UI) |
|
|
279
|
+
| `connectWallet(address, mnemonic)` | Connect programmatically with a 25-word mnemonic (Node.js / headless) |
|
|
280
|
+
| `disconnectWallet()` | Disconnect the active wallet session |
|
|
281
|
+
| `getAssetMetadata({ assetId })` | Alias for `getNFTMetadata` β works for both NFT and FT assets |
|
|
282
|
+
| `listNFT({ assetId: number, nftPrice: number })` | List an existing NFT to the marketplace |
|
|
283
|
+
| `unlistNFT({ assetId: number })` | Remove an NFT from the marketplace listing |
|
|
284
|
+
| `buyNFT({ assetId: number })` | Buy a listed NFT from the marketplace |
|
|
285
|
+
| `getListedNFTs(): Promise<Array<NFT>>` | Fetch all NFTs currently listed for sale |
|
|
286
|
+
| `getWalletAssets({ accountId?, marketplaceOnly? }): Promise<Array<Asset>>` | Retrieve assets owned by a wallet. Default returns **all NFTs and FTs**. Pass `marketplaceOnly: true` to return only assets matching the configured `marketplaceType` (`"NFT"` or `"FT"`). |
|
|
287
|
+
| `getWalletNFTs(...)` | Alias for `getWalletAssets()` |
|
|
288
|
+
| `getNFTMetadata({ assetId: number }): Promise<NFT>` | Fetch metadata of a specific NFT using its asset ID |
|
|
289
|
+
| `getFTMetadata({ assetId: number }): Promise<FT>` | Fetch metadata of a specific FT using its asset ID (type-aware metadata resolution) |
|
|
290
|
+
| `getMarketplaces(): Promise<Array<Marketplace>>` | Discover all marketplaces (unique `AMX{namespace}` values) that currently have on-chain listings, with aggregates |
|
|
291
|
+
| `getMarketplaceCount(): Promise<number>` | Return how many distinct marketplaces currently have at least one active listing |
|
|
292
|
+
| `listingStatus(assetId, marketplace?: string): Promise<object>` | O(1) listing lookup for a marketplace + asset |
|
|
293
|
+
| `getMarketplaceStats(marketplace?: string): Promise<object>` | Lightweight listings + metrics for one marketplace (defaults to this instance's marketplace) |
|
|
294
|
+
| `getMarketplaceData(marketplace?: string): Promise<object>` | Rich analytics for one marketplace: enriched listings (metadata, holder, images) + aggregate metrics |
|
|
295
|
+
| `minimizeSDK(): void` | Minimize the SDK UI to a floating button |
|
|
296
|
+
| `maximizeSDK(): void` | Restore the SDK UI to its full size |
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## π‘ SDK Events
|
|
301
|
+
|
|
302
|
+
The SDK emits various events during wallet operations, UI transitions, and NFT transactions. You can use these events in your frontend to update the UI, show loaders, display messages, etc.
|
|
303
|
+
|
|
304
|
+
β
Example Usage
|
|
305
|
+
|
|
306
|
+
```js
|
|
307
|
+
window.algoMintXClient.events.on(
|
|
308
|
+
"wallet:connection:connected",
|
|
309
|
+
({ address }) => {
|
|
310
|
+
console.log("Wallet connected:", address);
|
|
311
|
+
},
|
|
312
|
+
);
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
| Event Name | Description | Emitted Data (Type) |
|
|
316
|
+
| -------------------------------- | --------------------------------------------------- | ------------------------------------- |
|
|
317
|
+
| `wallet:connection:connected` | Fired when wallet is successfully connected | `{ address: string }` |
|
|
318
|
+
| `wallet:connection:disconnected` | Fired when wallet is disconnected | `{ address: string }` |
|
|
319
|
+
| `wallet:connection:failed` | Fired when wallet connection fails | `{ error: string }` |
|
|
320
|
+
| `window:size:minimized` | Fired when the SDK UI is minimized or restored | `{ minimized: boolean }` |
|
|
321
|
+
| `sdk:processing:started` | Fired when a process (minting, buying, etc.) starts | `{ processing: boolean }` |
|
|
322
|
+
| `sdk:processing:stopped` | Fired when the process ends | `{ processing: boolean }` |
|
|
323
|
+
| `nft:mint:success` | Fired after successful NFT minting | `{ transactionId: string, nft: NFT }` |
|
|
324
|
+
| `nft:mint:failed` | Fired if minting fails | `{ error: string }` |
|
|
325
|
+
| `ft:mint:success` | Fired after successful FT (ASA) minting | `{ transactionId: string, ft: FT }` |
|
|
326
|
+
| `ft:mint:failed` | Fired if FT minting fails | `{ error: string }` |
|
|
327
|
+
| `nft:list:success` | Fired after NFT is successfully listed | `{ transactionId: string, nft: NFT }` |
|
|
328
|
+
| `nft:list:failed` | Fired if listing fails | `{ error: string }` |
|
|
329
|
+
| `nft:unlist:success` | Fired after NFT is successfully unlisted | `{ transactionId: string, nft: NFT }` |
|
|
330
|
+
| `nft:unlist:failed` | Fired if unlisting fails | `{ error: string }` |
|
|
331
|
+
| `nft:buy:success` | Fired after successful NFT purchase | `{ transactionId: string, nft: NFT }` |
|
|
332
|
+
| `nft:buy:failed` | Fired if buying fails | `{ error: string }` |
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## π NFT Marketplace Analytics Dashboard
|
|
337
|
+
|
|
338
|
+
A standalone Vite + React analytics dashboard lives in [`NFT Marketplace Analytics Dashboard/`](NFT%20Marketplace%20Analytics%20Dashboard/). It uses the same box-scanning discovery as `getMarketplaces()` to find every marketplace with active listings and visualizes:
|
|
339
|
+
|
|
340
|
+
- Metric chips: Total Listed, Floor Price, Avg Price, Total Listed Value, Unique Sellers
|
|
341
|
+
- **Listings Over Time** (area chart)
|
|
342
|
+
- **Price Distribution** (bar histogram)
|
|
343
|
+
- **Top Sellers** (ranked by total listed value)
|
|
344
|
+
- Current listings preview and inferred marketplace asset type (NFT / FT)
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
cd "NFT Marketplace Analytics Dashboard"
|
|
348
|
+
npm install
|
|
349
|
+
npm run dev
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## π€ Contributing
|
|
355
|
+
|
|
356
|
+
Pull requests and feature suggestions are welcome! For major changes, please open an issue first to discuss your idea.
|
|
357
|
+
|
|
358
|
+
## π Appreciation
|
|
359
|
+
|
|
360
|
+
Thank you for checking out AlgoMintX! This project was crafted with care to simplify NFT marketplace development on Algorand and help developers ship faster.
|
|
361
|
+
|
|
362
|
+
If you found this useful, feel free to βοΈ star the repo and share it with others in the community.
|
|
363
|
+
|
|
364
|
+
## π¨βπ» About the Author
|
|
365
|
+
|
|
366
|
+
Built and maintained by Bhagyesh Jahangirpuria.
|
|
367
|
+
|
|
368
|
+
- π Website: https://ibhagyesh.com
|
|
369
|
+
- π LinkedIn: https://in.linkedin.com/in/ibhagyesh
|
|
370
|
+
|
|
371
|
+
**Feel free to connect for collaborations, feedback, or consulting!**
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
<div align="center">
|
|
376
|
+
|
|
377
|
+
**Made with β€οΈ for the Algorand Community**
|
|
378
|
+
|
|
379
|
+
If AlgoMintX helped you build something awesome, I'd love to hear about it!
|
|
380
|
+
|
|
381
|
+
</div>
|