create-0g-app 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +11 -5
- package/dist/index.js.map +1 -1
- package/dist/scaffold.d.ts +1 -0
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +101 -23
- package/dist/scaffold.js.map +1 -1
- package/package.json +1 -1
- package/templates/base/_gitignore +1 -0
- package/templates/base/packages/web/app/globals.css +11 -10
- package/templates/base/packages/web/components/Navbar.module.css +13 -11
- package/templates/base/packages/web/components/Navbar.tsx +1 -1
- package/templates/base/packages/web/next.config.ts +1 -0
- package/templates/compute/packages/web/app/api/compute/broker.ts +62 -0
- package/templates/compute/packages/web/app/api/compute/route.ts +15 -53
- package/templates/compute/packages/web/app/api/compute/setup/route.ts +21 -0
- package/templates/compute/packages/web/components/ComputeSection.module.css +179 -11
- package/templates/compute/packages/web/components/ComputeSection.tsx +126 -8
- package/templates/contracts/packages/web/components/ContractsSection.module.css +31 -0
- package/templates/contracts/packages/web/components/ContractsSection.tsx +17 -0
- package/templates/inft/packages/contracts/contracts/INFT.sol +49 -0
- package/templates/inft/packages/contracts/scripts/deployINFT.ts +33 -0
- package/templates/inft/packages/web/app/api/inft/mint/route.ts +92 -0
- package/templates/inft/packages/web/app/api/inft/token/route.ts +43 -0
- package/templates/inft/packages/web/components/INFTSection.module.css +194 -0
- package/templates/inft/packages/web/components/INFTSection.tsx +214 -0
- package/templates/inft/packages/web/lib/0g-inft.ts +40 -0
- package/templates/storage/packages/web/components/StorageSection.module.css +52 -1
- package/templates/storage/packages/web/components/StorageSection.tsx +37 -1
package/dist/index.js
CHANGED
|
@@ -72,7 +72,7 @@ async function main() {
|
|
|
72
72
|
projectName = name;
|
|
73
73
|
}
|
|
74
74
|
// Feature selection
|
|
75
|
-
const contracts = await p.confirm({ message: "Include
|
|
75
|
+
const contracts = await p.confirm({ message: "Include onchain contracts? (Hardhat + 0G Galileo)", initialValue: false });
|
|
76
76
|
if (p.isCancel(contracts)) {
|
|
77
77
|
p.cancel("Cancelled.");
|
|
78
78
|
process.exit(0);
|
|
@@ -87,6 +87,11 @@ async function main() {
|
|
|
87
87
|
p.cancel("Cancelled.");
|
|
88
88
|
process.exit(0);
|
|
89
89
|
}
|
|
90
|
+
const inft = await p.confirm({ message: "Use 0G INFT? (Intelligent NFTs — metadata on 0G Storage)", initialValue: false });
|
|
91
|
+
if (p.isCancel(inft)) {
|
|
92
|
+
p.cancel("Cancelled.");
|
|
93
|
+
process.exit(0);
|
|
94
|
+
}
|
|
90
95
|
const targetDir = path_1.default.resolve(process.cwd(), projectName);
|
|
91
96
|
if (fs_extra_1.default.existsSync(targetDir)) {
|
|
92
97
|
const overwrite = await p.confirm({
|
|
@@ -102,7 +107,7 @@ async function main() {
|
|
|
102
107
|
const s = p.spinner();
|
|
103
108
|
fs_extra_1.default.ensureDirSync(targetDir);
|
|
104
109
|
s.start("Scaffolding project");
|
|
105
|
-
(0, scaffold_1.scaffold)({ projectName: projectName, contracts: !!contracts, storage: !!storage, compute: !!compute }, targetDir);
|
|
110
|
+
(0, scaffold_1.scaffold)({ projectName: projectName, contracts: !!contracts, storage: !!storage, compute: !!compute, inft: !!inft }, targetDir);
|
|
106
111
|
s.stop(`Scaffolded project in ${picocolors_1.default.green(`./${projectName}`)}`);
|
|
107
112
|
// Install
|
|
108
113
|
console.log(picocolors_1.default.dim("\n Installing dependencies... (this may take a minute, hang tight)\n"));
|
|
@@ -118,8 +123,9 @@ async function main() {
|
|
|
118
123
|
contracts && "contracts",
|
|
119
124
|
storage && "storage",
|
|
120
125
|
compute && "compute",
|
|
126
|
+
inft && "inft",
|
|
121
127
|
].filter(Boolean);
|
|
122
|
-
const needsPrivateKey = !!(contracts || storage || compute);
|
|
128
|
+
const needsPrivateKey = !!(contracts || storage || compute || inft);
|
|
123
129
|
p.outro([
|
|
124
130
|
picocolors_1.default.green("Your 0G app is ready!"),
|
|
125
131
|
selectedFeatures.length > 0
|
|
@@ -132,8 +138,8 @@ async function main() {
|
|
|
132
138
|
needsPrivateKey ? ` ${picocolors_1.default.yellow("⚠")} Add your ${picocolors_1.default.bold("PRIVATE_KEY")} to ${picocolors_1.default.cyan(`${projectName}/packages/web/.env.local`)}` : "",
|
|
133
139
|
needsPrivateKey ? ` ${picocolors_1.default.dim("Get testnet OG at https://faucet.0g.ai")}` : "",
|
|
134
140
|
"",
|
|
135
|
-
contracts ? ` ${picocolors_1.default.cyan("npm run deploy")}
|
|
136
|
-
` ${picocolors_1.default.cyan("npm run dev")}
|
|
141
|
+
(contracts || inft) ? ` ${picocolors_1.default.cyan("npm run deploy")} ${picocolors_1.default.dim("→ deploy contract to Galileo testnet")}` : "",
|
|
142
|
+
` ${picocolors_1.default.cyan("npm run dev")} ${picocolors_1.default.dim("→ start local dev server")}`,
|
|
137
143
|
"",
|
|
138
144
|
` ${picocolors_1.default.dim("Docs: https://docs.0g.ai")}`,
|
|
139
145
|
]
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,kDAAoC;AACpC,4DAA4B;AAC5B,gDAAwB;AACxB,wDAA0B;AAC1B,iDAAyC;AACzC,yCAAsC;AAEtC,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,OAAO,CAAC,GAAG,CACT,oBAAE,CAAC,IAAI,CACL;QACE,yCAAyC;QACzC,UAAU,GAAG,oBAAE,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,oBAAoB;QAC5D,yCAAyC;KAC1C,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CACF,CAAC;IACF,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,CAAC,CAAC,KAAK,CAAC,oBAAE,CAAC,MAAM,CAAC,oBAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAEpD,eAAe;IACf,IAAI,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC;YACxB,OAAO,EAAE,eAAe;YACxB,WAAW,EAAE,WAAW;YACxB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;gBACd,IAAI,CAAC,CAAC;oBAAE,OAAO,0BAA0B,CAAC;gBAC1C,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;oBAAE,OAAO,gDAAgD,CAAC;YACzF,CAAC;SACF,CAAC,CAAC;QACH,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;QAClE,WAAW,GAAG,IAAc,CAAC;IAC/B,CAAC;IAED,oBAAoB;IACpB,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/scaffold.d.ts
CHANGED
package/dist/scaffold.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;CACf;AAID,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,QA0C7D"}
|
package/dist/scaffold.js
CHANGED
|
@@ -8,7 +8,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const TEMPLATES_DIR = path_1.default.join(__dirname, "..", "templates");
|
|
10
10
|
function scaffold(features, targetDir) {
|
|
11
|
-
const { contracts, storage, compute } = features;
|
|
11
|
+
const { contracts, storage, compute, inft } = features;
|
|
12
12
|
// 0. Ensure all required directories exist
|
|
13
13
|
fs_extra_1.default.ensureDirSync(path_1.default.join(targetDir, "packages", "web", "app"));
|
|
14
14
|
// 1. Always copy base
|
|
@@ -23,8 +23,15 @@ function scaffold(features, targetDir) {
|
|
|
23
23
|
if (compute) {
|
|
24
24
|
fs_extra_1.default.copySync(path_1.default.join(TEMPLATES_DIR, "compute"), targetDir, { filter: noDeps });
|
|
25
25
|
}
|
|
26
|
+
if (inft) {
|
|
27
|
+
// INFT needs the contracts base (hardhat.config.ts etc.) + its own files
|
|
28
|
+
fs_extra_1.default.copySync(path_1.default.join(TEMPLATES_DIR, "contracts"), targetDir, { filter: noDeps });
|
|
29
|
+
fs_extra_1.default.copySync(path_1.default.join(TEMPLATES_DIR, "inft"), targetDir, { filter: noDeps });
|
|
30
|
+
}
|
|
26
31
|
// 3. Generate dynamic files
|
|
27
32
|
writeRootPackageJson(targetDir, features);
|
|
33
|
+
if (contracts || inft)
|
|
34
|
+
writeContractsPackageJson(targetDir, features);
|
|
28
35
|
writeWebPackageJson(targetDir, features);
|
|
29
36
|
writeEnvExample(targetDir, features);
|
|
30
37
|
writePageTsx(targetDir, features);
|
|
@@ -44,31 +51,59 @@ function noDeps(src) {
|
|
|
44
51
|
const rel = path_1.default.relative(TEMPLATES_DIR, src);
|
|
45
52
|
return !rel.includes("node_modules") && !rel.includes(".next");
|
|
46
53
|
}
|
|
47
|
-
function writeRootPackageJson(targetDir, { projectName, contracts, storage }) {
|
|
54
|
+
function writeRootPackageJson(targetDir, { projectName, contracts, storage, inft }) {
|
|
48
55
|
const workspaces = ["packages/web"];
|
|
49
|
-
if (contracts)
|
|
56
|
+
if (contracts || inft)
|
|
50
57
|
workspaces.push("packages/contracts");
|
|
51
58
|
const scripts = {
|
|
52
59
|
dev: "npm run dev --workspace=packages/web",
|
|
53
60
|
build: "npm run build --workspace=packages/web",
|
|
54
61
|
};
|
|
55
|
-
if (storage) {
|
|
62
|
+
if (storage || inft) {
|
|
56
63
|
scripts.postinstall = "node scripts/patch-0g-sdk.js";
|
|
57
64
|
}
|
|
58
|
-
if (contracts) {
|
|
59
|
-
|
|
65
|
+
if (contracts || inft) {
|
|
66
|
+
const deploySteps = ["npm run compile --workspace=packages/contracts"];
|
|
67
|
+
if (contracts)
|
|
68
|
+
deploySteps.push("npm run deploy --workspace=packages/contracts");
|
|
69
|
+
if (inft)
|
|
70
|
+
deploySteps.push("npm run deploy:inft --workspace=packages/contracts");
|
|
71
|
+
scripts.deploy = deploySteps.join(" && ");
|
|
60
72
|
scripts.verify = "npm run verify --workspace=packages/contracts";
|
|
61
73
|
}
|
|
62
74
|
fs_extra_1.default.writeFileSync(path_1.default.join(targetDir, "package.json"), JSON.stringify({ name: projectName, version: "0.1.0", private: true, workspaces, scripts }, null, 2));
|
|
63
75
|
}
|
|
64
|
-
function
|
|
76
|
+
function writeContractsPackageJson(targetDir, { inft }) {
|
|
77
|
+
const pkg = {
|
|
78
|
+
name: "contracts",
|
|
79
|
+
version: "1.0.0",
|
|
80
|
+
private: true,
|
|
81
|
+
scripts: {
|
|
82
|
+
compile: "hardhat compile",
|
|
83
|
+
deploy: "hardhat run scripts/deploy.ts --network 0g-galileo",
|
|
84
|
+
"deploy:inft": "hardhat run scripts/deployINFT.ts --network 0g-galileo",
|
|
85
|
+
verify: "hardhat verify --network 0g-galileo $(cat .deployed-address)",
|
|
86
|
+
test: "hardhat test",
|
|
87
|
+
},
|
|
88
|
+
dependencies: {
|
|
89
|
+
...(inft ? { "@openzeppelin/contracts": "^5.0.0" } : {}),
|
|
90
|
+
},
|
|
91
|
+
devDependencies: {
|
|
92
|
+
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
|
|
93
|
+
dotenv: "^16.0.0",
|
|
94
|
+
hardhat: "^2.22.0",
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
fs_extra_1.default.writeFileSync(path_1.default.join(targetDir, "packages", "contracts", "package.json"), JSON.stringify(pkg, null, 2));
|
|
98
|
+
}
|
|
99
|
+
function writeWebPackageJson(targetDir, { storage, compute, inft }) {
|
|
65
100
|
const deps = {
|
|
66
|
-
"@tanstack/react-query": "
|
|
67
|
-
next: "
|
|
68
|
-
react: "
|
|
69
|
-
"react-dom": "
|
|
70
|
-
viem: "
|
|
71
|
-
wagmi: "
|
|
101
|
+
"@tanstack/react-query": "5.62.0",
|
|
102
|
+
next: "15.1.7",
|
|
103
|
+
react: "19.0.0",
|
|
104
|
+
"react-dom": "19.0.0",
|
|
105
|
+
viem: "2.21.58",
|
|
106
|
+
wagmi: "2.13.4",
|
|
72
107
|
};
|
|
73
108
|
if (storage) {
|
|
74
109
|
deps["@0glabs/0g-ts-sdk"] = "^0.3.3";
|
|
@@ -80,6 +115,12 @@ function writeWebPackageJson(targetDir, { storage, compute }) {
|
|
|
80
115
|
if (!deps["ethers"])
|
|
81
116
|
deps["ethers"] = "^6.13.0";
|
|
82
117
|
}
|
|
118
|
+
if (inft) {
|
|
119
|
+
if (!deps["@0glabs/0g-ts-sdk"])
|
|
120
|
+
deps["@0glabs/0g-ts-sdk"] = "^0.3.3";
|
|
121
|
+
if (!deps["ethers"])
|
|
122
|
+
deps["ethers"] = "^6.13.0";
|
|
123
|
+
}
|
|
83
124
|
const pkg = {
|
|
84
125
|
name: "web",
|
|
85
126
|
version: "0.1.0",
|
|
@@ -95,27 +136,32 @@ function writeWebPackageJson(targetDir, { storage, compute }) {
|
|
|
95
136
|
};
|
|
96
137
|
fs_extra_1.default.writeFileSync(path_1.default.join(targetDir, "packages", "web", "package.json"), JSON.stringify(pkg, null, 2));
|
|
97
138
|
}
|
|
98
|
-
function writeEnvExample(targetDir, { contracts, storage, compute }) {
|
|
139
|
+
function writeEnvExample(targetDir, { contracts, storage, compute, inft }) {
|
|
99
140
|
const lines = [
|
|
100
141
|
"# 0G Galileo Testnet",
|
|
101
142
|
"NEXT_PUBLIC_CHAIN_ID=16602",
|
|
102
143
|
"NEXT_PUBLIC_RPC_URL=https://evmrpc-testnet.0g.ai",
|
|
103
144
|
];
|
|
104
|
-
if (storage) {
|
|
145
|
+
if (storage || inft) {
|
|
105
146
|
lines.push("STORAGE_INDEXER_RPC=https://indexer-storage-testnet-turbo.0g.ai");
|
|
106
147
|
}
|
|
107
|
-
if (compute || contracts) {
|
|
148
|
+
if (compute || contracts || inft) {
|
|
108
149
|
lines.push("");
|
|
109
150
|
lines.push("# Private key — used server-side for compute inference payments and/or Hardhat deploy");
|
|
110
151
|
lines.push("# Never committed or exposed to the browser. Get testnet OG at https://faucet.0g.ai");
|
|
111
152
|
lines.push("PRIVATE_KEY=");
|
|
112
153
|
}
|
|
113
|
-
if (storage && !contracts) {
|
|
154
|
+
if (storage && !contracts && !inft) {
|
|
114
155
|
lines.push("");
|
|
115
156
|
lines.push("# Private key for signing storage transactions — never commit this");
|
|
116
157
|
lines.push("# Get testnet OG at https://faucet.0g.ai");
|
|
117
158
|
lines.push("PRIVATE_KEY=");
|
|
118
159
|
}
|
|
160
|
+
if (inft) {
|
|
161
|
+
lines.push("");
|
|
162
|
+
lines.push("# Populated automatically after `npm run deploy:inft`");
|
|
163
|
+
lines.push("NEXT_PUBLIC_INFT_ADDRESS=");
|
|
164
|
+
}
|
|
119
165
|
if (contracts) {
|
|
120
166
|
lines.push("");
|
|
121
167
|
lines.push("# Populated automatically after `npm run deploy`");
|
|
@@ -123,18 +169,26 @@ function writeEnvExample(targetDir, { contracts, storage, compute }) {
|
|
|
123
169
|
}
|
|
124
170
|
fs_extra_1.default.writeFileSync(path_1.default.join(targetDir, "packages", "web", ".env.example"), lines.join("\n") + "\n");
|
|
125
171
|
}
|
|
126
|
-
function writePageTsx(targetDir, { storage, compute }) {
|
|
127
|
-
const hasFeatures = storage || compute;
|
|
172
|
+
function writePageTsx(targetDir, { contracts, storage, compute, inft }) {
|
|
173
|
+
const hasFeatures = contracts || storage || compute || inft;
|
|
128
174
|
const imports = [
|
|
175
|
+
...(contracts ? [`import { ContractsSection } from "@/components/ContractsSection";`] : []),
|
|
129
176
|
...(storage ? [`import { StorageSection } from "@/components/StorageSection";`] : []),
|
|
130
177
|
...(compute ? [`import { ComputeSection } from "@/components/ComputeSection";`] : []),
|
|
178
|
+
...(inft ? [`import { INFTSection } from "@/components/INFTSection";`] : []),
|
|
131
179
|
];
|
|
132
180
|
const body = hasFeatures
|
|
133
181
|
? `
|
|
134
182
|
return (
|
|
135
183
|
<main className={styles.main}>
|
|
184
|
+
<div className={styles.hero}>
|
|
185
|
+
<h1 className={styles.heroTitle}>create-0g-app</h1>
|
|
186
|
+
<p className={styles.heroSubtitle}>The fastest way to build on 0G with one command</p>
|
|
187
|
+
</div>
|
|
188
|
+
${contracts ? "<ContractsSection />" : ""}
|
|
136
189
|
${storage ? "<StorageSection />" : ""}
|
|
137
190
|
${compute ? "<ComputeSection />" : ""}
|
|
191
|
+
${inft ? "<INFTSection />" : ""}
|
|
138
192
|
</main>
|
|
139
193
|
);`
|
|
140
194
|
: `
|
|
@@ -171,7 +225,23 @@ function writePageCss(targetDir) {
|
|
|
171
225
|
.main {
|
|
172
226
|
max-width: 800px;
|
|
173
227
|
margin: 0 auto;
|
|
174
|
-
padding:
|
|
228
|
+
padding: 0 24px 80px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.hero {
|
|
232
|
+
text-align: center;
|
|
233
|
+
padding: 56px 0 40px;
|
|
234
|
+
}
|
|
235
|
+
.heroTitle {
|
|
236
|
+
font-size: 3rem;
|
|
237
|
+
font-weight: 800;
|
|
238
|
+
color: #1e1b4b;
|
|
239
|
+
letter-spacing: -0.04em;
|
|
240
|
+
margin-bottom: 12px;
|
|
241
|
+
}
|
|
242
|
+
.heroSubtitle {
|
|
243
|
+
font-size: 1.05rem;
|
|
244
|
+
color: #4b5563;
|
|
175
245
|
}
|
|
176
246
|
|
|
177
247
|
/* Landing (no features selected) */
|
|
@@ -200,7 +270,7 @@ function writePageCss(targetDir) {
|
|
|
200
270
|
`.trimStart();
|
|
201
271
|
fs_extra_1.default.writeFileSync(path_1.default.join(targetDir, "packages", "web", "app", "page.module.css"), css);
|
|
202
272
|
}
|
|
203
|
-
function writeReadme(targetDir, { projectName, contracts, storage, compute }) {
|
|
273
|
+
function writeReadme(targetDir, { projectName, contracts, storage, compute, inft }) {
|
|
204
274
|
const lines = [
|
|
205
275
|
`# ${projectName}`,
|
|
206
276
|
"",
|
|
@@ -215,8 +285,13 @@ function writeReadme(targetDir, { projectName, contracts, storage, compute }) {
|
|
|
215
285
|
"npm run dev",
|
|
216
286
|
"```",
|
|
217
287
|
];
|
|
218
|
-
if (contracts) {
|
|
219
|
-
|
|
288
|
+
if (contracts || inft) {
|
|
289
|
+
const deploySection = ["", "## Deploy", "", "```bash", "npm run deploy", "npm run verify", "```", ""];
|
|
290
|
+
if (contracts)
|
|
291
|
+
deploySection.push("Deploys your smart contract to 0G Galileo Testnet and writes the address to `.env.local`.");
|
|
292
|
+
if (inft)
|
|
293
|
+
deploySection.push("Deploys `INFT.sol` to 0G Galileo Testnet and writes the address to `.env.local`.");
|
|
294
|
+
lines.push(...deploySection);
|
|
220
295
|
}
|
|
221
296
|
if (storage) {
|
|
222
297
|
lines.push("", "## Storage", "", "Files are uploaded to 0G decentralized storage via `@0glabs/0g-ts-sdk`.", "Edit `packages/web/components/StorageSection.tsx` to customize.");
|
|
@@ -224,6 +299,9 @@ function writeReadme(targetDir, { projectName, contracts, storage, compute }) {
|
|
|
224
299
|
if (compute) {
|
|
225
300
|
lines.push("", "## Compute", "", "AI inference is routed through the 0G compute network via `@0glabs/0g-serving-broker`.", "Edit `packages/web/components/ComputeSection.tsx` to customize.");
|
|
226
301
|
}
|
|
302
|
+
if (inft) {
|
|
303
|
+
lines.push("", "## INFT (Intelligent NFTs)", "", "Mint ERC-721 tokens whose metadata lives on 0G decentralized storage.", "The storage root hash and metadata hash are recorded on-chain for verifiability.", "", "Edit `packages/web/components/INFTSection.tsx` to customize the UI.");
|
|
304
|
+
}
|
|
227
305
|
lines.push("", "## Resources", "", "- [0G Docs](https://docs.0g.ai)", "- [Faucet](https://faucet.0g.ai)", "- [Explorer](https://chainscan-galileo.0g.ai)");
|
|
228
306
|
fs_extra_1.default.writeFileSync(path_1.default.join(targetDir, "README.md"), lines.join("\n") + "\n");
|
|
229
307
|
}
|
package/dist/scaffold.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
2
2
|
|
|
3
3
|
:root {
|
|
4
|
-
--bg: #
|
|
5
|
-
--surface: #
|
|
6
|
-
--border: #
|
|
7
|
-
--accent: #
|
|
8
|
-
--accent-dim: rgba(
|
|
9
|
-
--text: #
|
|
10
|
-
--muted: #
|
|
11
|
-
--error: #
|
|
12
|
-
--success: #
|
|
4
|
+
--bg: #faf5ff;
|
|
5
|
+
--surface: #ffffff;
|
|
6
|
+
--border: #e9d5ff;
|
|
7
|
+
--accent: #9333ea;
|
|
8
|
+
--accent-dim: rgba(147, 51, 234, 0.08);
|
|
9
|
+
--text: #111827;
|
|
10
|
+
--muted: #4b5563;
|
|
11
|
+
--error: #ef4444;
|
|
12
|
+
--success: #10b981;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
body {
|
|
16
|
-
background:
|
|
16
|
+
background: linear-gradient(135deg, #f5f3ff 0%, #faf5ff 50%, #eef2ff 100%);
|
|
17
|
+
background-attachment: fixed;
|
|
17
18
|
color: var(--text);
|
|
18
19
|
font-family: var(--font-geist-sans), system-ui, sans-serif;
|
|
19
20
|
min-height: 100vh;
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
justify-content: space-between;
|
|
5
5
|
padding: 0 24px;
|
|
6
6
|
height: 56px;
|
|
7
|
-
border-bottom: 1px solid
|
|
7
|
+
border-bottom: 1px solid #f3e8ff;
|
|
8
8
|
position: sticky;
|
|
9
9
|
top: 0;
|
|
10
|
-
background:
|
|
10
|
+
background: rgba(255, 255, 255, 0.7);
|
|
11
|
+
backdrop-filter: blur(12px);
|
|
12
|
+
-webkit-backdrop-filter: blur(12px);
|
|
11
13
|
z-index: 10;
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -15,12 +17,12 @@
|
|
|
15
17
|
font-size: 1rem;
|
|
16
18
|
font-weight: 700;
|
|
17
19
|
letter-spacing: -0.03em;
|
|
18
|
-
color:
|
|
20
|
+
color: #111827;
|
|
19
21
|
text-decoration: none;
|
|
20
22
|
}
|
|
21
23
|
.logo:hover { text-decoration: none; }
|
|
22
24
|
|
|
23
|
-
.accent { color:
|
|
25
|
+
.accent { color: #9333ea; }
|
|
24
26
|
|
|
25
27
|
.right {
|
|
26
28
|
display: flex;
|
|
@@ -35,11 +37,11 @@
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
.btnPrimary {
|
|
38
|
-
background:
|
|
39
|
-
color: #
|
|
40
|
+
background: linear-gradient(135deg, #9333ea, #4f46e5);
|
|
41
|
+
color: #ffffff;
|
|
40
42
|
border: none;
|
|
41
43
|
padding: 7px 16px;
|
|
42
|
-
border-radius:
|
|
44
|
+
border-radius: 20px;
|
|
43
45
|
font-weight: 600;
|
|
44
46
|
cursor: pointer;
|
|
45
47
|
font-size: 0.85rem;
|
|
@@ -49,12 +51,12 @@
|
|
|
49
51
|
|
|
50
52
|
.btnSecondary {
|
|
51
53
|
background: transparent;
|
|
52
|
-
color:
|
|
53
|
-
border: 1px solid
|
|
54
|
+
color: #4b5563;
|
|
55
|
+
border: 1px solid #e9d5ff;
|
|
54
56
|
padding: 5px 12px;
|
|
55
57
|
border-radius: 8px;
|
|
56
58
|
font-size: 0.8rem;
|
|
57
59
|
cursor: pointer;
|
|
58
|
-
transition: border-color 0.15s;
|
|
60
|
+
transition: border-color 0.15s, color 0.15s;
|
|
59
61
|
}
|
|
60
|
-
.btnSecondary:hover { border-color:
|
|
62
|
+
.btnSecondary:hover { border-color: #9333ea; color: #9333ea; }
|
|
@@ -11,7 +11,7 @@ export function Navbar() {
|
|
|
11
11
|
return (
|
|
12
12
|
<nav className={styles.nav}>
|
|
13
13
|
<Link href="/" className={styles.logo}>
|
|
14
|
-
|
|
14
|
+
create-<span className={styles.accent}>0G</span>-app
|
|
15
15
|
</Link>
|
|
16
16
|
<div className={styles.right}>
|
|
17
17
|
{isConnected ? (
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ethers } from "ethers";
|
|
2
|
+
import { createZGComputeNetworkBroker } from "@0glabs/0g-serving-broker";
|
|
3
|
+
|
|
4
|
+
export const RPC_URL = process.env.NEXT_PUBLIC_RPC_URL ?? "https://evmrpc-testnet.0g.ai";
|
|
5
|
+
|
|
6
|
+
export const PROVIDERS: Record<string, string> = {
|
|
7
|
+
"qwen/qwen-2.5-7b-instruct": "0xa48f01287233509FD694a22Bf840225062E67836",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// Use globalThis so state survives Next.js hot module reloads in dev mode
|
|
11
|
+
const g = globalThis as any;
|
|
12
|
+
if (!g._zgBroker) g._zgBroker = null;
|
|
13
|
+
if (!g._zgProviderReady) g._zgProviderReady = new Set<string>();
|
|
14
|
+
|
|
15
|
+
export function getProviderReady(): Set<string> {
|
|
16
|
+
return g._zgProviderReady;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getSigner() {
|
|
20
|
+
const privateKey = process.env.PRIVATE_KEY;
|
|
21
|
+
if (!privateKey) throw new Error("PRIVATE_KEY is not set in .env.local");
|
|
22
|
+
const provider = new ethers.JsonRpcProvider(RPC_URL);
|
|
23
|
+
return new ethers.Wallet(privateKey, provider);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function getBroker() {
|
|
27
|
+
if (g._zgBroker) return g._zgBroker;
|
|
28
|
+
|
|
29
|
+
const signer = getSigner();
|
|
30
|
+
const broker = await createZGComputeNetworkBroker(signer);
|
|
31
|
+
|
|
32
|
+
const MIN_BALANCE = BigInt("3000000000000000000"); // 3 OG minimum
|
|
33
|
+
try {
|
|
34
|
+
const ledger = await broker.ledger.getLedger();
|
|
35
|
+
if (ledger.availableBalance < MIN_BALANCE) {
|
|
36
|
+
console.log("[compute] balance low, topping up...");
|
|
37
|
+
await broker.ledger.depositFund(3);
|
|
38
|
+
}
|
|
39
|
+
} catch (e) {
|
|
40
|
+
const msg = (e as Error).message ?? "";
|
|
41
|
+
if (msg.includes("does not exist") || msg.includes("add-account")) {
|
|
42
|
+
console.log("[compute] creating ledger with 3 OG deposit...");
|
|
43
|
+
await broker.ledger.addLedger(3);
|
|
44
|
+
} else {
|
|
45
|
+
throw e;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
g._zgBroker = broker;
|
|
50
|
+
return broker;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function setupProvider(
|
|
54
|
+
broker: Awaited<ReturnType<typeof createZGComputeNetworkBroker>>,
|
|
55
|
+
providerAddress: string
|
|
56
|
+
) {
|
|
57
|
+
console.log("[compute] running one-time provider setup for", providerAddress);
|
|
58
|
+
await broker.inference.acknowledgeProviderSigner(providerAddress);
|
|
59
|
+
await broker.ledger.transferFund(providerAddress, "inference", BigInt("1000000000000000000")); // 1 OG
|
|
60
|
+
g._zgProviderReady.add(providerAddress);
|
|
61
|
+
console.log("[compute] provider setup done");
|
|
62
|
+
}
|
|
@@ -1,54 +1,18 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
import { ethers } from "ethers";
|
|
3
|
-
import { createZGComputeNetworkBroker } from "@0glabs/0g-serving-broker";
|
|
4
2
|
import OpenAI from "openai";
|
|
3
|
+
import { getBroker, PROVIDERS, getProviderReady } from "./broker";
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// Active testnet providers (verified on 0G Galileo testnet)
|
|
9
|
-
const PROVIDERS: Record<string, string> = {
|
|
10
|
-
"qwen/qwen-2.5-7b-instruct": "0xa48f01287233509FD694a22Bf840225062E67836",
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
function getSigner() {
|
|
14
|
-
const privateKey = process.env.PRIVATE_KEY;
|
|
15
|
-
if (!privateKey) throw new Error("PRIVATE_KEY is not set in .env.local");
|
|
16
|
-
const provider = new ethers.JsonRpcProvider(RPC_URL);
|
|
17
|
-
return new ethers.Wallet(privateKey, provider);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async function getBroker() {
|
|
21
|
-
const signer = getSigner();
|
|
22
|
-
const broker = await createZGComputeNetworkBroker(signer);
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
await broker.ledger.getLedger();
|
|
26
|
-
} catch (e) {
|
|
27
|
-
const msg = (e as Error).message ?? "";
|
|
28
|
-
if (msg.includes("does not exist") || msg.includes("add-account")) {
|
|
29
|
-
console.log("Creating ledger account with 0.1 OG deposit...");
|
|
30
|
-
await broker.ledger.addLedger(0.1);
|
|
31
|
-
} else {
|
|
32
|
-
throw e;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return broker;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// GET /api/compute — list available models
|
|
5
|
+
// GET /api/compute — provider setup status
|
|
40
6
|
export async function GET() {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return NextResponse.json({ models: Object.keys(PROVIDERS), services: safe });
|
|
46
|
-
} catch (e) {
|
|
47
|
-
return NextResponse.json({ error: (e as Error).message }, { status: 500 });
|
|
7
|
+
const ready = getProviderReady();
|
|
8
|
+
const providerReady: Record<string, boolean> = {};
|
|
9
|
+
for (const [model, addr] of Object.entries(PROVIDERS)) {
|
|
10
|
+
providerReady[model] = ready.has(addr);
|
|
48
11
|
}
|
|
12
|
+
return NextResponse.json({ models: Object.keys(PROVIDERS), providerReady });
|
|
49
13
|
}
|
|
50
14
|
|
|
51
|
-
// POST /api/compute —
|
|
15
|
+
// POST /api/compute — inference only (run /api/compute/setup first)
|
|
52
16
|
export async function POST(req: NextRequest) {
|
|
53
17
|
try {
|
|
54
18
|
const { model, messages } = await req.json();
|
|
@@ -61,17 +25,10 @@ export async function POST(req: NextRequest) {
|
|
|
61
25
|
|
|
62
26
|
const broker = await getBroker();
|
|
63
27
|
|
|
64
|
-
// Acknowledge provider (safe to call multiple times)
|
|
65
|
-
await broker.inference.acknowledgeProviderSigner(providerAddress);
|
|
66
|
-
|
|
67
|
-
// Get endpoint + model name from provider metadata
|
|
68
28
|
const { endpoint, model: modelName } = await broker.inference.getServiceMetadata(providerAddress);
|
|
69
|
-
|
|
70
|
-
// Get single-use auth headers
|
|
71
29
|
const query = JSON.stringify(messages);
|
|
72
30
|
const headers = await broker.inference.getRequestHeaders(providerAddress, query);
|
|
73
31
|
|
|
74
|
-
// Call the provider via OpenAI-compatible API
|
|
75
32
|
const openai = new OpenAI({ baseURL: endpoint, apiKey: "" });
|
|
76
33
|
const completion = await openai.chat.completions.create(
|
|
77
34
|
{ model: modelName, messages, max_tokens: 1024 },
|
|
@@ -81,8 +38,13 @@ export async function POST(req: NextRequest) {
|
|
|
81
38
|
const content = completion.choices[0].message.content ?? "";
|
|
82
39
|
const chatId = completion.id;
|
|
83
40
|
|
|
84
|
-
//
|
|
85
|
-
|
|
41
|
+
// processResponse settles payment — non-fatal if it fails (inference already completed)
|
|
42
|
+
let isValid = false;
|
|
43
|
+
try {
|
|
44
|
+
isValid = await broker.inference.processResponse(providerAddress, chatId, content);
|
|
45
|
+
} catch (e) {
|
|
46
|
+
console.warn("[compute] processResponse failed (settlement skipped):", (e as Error).message);
|
|
47
|
+
}
|
|
86
48
|
|
|
87
49
|
return NextResponse.json({ content, model, isValid });
|
|
88
50
|
} catch (e) {
|