Skip to content

Conversation

@0xmaayan
Copy link
Contributor

@0xmaayan 0xmaayan commented Jan 20, 2026

Adds a complete token-gated file marketplace example built on Solana. Users can upload encrypted files for sale and buyers can purchase access to decrypt and download them.

Tutorial:

  • Upload encrypted files — Sellers encrypt files with AES-GCM and register them on-chain with a price
  • Threshold cryptography — Encryption keys are protected via Octopus threshold IBE
  • SOL payments — Buyers pay SOL to purchase access, creating an on-chain receipt
  • Decentralized storage — Encrypted files stored on Shelby
  • Proof-based decryption — Buyers prove access via signed transaction without submitting on-chain

Note

Adds a complete Solana token-gated content example with on-chain access control and a minimal Next.js client.

  • Implements anchor programs: access_control (instructions: register_blob, purchase; accounts: BlobMetadata, Receipt) and ace_hook (instruction: assert_access) with deployed IDs and generated IDLs/types
  • New Next.js app files: file-upload.tsx (encrypts file, uploads to Shelby, registers on-chain), providers.tsx (Solana client setup), header.tsx; plus project configs (.env.example, .prettier*, .gitignore)

Written by Cursor Bugbot for commit 1fe1a7b. This will update automatically on new commits. Configure here.

@0xmaayan 0xmaayan force-pushed the solana_token_gated_dapp branch 5 times, most recently from eda3151 to 143bfa8 Compare January 20, 2026 04:55
@0xmaayan 0xmaayan changed the title feat: Add Solana token-gated file marketplace example feat: Add Solana token-gated file example Jan 20, 2026
Copy link
Collaborator

@GhostWalker562 GhostWalker562 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a couple of comments but nothing jarring

].filter((url): url is string => !!url)
: [
"https://xchain-worker-0-646682240579.europe-west1.run.app",
"https://xchain-worker-1-646682240579.europe-west1.run.app",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just so I can better understand this, these xchain workers have a custom implementation where it will query the octopus_hook program to determine whether the user is able to decrypt this?

But the octopus_hook program is only for assertions ("hooks"), the actual logic behind those assertions are defined by the access_control program which does the actual removing and adding of token gated content?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, octopus_hook is just the assertion layer, while access_control handles the actual token-gating logic.

1. access_control program - The Business Logic Layer

  • Registers files (creates BlobMetadata PDAs with price, encrypted key, owner)
  • Processes purchases (transfers SOL, creates AccessReceipt PDAs)
  • Manages the actual state of who has access to what

2. octopus_hook program - The Verification Interface

  • Exposes a single assert_access instruction
  • Checks if an AccessReceipt PDA exists for a given (blob, buyer) pair
  • Acts as a standardized "hook" that workers know how to call

3. xchain workers - The Threshold Decryption Committee

  • Hold shares of the decryption master key
  • When a user requests decryption, they verify permission by simulating the octopus_hook.assert_access instruction
  • If the simulation passes (i.e., AccessReceipt exists), they release their key share


export const LAMPORTS_PER_SOL = 1_000_000_000n;
export const SYSTEM_PROGRAM_ADDRESS =
"11111111111111111111111111111111" as Address;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's is this for? Is this just standard to include in instructions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea,https://github.com/shelby/examples/pull/16/files#diff-2090c43cfa260d2b00fc203cb9475a7fb255e2c9cc4194877e93fda118e4edcbR126, its a Solana thing. I searched for a constant exported form the Solana SDKs but couldn't find

ownerAptosAddrBytes: Uint8Array,
blobName: string
): Uint8Array {
const prefix = new TextEncoder().encode("0x");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on why the 0x prefix is used in the blob names when its @ on the smart contract?

cc @zjma

@0xmaayan 0xmaayan force-pushed the solana_token_gated_dapp branch from 143bfa8 to ab3a301 Compare January 21, 2026 21:27
@0xmaayan 0xmaayan force-pushed the solana_token_gated_dapp branch from ab3a301 to 1fe1a7b Compare January 21, 2026 21:35
@0xmaayan 0xmaayan merged commit 5663b23 into main Jan 21, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants