@medialane/sdk 0.1.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 ADDED
@@ -0,0 +1,380 @@
1
+ <img width="1260" height="640" alt="image" src="https://github.com/user-attachments/assets/a72bca86-bb82-42c4-8f61-9558484df5b9" />
2
+
3
+ # Medialane SDK
4
+
5
+ The Medialane SDK provides a unified interface for interacting with the Medialane marketplace, offering both **on-chain operations** (create listings, make offers, fulfill orders) and **REST API access** (search tokens, manage orders, upload metadata).
6
+
7
+ Framework-agnostic TypeScript SDK for [Medialane.xyz](https://medialane.xyz) portal for tokenization and monetization services and [Medialane.io](https://medialane.io) NFT marketplace.
8
+
9
+ ## Features
10
+
11
+ ✨ **On-Chain Operations**
12
+ - Create listings (ERC-721 for sale)
13
+ - Make offers (bid with ERC-20)
14
+ - Fulfill orders (purchase NFTs)
15
+ - Cancel active orders
16
+ - Atomic multi-item checkout
17
+ - Built-in approval checking
18
+ - SNIP-12 typed data signing
19
+
20
+ 🌐 **REST API**
21
+ - Query orders, tokens, and collections
22
+ - Search across the marketplace
23
+ - Stream activities and transactions
24
+ - Manage API keys and webhooks (authenticated)
25
+ - Upload metadata to IPFS
26
+
27
+ 🔧 **Developer-Friendly**
28
+ - Framework-agnostic TypeScript
29
+ - Dual ESM/CJS builds
30
+ - Zod schema validation
31
+ - Full type safety
32
+ - Zero runtime dependencies (except Zod)
33
+ - Peer dependency: `starknet >= 6.0.0`
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ npm install @medialane/sdk starknet
39
+ # or
40
+ yarn add @medialane/sdk starknet
41
+ # or
42
+ bun add @medialane/sdk starknet
43
+ ```
44
+
45
+ The SDK requires `starknet >= 6.0.0` as a peer dependency for on-chain operations.
46
+
47
+ ## Quick Start
48
+
49
+ ### Initialize the Client
50
+
51
+ ```typescript
52
+ import { MedialaneClient } from "@medialane/sdk";
53
+
54
+ const client = new MedialaneClient({
55
+ network: "mainnet", // "mainnet" | "sepolia"
56
+ rpcUrl: "https://starknet-mainnet.public.blastapi.io", // optional; auto-configured if omitted
57
+ backendUrl: "https://api.medialane.xyz", // optional; required for .api methods
58
+ apiKey: "ml_live_...", // optional; enables authenticated API routes
59
+ });
60
+ ```
61
+
62
+ ### Query the Marketplace (REST API)
63
+
64
+ ```typescript
65
+ // Get active listings
66
+ const orders = await client.api.getOrders({
67
+ status: "active",
68
+ sort: "newest",
69
+ page: 1,
70
+ limit: 20,
71
+ });
72
+
73
+ // Search for a specific token
74
+ const search = await client.api.search("vintage-nft", 10);
75
+
76
+ // Get activities
77
+ const activities = await client.api.getActivities({
78
+ type: "sale",
79
+ page: 1
80
+ });
81
+ ```
82
+
83
+ ### Create a Listing (On-Chain)
84
+
85
+ ```typescript
86
+ import { Account } from "starknet";
87
+
88
+ const account: Account = /* your starknet.js Account */;
89
+
90
+ const result = await client.marketplace.createListing(account, {
91
+ nftContract: "0x05e73b7be06d82beeb390a0e0d655f2c9e7cf519658e04f05d9c690ccc41da03",
92
+ tokenId: 42n,
93
+ currency: "USDC", // one of: "USDC", "USDT", "ETH", "STRK"
94
+ price: "1000000", // 1 USDC (6 decimals)
95
+ endTime: Math.floor(Date.now() / 1000) + 86400 * 30, // 30 days from now
96
+ });
97
+
98
+ console.log("Listing created:", result.txHash);
99
+ ```
100
+
101
+ ### Make an Offer
102
+
103
+ ```typescript
104
+ const result = await client.marketplace.makeOffer(account, {
105
+ nftContract: "0x05e73b7be06d82beeb390a0e0d655f2c9e7cf519658e04f05d9c690ccc41da03",
106
+ tokenId: 42n,
107
+ currency: "USDC",
108
+ price: "500000", // 0.5 USDC
109
+ endTime: Math.floor(Date.now() / 1000) + 86400 * 7, // 7 days
110
+ });
111
+
112
+ console.log("Offer created:", result.txHash);
113
+ ```
114
+
115
+ ### Fulfill an Order
116
+
117
+ ```typescript
118
+ const result = await client.marketplace.fulfillOrder(account, {
119
+ orderHash: "0x...",
120
+ fulfiller: "0x...", // your address
121
+ });
122
+
123
+ console.log("Order fulfilled:", result.txHash);
124
+ ```
125
+
126
+ ### Checkout Multiple Items
127
+
128
+ ```typescript
129
+ const result = await client.marketplace.checkoutCart(account, [
130
+ {
131
+ orderHash: "0x...",
132
+ fulfiller: "0x...",
133
+ },
134
+ {
135
+ orderHash: "0x...",
136
+ fulfiller: "0x...",
137
+ },
138
+ ]);
139
+
140
+ console.log("Cart checked out:", result.txHash);
141
+ ```
142
+
143
+ ## Configuration
144
+
145
+ The `MedialaneClient` constructor accepts a `MedialaneConfig` object with the following options:
146
+
147
+ | Option | Type | Default | Description |
148
+ |--------|------|---------|-------------|
149
+ | `network` | `"mainnet" \| "sepolia"` | `"mainnet"` | Starknet network |
150
+ | `rpcUrl` | `string` | BlastAPI endpoint | JSON-RPC URL for the network |
151
+ | `backendUrl` | `string` | *(required for `.api` calls)* | Medialane backend API base URL |
152
+ | `apiKey` | `string` | - | API key for authenticated routes (obtained from Medialane Portal) |
153
+ | `marketplaceContract` | `string` | Network-specific default | Marketplace contract address |
154
+
155
+ **Note:** If `backendUrl` is not provided, calling any `.api.*` method will throw an error with instructions to configure it.
156
+
157
+ ## API Reference
158
+
159
+ ### Marketplace Module
160
+
161
+ All methods require a `starknet.js` `AccountInterface`. They handle nonce management, SNIP-12 signing, and transaction waiting automatically.
162
+
163
+ #### Write Operations
164
+
165
+ | Method | Description |
166
+ |--------|-------------|
167
+ | `createListing(account, params)` | List an ERC-721 for sale. Auto-checks approval; includes approve call if needed. |
168
+ | `makeOffer(account, params)` | Bid on an ERC-721 with ERC-20. Includes token approval + order registration. |
169
+ | `fulfillOrder(account, params)` | Purchase a listed NFT. Fetches nonce and signs fulfillment typed data. |
170
+ | `cancelOrder(account, params)` | Cancel an active order. Fetches nonce and signs cancellation typed data. |
171
+ | `checkoutCart(account, items)` | Atomic multicall for multiple purchases. One approve per unique token, sequential nonces. |
172
+
173
+ #### View Operations
174
+
175
+ | Method | Description |
176
+ |--------|-------------|
177
+ | `getOrderDetails(orderHash)` | Fetch order details from the contract. |
178
+ | `getNonce(address)` | Get the current nonce for an address. |
179
+
180
+ ### REST API Client
181
+
182
+ The `client.api` object provides access to all backend endpoints. All methods throw `MedialaneApiError` on non-2xx responses.
183
+
184
+ #### Orders
185
+
186
+ ```typescript
187
+ client.api.getOrders(query?) // List all orders with optional filters
188
+ client.api.getOrder(orderHash) // Get a specific order
189
+ client.api.getActiveOrdersForToken(...) // Get active orders for a token
190
+ client.api.getOrdersByUser(address, ...) // Get orders by user
191
+ ```
192
+
193
+ #### Tokens
194
+
195
+ ```typescript
196
+ client.api.getToken(contract, tokenId, wait?) // Get token metadata
197
+ client.api.getTokensByOwner(address, ...) // Get tokens owned by address
198
+ client.api.getTokenHistory(contract, tokenId) // Get token transaction history
199
+ ```
200
+
201
+ #### Collections
202
+
203
+ ```typescript
204
+ client.api.getCollections(page?, limit?) // List all collections
205
+ client.api.getCollection(contract) // Get collection details
206
+ client.api.getCollectionTokens(contract, ...) // Get tokens in collection
207
+ ```
208
+
209
+ #### Activities
210
+
211
+ ```typescript
212
+ client.api.getActivities(query?) // Get marketplace activities
213
+ client.api.getActivitiesByAddress(address) // Get activities by user
214
+ ```
215
+
216
+ #### Search
217
+
218
+ ```typescript
219
+ client.api.search(query, limit?) // Search tokens and collections
220
+ ```
221
+
222
+ #### Intents (Advanced)
223
+
224
+ ```typescript
225
+ client.api.createListingIntent(params) // Create listing intent
226
+ client.api.createOfferIntent(params) // Create offer intent
227
+ client.api.createFulfillIntent(params) // Create fulfill intent
228
+ client.api.createCancelIntent(params) // Create cancel intent
229
+ client.api.submitIntentSignature(id, sig) // Submit signature for intent
230
+ ```
231
+
232
+ #### Metadata (IPFS)
233
+
234
+ ```typescript
235
+ client.api.uploadMetadata(metadata) // Upload JSON to IPFS
236
+ client.api.uploadFile(file) // Upload file to IPFS
237
+ client.api.resolveMetadata(uri) // Resolve ipfs://, data:, https://
238
+ client.api.getMetadataSignedUrl() // Get presigned Pinata URL
239
+ ```
240
+
241
+ #### Portal (Self-Service)
242
+
243
+ ```typescript
244
+ client.api.getMe() // Get current user info
245
+ client.api.getApiKeys() // List API keys
246
+ client.api.createApiKey(label?) // Create new API key
247
+ client.api.deleteApiKey(id) // Revoke API key
248
+ client.api.getUsage() // Get 30-day request usage
249
+ ```
250
+
251
+ ## Error Handling
252
+
253
+ The SDK throws two main error types:
254
+
255
+ ```typescript
256
+ import { MedialaneError, MedialaneApiError } from "@medialane/sdk";
257
+
258
+ // On-chain errors
259
+ try {
260
+ await client.marketplace.createListing(account, params);
261
+ } catch (error) {
262
+ if (error instanceof MedialaneError) {
263
+ console.error("On-chain error:", error.message);
264
+ }
265
+ }
266
+
267
+ // REST API errors
268
+ try {
269
+ await client.api.getOrders();
270
+ } catch (error) {
271
+ if (error instanceof MedialaneApiError) {
272
+ console.error(`API error ${error.status}:`, error.message);
273
+ }
274
+ }
275
+ ```
276
+
277
+ ## Supported Tokens
278
+
279
+ The following tokens are supported for on-chain operations:
280
+
281
+ | Symbol | Address | Decimals |
282
+ |--------|---------|----------|
283
+ | USDC | `0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8` | 6 |
284
+ | USDT | `0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8` | 6 |
285
+ | ETH | `0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7` | 18 |
286
+ | STRK | `0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d` | 18 |
287
+
288
+ Use the token symbol (e.g., `"USDC"`) in SDK methods, or access token details via:
289
+
290
+ ```typescript
291
+ import { getTokenBySymbol, getTokenByAddress } from "@medialane/sdk";
292
+
293
+ const usdc = getTokenBySymbol("USDC");
294
+ const token = getTokenByAddress("0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8");
295
+
296
+ console.log(usdc.decimals, token.address);
297
+ ```
298
+
299
+ ## Utilities
300
+
301
+ Helper functions for common tasks:
302
+
303
+ ```typescript
304
+ import {
305
+ normalizeAddress, // Normalize address to 0x-prefixed lowercase
306
+ shortenAddress, // Shorten to 0x1234...5678 format
307
+ parseAmount, // Convert human-readable amount to smallest unit (BigInt)
308
+ formatAmount, // Convert smallest unit (BigInt) to human-readable string
309
+ stringifyBigInts, // Recursively convert BigInts to strings for JSON serialization
310
+ } from "@medialane/sdk";
311
+
312
+ // Address utilities
313
+ const addr = normalizeAddress("0x123ABC");
314
+ const short = shortenAddress("0x123abc456def789012345678901234567890");
315
+
316
+ // Token amounts
317
+ const amountWei = parseAmount("1.5", 6); // "1500000" (USDC)
318
+ const readable = formatAmount("1500000", 6); // "1.5"
319
+ ```
320
+
321
+ ## Advanced Usage
322
+
323
+ ### Custom RPC Provider
324
+
325
+ ```typescript
326
+ import { RpcProvider } from "starknet";
327
+
328
+ const customProvider = new RpcProvider({
329
+ nodeUrl: "https://your-custom-rpc.com",
330
+ });
331
+
332
+ const client = new MedialaneClient({
333
+ network: "mainnet",
334
+ rpcUrl: "https://your-custom-rpc.com",
335
+ });
336
+ ```
337
+
338
+ ### Signing Typed Data (for integrations)
339
+
340
+ For advanced integrations like ChipiPay, you can access the SNIP-12 typed data builders directly:
341
+
342
+ ```typescript
343
+ import {
344
+ buildOrderTypedData,
345
+ buildFulfillmentTypedData,
346
+ buildCancellationTypedData,
347
+ } from "@medialane/sdk";
348
+
349
+ const typedData = buildOrderTypedData(orderParams, chainId);
350
+ const signature = await account.signMessage(typedData);
351
+
352
+ // Signature can then be submitted via API intents
353
+ await client.api.submitIntentSignature(intentId, signature);
354
+ ```
355
+
356
+ ## Development
357
+
358
+ Build and type-check the SDK:
359
+
360
+ ```bash
361
+ bun run build # Compile to dist/ (ESM + CJS)
362
+ bun run dev # Watch mode
363
+ bun run typecheck # Type check only (no emit)
364
+ ```
365
+
366
+ The SDK uses:
367
+ - **tsup** for dual ESM/CJS bundling
368
+ - **TypeScript** for type safety
369
+ - **Zod** for runtime config validation
370
+
371
+ ## License
372
+
373
+ [MIT](LICENSE)
374
+
375
+ ## Support
376
+
377
+ - **Services App**: [medialane.xyz](https://medialane.xyz)
378
+ - **Documentation**: [medialane.xyz/docs](https://medialane.xyz/docs)
379
+ - **Issues**: [GitHub Issues](https://github.com/medialane-io/sdk/issues)
380
+ - **Medialane Github**: [GitHub Issues](https://github.com/medialane-io)