Skip to content

Commit e4ade13

Browse files
authored
feat(community): add solana-pay-store template (solana-foundation#249)
* Token gated Metaplex + x402 template created * refactor: replace hardcoded tier validation with configurable TIER_ORDER constant in NFT minting route * refactor: use TIER_ORDER constant for tier validation in NFT renewal route * refactor: replace hardcoded tier validation with TIER_ORDER constant in buy, members, and renew routes * feat: add create-collections script to package.json and update README with usage instructions * docs: remove upgrade path feature from README for clarity * docs: update devnet testing instructions in README to include USDC faucet * refactor: abstracting tier type for better typing * Remove wallet UI and Gill, replace them with the framework-kit * linting * feat(x402-metaplex-token-gated): add dedicated /mint route for NFT minting - Create MintContent component with extracted minting logic - Add /mint/[tier] page for post-payment NFT minting - Update middleware to redirect to /mint after payment - Protect /mint route with payment cookie validation - Simplify tier-content to link to mint page - Fix member-content redirect logic for expired/missing NFTs * simplifying readme * upgrade next o latest version * Remove gill from the keywords * chore: regenerate pnpm-lock.yaml after rebase * deleted unused logo * formattiong * removing unused solana mobile * feat(community): add solana-pay-store template Add a Solana Pay e-commerce store template with product catalog, shopping cart, and QR code payment integration using itx-indexer for transaction viewing. * linting * removing unused import * bump nextjs to its latest version * refactor: migrate hooks to @solana/client - Migrate use-purchase-history.ts from @solana/web3.js to @solana/client - Migrate use-checkout.ts from @solana/web3.js to @solana/client - Re-implement findReference logic using getSignaturesForAddress RPC - Use useSolanaClient hook instead of manual Connection creation * removing un used deps * docs: add TODO comments for @solana/client migration Mark @solana/web3.js usage with TODO comments indicating these need to be migrated to @solana/client when @solana/pay adds support for it. * removing unneeded react import * feat(solana-pay-store): replace checkout with headless checkout implementation * refactor(solana-pay-store): update headless checkout and docs * removing test page * removing second template, we have a separate PR for that one * fix(solana-pay-store): improve wallet UI and remove purchase history - Add dark mode support for wallet dropdown - Add click-outside handler to close wallet dropdown - Remove purchase history feature (drawer, hook, and navbar icon) - Remove stock availability message to prevent layout shift * chore: regenerate template metadata * solana-pay-store: add noise background + bouncing image * feat(solana-pay-store): add hero section with glitch text, marquee, and dark mode - Add HeroText component with glitch effect from baluga-store - Add Marquee component with Solana branding and links - Force dark mode and remove theme selector - Fix noise background height issue by using fixed positioning - Update product prices to realistic values (, , ) - Add custom fonts for hero text styling * refactor(solana-pay-store): require merchant wallet and parameterize USDC mint - Add validation for NEXT_PUBLIC_MERCHANT_WALLET (lazy, at runtime) - Add NEXT_PUBLIC_USDC_MINT env var for mainnet/devnet switching - Export USDC_MINT_MAINNET and USDC_MINT_DEVNET constants - Remove unused use-solana.tsx wrapper (use @solana/react-hooks directly) - Rename template to commerce-kit in workflows/templates.json - Update README with new env var documentation * chore: rename solana-pay-store to commerce-kit-store and regenerate metadata * chore(commerce-kit-store): add .env.example * style(commerce-kit-store): fix prettier formatting
1 parent 38d8b5e commit e4ade13

File tree

84 files changed

+4776
-125
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+4776
-125
lines changed

.github/workflows/templates.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[
2+
"community/commerce-kit-store",
23
"community/kit-node-solanax402",
34
"community/merkle-airdrop",
45
"community/moneymq-x402",

TEMPLATES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ Templates using @solana/web3.js (legacy)
118118

119119
Templates maintained by the Solana community
120120

121+
### [commerce-kit-store](community/commerce-kit-store)
122+
123+
`gh:solana-foundation/templates/community/commerce-kit-store`
124+
125+
> Next.js store template using @solana-commerce/headless and @solana/kit
126+
127+
`nextjs` `react` `@solana/kit` `@solana-commerce/headless` `solana-pay` `tailwind` `typescript`
128+
121129
### [kit-node-solanax402](community/kit-node-solanax402)
122130

123131
`gh:solana-foundation/templates/community/kit-node-solanax402`
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Required: Your Solana wallet address to receive payments
2+
NEXT_PUBLIC_MERCHANT_WALLET=
3+
4+
# RPC endpoint (mainnet or devnet)
5+
NEXT_PUBLIC_RPC_URL=https://api.mainnet-beta.solana.com
6+
7+
# Optional: USDC mint address (defaults to mainnet USDC)
8+
# Mainnet: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
9+
# Devnet: 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU
10+
# NEXT_PUBLIC_USDC_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.*
7+
.yarn/*
8+
!.yarn/patches
9+
!.yarn/plugins
10+
!.yarn/releases
11+
!.yarn/versions
12+
13+
# testing
14+
/coverage
15+
16+
# next.js
17+
/.next/
18+
/out/
19+
20+
# production
21+
/build
22+
23+
# misc
24+
.DS_Store
25+
*.pem
26+
27+
# debug
28+
npm-debug.log*
29+
yarn-debug.log*
30+
yarn-error.log*
31+
.pnpm-debug.log*
32+
33+
# env files
34+
.env
35+
.env.local
36+
.env*.local
37+
38+
# vercel
39+
.vercel
40+
41+
# typescript
42+
*.tsbuildinfo
43+
next-env.d.ts
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Add files here to ignore them from prettier formatting
2+
/dist
3+
/coverage
4+
.next
5+
/tmp
6+
package-lock.json
7+
pnpm-lock.yaml
8+
yarn.lock
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"arrowParens": "always",
3+
"printWidth": 120,
4+
"semi": false,
5+
"singleQuote": true,
6+
"trailingComma": "all"
7+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Solana Commerce Kit Store
2+
3+
A Next.js e-commerce template demonstrating USDC payments on Solana using the Commerce Kit.
4+
5+
## How It Works
6+
7+
```
8+
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐
9+
│ Add items │ ──▶ │ Generate QR │ ──▶ │ Scan & Pay │ ──▶ │ Verified │
10+
│ to cart │ │ with unique │ │ with any │ │ on-chain │
11+
│ │ │ reference │ │ Solana │ │ │
12+
└─────────────┘ └──────────────┘ │ wallet │ └──────────────┘
13+
└─────────────┘
14+
```
15+
16+
1. **Cart** - User adds products to their shopping cart
17+
2. **Checkout** - App generates a Solana Pay QR code with a unique reference address
18+
3. **Payment** - User scans the QR with any Solana wallet and sends USDC
19+
4. **Verification** - App polls the blockchain, finds the transaction by reference, and verifies the amount
20+
21+
## Quick Start
22+
23+
### 1. Install
24+
25+
```bash
26+
pnpm install
27+
```
28+
29+
### 2. Configure
30+
31+
Create `.env.local`:
32+
33+
```bash
34+
# Required: Your Solana wallet address to receive payments
35+
NEXT_PUBLIC_MERCHANT_WALLET=<your-solana-wallet-address>
36+
37+
# RPC endpoint (mainnet or devnet)
38+
NEXT_PUBLIC_RPC_URL=https://api.mainnet-beta.solana.com
39+
40+
# Optional: USDC mint address (defaults to mainnet USDC)
41+
# Mainnet: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
42+
# Devnet: 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU
43+
# NEXT_PUBLIC_USDC_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
44+
```
45+
46+
### 3. Run
47+
48+
```bash
49+
pnpm dev
50+
```
51+
52+
Open [http://localhost:3000](http://localhost:3000)
53+
54+
## Solana Integration
55+
56+
### Key Files
57+
58+
| File | Purpose |
59+
| ------------------------------------------------------ | -------------------------------------------------------- |
60+
| `src/hooks/use-headless-checkout.ts` | Main payment hook - QR generation, polling, verification |
61+
| `src/components/checkout/headless-checkout-dialog.tsx` | Payment UI component |
62+
| `src/store/components/cart-drawer.tsx` | Cart with checkout integration |
63+
64+
### Payment Flow (useHeadlessCheckout)
65+
66+
```typescript
67+
// 1. Generate a unique reference keypair
68+
const referenceKeyPair = await generateKeyPair()
69+
const reference = await getAddressFromPublicKey(referenceKeyPair.publicKey)
70+
71+
// 2. Create Solana Pay request with QR code
72+
const { url, qr } = await createSolanaPayRequest({
73+
recipient: address(MERCHANT_WALLET),
74+
amount: BigInt(amountInMinorUnits),
75+
splToken: address(USDC_MINT),
76+
reference: reference, // This is how we track the payment
77+
})
78+
79+
// 3. Poll for transactions containing our reference
80+
const signatures = await rpc.getSignaturesForAddress(reference).send()
81+
82+
// 4. Verify the payment on-chain
83+
const result = await verifyPayment(rpc, signature, expectedAmount, recipient, mint)
84+
```
85+
86+
### Dependencies
87+
88+
| Package | Purpose |
89+
| --------------------------- | ---------------------------------------- |
90+
| `@solana-commerce/headless` | Payment requests, QR codes, verification |
91+
| `@solana/kit` | Key generation, address utilities |
92+
| `@solana/client` | RPC client for blockchain queries |
93+
| `@solana/react-hooks` | React hooks for Solana client |
94+
95+
### Why These Packages?
96+
97+
This template uses `@solana/kit` (the new Solana JavaScript SDK) instead of `@solana/web3.js`. Benefits:
98+
99+
- **Smaller bundle** - Tree-shakeable, only import what you need
100+
- **Type-safe** - Better TypeScript support
101+
- **Modern** - Uses native BigInt, no polyfills needed
102+
103+
## Project Structure
104+
105+
```
106+
src/
107+
├── hooks/
108+
│ ├── use-headless-checkout.ts # Payment flow hook
109+
│ └── use-purchase-history.ts # Transaction history
110+
├── components/
111+
│ ├── checkout/
112+
│ │ └── headless-checkout-dialog.tsx # Payment dialog
113+
│ └── wallet-ui.tsx # Wallet connect button
114+
├── store/
115+
│ ├── components/ # Product grid, cart drawer
116+
│ ├── hooks/ # Cart, product selection
117+
│ └── providers/ # Cart context
118+
└── app/
119+
└── page.tsx # Store home
120+
```
121+
122+
## Resources
123+
124+
- [Solana Commerce Kit Docs](https://launch.solana.com/docs/commerce-kit)
125+
- [Solana Pay Specification](https://docs.solanapay.com)
126+
- [@solana/kit Documentation](https://github.com/solana-labs/solana-web3.js)
127+
128+
## License
129+
130+
Apache-2.0
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "https://ui.shadcn.com/schema.json",
3+
"style": "new-york",
4+
"rsc": true,
5+
"tsx": true,
6+
"tailwind": {
7+
"config": "",
8+
"css": "src/app/globals.css",
9+
"baseColor": "neutral",
10+
"cssVariables": true,
11+
"prefix": ""
12+
},
13+
"aliases": {
14+
"components": "@/components",
15+
"utils": "@/lib/utils",
16+
"ui": "@/components/ui",
17+
"lib": "@/lib",
18+
"hooks": "@/hooks"
19+
},
20+
"iconLibrary": "lucide"
21+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { dirname } from 'path'
2+
import { fileURLToPath } from 'url'
3+
import { FlatCompat } from '@eslint/eslintrc'
4+
5+
const __filename = fileURLToPath(import.meta.url)
6+
const __dirname = dirname(__filename)
7+
8+
const compat = new FlatCompat({
9+
baseDirectory: __dirname,
10+
})
11+
12+
const eslintConfig = [...compat.extends('next/core-web-vitals', 'next/typescript')]
13+
14+
export default eslintConfig
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type { NextConfig } from 'next'
2+
3+
const nextConfig: NextConfig = {
4+
transpilePackages: [
5+
'@solana-commerce/react',
6+
'@solana-commerce/connector',
7+
'@solana-commerce/headless',
8+
'@solana-commerce/solana-pay',
9+
'@solana-commerce/sdk',
10+
],
11+
}
12+
13+
export default nextConfig

0 commit comments

Comments
 (0)