0g-orbit 0.1.0

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.
Files changed (105) hide show
  1. package/dist/cli/cli.d.ts +3 -0
  2. package/dist/cli/cli.d.ts.map +1 -0
  3. package/dist/cli/cli.js +59 -0
  4. package/dist/cli/cli.js.map +1 -0
  5. package/dist/cli/commands/account.d.ts +6 -0
  6. package/dist/cli/commands/account.d.ts.map +1 -0
  7. package/dist/cli/commands/account.js +23 -0
  8. package/dist/cli/commands/account.js.map +1 -0
  9. package/dist/cli/commands/inference.d.ts +15 -0
  10. package/dist/cli/commands/inference.d.ts.map +1 -0
  11. package/dist/cli/commands/inference.js +70 -0
  12. package/dist/cli/commands/inference.js.map +1 -0
  13. package/dist/cli/commands/init.d.ts +7 -0
  14. package/dist/cli/commands/init.d.ts.map +1 -0
  15. package/dist/cli/commands/init.js +60 -0
  16. package/dist/cli/commands/init.js.map +1 -0
  17. package/dist/cli/commands/storage.d.ts +19 -0
  18. package/dist/cli/commands/storage.d.ts.map +1 -0
  19. package/dist/cli/commands/storage.js +62 -0
  20. package/dist/cli/commands/storage.js.map +1 -0
  21. package/dist/cli/utils.d.ts +4 -0
  22. package/dist/cli/utils.d.ts.map +1 -0
  23. package/dist/cli/utils.js +20 -0
  24. package/dist/cli/utils.js.map +1 -0
  25. package/dist/errors.d.ts +26 -0
  26. package/dist/errors.d.ts.map +1 -0
  27. package/dist/errors.js +51 -0
  28. package/dist/errors.js.map +1 -0
  29. package/dist/index.d.ts +10 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +11 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/inference.d.ts +17 -0
  34. package/dist/inference.d.ts.map +1 -0
  35. package/dist/inference.js +179 -0
  36. package/dist/inference.js.map +1 -0
  37. package/dist/networks.d.ts +16 -0
  38. package/dist/networks.d.ts.map +1 -0
  39. package/dist/networks.js +48 -0
  40. package/dist/networks.js.map +1 -0
  41. package/dist/orbit.d.ts +27 -0
  42. package/dist/orbit.d.ts.map +1 -0
  43. package/dist/orbit.js +108 -0
  44. package/dist/orbit.js.map +1 -0
  45. package/dist/retry.d.ts +23 -0
  46. package/dist/retry.d.ts.map +1 -0
  47. package/dist/retry.js +90 -0
  48. package/dist/retry.js.map +1 -0
  49. package/dist/storage.d.ts +26 -0
  50. package/dist/storage.d.ts.map +1 -0
  51. package/dist/storage.js +121 -0
  52. package/dist/storage.js.map +1 -0
  53. package/dist/types.d.ts +81 -0
  54. package/dist/types.d.ts.map +1 -0
  55. package/dist/types.js +2 -0
  56. package/dist/types.js.map +1 -0
  57. package/examples/ai-chatbot/index.ts +74 -0
  58. package/examples/model-registry/index.ts +137 -0
  59. package/examples/quick-start/index.ts +65 -0
  60. package/package.json +42 -0
  61. package/packages/cli/package.json +30 -0
  62. package/packages/cli/src/cli.ts +69 -0
  63. package/packages/cli/src/commands/account.ts +29 -0
  64. package/packages/cli/src/commands/inference.ts +103 -0
  65. package/packages/cli/src/commands/init.ts +71 -0
  66. package/packages/cli/src/commands/storage.ts +91 -0
  67. package/packages/cli/src/utils.ts +21 -0
  68. package/packages/cli/tsconfig.json +8 -0
  69. package/packages/core/package.json +35 -0
  70. package/packages/core/src/errors.test.ts +99 -0
  71. package/packages/core/src/errors.ts +79 -0
  72. package/packages/core/src/index.ts +37 -0
  73. package/packages/core/src/inference.ts +256 -0
  74. package/packages/core/src/networks.test.ts +62 -0
  75. package/packages/core/src/networks.ts +62 -0
  76. package/packages/core/src/orbit.test.ts +153 -0
  77. package/packages/core/src/orbit.ts +159 -0
  78. package/packages/core/src/retry.test.ts +99 -0
  79. package/packages/core/src/retry.ts +99 -0
  80. package/packages/core/src/storage.test.ts +199 -0
  81. package/packages/core/src/storage.ts +158 -0
  82. package/packages/core/src/types.ts +85 -0
  83. package/packages/core/tsconfig.json +8 -0
  84. package/packages/core/vitest.config.ts +7 -0
  85. package/src/cli/cli.ts +69 -0
  86. package/src/cli/commands/account.ts +29 -0
  87. package/src/cli/commands/inference.ts +103 -0
  88. package/src/cli/commands/init.ts +71 -0
  89. package/src/cli/commands/storage.ts +91 -0
  90. package/src/cli/utils.ts +21 -0
  91. package/src/errors.test.ts +99 -0
  92. package/src/errors.ts +79 -0
  93. package/src/index.ts +37 -0
  94. package/src/inference.ts +256 -0
  95. package/src/networks.test.ts +62 -0
  96. package/src/networks.ts +62 -0
  97. package/src/orbit.test.ts +153 -0
  98. package/src/orbit.ts +159 -0
  99. package/src/retry.test.ts +99 -0
  100. package/src/retry.ts +99 -0
  101. package/src/storage.test.ts +199 -0
  102. package/src/storage.ts +158 -0
  103. package/src/types.ts +85 -0
  104. package/tsconfig.json +20 -0
  105. package/vitest.config.ts +7 -0
@@ -0,0 +1,121 @@
1
+ import { Indexer, ZgFile } from '@0gfoundation/0g-ts-sdk';
2
+ import { writeFileSync, unlinkSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { randomBytes } from 'node:crypto';
6
+ import { StorageError } from './errors.js';
7
+ import { withRetry, isTransientError } from './retry.js';
8
+ const DEFAULT_REPLICAS = 1;
9
+ const DEFAULT_MAX_GAS_PRICE = 25_000_000_000; // 25 gwei — generous ceiling for auto-escalation
10
+ export class StorageClient {
11
+ indexer;
12
+ rpcUrl;
13
+ signer;
14
+ constructor(network, signer) {
15
+ this.indexer = new Indexer(network.indexerUrl);
16
+ this.rpcUrl = network.rpcUrl;
17
+ this.signer = signer;
18
+ }
19
+ /**
20
+ * Upload a file to 0G Storage by file path.
21
+ * Retries transient failures automatically. Gas escalates on each retry.
22
+ */
23
+ async store(filePath, options = {}) {
24
+ return withRetry(() => this._store(filePath, options), {
25
+ maxAttempts: 3,
26
+ isRetryable: (err) => {
27
+ if (!(err instanceof StorageError))
28
+ return isTransientError(err);
29
+ const msg = err.message.toLowerCase();
30
+ return msg.includes('gas') ||
31
+ msg.includes('timeout') ||
32
+ msg.includes('etimedout') ||
33
+ msg.includes('econnrefused') ||
34
+ msg.includes('underpriced');
35
+ },
36
+ });
37
+ }
38
+ /**
39
+ * Upload raw data (string, Buffer, or Uint8Array) to 0G Storage.
40
+ * Writes to a temp file, uploads, then cleans up.
41
+ */
42
+ async storeData(data, options = {}) {
43
+ const tempPath = join(tmpdir(), `orbit-${randomBytes(8).toString('hex')}`);
44
+ try {
45
+ writeFileSync(tempPath, data);
46
+ return await this.store(tempPath, options);
47
+ }
48
+ finally {
49
+ try {
50
+ unlinkSync(tempPath);
51
+ }
52
+ catch { /* ignore cleanup errors */ }
53
+ }
54
+ }
55
+ async _store(filePath, options) {
56
+ const file = await ZgFile.fromFilePath(filePath);
57
+ try {
58
+ const [tree, treeErr] = await file.merkleTree();
59
+ if (treeErr || !tree) {
60
+ throw new StorageError(`Failed to compute merkle tree: ${treeErr?.message ?? 'unknown error'}`, 'Ensure the file exists, is readable, and is not empty.');
61
+ }
62
+ // Always enable gas auto-escalation via the SDK's built-in retry.
63
+ // MaxGasPrice sets the ceiling — the SDK starts from the network estimate
64
+ // and bumps 10% on each retry until it hits this cap.
65
+ const maxGas = options.maxGasPrice
66
+ ? Number(options.maxGasPrice)
67
+ : DEFAULT_MAX_GAS_PRICE;
68
+ // Cast signer to avoid ESM/CJS ethers type mismatch
69
+ const [result, uploadErr] = await this.indexer.upload(file, this.rpcUrl, this.signer, {
70
+ tags: options.tags ?? '0x',
71
+ expectedReplica: options.replicas ?? DEFAULT_REPLICAS,
72
+ }, { Retries: 5, Interval: 3, MaxGasPrice: maxGas });
73
+ if (uploadErr) {
74
+ const msg = uploadErr.message;
75
+ let suggestion = 'Check your OG balance and try again.';
76
+ if (msg.includes('gas') || msg.includes('underpriced')) {
77
+ suggestion = `Gas auto-escalation hit the ceiling (${maxGas} wei). Try a higher maxGasPrice, e.g. { maxGasPrice: ${maxGas * 2}n }`;
78
+ }
79
+ else if (msg.includes('timeout') || msg.includes('ETIMEDOUT')) {
80
+ suggestion = 'The RPC endpoint timed out. Try a different RPC URL with the rpcUrl option.';
81
+ }
82
+ else if (msg.includes('insufficient funds')) {
83
+ suggestion = 'Your wallet needs more OG for gas. Get testnet OG from: https://faucet.0g.ai';
84
+ }
85
+ throw new StorageError(`Upload failed: ${msg}`, suggestion);
86
+ }
87
+ if ('txHash' in result) {
88
+ return {
89
+ root: result.rootHash,
90
+ txHash: result.txHash,
91
+ };
92
+ }
93
+ // Fragmented upload — return the first root hash as primary handle
94
+ return {
95
+ root: result.rootHashes[0],
96
+ txHash: result.txHashes[0],
97
+ };
98
+ }
99
+ finally {
100
+ await file.close();
101
+ }
102
+ }
103
+ /**
104
+ * Download a file from 0G Storage by root hash.
105
+ */
106
+ async retrieve(rootHash, outputPath, options = {}) {
107
+ return withRetry(() => this._retrieve(rootHash, outputPath, options), { maxAttempts: 3 });
108
+ }
109
+ async _retrieve(rootHash, outputPath, options) {
110
+ const err = await this.indexer.download(rootHash, outputPath, options.proof ?? false);
111
+ if (err) {
112
+ const msg = err.message;
113
+ let suggestion = 'Verify the root hash is correct and the file was uploaded successfully.';
114
+ if (msg.includes('not found') || msg.includes('404')) {
115
+ suggestion = 'This root hash was not found on the network. Double-check the hash or ensure the upload completed.';
116
+ }
117
+ throw new StorageError(`Download failed: ${msg}`, suggestion);
118
+ }
119
+ }
120
+ }
121
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { NetworkName } from './networks.js';
2
+ export interface OrbitConfig {
3
+ /** Private key for signing transactions. Falls back to PRIVATE_KEY env var if omitted. */
4
+ privateKey?: string;
5
+ /** Network to connect to */
6
+ network: NetworkName;
7
+ /** Custom RPC URL (overrides network default) */
8
+ rpcUrl?: string;
9
+ /** Custom indexer URL (overrides network default) */
10
+ indexerUrl?: string;
11
+ }
12
+ export interface StoreResult {
13
+ /** Merkle root hash — use this to retrieve the file */
14
+ root: string;
15
+ /** On-chain transaction hash */
16
+ txHash: string;
17
+ }
18
+ export interface StoreOptions {
19
+ /** Custom tags for the upload (hex string) */
20
+ tags?: string;
21
+ /** Expected number of replicas */
22
+ replicas?: number;
23
+ /** Maximum gas price in wei */
24
+ maxGasPrice?: bigint;
25
+ }
26
+ export interface RetrieveOptions {
27
+ /** Whether to verify merkle proofs during download */
28
+ proof?: boolean;
29
+ }
30
+ export interface InferResult {
31
+ /** The model's response text */
32
+ content: string;
33
+ /** The model used */
34
+ model: string;
35
+ /** Token usage */
36
+ usage?: {
37
+ promptTokens: number;
38
+ completionTokens: number;
39
+ totalTokens: number;
40
+ };
41
+ /** Whether the response passed TEE verification (null if not verifiable) */
42
+ verified: boolean | null;
43
+ }
44
+ export interface InferOptions {
45
+ /** Messages for chat completion */
46
+ messages: Array<{
47
+ role: 'system' | 'user' | 'assistant';
48
+ content: string;
49
+ }>;
50
+ /** Temperature for sampling (0-2) */
51
+ temperature?: number;
52
+ /** Maximum tokens to generate */
53
+ maxTokens?: number;
54
+ /** Specific provider address (auto-selected if omitted) */
55
+ provider?: string;
56
+ /** Request timeout in milliseconds (default: 30000) */
57
+ timeout?: number;
58
+ }
59
+ export interface ServiceInfo {
60
+ /** Provider wallet address */
61
+ provider: string;
62
+ /** Model name */
63
+ model: string;
64
+ /** Service endpoint URL */
65
+ url: string;
66
+ /** Input token price (neuron) */
67
+ inputPrice: bigint;
68
+ /** Output token price (neuron) */
69
+ outputPrice: bigint;
70
+ /** Whether TEE verification is available */
71
+ verifiable: boolean;
72
+ }
73
+ export interface AccountStatus {
74
+ /** Main ledger balance in OG */
75
+ balance: string;
76
+ /** Network name */
77
+ network: NetworkName;
78
+ /** Wallet address */
79
+ address: string;
80
+ }
81
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,WAAW,WAAW;IACxB,0FAA0F;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,4BAA4B;IAC5B,OAAO,EAAE,WAAW,CAAA;IACpB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qDAAqD;IACrD,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,WAAW;IACxB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAA;IACZ,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,YAAY;IACzB,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,eAAe;IAC5B,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IACxB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,kBAAkB;IAClB,KAAK,CAAC,EAAE;QACJ,YAAY,EAAE,MAAM,CAAA;QACpB,gBAAgB,EAAE,MAAM,CAAA;QACxB,WAAW,EAAE,MAAM,CAAA;KACtB,CAAA;IACD,4EAA4E;IAC5E,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,YAAY;IACzB,mCAAmC;IACnC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC3E,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,WAAW;IACxB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAA;IACnB,4CAA4C;IAC5C,UAAU,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,aAAa;IAC1B,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,mBAAmB;IACnB,OAAO,EAAE,WAAW,CAAA;IACpB,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAA;CAClB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * 0G Orbit — AI Chatbot Example
3
+ *
4
+ * A simple interactive chatbot using 0G Compute Network.
5
+ * Demonstrates multi-turn conversations with TEE verification.
6
+ *
7
+ * Usage:
8
+ * PRIVATE_KEY=0x... npx tsx index.ts
9
+ */
10
+
11
+ import { Orbit } from '@0g-orbit/core'
12
+ import { createInterface } from 'node:readline'
13
+
14
+ const MODEL = 'meta-llama/Llama-3.3-70B'
15
+
16
+ async function main() {
17
+ const orbit = await Orbit.connect({
18
+ network: 'testnet',
19
+ privateKey: process.env.PRIVATE_KEY!,
20
+ })
21
+
22
+ const status = await orbit.status()
23
+ console.log(`Connected: ${status.address} (${status.balance} OG)`)
24
+ console.log(`Model: ${MODEL}`)
25
+ console.log('Type "quit" to exit.\n')
26
+
27
+ const history: Array<{ role: 'system' | 'user' | 'assistant'; content: string }> = [
28
+ {
29
+ role: 'system',
30
+ content: 'You are a helpful AI assistant running on 0G decentralized compute. Be concise.',
31
+ },
32
+ ]
33
+
34
+ const rl = createInterface({
35
+ input: process.stdin,
36
+ output: process.stdout,
37
+ })
38
+
39
+ const ask = (prompt: string): Promise<string> =>
40
+ new Promise((resolve) => rl.question(prompt, resolve))
41
+
42
+ while (true) {
43
+ const input = await ask('You: ')
44
+ if (input.toLowerCase() === 'quit') break
45
+ if (!input.trim()) continue
46
+
47
+ history.push({ role: 'user', content: input })
48
+
49
+ try {
50
+ const result = await orbit.infer(MODEL, {
51
+ messages: history,
52
+ temperature: 0.7,
53
+ maxTokens: 1024,
54
+ })
55
+
56
+ history.push({ role: 'assistant', content: result.content })
57
+
58
+ console.log(`\nAssistant: ${result.content}`)
59
+
60
+ const meta: string[] = []
61
+ if (result.usage) meta.push(`${result.usage.totalTokens} tokens`)
62
+ if (result.verified === true) meta.push('TEE verified')
63
+ if (meta.length) console.log(` (${meta.join(' | ')})`)
64
+ console.log()
65
+ } catch (err) {
66
+ console.error(`Error: ${err instanceof Error ? err.message : err}\n`)
67
+ }
68
+ }
69
+
70
+ rl.close()
71
+ console.log('Goodbye!')
72
+ }
73
+
74
+ main().catch(console.error)
@@ -0,0 +1,137 @@
1
+ /**
2
+ * 0G Orbit — Model Registry Example
3
+ *
4
+ * Store AI model weights on 0G Storage and maintain
5
+ * a registry of model versions with their root hashes.
6
+ *
7
+ * Usage:
8
+ * PRIVATE_KEY=0x... npx tsx index.ts
9
+ */
10
+
11
+ import { Orbit } from '@0g-orbit/core'
12
+ import { writeFileSync, readFileSync, existsSync } from 'node:fs'
13
+
14
+ const REGISTRY_FILE = './registry.json'
15
+
16
+ interface ModelEntry {
17
+ name: string
18
+ version: string
19
+ rootHash: string
20
+ txHash: string
21
+ uploadedAt: string
22
+ sizeBytes?: number
23
+ }
24
+
25
+ interface Registry {
26
+ models: ModelEntry[]
27
+ }
28
+
29
+ function loadRegistry(): Registry {
30
+ if (existsSync(REGISTRY_FILE)) {
31
+ return JSON.parse(readFileSync(REGISTRY_FILE, 'utf-8'))
32
+ }
33
+ return { models: [] }
34
+ }
35
+
36
+ function saveRegistry(registry: Registry) {
37
+ writeFileSync(REGISTRY_FILE, JSON.stringify(registry, null, 2) + '\n')
38
+ }
39
+
40
+ async function registerModel(
41
+ orbit: Orbit,
42
+ name: string,
43
+ version: string,
44
+ filePath: string
45
+ ) {
46
+ console.log(`\nUploading ${name} v${version}...`)
47
+ const { root, txHash } = await orbit.store(filePath)
48
+
49
+ const registry = loadRegistry()
50
+ registry.models.push({
51
+ name,
52
+ version,
53
+ rootHash: root,
54
+ txHash,
55
+ uploadedAt: new Date().toISOString(),
56
+ })
57
+ saveRegistry(registry)
58
+
59
+ console.log(`Registered: ${name} v${version}`)
60
+ console.log(` Root: ${root}`)
61
+ console.log(` Tx: ${txHash}`)
62
+ return root
63
+ }
64
+
65
+ async function downloadModel(
66
+ orbit: Orbit,
67
+ name: string,
68
+ version: string,
69
+ outputPath: string
70
+ ) {
71
+ const registry = loadRegistry()
72
+ const entry = registry.models.find(
73
+ (m) => m.name === name && m.version === version
74
+ )
75
+
76
+ if (!entry) {
77
+ console.error(`Model ${name} v${version} not found in registry.`)
78
+ return
79
+ }
80
+
81
+ console.log(`\nDownloading ${name} v${version}...`)
82
+ await orbit.retrieve(entry.rootHash, outputPath)
83
+ console.log(`Downloaded to ${outputPath}`)
84
+ }
85
+
86
+ function listModels() {
87
+ const registry = loadRegistry()
88
+ if (registry.models.length === 0) {
89
+ console.log('No models registered.')
90
+ return
91
+ }
92
+
93
+ console.log('\nRegistered models:')
94
+ for (const m of registry.models) {
95
+ console.log(` ${m.name} v${m.version}`)
96
+ console.log(` root: ${m.rootHash}`)
97
+ console.log(` date: ${m.uploadedAt}`)
98
+ }
99
+ }
100
+
101
+ async function main() {
102
+ const orbit = await Orbit.connect({
103
+ network: 'testnet',
104
+ privateKey: process.env.PRIVATE_KEY!,
105
+ })
106
+
107
+ const status = await orbit.status()
108
+ console.log(`Connected: ${status.address} (${status.balance} OG)`)
109
+
110
+ const command = process.argv[2] || 'list'
111
+
112
+ switch (command) {
113
+ case 'register': {
114
+ const [, , , name, version, filePath] = process.argv
115
+ if (!name || !version || !filePath) {
116
+ console.error('Usage: npx tsx index.ts register <name> <version> <file>')
117
+ process.exit(1)
118
+ }
119
+ await registerModel(orbit, name, version, filePath)
120
+ break
121
+ }
122
+ case 'download': {
123
+ const [, , , name, version, outputPath] = process.argv
124
+ if (!name || !version || !outputPath) {
125
+ console.error('Usage: npx tsx index.ts download <name> <version> <output>')
126
+ process.exit(1)
127
+ }
128
+ await downloadModel(orbit, name, version, outputPath)
129
+ break
130
+ }
131
+ case 'list':
132
+ default:
133
+ listModels()
134
+ }
135
+ }
136
+
137
+ main().catch(console.error)
@@ -0,0 +1,65 @@
1
+ /**
2
+ * 0G Orbit — Quick Start
3
+ *
4
+ * Demonstrates the three core operations:
5
+ * 1. Check account status
6
+ * 2. Store a file to 0G Storage
7
+ * 3. Run AI inference on 0G Compute
8
+ *
9
+ * Usage:
10
+ * PRIVATE_KEY=0x... npx tsx index.ts
11
+ */
12
+
13
+ import { Orbit } from '@0g-orbit/core'
14
+ import { writeFileSync, unlinkSync } from 'node:fs'
15
+
16
+ async function main() {
17
+ // Connect
18
+ const orbit = await Orbit.connect({
19
+ network: 'testnet',
20
+ privateKey: process.env.PRIVATE_KEY!,
21
+ })
22
+
23
+ // 1. Account status
24
+ const status = await orbit.status()
25
+ console.log(`Connected: ${status.address}`)
26
+ console.log(`Balance: ${status.balance} OG on ${status.network}`)
27
+
28
+ // 2. Store a file
29
+ const testFile = '/tmp/orbit-test.txt'
30
+ writeFileSync(testFile, 'Hello from 0G Orbit!')
31
+
32
+ console.log('\nUploading file...')
33
+ const { root, txHash } = await orbit.store(testFile)
34
+ console.log(`Stored! Root: ${root}`)
35
+ console.log(`Tx: ${txHash}`)
36
+
37
+ unlinkSync(testFile)
38
+
39
+ // 3. Retrieve it back
40
+ const outputFile = '/tmp/orbit-test-downloaded.txt'
41
+ console.log('\nDownloading...')
42
+ await orbit.retrieve(root, outputFile)
43
+ console.log(`Downloaded to ${outputFile}`)
44
+
45
+ // 4. AI inference
46
+ console.log('\nRunning inference...')
47
+ const result = await orbit.infer('meta-llama/Llama-3.3-70B', {
48
+ messages: [
49
+ { role: 'system', content: 'You are a helpful assistant.' },
50
+ { role: 'user', content: 'Explain what 0G is in one sentence.' },
51
+ ],
52
+ temperature: 0.7,
53
+ })
54
+
55
+ console.log(`\nResponse: ${result.content}`)
56
+ console.log(`Model: ${result.model}`)
57
+ if (result.usage) {
58
+ console.log(`Tokens: ${result.usage.totalTokens}`)
59
+ }
60
+ if (result.verified !== null) {
61
+ console.log(`Verified: ${result.verified}`)
62
+ }
63
+ }
64
+
65
+ main().catch(console.error)
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "0g-orbit",
3
+ "version": "0.1.0",
4
+ "description": "The developer toolkit for 0G. Store, infer, deploy — one SDK, one CLI, five minutes.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "bin": {
15
+ "orbit": "./dist/cli/cli.js"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "test": "vitest run",
20
+ "test:watch": "vitest",
21
+ "lint": "tsc --noEmit",
22
+ "clean": "rm -rf dist"
23
+ },
24
+ "dependencies": {
25
+ "@0gfoundation/0g-ts-sdk": "^1.0.1",
26
+ "@0glabs/0g-serving-broker": "^0.7.4",
27
+ "chalk": "^5.3.0",
28
+ "commander": "^12.1.0",
29
+ "ethers": "^6.13.1",
30
+ "ora": "^8.0.1"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^20.12.0",
34
+ "typescript": "^5.4.0",
35
+ "vitest": "^1.6.0"
36
+ },
37
+ "keywords": ["0g", "blockchain", "ai", "storage", "inference", "sdk", "cli"],
38
+ "license": "MIT",
39
+ "engines": {
40
+ "node": ">=18.0.0"
41
+ }
42
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "0g-orbit-cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI for 0G Orbit — store, infer, deploy from your terminal.",
5
+ "type": "module",
6
+ "bin": {
7
+ "orbit": "./dist/cli.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "tsc --watch",
12
+ "lint": "tsc --noEmit",
13
+ "clean": "rm -rf dist"
14
+ },
15
+ "dependencies": {
16
+ "0g-orbit-core": "workspace:*",
17
+ "commander": "^12.1.0",
18
+ "ora": "^8.0.1",
19
+ "chalk": "^5.3.0"
20
+ },
21
+ "devDependencies": {
22
+ "typescript": "^5.4.0",
23
+ "@types/node": "^20.12.0"
24
+ },
25
+ "keywords": ["0g", "cli", "blockchain", "ai"],
26
+ "license": "MIT",
27
+ "engines": {
28
+ "node": ">=18.0.0"
29
+ }
30
+ }
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander'
4
+ import { storeCommand, storeDataCommand, retrieveCommand } from './commands/storage.js'
5
+ import { inferCommand, listServicesCommand } from './commands/inference.js'
6
+ import { statusCommand } from './commands/account.js'
7
+ import { initCommand } from './commands/init.js'
8
+
9
+ const program = new Command()
10
+
11
+ program
12
+ .name('orbit')
13
+ .description('The developer toolkit for 0G')
14
+ .version('0.1.0')
15
+
16
+ program
17
+ .command('init')
18
+ .description('Initialize a new 0G project')
19
+ .option('-t, --template <name>', 'template to use', 'default')
20
+ .option('-d, --dir <path>', 'directory to create', '.')
21
+ .action(initCommand)
22
+
23
+ program
24
+ .command('store <file>')
25
+ .description('Upload a file to 0G Storage')
26
+ .option('-n, --network <name>', 'network (testnet|mainnet)', 'testnet')
27
+ .option('--tags <hex>', 'custom tags (hex string)')
28
+ .option('--replicas <n>', 'number of replicas', '1')
29
+ .action(storeCommand)
30
+
31
+ program
32
+ .command('store-data <text>')
33
+ .description('Upload a text string to 0G Storage')
34
+ .option('-n, --network <name>', 'network (testnet|mainnet)', 'testnet')
35
+ .option('--tags <hex>', 'custom tags (hex string)')
36
+ .option('--replicas <n>', 'number of replicas', '1')
37
+ .action(storeDataCommand)
38
+
39
+ program
40
+ .command('retrieve <rootHash> <output>')
41
+ .description('Download a file from 0G Storage')
42
+ .option('-n, --network <name>', 'network (testnet|mainnet)', 'testnet')
43
+ .option('--proof', 'verify merkle proofs during download')
44
+ .action(retrieveCommand)
45
+
46
+ program
47
+ .command('infer <model>')
48
+ .description('Run AI inference on the 0G Compute Network')
49
+ .option('-n, --network <name>', 'network (testnet|mainnet)', 'testnet')
50
+ .option('-m, --message <text>', 'message to send')
51
+ .option('-s, --system <text>', 'system prompt')
52
+ .option('-t, --temperature <n>', 'sampling temperature', '0.7')
53
+ .option('--max-tokens <n>', 'maximum tokens to generate')
54
+ .option('--provider <address>', 'specific provider address')
55
+ .action(inferCommand)
56
+
57
+ program
58
+ .command('services')
59
+ .description('List available AI services on the network')
60
+ .option('-n, --network <name>', 'network (testnet|mainnet)', 'testnet')
61
+ .action(listServicesCommand)
62
+
63
+ program
64
+ .command('status')
65
+ .description('Show account status and balance')
66
+ .option('-n, --network <name>', 'network (testnet|mainnet)', 'testnet')
67
+ .action(statusCommand)
68
+
69
+ program.parse()
@@ -0,0 +1,29 @@
1
+ import ora from 'ora'
2
+ import chalk from 'chalk'
3
+ import { connectOrbit, formatError } from '../utils.js'
4
+
5
+ interface StatusOpts {
6
+ network: string
7
+ }
8
+
9
+ export async function statusCommand(opts: StatusOpts) {
10
+ const spinner = ora('Checking status...').start()
11
+
12
+ try {
13
+ const orbit = await connectOrbit(opts.network)
14
+ const status = await orbit.status()
15
+
16
+ spinner.stop()
17
+
18
+ console.log()
19
+ console.log(chalk.bold(' 0G Orbit'))
20
+ console.log(` ${chalk.dim('Network:')} ${status.network}`)
21
+ console.log(` ${chalk.dim('Address:')} ${status.address}`)
22
+ console.log(` ${chalk.dim('Balance:')} ${chalk.cyan(status.balance)} OG`)
23
+ console.log()
24
+ } catch (err) {
25
+ spinner.fail(chalk.red('Failed to get status'))
26
+ console.error(chalk.dim(` ${formatError(err)}`))
27
+ process.exit(1)
28
+ }
29
+ }