run402 1.38.0 → 1.40.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.
package/lib/billing.mjs CHANGED
@@ -1,4 +1,6 @@
1
1
  import { API } from "./config.mjs";
2
+ import { getSdk } from "./sdk.mjs";
3
+ import { reportSdkError } from "./sdk-errors.mjs";
2
4
 
3
5
  const HELP = `run402 billing — Email billing accounts, Stripe tier checkout, email packs
4
6
 
@@ -98,14 +100,12 @@ async function createEmail(args) {
98
100
  console.error(JSON.stringify({ status: "error", message: "Missing email. Usage: run402 billing create-email <email>" }));
99
101
  process.exit(1);
100
102
  }
101
- const res = await fetch(`${API}/billing/v1/accounts`, {
102
- method: "POST",
103
- headers: { "Content-Type": "application/json" },
104
- body: JSON.stringify({ email }),
105
- });
106
- const data = await res.json();
107
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
108
- console.log(JSON.stringify(data, null, 2));
103
+ try {
104
+ const data = await getSdk().billing.createEmailAccount(email);
105
+ console.log(JSON.stringify(data, null, 2));
106
+ } catch (err) {
107
+ reportSdkError(err);
108
+ }
109
109
  }
110
110
 
111
111
  async function linkWallet(args) {
@@ -115,14 +115,12 @@ async function linkWallet(args) {
115
115
  console.error(JSON.stringify({ status: "error", message: "Usage: run402 billing link-wallet <account_id> <wallet>" }));
116
116
  process.exit(1);
117
117
  }
118
- const res = await fetch(`${API}/billing/v1/accounts/${encodeURIComponent(accountId)}/link-wallet`, {
119
- method: "POST",
120
- headers: { "Content-Type": "application/json" },
121
- body: JSON.stringify({ wallet }),
122
- });
123
- const data = await res.json();
124
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
125
- console.log(JSON.stringify(data, null, 2));
118
+ try {
119
+ await getSdk().billing.linkWallet(accountId, wallet);
120
+ console.log(JSON.stringify({ status: "ok", billing_account_id: accountId, wallet }));
121
+ } catch (err) {
122
+ reportSdkError(err);
123
+ }
126
124
  }
127
125
 
128
126
  async function tierCheckout(args) {
@@ -137,15 +135,12 @@ async function tierCheckout(args) {
137
135
  console.error(JSON.stringify({ status: "error", message: "Must provide --email or --wallet" }));
138
136
  process.exit(1);
139
137
  }
140
- const body = email ? { email } : { wallet };
141
- const res = await fetch(`${API}/billing/v1/tiers/${encodeURIComponent(tier)}/checkout`, {
142
- method: "POST",
143
- headers: { "Content-Type": "application/json" },
144
- body: JSON.stringify(body),
145
- });
146
- const data = await res.json();
147
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
148
- console.log(JSON.stringify(data, null, 2));
138
+ try {
139
+ const data = await getSdk().billing.tierCheckout(tier, { email: email ?? undefined, wallet: wallet ?? undefined });
140
+ console.log(JSON.stringify(data, null, 2));
141
+ } catch (err) {
142
+ reportSdkError(err);
143
+ }
149
144
  }
150
145
 
151
146
  async function buyPack(args) {
@@ -155,15 +150,12 @@ async function buyPack(args) {
155
150
  console.error(JSON.stringify({ status: "error", message: "Must provide --email or --wallet" }));
156
151
  process.exit(1);
157
152
  }
158
- const body = email ? { email } : { wallet };
159
- const res = await fetch(`${API}/billing/v1/email-packs/checkout`, {
160
- method: "POST",
161
- headers: { "Content-Type": "application/json" },
162
- body: JSON.stringify(body),
163
- });
164
- const data = await res.json();
165
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
166
- console.log(JSON.stringify(data, null, 2));
153
+ try {
154
+ const data = await getSdk().billing.buyEmailPack({ email: email ?? undefined, wallet: wallet ?? undefined });
155
+ console.log(JSON.stringify(data, null, 2));
156
+ } catch (err) {
157
+ reportSdkError(err);
158
+ }
167
159
  }
168
160
 
169
161
  async function autoRecharge(args) {
@@ -174,22 +166,20 @@ async function autoRecharge(args) {
174
166
  process.exit(1);
175
167
  }
176
168
  const thresholdStr = parseFlag(args, "--threshold");
177
- const body = {
178
- billing_account_id: accountId,
179
- enabled: state === "on",
180
- };
181
- if (thresholdStr) body.threshold = Number(thresholdStr);
182
- const res = await fetch(`${API}/billing/v1/email-packs/auto-recharge`, {
183
- method: "POST",
184
- headers: { "Content-Type": "application/json" },
185
- body: JSON.stringify(body),
186
- });
187
- const data = await res.json();
188
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
189
- console.log(JSON.stringify(data, null, 2));
169
+ try {
170
+ await getSdk().billing.setAutoRecharge({
171
+ billingAccountId: accountId,
172
+ enabled: state === "on",
173
+ threshold: thresholdStr ? Number(thresholdStr) : undefined,
174
+ });
175
+ console.log(JSON.stringify({ status: "ok", billing_account_id: accountId, enabled: state === "on" }));
176
+ } catch (err) {
177
+ reportSdkError(err);
178
+ }
190
179
  }
191
180
 
192
181
  async function balance(args) {
182
+ // Accepts email OR wallet — SDK only models wallet, so keep direct fetch.
193
183
  const id = args[0];
194
184
  if (!id) {
195
185
  console.error(JSON.stringify({ status: "error", message: "Usage: run402 billing balance <email-or-wallet>" }));
package/lib/blob.mjs CHANGED
@@ -34,7 +34,9 @@ import { basename, dirname, join, resolve as resolvePath } from "node:path";
34
34
  import { homedir } from "node:os";
35
35
  import { pipeline } from "node:stream/promises";
36
36
 
37
- import { resolveProject, API } from "./config.mjs";
37
+ import { resolveProject, resolveProjectId, API } from "./config.mjs";
38
+ import { getSdk } from "./sdk.mjs";
39
+ import { reportSdkError } from "./sdk-errors.mjs";
38
40
 
39
41
  const HELP = `run402 blob — Direct-to-S3 blob storage
40
42
 
@@ -381,15 +383,18 @@ async function put(projectId, argv) {
381
383
  async function get(projectId, argv) {
382
384
  const opts = parseArgs(argv);
383
385
  opts.project = opts.project || projectId;
384
- const project = resolveProject(opts.project);
386
+ const resolvedId = resolveProjectId(opts.project);
385
387
  if (opts.positional.length === 0) die("Key required");
386
388
  if (!opts.output) die("--output <file> required");
387
389
  const key = opts.positional[0];
388
390
 
389
- const res = await fetch(`${API}/storage/v1/blob/${encodeKey(key)}`, {
390
- headers: { apikey: project.anon_key, Authorization: `Bearer ${project.anon_key}` },
391
- });
392
- if (!res.ok) die(`GET failed: HTTP ${res.status}`);
391
+ let res;
392
+ try {
393
+ res = await getSdk().blobs.get(resolvedId, key);
394
+ } catch (err) {
395
+ reportSdkError(err);
396
+ return;
397
+ }
393
398
  if (!res.body) die("Empty response body");
394
399
 
395
400
  mkdirSync(dirname(resolvePath(opts.output)), { recursive: true });
@@ -404,19 +409,17 @@ async function get(projectId, argv) {
404
409
  async function ls(projectId, argv) {
405
410
  const opts = parseArgs(argv);
406
411
  opts.project = opts.project || projectId;
407
- const project = resolveProject(opts.project);
412
+ const resolvedId = resolveProjectId(opts.project);
408
413
 
409
- const qs = new URLSearchParams();
410
- if (opts.prefix) qs.set("prefix", opts.prefix);
411
- if (opts.limit) qs.set("limit", String(opts.limit));
412
- const url = `${API}/storage/v1/blobs${qs.toString() ? "?" + qs.toString() : ""}`;
413
-
414
- const res = await fetch(url, {
415
- headers: { apikey: project.anon_key, Authorization: `Bearer ${project.anon_key}` },
416
- });
417
- const data = await res.json();
418
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
419
- console.log(JSON.stringify(data, null, 2));
414
+ try {
415
+ const data = await getSdk().blobs.ls(resolvedId, {
416
+ prefix: opts.prefix ?? undefined,
417
+ limit: opts.limit ?? undefined,
418
+ });
419
+ console.log(JSON.stringify(data, null, 2));
420
+ } catch (err) {
421
+ reportSdkError(err);
422
+ }
420
423
  }
421
424
 
422
425
  // ---------------------------------------------------------------------------
@@ -426,17 +429,16 @@ async function ls(projectId, argv) {
426
429
  async function rm(projectId, argv) {
427
430
  const opts = parseArgs(argv);
428
431
  opts.project = opts.project || projectId;
429
- const project = resolveProject(opts.project);
432
+ const resolvedId = resolveProjectId(opts.project);
430
433
  if (opts.positional.length === 0) die("Key required");
431
434
  const key = opts.positional[0];
432
435
 
433
- const res = await fetch(`${API}/storage/v1/blob/${encodeKey(key)}`, {
434
- method: "DELETE",
435
- headers: { apikey: project.anon_key, Authorization: `Bearer ${project.anon_key}` },
436
- });
437
- const data = await res.json().catch(() => ({}));
438
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
439
- console.log(JSON.stringify(data, null, 2));
436
+ try {
437
+ await getSdk().blobs.rm(resolvedId, key);
438
+ console.log(JSON.stringify({ status: "ok", key }));
439
+ } catch (err) {
440
+ reportSdkError(err);
441
+ }
440
442
  }
441
443
 
442
444
  // ---------------------------------------------------------------------------
@@ -446,18 +448,18 @@ async function rm(projectId, argv) {
446
448
  async function sign(projectId, argv) {
447
449
  const opts = parseArgs(argv);
448
450
  opts.project = opts.project || projectId;
449
- const project = resolveProject(opts.project);
451
+ const resolvedId = resolveProjectId(opts.project);
450
452
  if (opts.positional.length === 0) die("Key required");
451
453
  const key = opts.positional[0];
452
454
 
453
- const res = await fetch(`${API}/storage/v1/blob/${encodeKey(key)}/sign`, {
454
- method: "POST",
455
- headers: { "content-type": "application/json", apikey: project.anon_key, Authorization: `Bearer ${project.anon_key}` },
456
- body: JSON.stringify(opts.ttl ? { ttl_seconds: opts.ttl } : {}),
457
- });
458
- const data = await res.json();
459
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
460
- console.log(JSON.stringify(data, null, 2));
455
+ try {
456
+ const data = await getSdk().blobs.sign(resolvedId, key, {
457
+ ttl_seconds: opts.ttl ?? undefined,
458
+ });
459
+ console.log(JSON.stringify(data, null, 2));
460
+ } catch (err) {
461
+ reportSdkError(err);
462
+ }
461
463
  }
462
464
 
463
465
  // ---------------------------------------------------------------------------
package/lib/contracts.mjs CHANGED
@@ -1,4 +1,6 @@
1
1
  import { findProject, API } from "./config.mjs";
2
+ import { getSdk } from "./sdk.mjs";
3
+ import { reportSdkError } from "./sdk-errors.mjs";
2
4
 
3
5
  const HELP = `run402 contracts — KMS-backed Ethereum wallets for smart-contract calls
4
6
 
@@ -49,128 +51,38 @@ Options:
49
51
  --chain <chain> Required: base-mainnet or base-sepolia
50
52
  --recovery 0x... Optional recovery address (can be set later)
51
53
  --yes Skip confirmation when project already has a wallet
52
-
53
- Pricing:
54
- $0.04/day per wallet ($1.20/month). Creation requires $1.20 prepay
55
- (30 days of rent). Non-custodial — see terms.html#non-custodial-kms-wallets.
56
-
57
- Examples:
58
- run402 contracts provision-wallet proj_abc --chain base-mainnet
59
- run402 contracts provision-wallet proj_abc --chain base-sepolia --recovery 0xAbC...
60
54
  `,
61
55
  "set-recovery": `run402 contracts set-recovery — Set or clear the wallet recovery address
62
56
 
63
57
  Usage:
64
58
  run402 contracts set-recovery <project_id> <wallet_id> [options]
65
-
66
- Arguments:
67
- <project_id> Target project ID
68
- <wallet_id> KMS wallet ID (cwlt_...)
69
-
70
- Options:
71
- --address 0x... New recovery address
72
- --clear Clear the recovery address (mutually exclusive with --address)
73
-
74
- Examples:
75
- run402 contracts set-recovery proj_abc cwlt_xyz --address 0xAbC...
76
- run402 contracts set-recovery proj_abc cwlt_xyz --clear
77
59
  `,
78
60
  "set-alert": `run402 contracts set-alert — Set the low-balance alert threshold
79
61
 
80
62
  Usage:
81
63
  run402 contracts set-alert <project_id> <wallet_id> --threshold-wei <n>
82
-
83
- Arguments:
84
- <project_id> Target project ID
85
- <wallet_id> KMS wallet ID (cwlt_...)
86
-
87
- Options:
88
- --threshold-wei <n> Required: alert threshold in wei
89
-
90
- Examples:
91
- run402 contracts set-alert proj_abc cwlt_xyz --threshold-wei 1000000000000000
92
64
  `,
93
65
  call: `run402 contracts call — Submit a contract write call
94
66
 
95
67
  Usage:
96
68
  run402 contracts call <project_id> <wallet_id> --to 0x... --abi <json>
97
69
  --fn <name> --args <json> [options]
98
-
99
- Arguments:
100
- <project_id> Target project ID
101
- <wallet_id> KMS wallet ID (cwlt_...)
102
-
103
- Options:
104
- --to 0x... Required: contract address
105
- --abi <json> Required: ABI fragment (JSON string)
106
- --fn <name> Required: function name to invoke
107
- --args <json> Required: function args (JSON array)
108
- --value-wei <n> Native value to send (default 0)
109
- --chain <chain> Chain override (default: base-mainnet)
110
- --idempotency-key <k> Idempotency key for safe retries
111
-
112
- Pricing:
113
- Chain gas + $0.000005 KMS sign fee per call.
114
-
115
- Examples:
116
- run402 contracts call proj_abc cwlt_xyz --to 0x1234... \\
117
- --abi '[{"type":"function","name":"ping","inputs":[],"outputs":[]}]' \\
118
- --fn ping --args '[]'
119
70
  `,
120
71
  read: `run402 contracts read — Read-only contract call (free)
121
72
 
122
73
  Usage:
123
74
  run402 contracts read --chain <chain> --to 0x... --abi <json>
124
75
  --fn <name> --args <json>
125
-
126
- Options:
127
- --chain <chain> Required: base-mainnet or base-sepolia
128
- --to 0x... Required: contract address
129
- --abi <json> Required: ABI fragment (JSON string)
130
- --fn <name> Required: function name to invoke
131
- --args <json> Required: function args (JSON array)
132
-
133
- Examples:
134
- run402 contracts read --chain base-mainnet --to 0x1234... \\
135
- --abi '[{"type":"function","name":"balanceOf","inputs":[{"type":"address"}],"outputs":[{"type":"uint256"}]}]' \\
136
- --fn balanceOf --args '["0xAbC..."]'
137
76
  `,
138
77
  drain: `run402 contracts drain — Drain native balance to a destination address
139
78
 
140
79
  Usage:
141
80
  run402 contracts drain <project_id> <wallet_id> --to 0x... --confirm
142
-
143
- Arguments:
144
- <project_id> Target project ID
145
- <wallet_id> KMS wallet ID (cwlt_...)
146
-
147
- Options:
148
- --to 0x... Required: destination address
149
- --confirm Required: explicit confirmation flag
150
-
151
- Notes:
152
- Works on suspended wallets. Cost: chain gas + $0.000005 KMS sign fee.
153
-
154
- Examples:
155
- run402 contracts drain proj_abc cwlt_xyz --to 0xAbC... --confirm
156
81
  `,
157
82
  delete: `run402 contracts delete — Schedule the KMS key for deletion
158
83
 
159
84
  Usage:
160
85
  run402 contracts delete <project_id> <wallet_id> --confirm
161
-
162
- Arguments:
163
- <project_id> Target project ID
164
- <wallet_id> KMS wallet ID (cwlt_...)
165
-
166
- Options:
167
- --confirm Required: explicit confirmation flag
168
-
169
- Notes:
170
- Refused if wallet balance is greater than or equal to dust. Drain first.
171
-
172
- Examples:
173
- run402 contracts delete proj_abc cwlt_xyz --confirm
174
86
  `,
175
87
  };
176
88
 
@@ -192,7 +104,9 @@ async function provisionWallet(projectId, args) {
192
104
  process.exit(1);
193
105
  }
194
106
  const recovery = parseFlag(args, "--recovery");
195
- // Soft default of one wallet — confirm if project already has one
107
+ // Soft default of one wallet — confirm if project already has one. This
108
+ // pre-check stays on raw fetch because it's a discovery best-effort, not
109
+ // a primary API call.
196
110
  try {
197
111
  const listRes = await fetch(`${API}/contracts/v1/wallets`, {
198
112
  headers: { Authorization: `Bearer ${p.service_key}` },
@@ -206,76 +120,66 @@ async function provisionWallet(projectId, args) {
206
120
  }
207
121
  }
208
122
  } catch { /* best-effort */ }
209
- const body = { chain };
210
- if (recovery) body.recovery_address = recovery;
211
- const res = await fetch(`${API}/contracts/v1/wallets`, {
212
- method: "POST",
213
- headers: { Authorization: `Bearer ${p.service_key}`, "Content-Type": "application/json" },
214
- body: JSON.stringify(body),
215
- });
216
- const data = await res.json();
217
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
218
- console.log(JSON.stringify(data, null, 2));
123
+
124
+ try {
125
+ const data = await getSdk().contracts.provisionWallet(projectId, {
126
+ chain,
127
+ recoveryAddress: recovery ?? undefined,
128
+ });
129
+ console.log(JSON.stringify(data, null, 2));
130
+ } catch (err) {
131
+ reportSdkError(err);
132
+ }
219
133
  }
220
134
 
221
135
  async function getWallet(projectId, walletId) {
222
- const p = findProject(projectId);
223
- const res = await fetch(`${API}/contracts/v1/wallets/${encodeURIComponent(walletId)}`, {
224
- headers: { Authorization: `Bearer ${p.service_key}` },
225
- });
226
- const data = await res.json();
227
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
228
- console.log(JSON.stringify(data, null, 2));
136
+ try {
137
+ const data = await getSdk().contracts.getWallet(projectId, walletId);
138
+ console.log(JSON.stringify(data, null, 2));
139
+ } catch (err) {
140
+ reportSdkError(err);
141
+ }
229
142
  }
230
143
 
231
144
  async function listWallets(projectId) {
232
- const p = findProject(projectId);
233
- const res = await fetch(`${API}/contracts/v1/wallets`, {
234
- headers: { Authorization: `Bearer ${p.service_key}` },
235
- });
236
- const data = await res.json();
237
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
238
- console.log(JSON.stringify(data, null, 2));
145
+ try {
146
+ const data = await getSdk().contracts.listWallets(projectId);
147
+ console.log(JSON.stringify(data, null, 2));
148
+ } catch (err) {
149
+ reportSdkError(err);
150
+ }
239
151
  }
240
152
 
241
153
  async function setRecovery(projectId, walletId, args) {
242
- const p = findProject(projectId);
243
154
  const clear = hasFlag(args, "--clear");
244
155
  const address = parseFlag(args, "--address");
245
156
  if (!clear && !address) {
246
157
  console.error(JSON.stringify({ status: "error", message: "Provide --address 0x... or --clear" }));
247
158
  process.exit(1);
248
159
  }
249
- const body = { recovery_address: clear ? null : address };
250
- const res = await fetch(`${API}/contracts/v1/wallets/${encodeURIComponent(walletId)}/recovery-address`, {
251
- method: "POST",
252
- headers: { Authorization: `Bearer ${p.service_key}`, "Content-Type": "application/json" },
253
- body: JSON.stringify(body),
254
- });
255
- const data = await res.json();
256
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
257
- console.log(JSON.stringify(data, null, 2));
160
+ try {
161
+ await getSdk().contracts.setRecovery(projectId, walletId, clear ? null : address);
162
+ console.log(JSON.stringify({ status: "ok", wallet_id: walletId, recovery_address: clear ? null : address }));
163
+ } catch (err) {
164
+ reportSdkError(err);
165
+ }
258
166
  }
259
167
 
260
168
  async function setAlert(projectId, walletId, args) {
261
- const p = findProject(projectId);
262
169
  const threshold = parseFlag(args, "--threshold-wei");
263
170
  if (!threshold) {
264
171
  console.error(JSON.stringify({ status: "error", message: "Missing --threshold-wei <n>" }));
265
172
  process.exit(1);
266
173
  }
267
- const res = await fetch(`${API}/contracts/v1/wallets/${encodeURIComponent(walletId)}/alert`, {
268
- method: "POST",
269
- headers: { Authorization: `Bearer ${p.service_key}`, "Content-Type": "application/json" },
270
- body: JSON.stringify({ threshold_wei: threshold }),
271
- });
272
- const data = await res.json();
273
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
274
- console.log(JSON.stringify(data, null, 2));
174
+ try {
175
+ await getSdk().contracts.setLowBalanceAlert(projectId, walletId, threshold);
176
+ console.log(JSON.stringify({ status: "ok", wallet_id: walletId, threshold_wei: threshold }));
177
+ } catch (err) {
178
+ reportSdkError(err);
179
+ }
275
180
  }
276
181
 
277
182
  async function call(projectId, walletId, args) {
278
- const p = findProject(projectId);
279
183
  const to = parseFlag(args, "--to");
280
184
  const abi = parseFlag(args, "--abi");
281
185
  const fn = parseFlag(args, "--fn");
@@ -287,21 +191,21 @@ async function call(projectId, walletId, args) {
287
191
  console.error(JSON.stringify({ status: "error", message: "Required flags: --to, --abi, --fn, --args. Cost: chain gas + $0.000005 KMS sign fee." }));
288
192
  process.exit(1);
289
193
  }
290
- const body = {
291
- wallet_id: walletId,
292
- chain,
293
- contract_address: to,
294
- abi_fragment: JSON.parse(abi),
295
- function_name: fn,
296
- args: JSON.parse(argsJson),
297
- };
298
- if (value) body.value = value;
299
- const headers = { Authorization: `Bearer ${p.service_key}`, "Content-Type": "application/json" };
300
- if (idempotency) headers["Idempotency-Key"] = idempotency;
301
- const res = await fetch(`${API}/contracts/v1/call`, { method: "POST", headers, body: JSON.stringify(body) });
302
- const data = await res.json();
303
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
304
- console.log(JSON.stringify(data, null, 2));
194
+ try {
195
+ const data = await getSdk().contracts.call(projectId, {
196
+ walletId,
197
+ chain,
198
+ contractAddress: to,
199
+ abiFragment: JSON.parse(abi),
200
+ functionName: fn,
201
+ args: JSON.parse(argsJson),
202
+ value: value ?? undefined,
203
+ idempotencyKey: idempotency ?? undefined,
204
+ });
205
+ console.log(JSON.stringify(data, null, 2));
206
+ } catch (err) {
207
+ reportSdkError(err);
208
+ }
305
209
  }
306
210
 
307
211
  async function read(args) {
@@ -314,69 +218,54 @@ async function read(args) {
314
218
  console.error(JSON.stringify({ status: "error", message: "Required flags: --chain, --to, --abi, --fn, --args" }));
315
219
  process.exit(1);
316
220
  }
317
- const res = await fetch(`${API}/contracts/v1/read`, {
318
- method: "POST",
319
- headers: { "Content-Type": "application/json" },
320
- body: JSON.stringify({
221
+ try {
222
+ const data = await getSdk().contracts.read({
321
223
  chain,
322
- contract_address: to,
323
- abi_fragment: JSON.parse(abi),
324
- function_name: fn,
224
+ contractAddress: to,
225
+ abiFragment: JSON.parse(abi),
226
+ functionName: fn,
325
227
  args: JSON.parse(argsJson),
326
- }),
327
- });
328
- const data = await res.json();
329
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
330
- console.log(JSON.stringify(data, null, 2));
228
+ });
229
+ console.log(JSON.stringify(data, null, 2));
230
+ } catch (err) {
231
+ reportSdkError(err);
232
+ }
331
233
  }
332
234
 
333
235
  async function status(projectId, callId) {
334
- const p = findProject(projectId);
335
- const res = await fetch(`${API}/contracts/v1/calls/${encodeURIComponent(callId)}`, {
336
- headers: { Authorization: `Bearer ${p.service_key}` },
337
- });
338
- const data = await res.json();
339
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
340
- console.log(JSON.stringify(data, null, 2));
236
+ try {
237
+ const data = await getSdk().contracts.callStatus(projectId, callId);
238
+ console.log(JSON.stringify(data, null, 2));
239
+ } catch (err) {
240
+ reportSdkError(err);
241
+ }
341
242
  }
342
243
 
343
244
  async function drain(projectId, walletId, args) {
344
- const p = findProject(projectId);
345
245
  const to = parseFlag(args, "--to");
346
246
  if (!to || !hasFlag(args, "--confirm")) {
347
247
  console.error(JSON.stringify({ status: "error", message: "Required: --to 0x... and --confirm. Cost: chain gas + $0.000005 KMS sign fee." }));
348
248
  process.exit(1);
349
249
  }
350
- const res = await fetch(`${API}/contracts/v1/wallets/${encodeURIComponent(walletId)}/drain`, {
351
- method: "POST",
352
- headers: {
353
- Authorization: `Bearer ${p.service_key}`,
354
- "Content-Type": "application/json",
355
- "X-Confirm-Drain": walletId,
356
- },
357
- body: JSON.stringify({ destination_address: to }),
358
- });
359
- const data = await res.json();
360
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
361
- console.log(JSON.stringify(data, null, 2));
250
+ try {
251
+ const data = await getSdk().contracts.drain(projectId, walletId, to);
252
+ console.log(JSON.stringify(data, null, 2));
253
+ } catch (err) {
254
+ reportSdkError(err);
255
+ }
362
256
  }
363
257
 
364
258
  async function deleteWallet(projectId, walletId, args) {
365
- const p = findProject(projectId);
366
259
  if (!hasFlag(args, "--confirm")) {
367
260
  console.error(JSON.stringify({ status: "error", message: "Required: --confirm" }));
368
261
  process.exit(1);
369
262
  }
370
- const res = await fetch(`${API}/contracts/v1/wallets/${encodeURIComponent(walletId)}`, {
371
- method: "DELETE",
372
- headers: {
373
- Authorization: `Bearer ${p.service_key}`,
374
- "X-Confirm-Delete": walletId,
375
- },
376
- });
377
- const data = await res.json().catch(() => ({}));
378
- if (!res.ok) { console.error(JSON.stringify({ status: "error", http: res.status, ...data })); process.exit(1); }
379
- console.log(JSON.stringify(data, null, 2));
263
+ try {
264
+ const data = await getSdk().contracts.deleteWallet(projectId, walletId);
265
+ console.log(JSON.stringify(data, null, 2));
266
+ } catch (err) {
267
+ reportSdkError(err);
268
+ }
380
269
  }
381
270
 
382
271
  export async function run(sub, args) {