NodeOps
FR

Complete Example

Deploy to CreateOS with plain fetch + viem. No SDK or special dependencies needed.


Prerequisites

Install viem:

Bash
1npm install viem

Generate a wallet if you don't have one:

TypeScript
1import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
2const privateKey = generatePrivateKey();
3const account = privateKeyToAccount(privateKey);
4console.log("Address:", account.address);
5// Save privateKey securely

Fund the wallet with ETH (gas) and USDC on Arbitrum or Base.


Full Deploy Script

TypeScript
1import { privateKeyToAccount } from "viem/accounts";
2import { createWalletClient, createPublicClient, http } from "viem";
3import { arbitrum } from "viem/chains";
4import { randomUUID } from "crypto";
5
6const GATEWAY = "https://mpp-createos.nodeops.network";
7const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY");
8
9// --- Auth helper ---
10const auth = async () => {
11 const nonce = randomUUID();
12 const timestamp = String(Date.now());
13 const signature = await account.signMessage({
14 message: `${account.address}:${timestamp}:${nonce}`,
15 });
16 return {
17 "X-Wallet-Address": account.address,
18 "X-Signature": signature,
19 "X-Timestamp": timestamp,
20 "X-Nonce": nonce,
21 };
22};
23
24// --- ERC20 ABI ---
25const ERC20_ABI = [{
26 name: "transfer",
27 type: "function",
28 stateMutability: "nonpayable",
29 inputs: [
30 { name: "to", type: "address" },
31 { name: "value", type: "uint256" },
32 ],
33 outputs: [{ name: "", type: "bool" }],
34}] as const;
35
36// --- Deploy body ---
37const body = {
38 uniqueName: `app-${Date.now()}`,
39 displayName: "My App",
40 upload: {
41 type: "files",
42 files: [
43 {
44 path: "index.js",
45 content: btoa(
46 'require("http").createServer((q,s) => s.end("Hello from CreateOS!")).listen(3000)'
47 ),
48 },
49 { path: "package.json", content: btoa('{"name":"app"}') },
50 ],
51 },
52};
53
54// 1. Get quote
55const quoteRes = await fetch(`${GATEWAY}/agent/deploy`, {
56 method: "POST",
57 headers: { "Content-Type": "application/json", ...(await auth()) },
58 body: JSON.stringify(body),
59});
60
61if (quoteRes.ok) {
62 // Already had credits - deployed for free
63 const result = await quoteRes.json();
64 console.log("Deployed (credits):", result);
65} else if (quoteRes.status === 402) {
66 const quote = await quoteRes.json();
67 console.log(`Payment required: $${quote.amount_usd} ${quote.token}`);
68
69 // 2. Pay
70 const walletClient = createWalletClient({
71 account,
72 chain: arbitrum,
73 transport: http(),
74 });
75 const publicClient = createPublicClient({
76 chain: arbitrum,
77 transport: http(),
78 });
79
80 const txHash = await walletClient.writeContract({
81 address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // USDC on Arbitrum
82 abi: ERC20_ABI,
83 functionName: "transfer",
84 args: [quote.pay_to, BigInt(quote.amount_token)],
85 });
86 await publicClient.waitForTransactionReceipt({ hash: txHash });
87 console.log("Payment confirmed:", txHash);
88
89 // 3. Deploy with payment proof
90 const deployRes = await fetch(`${GATEWAY}/agent/deploy`, {
91 method: "POST",
92 headers: {
93 "Content-Type": "application/json",
94 "X-Payment-Tx": txHash,
95 "X-Payment-Chain": quote.payment_chain,
96 "X-Payment-Token": quote.token,
97 ...(await auth()),
98 },
99 body: JSON.stringify(body),
100 });
101 const { projectId, deploymentId } = await deployRes.json();
102
103 // 4. Poll until ready
104 let endpoint;
105 while (!endpoint) {
106 await new Promise((r) => setTimeout(r, 5000));
107 const statusRes = await fetch(
108 `${GATEWAY}/agent/deploy/${projectId}/${deploymentId}/status`,
109 { headers: await auth() }
110 );
111 const status = await statusRes.json();
112 if (status.status === "ready") endpoint = status.endpoint;
113 if (status.status === "failed") throw new Error(status.reason);
114 console.log("Status:", status.status);
115 }
116
117 console.log(`Live: ${endpoint}`);
118}

Zip Upload

Replace the upload field in the body:

TypeScript
1import { readFileSync } from "fs";
2
3const body = {
4 uniqueName: `app-${Date.now()}`,
5 displayName: "My App",
6 upload: {
7 type: "zip",
8 data: readFileSync("code.zip").toString("base64"),
9 filename: "code.zip",
10 },
11};

List Your Projects

TypeScript
1const res = await fetch(`${GATEWAY}/agent/projects`, {
2 headers: await auth(),
3});
4const { projects } = await res.json();
5projects.forEach((p) => console.log(`${p.name}: ${p.url ?? "deploying..."}`));

Check Balance

TypeScript
1const res = await fetch(
2 `${GATEWAY}/agent/balance/${account.address}?chain=arbitrum`
3);
4const { balances } = await res.json();
5balances.forEach((b) => console.log(`${b.symbol}: ${b.balance}`));

Plus de 100 000 créateurs. Un seul espace de travail.

Recevez les mises à jour produit, les témoignages de créateurs et un accès anticipé aux fonctionnalités qui vous aident à livrer plus vite.

CreateOS est un espace de travail intelligent et unifié où les idées passent sans friction du concept au déploiement en production, éliminant les changements de contexte entre outils, infrastructure et flux de travail, avec la possibilité de monétiser vos idées immédiatement sur le Marketplace CreateOS.