Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This skill gives your AI coding agent full knowledge of Metaplex programs, CLI c
| **Agent Registry** | On-chain agent identity, wallets, execution delegation | Yes | Yes | - |
| **Genesis** | Token launches (launchpool + bonding curve) + Raydium graduation | Yes | Yes | - |
| **Core** | Next-gen NFTs — single account, plugins, royalty enforcement | Yes | Yes | - |
| **DAS API** | Indexed asset queries (owner/collection/group/agents) + Core helpers | - | Yes | - |
| **Token Metadata** | Fungible tokens, NFTs, pNFTs, editions | Yes | Yes | Yes |
| **Bubblegum** | Compressed NFTs via Merkle trees — massive scale at minimal cost | Yes | Yes | - |
| **Candy Machine** | NFT drops with guards (allowlists, payments, limits) | Yes | Yes | - |
Expand All @@ -33,7 +34,7 @@ This skill gives your AI coding agent full knowledge of Metaplex programs, CLI c
- Agent Registry: mint agents, register identity, delegate execution, set agent token
- Genesis Launch API: launchpool and bonding curve launches, agent integration, creator fees, first buy
- Bonding curve swap integration: fetch state, lifecycle helpers, quotes, slippage, execute swaps
- All CLI operations plus: fetch by owner/collection/creator, DAS API queries, delegates, lock/unlock, print editions, verify/unverify creators and collections, freeze/thaw, soulbound NFTs, plugin management
- All CLI operations plus: fetch by owner/collection/creator/group, DAS API queries (`digital-asset-standard-api` + `mpl-core-das`), delegates, lock/unlock, print editions, verify/unverify creators and collections, freeze/thaw, soulbound NFTs, plugin management

**Kit SDK** (@solana/kit) — minimal dependencies:
- Token Metadata operations: create/transfer NFTs, pNFTs, fungibles, PDAs
Expand All @@ -46,9 +47,10 @@ The skill uses progressive disclosure — a lightweight router (SKILL.md, ~100 l
SKILL.md Router — loaded when skill activates
references/cli.md Shared CLI setup (loaded for any CLI task)
references/cli-core.md Core CLI commands
references/sdk-das.md DAS API + mpl-core-das helpers
references/sdk-token-metadata.md TM SDK patterns
references/concepts.md Account structures, PDAs
... (12 reference files total)
... (reference files)
```

## Install
Expand Down
7 changes: 4 additions & 3 deletions skills/metaplex/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: Metaplex development on Solana — NFTs, tokens, compressed NFTs, c
license: Apache-2.0
metadata:
author: metaplex-foundation
version: "0.3.0"
version: "0.4.0"
openclaw: {"emoji":"💎","os":["darwin","linux","win32"],"requires":{"bins":["node"]},"homepage":"https://metaplex.com/docs"}
---

Expand Down Expand Up @@ -48,6 +48,7 @@ Metaplex provides the standard infrastructure for NFTs and tokens on Solana:
| CLI: Fungible tokens | `./references/cli.md` + `./references/cli-toolbox.md` |
| SDK setup (Umi) | `./references/sdk-umi.md` |
| SDK: Core NFTs | `./references/sdk-umi.md` + `./references/sdk-core.md` + `./references/metadata-json.md` |
| SDK: DAS API (asset queries, Core listing helpers) | `./references/sdk-umi.md` + `./references/sdk-das.md` |
| SDK: Token Metadata | `./references/sdk-umi.md` + `./references/sdk-token-metadata.md` + `./references/metadata-json.md` |
| SDK: Compressed NFTs (Bubblegum) | `./references/sdk-umi.md` + `./references/sdk-bubblegum.md` + `./references/metadata-json.md` |
| SDK: Token Metadata with Kit | `./references/sdk-token-metadata-kit.md` + `./references/metadata-json.md` |
Expand Down Expand Up @@ -83,7 +84,7 @@ The `mplx` CLI can handle most Metaplex operations directly. **Read `./reference
| Compressed NFTs (cNFTs) | ✅ (batch limit ~100, use SDK for larger) |
| Execute (asset-signer wallets) | ✅ |
| Check SOL balance / Airdrop | ✅ |
| Query assets by owner/collection | ❌ SDK only (DAS API) |
| Query assets by owner/collection/group | ❌ SDK only (DAS API — see `./references/sdk-das.md`) |
| Token launch (Genesis) | ✅ |
| Bonding curve swap (Genesis) | ✅ |

Expand All @@ -104,7 +105,7 @@ Core Candy: CMACYFENjoBMHzapRXyo1JZkVS6EtaDDzkjMrmQLvr4J

### Autonomous Agents

Use **Agent Registry** to register on-chain identity and execution delegation for MPL Core assets. The **Mint Agent API** (`mintAndSubmitAgent`) is the recommended path — it creates the Core asset and registers identity in a single transaction. For existing assets, use `registerIdentityV1` directly. Any Core asset already has a built-in wallet (Asset Signer PDA) via Core's Execute hook — the registry adds discoverable identity records and lets owners delegate an off-chain executive to operate the agent. Agents can optionally link a Genesis token via `setAgentTokenV1`. Read `./references/cli-agent.md` (CLI) or `./references/sdk-umi.md` + `./references/sdk-agent.md` (SDK).
Use **Agent Registry** to register on-chain identity and execution delegation for MPL Core assets. The **Mint Agent API** (`mintAndSubmitAgent`) is the recommended path — it creates the Core asset and registers identity in a single transaction. For existing assets, use `registerIdentityV1` directly. Any Core asset already has a built-in wallet (Asset Signer PDA) via Core's Execute hook — the registry adds discoverable identity records and lets owners delegate an off-chain executive to operate the agent. Agents can optionally link a Genesis token via `setAgentTokenV1`. Discover agents via DAS (`searchAssets({ isAgent: true })` — see `./references/sdk-das.md`). Read `./references/cli-agent.md` (CLI) or `./references/sdk-umi.md` + `./references/sdk-agent.md` (SDK).

### Token Launches (Token Generation Event / Fair Launch / Bonding Curve)

Expand Down
22 changes: 22 additions & 0 deletions skills/metaplex/references/sdk-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,28 @@ await setAgentTokenV1(umi, {

> The agent token can only be set once. Calling on an identity that already has a token fails with `AgentTokenAlreadySet`.

### Discover Agents via DAS

Registered agents are queryable through the DAS API (requires `dasApi()`). Prefer Core-typed helpers when you need `AssetV1`:

```typescript
import { dasApi } from '@metaplex-foundation/digital-asset-standard-api';
import { das } from '@metaplex-foundation/mpl-core-das';

umi.use(dasApi());

const agents = await das.searchAssets(umi, {
isAgent: true,
// agentToken: genesisMint, // optional
// assetSigner: assetSignerPda, // optional
skipDerivePlugins: true,
});

// agents[i].is_agent, .agent_token, .asset_signer when indexed
```

See `./sdk-das.md` for full DAS coverage.

---

## Check Registration
Expand Down
9 changes: 5 additions & 4 deletions skills/metaplex/references/sdk-bubblegum.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ await unverifyCreatorV2(umi, {

## Fetch cNFTs (DAS API)

> Requires a DAS-compatible RPC (e.g., Helius, Triton, QuickNode) and the `dasApi()` plugin. See `./sdk-umi.md` DAS section.
> Requires a DAS-compatible RPC (e.g., Helius, Triton, QuickNode) and the `dasApi()` plugin. See `./sdk-das.md`.

```typescript
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
Expand All @@ -294,9 +294,10 @@ const asset = await umi.rpc.getAsset(assetId);
// By owner
const assets = await umi.rpc.getAssetsByOwner({ owner: walletAddress });

// By collection
const collectionAssets = await umi.rpc.getAssetsByCollection({
collection: collectionAddress,
// By collection (base DAS — cNFTs are not Core AssetV1)
const collectionAssets = await umi.rpc.getAssetsByGroup({
groupKey: 'collection',
groupValue: collectionAddress,
});
```

Expand Down
17 changes: 15 additions & 2 deletions skills/metaplex/references/sdk-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,20 @@ const ownerAssets = await fetchAssetsByOwner(umi, ownerAddress);
const collectionAssets = await fetchAssetsByCollection(umi, collectionAddress);
```

> `fetchAssetsByOwner` and `fetchAssetsByCollection` use GPA (getProgramAccounts) queries. They may throw deserialization errors if the wallet/collection has burned asset account remnants. For production, prefer DAS API queries (see `./sdk-umi.md` DAS section).
> `fetchAssetsByOwner` and `fetchAssetsByCollection` use GPA (getProgramAccounts) queries. They may throw deserialization errors if the wallet/collection has burned asset account remnants. For production, prefer DAS via `@metaplex-foundation/mpl-core-das` (see `./sdk-das.md`):

```typescript
import { dasApi } from '@metaplex-foundation/digital-asset-standard-api';
import { das } from '@metaplex-foundation/mpl-core-das';

umi.use(dasApi());

const ownerAssets = await das.getAssetsByOwner(umi, { owner: ownerAddress });
const collectionAssets = await das.getAssetsByCollection(umi, {
collection: collectionAddress,
});
const groupMembers = await das.getAssetsByGroup(umi, { group: groupAddress });
```

## Transfer Asset

Expand Down Expand Up @@ -579,7 +592,7 @@ await execute(umi, {
Core uses a **single-account model** — asset and collection addresses are the public keys of the `generateSigner()` used at creation, not PDAs derived from other accounts. This means:

- **No PDA derivation needed** to find an asset. The address returned from `create()` IS the asset address.
- To look up assets, use `fetchAssetsByOwner`, `fetchAssetsByCollection`, or DAS API queries.
- To look up assets, prefer `das.getAssetsByOwner` / `das.getAssetsByCollection` / `das.getAssetsByGroup` (see `./sdk-das.md`). GPA helpers (`fetchAssetsByOwner`, `fetchAssetsByCollection`) are fine for small local sets.
- Core collections are also direct accounts (not PDAs like TM's Metadata/MasterEdition).

This differs from Token Metadata, where you derive Metadata, MasterEdition, and TokenRecord PDAs from a mint address.
Expand Down
213 changes: 213 additions & 0 deletions skills/metaplex/references/sdk-das.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# DAS API SDK Reference

Query Solana digital assets via the Metaplex Digital Asset Standard (DAS) API.

> **Prerequisites**: Umi setup — see `./sdk-umi.md`.
>
> **Important**: DAS requires a DAS-compatible RPC (Helius, Triton, QuickNode, Shyft, Hello Moon). The default public Solana RPC does **not** support DAS methods.

## Which package?

| Need | Package | Call style |
|------|---------|------------|
| Core assets/collections/groups as `AssetResult` / `CollectionResult` / `GroupResult` | `@metaplex-foundation/mpl-core-das` | `das.getAssetsByCollection(umi, …)` |
| Multi-standard assets, cNFT proofs, editions, token accounts, raw DAS shapes | `@metaplex-foundation/digital-asset-standard-api` | `umi.rpc.getAsset(…)` |

Always register the base plugin. Add `mpl-core-das` when reading Core data as Core types. Requires DAS client `>=2.1.0` for groups / `getGrouping` / agent filters, and `mpl-core` `>=1.9.0` for `GroupV1`.

```bash
npm install @metaplex-foundation/digital-asset-standard-api
# Core-typed helpers (recommended for Core apps):
npm install @metaplex-foundation/mpl-core-das @metaplex-foundation/mpl-core
```

```typescript
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
import { dasApi } from '@metaplex-foundation/digital-asset-standard-api';

const umi = createUmi('https://mainnet.helius-rpc.com/?api-key=YOUR_KEY').use(dasApi());

// Helius-only param names for getNftEditions / getTokenAccounts:
// umi.use(dasApi({ heliusCompatibility: true }));
```

---

## Core helpers (`mpl-core-das`)

Preferred for Core listing. Returns `AssetResult` / `CollectionResult` / `GroupResult` (Core types + DAS `content`, and optional `is_agent` / `agent_token` / `asset_signer`) and derives collection plugins by default.

```typescript
import { publicKey } from '@metaplex-foundation/umi';
import { das } from '@metaplex-foundation/mpl-core-das';

const byOwner = await das.getAssetsByOwner(umi, { owner: wallet });
const byCollection = await das.getAssetsByCollection(umi, {
collection: collectionAddress,
});
const byGroup = await das.getAssetsByGroup(umi, { group: groupAddress });

const asset = await das.getAsset(umi, assetAddress);
const collection = await das.getCollection(umi, collectionAddress);
const group = await das.getGroup(umi, groupAddress);

// Agent discovery
const agents = await das.searchAssets(umi, {
isAgent: true,
skipDerivePlugins: true,
});
// agents[i].is_agent, .agent_token, .asset_signer when indexed
```

| Helper | Description |
|--------|-------------|
| `das.getAsset` / `getCollection` / `getGroup` | Single account by pubkey |
| `das.getAssetsByOwner` / `ByAuthority` / `ByCollection` | List Core assets |
| `das.getAssetsByGroup` | Members of an mpl-core `GroupV1` — assets, collections, or nested groups (`groupKey: 'group'`) |
| `das.getGrouping` | Group summary (`group_name`, `group_size`) without listing members |
| `das.searchAssets` / `searchCollections` / `searchGroups` | Filtered search |
| `das.getCollectionsByUpdateAuthority` / `getGroupsByUpdateAuthority` | By update authority |
| `das.dasAssetsToCoreAssets` | Raw `MplCoreAsset` items → `AssetResult[]` |
| `das.dasAssetToCoreCollection` | Raw `MplCoreCollection` → `CollectionResult` |
| `das.dasAssetToCoreGroup` | Raw `MplCoreGroup` → `GroupResult` |

Options: `skipDerivePlugins: true` to skip collection plugin inheritance. Only `displayOptions.showCollectionMetadata` is supported.

> `GroupResult` membership vectors may be empty from DAS — use `fetchGroupV1` from `mpl-core` for authoritative on-chain membership.

> Do **not** call `umi.rpc.getAssetsByCollection` — that method does not exist on base DAS. Use `das.getAssetsByCollection` (Core) or `umi.rpc.getAssetsByGroup({ groupKey: 'collection', … })` (base).

---

## Base DAS methods (`umi.rpc`)

| Method | Description |
|--------|-------------|
| `getAsset` | Single asset by ID |
| `getAssets` | Multiple assets by IDs |
| `getAssetProof` / `getAssetProofs` | Merkle proofs (cNFTs) |
| `getAssetsByOwner` | Assets owned by a wallet |
| `getAssetsByAuthority` | Assets by authority |
| `getAssetsByCreator` | Assets by creator (`onlyVerified`) |
| `getAssetsByGroup` | By grouping key/value (`collection` or `group`) |
| `getGrouping` | Grouping metadata (name + size) |
| `getAssetSignatures` | Transaction signatures for a compressed asset |
| `getNftEditions` | Print editions for a master edition mint |
| `getTokenAccounts` | Token accounts by owner and/or mint |
| `searchAssets` | Flexible multi-filter search |

### Common examples

```typescript
import { publicKey } from '@metaplex-foundation/umi';

const asset = await umi.rpc.getAsset(assetId);
// or with display options:
const asset2 = await umi.rpc.getAsset({
assetId,
displayOptions: { showCollectionMetadata: true },
});

const batch = await umi.rpc.getAssets([assetId1, assetId2]);

const byOwner = await umi.rpc.getAssetsByOwner({
owner: wallet,
limit: 100,
page: 1,
});

// Collections (TM or Core) — NOT getAssetsByCollection
const byCollection = await umi.rpc.getAssetsByGroup({
groupKey: 'collection',
groupValue: collectionAddress,
});

// mpl-core GroupV1 members
const byCoreGroup = await umi.rpc.getAssetsByGroup({
groupKey: 'group',
groupValue: groupAddress,
});

const grouping = await umi.rpc.getGrouping({
groupKey: 'group',
groupValue: groupAddress,
});

const byCreator = await umi.rpc.getAssetsByCreator({
creator: creatorAddress,
onlyVerified: true,
});

const proof = await umi.rpc.getAssetProof(cnftAssetId);
```

### searchAssets

```typescript
const results = await umi.rpc.searchAssets({
owner: wallet,
burnt: false,
compressed: true,
interface: 'MplCoreAsset', // or MplCoreCollection, MplCoreGroup, V1_NFT, …
limit: 50,
page: 1,
});

// Agent filters (MPL Core only)
const agents = await umi.rpc.searchAssets({
isAgent: true,
agentToken: genesisMint, // optional
assetSigner: assetSignerPda, // optional
interface: 'MplCoreAsset',
});
```

Useful filters: `owner`, `creator`, `authority`, `grouping: ['collection'|'group', value]`, `delegate`, `frozen`, `compressed`, `burnt`, `jsonUri`, `name`, `tokenType`, `royaltyModel`, `isAgent`, `agentToken`, `assetSigner`, `negate`, `conditionType`.

Core response extras when present: `is_agent`, `agent_token`, `asset_signer`, plus `plugins` / `external_plugins` / `mpl_core_info`.

### Editions & token accounts

```typescript
const editions = await umi.rpc.getNftEditions({
mintAddress: masterEditionMint,
page: 1,
});

const tokenAccounts = await umi.rpc.getTokenAccounts({
ownerAddress: wallet,
// mintAddress: optionalMint,
options: { showZeroBalance: false },
});
```

With `dasApi({ heliusCompatibility: true })`, these methods send Helius param names (`mint` / `owner`) instead of Metaplex names (`mintAddress` / `ownerAddress`).

### Pagination

Use **either** `page` **or** `before`/`after` — not both (the client throws `DasApiError`). `cursor` is also supported where the RPC provides it. `sortBy: { sortBy, sortDirection }`.

### Display options

`showUnverifiedCollections`, `showCollectionMetadata`, `showFungible`, `showInscription` (plus `showZeroBalance` on `getTokenAccounts`).

---

## GPA vs DAS (Core)

`fetchAssetsByOwner` / `fetchAssetsByCollection` in `mpl-core` use GPA and can fail on burned account remnants. Prefer:

```typescript
import { das } from '@metaplex-foundation/mpl-core-das';

const assets = await das.getAssetsByOwner(umi, { owner: wallet });
```

---

## For more info

- DAS API: https://metaplex.com/docs/dev-tools/das-api
- Getting started: https://metaplex.com/docs/dev-tools/das-api/getting-started
- Core groups: https://metaplex.com/docs/smart-contracts/core/groups
- OpenRPC playground: https://playground.open-rpc.org/?url=https://raw.githubusercontent.com/metaplex-foundation/digital-asset-standard-api/main/specification/metaplex-das-api.json
Loading