Skip to content

Latest commit

 

History

357 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Medialane SDK

@medialane/sdk

Framework-agnostic TypeScript SDK for the Medialane IP marketplace on Starknet

The Medialane SDK provides a unified interface for interacting with the Medialane marketplace: both on-chain operations (create listings, make offers, fulfill orders, mint IP assets) and REST API access (search tokens, manage orders, upload metadata to IPFS). Built for medialane.io, starknet.medialane.io, portal.medialane.io, and media-wallet.


Features

On-Chain Operations

  • Create listings (ERC-721 / ERC-1155 for sale)
  • Make offers (bid with ERC-20)
  • Fulfill orders (purchase NFTs)
  • Cancel active orders
  • Atomic multi-item cart checkout
  • Built-in approval checking
  • SNIP-12 typed data signing
  • Mint IP NFTs into any collection
  • Deploy new ERC-721 or ERC-1155 collections

REST API Client

  • Query orders, tokens, collections, and activities
  • Full-text search across the marketplace
  • Intent-based transaction orchestration
  • Upload metadata and files to IPFS (Pinata)
  • Tenant portal: API keys, webhooks, usage
  • ERC-1155 multi-holder ownership via token.balances

IP Metadata Types

  • IpAttribute: typed OpenSea ERC-721 attribute
  • IpNftMetadata: full IPFS metadata shape with licensing fields
  • ApiTokenMetadata: indexed token metadata with all licensing attributes
  • Berne Convention-compatible licensing data model

Developer-Friendly

  • Framework-agnostic TypeScript
  • Dual ESM + CJS builds
  • Zod schema config validation
  • Full type safety
  • Peer dependency: starknet >= 6.0.0

Installation

npm install @medialane/sdk starknet
# or
bun add @medialane/sdk starknet
# or
yarn add @medialane/sdk starknet

Quick Start

Initialize the Client

import { MedialaneClient } from "@medialane/sdk";

const client = new MedialaneClient({
  chain: "STARKNET",                                                          // chain-scoped (default "STARKNET"); replaces `network` (v0.37.0)
  rpcUrl: "https://rpc.starknet.lava.build",                                  // optional; defaults to the chain's registry rpcUrl
  backendUrl: "https://medialane-backend-production.up.railway.app",          // required for .api methods
  apiKey: "ml_live_...",                                                       // from Medialane Portal
});

Marketplace Operations (On-Chain)

All methods require a starknet.js AccountInterface. SNIP-12 signing and waitForTransaction are handled automatically. Fulfilment is unsigned: the caller is the fulfiller, so there is no fulfiller/offerer field to pass; cancellation still signs, but without a nonce (a per-offerer counter replaces it, see incrementCounter).

Two marketplace modules are available:

  • client.marketplace: ERC-721 marketplace (Medialane721)
  • client.marketplace1155: ERC-1155 marketplace (Medialane1155)

Create a Listing (ERC-721)

import { Account } from "starknet";

const result = await client.marketplace.createListing(account, {
  nftContract: "0x05e73b7...",
  tokenId: "42",
  currency: "USDC",
  price: "1000000", // 1 USDC (6 decimals)
  durationSeconds: 86400 * 30, // 30 days
});
console.log("Listed:", result.txHash);

Make an Offer

const result = await client.marketplace.makeOffer(account, {
  nftContract: "0x05e73b7...",
  tokenId: "42",
  currency: "USDC",
  price: "500000", // 0.5 USDC
  durationSeconds: 86400 * 7,
});

Fulfill an Order

// Fetch order details first to get paymentToken and totalPrice
const details = await client.api.getOrder(orderHash);

const result = await client.marketplace.fulfillOrder(account, {
  orderHash: "0x...",
  paymentToken: "0x033068...",  // from order details
  totalPrice: "1000000",        // raw token units
});

Cart Checkout (Multiple Items)

const result = await client.marketplace.checkoutCart(account, [
  { orderHash: "0x...", considerationToken: "0x033068...", considerationAmount: "1000000" },
  { orderHash: "0x...", considerationToken: "0x033068...", considerationAmount: "500000" },
]);

Cancel an Order

const result = await client.marketplace.cancelOrder(account, {
  orderHash: "0x...",
});

Bulk-Cancel (Invalidate All Open Orders)

// Bumps the caller's counter: every previously-registered order becomes unfulfillable.
await client.marketplace.incrementCounter(account);

Mint an IP Asset

const result = await client.marketplace.mint(account, {
  collectionId: "1",          // collection ID on the registry
  recipient: account.address,
  tokenUri: "ipfs://...",     // IPFS URI of the metadata JSON
  royaltyBps: 500,            // EIP-2981 secondary-sale royalty, 0-10_000 (required since MIP v0.4.0)
});

Deploy a Collection

const result = await client.marketplace.createCollection(account, {
  name: "My Creative Works",
  symbol: "MCW",
  baseUri: "",
});

ERC-1155 Marketplace (Medialane1155)

For IP assets from ERC-1155 collections (e.g. IP-Programmable-ERC1155-Collections). Contract address: read getCoordinates("STARKNET").marketplace1155 from src/chains.ts, the single source of truth across redeploys.

Create an ERC-1155 Listing

const result = await client.marketplace1155.createListing(account, {
  nftContract: "0x...",    // ERC-1155 collection address
  tokenId: "1",
  amount: "10",             // number of tokens to sell
  pricePerUnit: "1",        // human-readable price per token (e.g. "1" USDC)
  currency: "USDC",
  durationSeconds: 86400 * 30,
});

set_approval_for_all is granted automatically if not already in place.

Fulfill an ERC-1155 Order

// Fetch order details first to get paymentToken and totalPrice
const details = await client.api.getOrder(orderHash);

const result = await client.marketplace1155.fulfillOrder(account, {
  orderHash: "0x...",
  paymentToken: "0x033068...",  // from order details
  totalPrice: "10000000",       // pricePerUnit × amount in raw token units
});

ERC-2981 royalties are automatically deducted by the contract at fulfillment.

Cancel an ERC-1155 Order

const result = await client.marketplace1155.cancelOrder(account, {
  orderHash: "0x...",
});

SNIP-12 Typed Data Builders (custodial-wallet / custom flows)

Listing/offer and cancellation are signed; fulfilment is an unsigned call (the buyer is the fulfiller, since v0.26.0): there is no fulfillment typed-data builder.

import { build1155OrderTypedData, build1155CancellationTypedData } from "@medialane/sdk";
import { constants } from "starknet";

const typedData = build1155OrderTypedData(orderParams, constants.StarknetChainId.SN_MAIN);

REST API

Query Orders

const orders = await client.api.getOrders({
  status: "ACTIVE",
  sort: "price_asc",
  currency: "0x033068...", // USDC address
  page: 1,
  limit: 20,
});

const order = await client.api.getOrder("0x...");
const tokenOrders = await client.api.getActiveOrdersForToken(contract, tokenId);
const userOrders = await client.api.getOrdersByUser(address);

Query Tokens

const token = await client.api.getToken(contract, tokenId);
const tokens = await client.api.getTokensByOwner(address);
const history = await client.api.getTokenHistory(contract, tokenId);

ERC-1155 Ownership

For ERC-1155 tokens, a single token ID can be held by many wallets simultaneously; read ownership from token.balances:

import type { ApiTokenBalance } from "@medialane/sdk";

const { data: token } = await client.api.getToken(contract, tokenId);

// Check if a wallet owns any quantity of this token
const isOwner = token.balances?.some(
  (b: ApiTokenBalance) => b.owner.toLowerCase() === wallet.toLowerCase() && BigInt(b.amount) > 0n
) ?? (token.owner?.toLowerCase() === wallet.toLowerCase());

// How many copies does a wallet hold?
const balance = token.balances?.find((b) => b.owner.toLowerCase() === wallet.toLowerCase());
console.log(`${wallet} holds ${balance?.amount ?? "0"} copies`);

// All current holders
token.balances?.forEach((b: ApiTokenBalance) => {
  console.log(`${b.owner}: ${b.amount}`);
});

token.owner is deprecated and always null post-migration. token.balances is only populated on single-token fetches (getToken): it is null on list responses.

Query Collections

// All collections: newest first by default
const collections = await client.api.getCollections();

// With sort and pagination
const byVolume = await client.api.getCollections(1, 20, undefined, "volume");
const verified = await client.api.getCollections(1, 18, true, "recent");

// Sort options: "recent" | "supply" | "floor" | "volume" | "name"
const collection = await client.api.getCollection(contract);
const tokens = await client.api.getCollectionTokens(contract);

Search

const results = await client.api.search("landscape painting", 10);
// results.data.tokens: matching tokens
// results.data.collections: matching collections
// results.data.creators: matching creator profiles (v0.4.5)

Activities

const feed = await client.api.getActivities({ type: "sale", page: 1 });
const userFeed = await client.api.getActivitiesByAddress(address);

Upload Metadata to IPFS

// Upload a file
const fileResult = await client.api.uploadFile(imageFile);
// fileResult.data.url → "ipfs://..."

// Upload metadata JSON
const metaResult = await client.api.uploadMetadata({
  name: "My Work",
  description: "...",
  image: "ipfs://...",
  external_url: "https://medialane.io",
  attributes: [
    { trait_type: "License", value: "CC BY-NC" },
    { trait_type: "Commercial Use", value: "No" },
    // ...
  ],
});
// metaResult.data.url → "ipfs://..."

Intents (Advanced)

The intent system handles the SNIP-12 signing flow for marketplace operations:

// 1. Create intent (gets typedData to sign)
const intent = await client.api.createListingIntent({
  offerer: address,
  nftContract: "0x...",
  tokenId: "42",
  currency: "0x033068...",
  price: "1000000",
  endTime: Math.floor(Date.now() / 1000) + 86400 * 30,
});

// 2. Sign typedData
const signature = await account.signMessage(intent.data.typedData);

// 3. Submit signature
await client.api.submitIntentSignature(intent.data.id, toSignatureArray(signature));

Mint and collection intents are pre-signed: no signature step needed:

const mintIntent = await client.api.createMintIntent({
  owner: ownerAddress,
  collectionId: "1",
  recipient: recipientAddress,
  tokenUri: "ipfs://...",
});
// mintIntent.data.calls → ready to execute

IP Metadata Types

import type { IpAttribute, IpNftMetadata, ApiTokenMetadata } from "@medialane/sdk";

// Single OpenSea ERC-721 attribute
const attr: IpAttribute = { trait_type: "License", value: "CC BY-NC-SA" };

// Full IPFS metadata shape for a Medialane IP NFT
const metadata: IpNftMetadata = {
  name: "My Track",
  description: "Original music",
  image: "ipfs://...",
  external_url: "https://medialane.io",
  attributes: [
    { trait_type: "IP Type",        value: "Audio" },
    { trait_type: "License",        value: "CC BY-NC-SA" },
    { trait_type: "Commercial Use", value: "No" },
    { trait_type: "Derivatives",    value: "Share-Alike" },
    { trait_type: "Attribution",    value: "Required" },
    { trait_type: "Territory",      value: "Worldwide" },
    { trait_type: "AI Policy",      value: "Not Allowed" },
    { trait_type: "Royalty",        value: "10%" },
    { trait_type: "Standard",       value: "Berne Convention" },
    { trait_type: "Registration",   value: "2026-03-06" },
  ],
};

// Token from the API: includes indexed licensing fields for fast access
const token = await client.api.getToken(contract, tokenId);
token.data.metadata.licenseType;   // "CC BY-NC-SA"
token.data.metadata.commercialUse; // "No"
token.data.metadata.derivatives;   // "Share-Alike"
token.data.metadata.attributes;    // IpAttribute[] | null

Supported Tokens

Symbol Address Decimals Listable
USDC 0x033068f6539f8e6e6b131e6b2b814e6c34a5224bc66947c47dab9dfee93b35fb 6
USDT 0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8 6
ETH 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 18
STRK 0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d 18
WBTC 0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac 8
import { getTokenBySymbol, getTokenByAddress, getListableTokens, SUPPORTED_TOKENS } from "@medialane/sdk";

const usdc = getTokenBySymbol("USDC");
const token = getTokenByAddress("0x033068...");

Utilities

import {
  normalizeAddress,    // (chain, address) → canonical form per chain (Starknet pad / EVM EIP-55 / Solana base58)
  shortenAddress,      // (chain, address) → "0x1234...5678"
  getCoordinates,      // (chain) → that chain's service coordinates from the registry
  CHAINS,              // readonly ["STARKNET","ETHEREUM","SOLANA","BASE","BITCOIN"]
  type Chain,
  parseAmount,         // Human-readable → smallest unit BigInt ("1.5", 6) → 1500000n
  formatAmount,        // Smallest unit → human-readable ("1500000", 6) → "1.5"
  stringifyBigInts,    // Recursively convert BigInt → string (for JSON)
  u256ToBigInt,        // u256 { low, high } → BigInt
  getListableTokens,   // ReadonlyArray<SupportedToken> filtered to listable: true (for dialogs)
} from "@medialane/sdk";

Error Handling

import { MedialaneError, MedialaneApiError } from "@medialane/sdk";

// On-chain errors (marketplace module)
try {
  await client.marketplace.createListing(account, params);
} catch (err) {
  if (err instanceof MedialaneError) {
    console.error("On-chain error:", err.message, err.cause);
  }
}

// REST API errors
try {
  await client.api.getOrders();
} catch (err) {
  if (err instanceof MedialaneApiError) {
    console.error(`API ${err.status}:`, err.message);
  }
}

Configuration Reference

Option Type Default Description
chain Chain ("STARKNET" | "ETHEREUM" | "SOLANA" | "BASE" | "BITCOIN") "STARKNET" The chain this client is scoped to. Coordinates resolve from the coordinates[chain] registry (chains.ts). Replaces network (v0.37.0).
rpcUrl string the chain's registry rpcUrl JSON-RPC URL override
backendUrl string (none) Medialane API base URL (required for .api.*)
apiKey string (none) API key from Medialane Portal
marketplace721Contract string Mainnet default ERC-721 marketplace protocol override
marketplaceContract string Mainnet default Legacy alias for marketplace721Contract
marketplace1155Contract string Mainnet default ERC-1155 marketplace protocol override
collection721Contract string Mainnet default ERC-721 mint / collection registry override
collectionContract string Mainnet default Legacy alias for collection721Contract
collection1155Contract string Mainnet default ERC-1155 mint / collection factory override

Advanced: SNIP-12 Typed Data Builders

For integrations that handle signing externally (e.g. a custodial wallet service, Cartridge Controller):

import {
  buildOrderTypedData,
  buildFulfillmentTypedData,
  buildCancellationTypedData,
} from "@medialane/sdk";

const typedData = buildOrderTypedData(orderParams, chainId);
const signature = await account.signMessage(typedData);
await client.api.submitIntentSignature(intentId, signatureArray);

Development

bun run build      # Compile to dist/ (ESM + CJS dual output)
bun run dev        # Watch mode
bun run typecheck  # tsc --noEmit

Built with:

  • tsup: dual ESM/CJS bundling
  • TypeScript: full type safety
  • Zod: runtime config validation
  • Peer dep: starknet >= 6.0.0

Changelog

Full history in CHANGELOG.md. Highlights below.

v0.37.0: multichain readiness (BREAKING)

  • Chain is a first-class axis. New chains.ts coordinates[chain] registry is the single source of per-chain service coordinates (CHAINS, getCoordinates, DEFAULT_CHAIN, Chain, ChainCoordinates); the flat *_MAINNET constants derive from it.
  • MedialaneConfig.chain replaces network: the client is chain-scoped; client.network getter → client.chain.
  • ServiceDefinition.onchain is per-chain: Partial<Record<Chain, …>>; read service.onchain?.STARKNET?.factoryAddress.
  • normalizeAddress(chain, address): per-chain codec (Starknet pad / EVM EIP-55 / Solana base58; Bitcoin not yet implemented).
  • Removed SUPPORTED_NETWORKS, DEFAULT_RPC_URL, Network (mainnet-only: coordinates key by chain alone). getChainId(config) throws for non-Starknet.

v0.6.7

  • CollectionRegistryABI exported from @medialane/sdk: minimal ABI covering list_user_collections and get_collection on the collection registry contract. Eliminates duplicated inline ABI definitions in consuming apps.

v0.6.6

  • COLLECTION_CONTRACT_MAINNET updated to audited v2 contract address 0x05c49ee5d3208a2c2e150fdd0c247d1195ed9ab54fa2d5dea7a633f39e4b205b

v0.6.5

  • ERC-1155 support: ApiToken.balances: ApiTokenBalance[] | null replaces the single owner field for ownership checks
  • ApiTokenBalance type: { owner: string; amount: string }: each entry represents one holder and their quantity
  • ApiToken.owner deprecated: always null after the ERC-1155 migration; use balances instead
  • ApiCollection.standard: "ERC721" | "ERC1155" | "UNKNOWN" detected via ERC-165 supportsInterface
  • totalSupply fix: ERC-1155 collections now report SUM(holder amounts) for an accurate circulating total

v0.6.1

  • Collection Drop: new DropService (client.services.drop) with full on-chain drop management: claim, adminMint, setClaimConditions, setAllowlistEnabled, addToAllowlist, batchAddToAllowlist, setPaused, withdrawPayments, createDrop
  • client.api.getDropCollections(opts?): list all COLLECTION_DROP collections
  • client.api.getDropMintStatus(collection, wallet): returns { mintedByWallet, totalMinted }
  • DropMintStatus, ClaimConditions, CreateDropParams types exported
  • DropCollectionABI and DropFactoryABI exported from @medialane/sdk
  • DROP_FACTORY_CONTRACT_MAINNET and DROP_COLLECTION_CLASS_HASH_MAINNET constants exported
  • CollectionSource union extended with "COLLECTION_DROP"

v0.6.0

  • POP Protocol: PopService (client.services.pop): claim, adminMint, addToAllowlist, batchAddToAllowlist, removeFromAllowlist, setTokenUri, setPaused, createCollection
  • client.api.getPopCollections(opts?) and client.api.getPopEligibility(collection, wallet)
  • POPCollectionABI and POPFactoryABI exported
  • POP_FACTORY_CONTRACT_MAINNET and POP_COLLECTION_CLASS_HASH_MAINNET constants exported

v0.5.7

  • ApiCollectionProfile.hasGatedContent: boolean: whether the collection has token-gated content configured
  • ApiCollectionProfile.gatedContentTitle: string | null: public title of gated content (shown to all users; URL is accessible to holders only via the backend gated-content endpoint)

v0.5.5

  • extendRemixOffer(id, days, siwsToken): requester extends expiry of a PENDING/AUTO_PENDING remix offer by 1–30 days (POST /v1/remix-offers/:id/extend)
  • ApiRemixOfferPrice type: { raw, formatted, currency, decimals } replaces flat proposedPrice/proposedCurrency fields on ApiRemixOffer.price (visible to participants only)

v0.5.4

  • ApiRemixOffer.price shape introduced: backend now serializes price as a structured object (raw, formatted, currency, decimals), replacing raw wei strings

v0.5.3

  • getTokenComments(contract, tokenId, opts?): fetch on-chain NFT comments for a token (GET /v1/tokens/:contract/:tokenId/comments)
  • ApiComment type: { id, author, content, txHash, blockNumber, blockTimestamp, isHidden, createdAt }

v0.5.0

  • Counter-offer support: createCounterOfferIntent(params, siwsToken), getCounterOffers(query), ApiCounterOffersQuery, CreateCounterOfferIntentParams
  • OrderStatus extended with "COUNTER_OFFERED"; IntentType with "COUNTER_OFFER"
  • ApiOrder extended: parentOrderHash?: string | null, counterOfferMessage?: string | null
  • Remix licensing: full set of remix offer methods and types:
    • submitRemixOffer(params, siwsToken): custom offer
    • submitAutoRemixOffer(params, siwsToken): auto offer for open-license tokens
    • confirmSelfRemix(params, siwsToken): record owner self-remix
    • getRemixOffers(query, siwsToken): list by role
    • getRemixOffer(id, siwsToken?): single offer
    • confirmRemixOffer(id, params, siwsToken): creator approves
    • rejectRemixOffer(id, siwsToken): creator rejects
    • getTokenRemixes(contract, tokenId, opts?): public remix list
  • New types: RemixOfferStatus, ApiRemixOffer, ApiPublicRemix, OPEN_LICENSES, OpenLicense, CreateRemixOfferParams, AutoRemixOfferParams, ConfirmSelfRemixParams, ConfirmRemixOfferParams, ApiRemixOffersQuery

v0.4.8

  • ApiComment type + getTokenComments (patch release, backported into v0.5.3)

v0.4.7

  • IPType union type exported: "Audio" | "Art" | "Documents" | "NFT" | "Video" | "Photography" | "Patents" | "Posts" | "Publications" | "RWA" | "Software" | "Custom"

v0.4.6

  • ApiUserWallet type + upsertMyWallet(siwsToken) / getMyWallet(siwsToken) for wallet registration fallback (POST/GET /v1/users/me)

v0.4.5

  • ApiSearchCreatorResult type + ApiSearchResult.creators: creator profiles now included in search results

v0.4.4

  • ApiCreatorListResult + getCreators(opts?): list creators with search/pagination via GET /v1/creators

v0.4.3

  • ApiCreatorProfile.username field + getCreatorByUsername(username): resolve username slug to creator profile

v0.4.2

  • WBTC added to SUPPORTED_TOKENS (0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac, 8 decimals)
  • listable field on every SUPPORTED_TOKENS entry: controls whether a token appears in listing/offer dialogs vs filter-only
  • getListableTokens(): returns tokens filtered to listable: true; exported from package root
  • ETH promoted to listable: true: now available in listing and offer dialogs
  • USDC.e removed: bridged USDC (0x053c91...) removed entirely; only Circle-native USDC remains, to avoid user confusion

v0.4.1

  • Collection claims: claimCollection(contractAddress, walletAddress, siwsToken) for on-chain ownership verification; requestCollectionClaim({ contractAddress, walletAddress?, email, notes? }) for manual review
  • Collection profiles: getCollectionProfile(contractAddress) and updateCollectionProfile(contractAddress, data, siwsToken) for enriched display metadata (displayName, description, image, bannerImage, social links)
  • Creator profiles: getCreatorProfile(walletAddress) and updateCreatorProfile(walletAddress, data, siwsToken) for creator display metadata
  • New types: ApiCollectionClaim, ApiAdminCollectionClaim, ApiCollectionProfile, ApiCreatorProfile
  • ApiCollection extended with source ("MEDIALANE_REGISTRY" | "EXTERNAL" | "PARTNERSHIP" | "IP_TICKET" | "IP_CLUB" | "GAME") and claimedBy: string | null
  • profile?: ApiCollectionProfile | null optionally embedded on ApiCollection when ?include=profile

v0.4.0

  • Typed error codes: MedialaneError and MedialaneApiError now expose a .code: MedialaneErrorCode property ("TOKEN_NOT_FOUND" | "RATE_LIMITED" | "INTENT_EXPIRED" | "UNAUTHORIZED" | "INVALID_PARAMS" | "NETWORK_NOT_SUPPORTED" | "UNKNOWN")
  • Automatic retry: all API requests retry up to 3 times with exponential backoff (300ms base, 5s cap) on transient failures. Configure via retryOptions in MedialaneConfig
  • RetryOptions type exported from index
  • CollectionSort named union type exported ("recent" | "supply" | "floor" | "volume" | "name")
  • Sepolia guard: constructing a client with network: "sepolia" and no explicit contract addresses now throws NETWORK_NOT_SUPPORTED immediately

v0.3.3

  • getCollections(page?, limit?, isKnown?, sort?): added sort parameter: "recent" (default) | "supply" | "floor" | "volume" | "name"
  • Default sort changed from totalSupply DESC to createdAt DESC (newest first): matches backend default

v0.3.1

  • ApiCollection.collectionId: string | null: on-chain registry numeric ID (decimal string). Required for createMintIntent. Populated for collections indexed after 2026-03-09.

v0.3.0

  • normalizeAddress() applied internally before all API calls: callers no longer need to normalize Starknet addresses
  • ApiCollection.owner: string | null: populated from intent typedData or on-chain owner() call
  • getCollectionsByOwner(owner): fetch collections by wallet address via GET /v1/collections?owner=

v0.2.6

  • ApiOrder.token: ApiOrderTokenMeta | null: token name/image/description embedded on orders (batchTokenMeta); no per-row getToken calls needed

v0.2.0

  • IpAttribute and IpNftMetadata interfaces for IP metadata
  • ApiTokenMetadata.attributes typed as IpAttribute[] | null (was unknown)
  • ApiTokenMetadata extended with derivatives, attribution, territory, aiPolicy, royalty, registration, standard
  • Added USDC.e (bridged USDC via Starkgate) to SUPPORTED_TOKENS

v0.1.0

  • Initial release: orders, tokens, collections, activities, intents, metadata, portal

Links


License

MIT

Releases

Packages

Contributors

Languages