NodeOps
UK

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}`));

100,000+ Builders. One Workspace.

Get product updates, builder stories, and early access to features that help you ship faster.

CreateOS is a unified intelligent workspace where ideas move seamlessly from concept to live deployment, eliminating context-switching across tools, infrastructure, and workflows with the opportunity to monetize ideas immediately on the CreateOS Marketplace.