@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 +380 -0
- package/dist/index.cjs +1154 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +922 -0
- package/dist/index.d.ts +922 -0
- package/dist/index.js +1130 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -0
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)
|