Skip to content

Commit

Permalink
poc: minikit
Browse files Browse the repository at this point in the history
  • Loading branch information
alessey committed Feb 26, 2025
1 parent a33bcac commit 4f809bb
Show file tree
Hide file tree
Showing 55 changed files with 3,555 additions and 65 deletions.
254 changes: 244 additions & 10 deletions create-onchain/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@ import pc from 'picocolors';
import ora from 'ora';
import {
createClickableLink,
detectPackageManager,
isValidPackageName,
toValidPackageName,
optimizedCopy,
} from './utils.js';

const sourceDir = path.resolve(
fileURLToPath(import.meta.url),
'../../../templates/next'
);
import { spawn } from 'child_process';

const renameFiles: Record<string, string | undefined> = {
_gitignore: '.gitignore',
Expand Down Expand Up @@ -46,7 +41,205 @@ async function copyDir(src: string, dest: string) {
}
}

async function init() {
async function createMiniKitTemplate() {
console.log(
`${pc.greenBright(`
/////////////////////////////////////////////////////////////////////////////////////////////////
// //
// ::: ::: ::::::::::: :::: ::: ::::::::::: ::: ::: ::::::::::: ::::::::::: //
// :+:+: :+:+: :+: :+:+: :+: :+: :+: :+: :+: :+: //
// +:+ +:+:+ +:+ +:+ :+:+:+ +:+ +:+ +:+ +:+ +:+ +:+ //
// +#+ +:+ +#+ +#+ +#+ +:+ +#+ +#+ +#++:++ +#+ +#+ //
// +#+ +#+ +#+ +#+ +#+#+# +#+ +#+ +#+ +#+ +#+ //
// #+# #+# #+# #+# #+#+# #+# #+# #+# #+# #+# //
// ### ### ######## ### #### ######## ### ### ######## ### //
// //
// Powered by OnchainKit //
/////////////////////////////////////////////////////////////////////////////////////////////////`)}\n\n`
);

const defaultProjectName = 'my-minikit-app';

let result: prompts.Answers<
'projectName' | 'packageName' | 'clientKey'
>;

try {
result = await prompts(
[
{
type: 'text',
name: 'projectName',
message: pc.reset('Project name:'),
initial: defaultProjectName,
onState: (state) => {
state.value = state.value.trim();
},
validate: (value) => {
const targetDir = path.join(process.cwd(), value);
if (
fs.existsSync(targetDir) &&
fs.readdirSync(targetDir).length > 0
) {
return 'Directory already exists and is not empty. Please choose a different name.';
}
return true;
},
},
{
type: (_, { projectName }: { projectName: string }) =>
isValidPackageName(projectName) ? null : 'text',
name: 'packageName',
message: pc.reset('Package name:'),
initial: (_, { projectName }: { projectName: string }) =>
toValidPackageName(projectName),
validate: (dir) =>
isValidPackageName(dir) || 'Invalid package.json name',
},
{
type: 'password',
name: 'clientKey',
message: pc.reset(
`Enter your ${createClickableLink(
'Coinbase Developer Platform Client API Key:',
'https://portal.cdp.coinbase.com/products/onchainkit'
)} (optional)`
),
},
],
{
onCancel: () => {
console.log('\nProject creation cancelled.');
process.exit(0);
},
}
);
} catch (cancelled: any) {
console.log(cancelled.message);
process.exit(1);
}

const { projectName, packageName, clientKey } = result;
const root = path.join(process.cwd(), projectName);

const spinner = ora(`Creating ${projectName}...`).start();

const sourceDir = path.resolve(
fileURLToPath(import.meta.url),
'../../../templates/minikit'
);

await copyDir(sourceDir, root);
const pkgPath = path.join(root, 'package.json');
const pkg = JSON.parse(await fs.promises.readFile(pkgPath, 'utf-8'));
pkg.name = packageName || toValidPackageName(projectName);
await fs.promises.writeFile(pkgPath, JSON.stringify(pkg, null, 2));

// Create .env file
const envPath = path.join(root, '.env');
await fs.promises.writeFile(
envPath,
`NEXT_PUBLIC_ONCHAINKIT_PROJECT_NAME=${projectName}
NEXT_PUBLIC_ONCHAINKIT_API_KEY=${clientKey}
NEXT_PUBLIC_URL=
NEXT_PUBLIC_SPLASH_IMAGE_URL=$NEXT_PUBLIC_URL/minikit.png
NEXT_PUBLIC_SPLASH_BACKGROUND_COLOR=FFFFFF
NEXT_PUBLIC_IMAGE_URL=$NEXT_PUBLIC_URL/minikit.png
NEXT_PUBLIC_ICON_URL=https://onchainkit.xyz/favicon/48x48.png
NEXT_PUBLIC_VERSION=next
REDIS_URL=
REDIS_TOKEN=`
);

spinner.succeed();

console.log(`\n${pc.magenta(`Created new MiniKit project in ${root}`)}`);

console.log('\nWould you like to set up your Frames Account Association now?');
console.log(pc.blue('* You can set this up later by running `npm run generate-account-association` or updating your `.env` file manually.\n'));

let setUpFrameResult: prompts.Answers<'setUpFrame'>;
try {
setUpFrameResult = await prompts(
[
{
type: 'toggle',
name: 'setUpFrame',
message: pc.reset('Set up Frame integration now?'),
initial: true,
active: 'yes',
inactive: 'no',
}
],
{
onCancel: () => {
console.log('\nSetup frame cancelled.');
process.exit(1);
},
}
);
} catch (cancelled: any) {
console.log(cancelled.message);
process.exit(1);
}

const { setUpFrame } = setUpFrameResult;
if (setUpFrame) {
const scriptPath = path.resolve(
fileURLToPath(import.meta.url),
'../../../templates/minikit/scripts/generateAccountAssociation.mjs'
);

// spawn the generate-account-association command
const generateAccountAssociation = spawn('node', [scriptPath, root], {
stdio: 'inherit',
cwd: process.cwd(),
shell: true
});

generateAccountAssociation.on('close', (code: number) => {
if (code === 0) {
logMiniKitSetupSummary(projectName, root, clientKey);
} else {
console.error('Failed to generate account association');
logMiniKitSetupSummary(projectName, root, clientKey);
}
});
} else {
logMiniKitSetupSummary(projectName, root, clientKey);
}
}

function logMiniKitSetupSummary(projectName: string, root: string, clientKey: string) {
console.log(`\nIntegrations:`);

console.log(`${pc.greenBright('\u2713')} ${pc.blueBright(`MiniKit`)}`);
console.log(`${pc.greenBright('\u2713')} ${pc.blueBright(`OnchainKit`)}`);
console.log(`${pc.greenBright('\u2713')} ${pc.blueBright(`Base`)}`);
if (clientKey) {
console.log(`${pc.greenBright('\u2713')} ${pc.blueBright(`Coinbase Developer Platform`)}`);
console.log(`${pc.greenBright('\u2713')} ${pc.blueBright(`Paymaster`)}`);
}

console.log(`\nFrameworks:`);
console.log(`${pc.cyan('- Wagmi')}`);
console.log(`${pc.cyan('- React')}`);
console.log(`${pc.cyan('- Next.js')}`);
console.log(`${pc.cyan('- Tailwind CSS')}`);
console.log(`${pc.cyan('- ESLint')}`);
console.log(`${pc.cyan('- Upstash Redis')}`);

console.log(`\nTo get started with ${pc.green(projectName)}, run the following commands:\n`);
if (root !== process.cwd()) {
console.log(` - cd ${path.relative(process.cwd(), root)}`);
}
console.log(' - npm install');
console.log(' - npm run dev');

console.log(pc.blue('\n* Don\'t forget to update the environment variables for your project in the `.env` file.'));
}

async function createOnchainKitTemplate() {
console.log(
`${pc.greenBright(`
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand All @@ -62,6 +255,7 @@ async function init() {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////`)}\n\n`
);


const defaultProjectName = 'my-onchainkit-app';

let result: prompts.Answers<
Expand Down Expand Up @@ -117,7 +311,7 @@ async function init() {
initial: true,
active: 'yes',
inactive: 'no',
},
}
],
{
onCancel: () => {
Expand All @@ -136,8 +330,12 @@ async function init() {

const spinner = ora(`Creating ${projectName}...`).start();

const sourceDir = path.resolve(
fileURLToPath(import.meta.url),
'../../../templates/next'
);

await copyDir(sourceDir, root);

const pkgPath = path.join(root, 'package.json');
const pkg = JSON.parse(await fs.promises.readFile(pkgPath, 'utf-8'));
pkg.name = packageName || toValidPackageName(projectName);
Expand All @@ -151,7 +349,7 @@ async function init() {
smartWallet ? 'smartWalletOnly' : 'all'
}`
);

spinner.succeed();
console.log(`\n${pc.magenta(`Created new OnchainKit project in ${root}`)}`);

Expand Down Expand Up @@ -192,6 +390,42 @@ async function init() {
console.log(' - npm run dev');
}

async function init() {
const isHelp = process.argv.some(arg => ['--help', '-h'].includes(arg));
const isVersion = process.argv.some(arg => ['--version', '-v'].includes(arg));
const isMinikit = process.argv.some(arg => ['--mini', '-m'].includes(arg));

if (isHelp) {
console.log(
`${pc.greenBright(`
Usage:
npm create-onchain [options]
Creates an OnchainKit project based on nextJs.
Options:
--version, -v: Show version
--mini, -m: Create a MiniKit project
--help, -h: Show help
`)}`
);
process.exit(0);
}

if (isVersion) {
const packageJsonContent = fs.readFileSync('./package.json', 'utf8');
const packageJson = JSON.parse(packageJsonContent);
console.log(`${pc.greenBright(`v${packageJson.version}`)}`);
process.exit(0);
}

if (isMinikit) {
await createMiniKitTemplate();
} else {
await createOnchainKitTemplate();
}
}

init().catch((e) => {
console.error(e);
});
3 changes: 3 additions & 0 deletions create-onchain/templates/minikit/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["next/core-web-vitals", "next/typescript"]
}
2 changes: 2 additions & 0 deletions create-onchain/templates/minikit/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# You can remove this file if you don't want to use Yarn package manager.
nodeLinker: node-modules
39 changes: 39 additions & 0 deletions create-onchain/templates/minikit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-onchain`]().


## Getting Started

First, install dependencies:

```bash
npm install
# or
yarn install
# or
pnpm install
# or
bun install
```

Next, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.


## Learn More

To learn more about OnchainKit, see our [documentation](https://onchainkit.xyz/getting-started).

To learn more about Next.js, see the [Next.js documentation](https://nextjs.org/docs).
36 changes: 36 additions & 0 deletions create-onchain/templates/minikit/_gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
Loading

0 comments on commit 4f809bb

Please sign in to comment.