Wen Open Lab · open integration

Stage 2: Creator Royaltieshook read verified

Wen creator coin art
Art that pays its creator

For years, NFT royalties depended on whether a marketplace felt like paying them. WNS moved that rule into the token: a transfer hook runs on every transfer and enforces the creator's share. This model shows how to see which program guards an NFT, and how to move the NFT so that guard actually runs.

The task

Make sure a creator receives their share on every resale, whether the NFT is sold on a big marketplace, a small one, or passed directly between wallets.

The model

  1. An NFT mint carries the Token-2022 Transfer Hook extension, which names a hook program. For WNS assets that program is WNS royalty distribution: diste3nXmK7ddDTs1zb6uday6j4etCa9RChD8fJ1xay.
  2. On every transfer, Token-2022 calls the hook. If the hook's conditions are not met, the whole transaction is rolled back.
  3. The hook needs extra accounts. The official helper createTransferCheckedWithTransferHookInstruction reads them from the chain, so wallets and marketplaces do not have to guess.
Before (classic NFTs)With a WNS transfer hook
Who enforces royaltiesEach marketplace, if it wants toThe token itself, on every transfer
Wallet-to-wallet saleRoyalty easily skippedHook still runs
IntegrationCustom per marketplaceOne standard flow for everyone

The code

File: lab/code/src/02-royalty-transfer.ts · Apache-2.0

// Model 2: creator royalties. Inspect which program enforces royalties on an NFT,
// then transfer it so that the transfer hook (e.g. WNS royalty distribution) runs.
// License: Apache-2.0. Example code, not audited. Devnet first.
import { PublicKey, Transaction, sendAndConfirmTransaction } from '@solana/web3.js';
import {
  TOKEN_2022_PROGRAM_ID, createAssociatedTokenAccountIdempotentInstruction,
  createTransferCheckedWithTransferHookInstruction, getAssociatedTokenAddressSync, getMint, getTransferHook,
} from '@solana/spl-token';
import { WNS_ROYALTY_PROGRAM_ID, detectTokenProgram, getConnection, loadKeypair } from './common.js';

/** Read the transfer-hook program attached to a mint. */
export async function inspectRoyaltyHook(mintAddress: string) {
  const connection = getConnection();
  const mint = new PublicKey(mintAddress);
  const program = await detectTokenProgram(connection, mint);
  if (!program.equals(TOKEN_2022_PROGRAM_ID)) return { mint: mintAddress, hook: null, note: 'Classic SPL token: no transfer hooks' };
  const info = await getMint(connection, mint, 'confirmed', TOKEN_2022_PROGRAM_ID);
  const hook = getTransferHook(info);
  const hookProgram = hook?.programId ?? null;
  return {
    mint: mintAddress,
    hook: hookProgram?.toBase58() ?? null,
    isWnsRoyalty: hookProgram ? hookProgram.equals(WNS_ROYALTY_PROGRAM_ID) : false,
  };
}

/** Transfer one NFT. The helper resolves the hook's extra accounts on-chain, so royalties logic runs. */
export async function transferWithRoyalties(mintAddress: string, to: string) {
  const connection = getConnection();
  const owner = loadKeypair();
  const mint = new PublicKey(mintAddress);
  const recipient = new PublicKey(to);
  const source = getAssociatedTokenAddressSync(mint, owner.publicKey, false, TOKEN_2022_PROGRAM_ID);
  const destination = getAssociatedTokenAddressSync(mint, recipient, false, TOKEN_2022_PROGRAM_ID);

  const transferIx = await createTransferCheckedWithTransferHookInstruction(
    connection, source, mint, destination, owner.publicKey, 1n, 0, [], 'confirmed', TOKEN_2022_PROGRAM_ID,
  );
  const tx = new Transaction().add(
    createAssociatedTokenAccountIdempotentInstruction(owner.publicKey, destination, recipient, mint, TOKEN_2022_PROGRAM_ID),
    transferIx,
  );
  // If the hook rejects the transfer (for example, royalties not approved), the whole transaction rolls back.
  return sendAndConfirmTransaction(connection, tx, [owner]);
}

// Example: npx tsx src/02-royalty-transfer.ts <MINT_ADDRESS>
if (process.argv[2]) inspectRoyaltyHook(process.argv[2]).then(r => console.log(r)).catch(e => { console.error(e); process.exit(1); });

What was verified

In LiteSVM: an NFT mint is created with a transfer hook pointing to the WNS royalty program, and the inspection logic reads that program back from the mint correctly. The transfer function is type-checked against the official @solana/spl-token API; running it end to end needs the real WNS programs, which is the job of the devnet stage on the roadmap.

Where it is useful

  • Digital art, music and video NFTs.
  • Game items whose designers earn from the secondary market.
  • Licensed brand collectibles, where the license fee follows every sale.

Limits and risks

  • The hook sees the number of tokens moved, not the price. A sale settled in a separate transaction ("a gift for 0 SOL") can dodge a percentage royalty. WNS handles this with approval logic; read the program before relying on it.
  • Every hook call costs compute units. Aggregators may need to request more.
  • The WNS audit is documented as not formally completed. Treat it accordingly.

Wen in pictures

Wen royalty coin design
Royalties written into the token
Wen meme artists gallery
Meme culture, fair rewards
Anime Wen cat creator
Creators first
Wen anime royalty story
Every resale remembers the artist
Wen idol cat collection
Collections with a conscience

Where Wen fits in this model

This is Wen's own invention at work: wen_royalty_distribution is one of the two programs of the Wen Program Library. A creator community can choose to quote prices or pay tips in WEN, while the royalty rule itself stays in the token. Read the Wen Program Library review for the full picture.

The Wen thread: one contract, everywhere

Every model in the Lab is free and open, and every one carries the same signature: the $WEN token contract. Copy it, repeat it in your own docs, and always verify it against an explorer before use.

WENWENvqqNya429ubCdR81ZmD69brwQaaBYY6p3LCpk

Check: Solana Explorer · how to find the contract ID

Open use policy

  • Free and open. All Lab code is released under the Apache License 2.0, the same license as the Wen Program Library. Use it, change it, ship it, commercially or not; keep the license notice.
  • Open tools only. Built on public, documented tools: Solana SPL Token-2022 (Token Extensions), the token layout of the Wen New Standard (WNS), Solana Pay, and LiteSVM for local testing.
  • The rule: always verify your own model. Run the tests, start on devnet, read the official documentation, review every account and amount, and get an independent audit before any mainnet use. A model that is not checked is not a model, it is a guess.
  • Not audited, not advice. These are educational examples. They are not financial, legal or tax advice, and not a licensed payment or banking product. Payments, stablecoins and acquiring are regulated activities in most countries.
  • Security. Never paste a private key into a website. Do not install the npm package @wen-community/wen-new-standard: npm removed it as malicious. Build from official sources.

Spoken by Wen, for the community. More in our editorial and data policy.

Wen Open Lab · roadmap · all code · Wen Program Library on GitHub