@shelby-protocol/cli 0.0.13 → 0.0.15

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 (2) hide show
  1. package/bin/entry.js +1443 -598
  2. package/package.json +8 -6
package/bin/entry.js CHANGED
@@ -4,7 +4,8 @@
4
4
  import { Command } from "commander";
5
5
 
6
6
  // package.json
7
- var version = "0.0.13";
7
+ var name = "@shelby-protocol/cli";
8
+ var version = "0.0.15";
8
9
 
9
10
  // src/commands/account.tsx
10
11
  import readline from "readline";
@@ -68,7 +69,7 @@ import {
68
69
 
69
70
  // ../../packages/sdk/dist/chunk-I6NG5GNL.mjs
70
71
  function sleep(ms) {
71
- return new Promise((resolve2) => setTimeout(resolve2, ms));
72
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
72
73
  }
73
74
 
74
75
  // ../../node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.es6.mjs
@@ -228,10 +229,10 @@ var GraphQLError = class _GraphQLError extends Error {
228
229
  */
229
230
  constructor(message, ...rawArgs) {
230
231
  var _this$nodes, _nodeLocations$, _ref;
231
- const { nodes, source, positions, path: path6, originalError, extensions } = toNormalizedOptions(rawArgs);
232
+ const { nodes, source, positions, path: path7, originalError, extensions } = toNormalizedOptions(rawArgs);
232
233
  super(message);
233
234
  this.name = "GraphQLError";
234
- this.path = path6 !== null && path6 !== void 0 ? path6 : void 0;
235
+ this.path = path7 !== null && path7 !== void 0 ? path7 : void 0;
235
236
  this.originalError = originalError !== null && originalError !== void 0 ? originalError : void 0;
236
237
  this.nodes = undefinedIfEmpty(
237
238
  Array.isArray(nodes) ? nodes : nodes ? [nodes] : void 0
@@ -1277,9 +1278,9 @@ function formatArray(array, seenValues) {
1277
1278
  function getObjectTag(object) {
1278
1279
  const tag = Object.prototype.toString.call(object).replace(/^\[object /, "").replace(/]$/, "");
1279
1280
  if (tag === "Object" && typeof object.constructor === "function") {
1280
- const name = object.constructor.name;
1281
- if (typeof name === "string" && name !== "") {
1282
- return name;
1281
+ const name2 = object.constructor.name;
1282
+ if (typeof name2 === "string" && name2 !== "") {
1283
+ return name2;
1283
1284
  }
1284
1285
  }
1285
1286
  return tag;
@@ -1326,13 +1327,13 @@ spurious results.`);
1326
1327
 
1327
1328
  // ../../node_modules/.pnpm/graphql@16.11.0/node_modules/graphql/language/source.mjs
1328
1329
  var Source = class {
1329
- constructor(body, name = "GraphQL request", locationOffset = {
1330
+ constructor(body, name2 = "GraphQL request", locationOffset = {
1330
1331
  line: 1,
1331
1332
  column: 1
1332
1333
  }) {
1333
1334
  typeof body === "string" || devAssert(false, `Body must be a string. Received: ${inspect(body)}.`);
1334
1335
  this.body = body;
1335
- this.name = name;
1336
+ this.name = name2;
1336
1337
  this.locationOffset = locationOffset;
1337
1338
  this.locationOffset.line > 0 || devAssert(
1338
1339
  false,
@@ -1482,14 +1483,14 @@ var Parser = class {
1482
1483
  });
1483
1484
  }
1484
1485
  const operation = this.parseOperationType();
1485
- let name;
1486
+ let name2;
1486
1487
  if (this.peek(TokenKind.NAME)) {
1487
- name = this.parseName();
1488
+ name2 = this.parseName();
1488
1489
  }
1489
1490
  return this.node(start, {
1490
1491
  kind: Kind.OPERATION_DEFINITION,
1491
1492
  operation,
1492
- name,
1493
+ name: name2,
1493
1494
  variableDefinitions: this.parseVariableDefinitions(),
1494
1495
  directives: this.parseDirectives(false),
1495
1496
  selectionSet: this.parseSelectionSet()
@@ -1576,17 +1577,17 @@ var Parser = class {
1576
1577
  const start = this._lexer.token;
1577
1578
  const nameOrAlias = this.parseName();
1578
1579
  let alias;
1579
- let name;
1580
+ let name2;
1580
1581
  if (this.expectOptionalToken(TokenKind.COLON)) {
1581
1582
  alias = nameOrAlias;
1582
- name = this.parseName();
1583
+ name2 = this.parseName();
1583
1584
  } else {
1584
- name = nameOrAlias;
1585
+ name2 = nameOrAlias;
1585
1586
  }
1586
1587
  return this.node(start, {
1587
1588
  kind: Kind.FIELD,
1588
1589
  alias,
1589
- name,
1590
+ name: name2,
1590
1591
  arguments: this.parseArguments(false),
1591
1592
  directives: this.parseDirectives(false),
1592
1593
  selectionSet: this.peek(TokenKind.BRACE_L) ? this.parseSelectionSet() : void 0
@@ -1604,11 +1605,11 @@ var Parser = class {
1604
1605
  */
1605
1606
  parseArgument(isConst = false) {
1606
1607
  const start = this._lexer.token;
1607
- const name = this.parseName();
1608
+ const name2 = this.parseName();
1608
1609
  this.expectToken(TokenKind.COLON);
1609
1610
  return this.node(start, {
1610
1611
  kind: Kind.ARGUMENT,
1611
- name,
1612
+ name: name2,
1612
1613
  value: this.parseValueLiteral(isConst)
1613
1614
  });
1614
1615
  }
@@ -1803,11 +1804,11 @@ var Parser = class {
1803
1804
  */
1804
1805
  parseObjectField(isConst) {
1805
1806
  const start = this._lexer.token;
1806
- const name = this.parseName();
1807
+ const name2 = this.parseName();
1807
1808
  this.expectToken(TokenKind.COLON);
1808
1809
  return this.node(start, {
1809
1810
  kind: Kind.OBJECT_FIELD,
1810
- name,
1811
+ name: name2,
1811
1812
  value: this.parseValueLiteral(isConst)
1812
1813
  });
1813
1814
  }
@@ -1931,12 +1932,12 @@ var Parser = class {
1931
1932
  const start = this._lexer.token;
1932
1933
  const description = this.parseDescription();
1933
1934
  this.expectKeyword("scalar");
1934
- const name = this.parseName();
1935
+ const name2 = this.parseName();
1935
1936
  const directives = this.parseConstDirectives();
1936
1937
  return this.node(start, {
1937
1938
  kind: Kind.SCALAR_TYPE_DEFINITION,
1938
1939
  description,
1939
- name,
1940
+ name: name2,
1940
1941
  directives
1941
1942
  });
1942
1943
  }
@@ -1949,14 +1950,14 @@ var Parser = class {
1949
1950
  const start = this._lexer.token;
1950
1951
  const description = this.parseDescription();
1951
1952
  this.expectKeyword("type");
1952
- const name = this.parseName();
1953
+ const name2 = this.parseName();
1953
1954
  const interfaces = this.parseImplementsInterfaces();
1954
1955
  const directives = this.parseConstDirectives();
1955
1956
  const fields = this.parseFieldsDefinition();
1956
1957
  return this.node(start, {
1957
1958
  kind: Kind.OBJECT_TYPE_DEFINITION,
1958
1959
  description,
1959
- name,
1960
+ name: name2,
1960
1961
  interfaces,
1961
1962
  directives,
1962
1963
  fields
@@ -1989,7 +1990,7 @@ var Parser = class {
1989
1990
  parseFieldDefinition() {
1990
1991
  const start = this._lexer.token;
1991
1992
  const description = this.parseDescription();
1992
- const name = this.parseName();
1993
+ const name2 = this.parseName();
1993
1994
  const args = this.parseArgumentDefs();
1994
1995
  this.expectToken(TokenKind.COLON);
1995
1996
  const type = this.parseTypeReference();
@@ -1997,7 +1998,7 @@ var Parser = class {
1997
1998
  return this.node(start, {
1998
1999
  kind: Kind.FIELD_DEFINITION,
1999
2000
  description,
2000
- name,
2001
+ name: name2,
2001
2002
  arguments: args,
2002
2003
  type,
2003
2004
  directives
@@ -2020,7 +2021,7 @@ var Parser = class {
2020
2021
  parseInputValueDef() {
2021
2022
  const start = this._lexer.token;
2022
2023
  const description = this.parseDescription();
2023
- const name = this.parseName();
2024
+ const name2 = this.parseName();
2024
2025
  this.expectToken(TokenKind.COLON);
2025
2026
  const type = this.parseTypeReference();
2026
2027
  let defaultValue;
@@ -2031,7 +2032,7 @@ var Parser = class {
2031
2032
  return this.node(start, {
2032
2033
  kind: Kind.INPUT_VALUE_DEFINITION,
2033
2034
  description,
2034
- name,
2035
+ name: name2,
2035
2036
  type,
2036
2037
  defaultValue,
2037
2038
  directives
@@ -2045,14 +2046,14 @@ var Parser = class {
2045
2046
  const start = this._lexer.token;
2046
2047
  const description = this.parseDescription();
2047
2048
  this.expectKeyword("interface");
2048
- const name = this.parseName();
2049
+ const name2 = this.parseName();
2049
2050
  const interfaces = this.parseImplementsInterfaces();
2050
2051
  const directives = this.parseConstDirectives();
2051
2052
  const fields = this.parseFieldsDefinition();
2052
2053
  return this.node(start, {
2053
2054
  kind: Kind.INTERFACE_TYPE_DEFINITION,
2054
2055
  description,
2055
- name,
2056
+ name: name2,
2056
2057
  interfaces,
2057
2058
  directives,
2058
2059
  fields
@@ -2066,13 +2067,13 @@ var Parser = class {
2066
2067
  const start = this._lexer.token;
2067
2068
  const description = this.parseDescription();
2068
2069
  this.expectKeyword("union");
2069
- const name = this.parseName();
2070
+ const name2 = this.parseName();
2070
2071
  const directives = this.parseConstDirectives();
2071
2072
  const types = this.parseUnionMemberTypes();
2072
2073
  return this.node(start, {
2073
2074
  kind: Kind.UNION_TYPE_DEFINITION,
2074
2075
  description,
2075
- name,
2076
+ name: name2,
2076
2077
  directives,
2077
2078
  types
2078
2079
  });
@@ -2093,13 +2094,13 @@ var Parser = class {
2093
2094
  const start = this._lexer.token;
2094
2095
  const description = this.parseDescription();
2095
2096
  this.expectKeyword("enum");
2096
- const name = this.parseName();
2097
+ const name2 = this.parseName();
2097
2098
  const directives = this.parseConstDirectives();
2098
2099
  const values = this.parseEnumValuesDefinition();
2099
2100
  return this.node(start, {
2100
2101
  kind: Kind.ENUM_TYPE_DEFINITION,
2101
2102
  description,
2102
- name,
2103
+ name: name2,
2103
2104
  directives,
2104
2105
  values
2105
2106
  });
@@ -2122,12 +2123,12 @@ var Parser = class {
2122
2123
  parseEnumValueDefinition() {
2123
2124
  const start = this._lexer.token;
2124
2125
  const description = this.parseDescription();
2125
- const name = this.parseEnumValueName();
2126
+ const name2 = this.parseEnumValueName();
2126
2127
  const directives = this.parseConstDirectives();
2127
2128
  return this.node(start, {
2128
2129
  kind: Kind.ENUM_VALUE_DEFINITION,
2129
2130
  description,
2130
- name,
2131
+ name: name2,
2131
2132
  directives
2132
2133
  });
2133
2134
  }
@@ -2154,13 +2155,13 @@ var Parser = class {
2154
2155
  const start = this._lexer.token;
2155
2156
  const description = this.parseDescription();
2156
2157
  this.expectKeyword("input");
2157
- const name = this.parseName();
2158
+ const name2 = this.parseName();
2158
2159
  const directives = this.parseConstDirectives();
2159
2160
  const fields = this.parseInputFieldsDefinition();
2160
2161
  return this.node(start, {
2161
2162
  kind: Kind.INPUT_OBJECT_TYPE_DEFINITION,
2162
2163
  description,
2163
- name,
2164
+ name: name2,
2164
2165
  directives,
2165
2166
  fields
2166
2167
  });
@@ -2246,14 +2247,14 @@ var Parser = class {
2246
2247
  const start = this._lexer.token;
2247
2248
  this.expectKeyword("extend");
2248
2249
  this.expectKeyword("scalar");
2249
- const name = this.parseName();
2250
+ const name2 = this.parseName();
2250
2251
  const directives = this.parseConstDirectives();
2251
2252
  if (directives.length === 0) {
2252
2253
  throw this.unexpected();
2253
2254
  }
2254
2255
  return this.node(start, {
2255
2256
  kind: Kind.SCALAR_TYPE_EXTENSION,
2256
- name,
2257
+ name: name2,
2257
2258
  directives
2258
2259
  });
2259
2260
  }
@@ -2267,7 +2268,7 @@ var Parser = class {
2267
2268
  const start = this._lexer.token;
2268
2269
  this.expectKeyword("extend");
2269
2270
  this.expectKeyword("type");
2270
- const name = this.parseName();
2271
+ const name2 = this.parseName();
2271
2272
  const interfaces = this.parseImplementsInterfaces();
2272
2273
  const directives = this.parseConstDirectives();
2273
2274
  const fields = this.parseFieldsDefinition();
@@ -2276,7 +2277,7 @@ var Parser = class {
2276
2277
  }
2277
2278
  return this.node(start, {
2278
2279
  kind: Kind.OBJECT_TYPE_EXTENSION,
2279
- name,
2280
+ name: name2,
2280
2281
  interfaces,
2281
2282
  directives,
2282
2283
  fields
@@ -2292,7 +2293,7 @@ var Parser = class {
2292
2293
  const start = this._lexer.token;
2293
2294
  this.expectKeyword("extend");
2294
2295
  this.expectKeyword("interface");
2295
- const name = this.parseName();
2296
+ const name2 = this.parseName();
2296
2297
  const interfaces = this.parseImplementsInterfaces();
2297
2298
  const directives = this.parseConstDirectives();
2298
2299
  const fields = this.parseFieldsDefinition();
@@ -2301,7 +2302,7 @@ var Parser = class {
2301
2302
  }
2302
2303
  return this.node(start, {
2303
2304
  kind: Kind.INTERFACE_TYPE_EXTENSION,
2304
- name,
2305
+ name: name2,
2305
2306
  interfaces,
2306
2307
  directives,
2307
2308
  fields
@@ -2316,7 +2317,7 @@ var Parser = class {
2316
2317
  const start = this._lexer.token;
2317
2318
  this.expectKeyword("extend");
2318
2319
  this.expectKeyword("union");
2319
- const name = this.parseName();
2320
+ const name2 = this.parseName();
2320
2321
  const directives = this.parseConstDirectives();
2321
2322
  const types = this.parseUnionMemberTypes();
2322
2323
  if (directives.length === 0 && types.length === 0) {
@@ -2324,7 +2325,7 @@ var Parser = class {
2324
2325
  }
2325
2326
  return this.node(start, {
2326
2327
  kind: Kind.UNION_TYPE_EXTENSION,
2327
- name,
2328
+ name: name2,
2328
2329
  directives,
2329
2330
  types
2330
2331
  });
@@ -2338,7 +2339,7 @@ var Parser = class {
2338
2339
  const start = this._lexer.token;
2339
2340
  this.expectKeyword("extend");
2340
2341
  this.expectKeyword("enum");
2341
- const name = this.parseName();
2342
+ const name2 = this.parseName();
2342
2343
  const directives = this.parseConstDirectives();
2343
2344
  const values = this.parseEnumValuesDefinition();
2344
2345
  if (directives.length === 0 && values.length === 0) {
@@ -2346,7 +2347,7 @@ var Parser = class {
2346
2347
  }
2347
2348
  return this.node(start, {
2348
2349
  kind: Kind.ENUM_TYPE_EXTENSION,
2349
- name,
2350
+ name: name2,
2350
2351
  directives,
2351
2352
  values
2352
2353
  });
@@ -2360,7 +2361,7 @@ var Parser = class {
2360
2361
  const start = this._lexer.token;
2361
2362
  this.expectKeyword("extend");
2362
2363
  this.expectKeyword("input");
2363
- const name = this.parseName();
2364
+ const name2 = this.parseName();
2364
2365
  const directives = this.parseConstDirectives();
2365
2366
  const fields = this.parseInputFieldsDefinition();
2366
2367
  if (directives.length === 0 && fields.length === 0) {
@@ -2368,7 +2369,7 @@ var Parser = class {
2368
2369
  }
2369
2370
  return this.node(start, {
2370
2371
  kind: Kind.INPUT_OBJECT_TYPE_EXTENSION,
2371
- name,
2372
+ name: name2,
2372
2373
  directives,
2373
2374
  fields
2374
2375
  });
@@ -2384,7 +2385,7 @@ var Parser = class {
2384
2385
  const description = this.parseDescription();
2385
2386
  this.expectKeyword("directive");
2386
2387
  this.expectToken(TokenKind.AT);
2387
- const name = this.parseName();
2388
+ const name2 = this.parseName();
2388
2389
  const args = this.parseArgumentDefs();
2389
2390
  const repeatable = this.expectOptionalKeyword("repeatable");
2390
2391
  this.expectKeyword("on");
@@ -2392,7 +2393,7 @@ var Parser = class {
2392
2393
  return this.node(start, {
2393
2394
  kind: Kind.DIRECTIVE_DEFINITION,
2394
2395
  description,
2395
- name,
2396
+ name: name2,
2396
2397
  arguments: args,
2397
2398
  repeatable,
2398
2399
  locations
@@ -2435,9 +2436,9 @@ var Parser = class {
2435
2436
  */
2436
2437
  parseDirectiveLocation() {
2437
2438
  const start = this._lexer.token;
2438
- const name = this.parseName();
2439
- if (Object.prototype.hasOwnProperty.call(DirectiveLocation, name.value)) {
2440
- return name;
2439
+ const name2 = this.parseName();
2440
+ if (Object.prototype.hasOwnProperty.call(DirectiveLocation, name2.value)) {
2441
+ return name2;
2441
2442
  }
2442
2443
  throw this.unexpected(start);
2443
2444
  }
@@ -2799,14 +2800,14 @@ function visit(root, visitor, visitorKeys = QueryDocumentKeys) {
2799
2800
  let node = root;
2800
2801
  let key = void 0;
2801
2802
  let parent = void 0;
2802
- const path6 = [];
2803
+ const path7 = [];
2803
2804
  const ancestors = [];
2804
2805
  do {
2805
2806
  index++;
2806
2807
  const isLeaving = index === keys.length;
2807
2808
  const isEdited = isLeaving && edits.length !== 0;
2808
2809
  if (isLeaving) {
2809
- key = ancestors.length === 0 ? void 0 : path6[path6.length - 1];
2810
+ key = ancestors.length === 0 ? void 0 : path7[path7.length - 1];
2810
2811
  node = parent;
2811
2812
  parent = ancestors.pop();
2812
2813
  if (isEdited) {
@@ -2840,20 +2841,20 @@ function visit(root, visitor, visitorKeys = QueryDocumentKeys) {
2840
2841
  if (node === null || node === void 0) {
2841
2842
  continue;
2842
2843
  }
2843
- path6.push(key);
2844
+ path7.push(key);
2844
2845
  }
2845
2846
  let result;
2846
2847
  if (!Array.isArray(node)) {
2847
2848
  var _enterLeaveMap$get, _enterLeaveMap$get2;
2848
2849
  isNode(node) || devAssert(false, `Invalid AST Node: ${inspect(node)}.`);
2849
2850
  const visitFn = isLeaving ? (_enterLeaveMap$get = enterLeaveMap.get(node.kind)) === null || _enterLeaveMap$get === void 0 ? void 0 : _enterLeaveMap$get.leave : (_enterLeaveMap$get2 = enterLeaveMap.get(node.kind)) === null || _enterLeaveMap$get2 === void 0 ? void 0 : _enterLeaveMap$get2.enter;
2850
- result = visitFn === null || visitFn === void 0 ? void 0 : visitFn.call(visitor, node, key, parent, path6, ancestors);
2851
+ result = visitFn === null || visitFn === void 0 ? void 0 : visitFn.call(visitor, node, key, parent, path7, ancestors);
2851
2852
  if (result === BREAK) {
2852
2853
  break;
2853
2854
  }
2854
2855
  if (result === false) {
2855
2856
  if (!isLeaving) {
2856
- path6.pop();
2857
+ path7.pop();
2857
2858
  continue;
2858
2859
  }
2859
2860
  } else if (result !== void 0) {
@@ -2862,7 +2863,7 @@ function visit(root, visitor, visitorKeys = QueryDocumentKeys) {
2862
2863
  if (isNode(result)) {
2863
2864
  node = result;
2864
2865
  } else {
2865
- path6.pop();
2866
+ path7.pop();
2866
2867
  continue;
2867
2868
  }
2868
2869
  }
@@ -2872,7 +2873,7 @@ function visit(root, visitor, visitorKeys = QueryDocumentKeys) {
2872
2873
  edits.push([key, node]);
2873
2874
  }
2874
2875
  if (isLeaving) {
2875
- path6.pop();
2876
+ path7.pop();
2876
2877
  } else {
2877
2878
  var _node$kind;
2878
2879
  stack = {
@@ -2950,8 +2951,8 @@ var printDocASTReducer = {
2950
2951
  leave: ({ selections }) => block(selections)
2951
2952
  },
2952
2953
  Field: {
2953
- leave({ alias, name, arguments: args, directives, selectionSet }) {
2954
- const prefix = wrap("", alias, ": ") + name;
2954
+ leave({ alias, name: name2, arguments: args, directives, selectionSet }) {
2955
+ const prefix = wrap("", alias, ": ") + name2;
2955
2956
  let argsLine = prefix + wrap("(", join(args, ", "), ")");
2956
2957
  if (argsLine.length > MAX_LINE_LENGTH) {
2957
2958
  argsLine = prefix + wrap("(\n", indent(join(args, "\n")), "\n)");
@@ -2960,11 +2961,11 @@ var printDocASTReducer = {
2960
2961
  }
2961
2962
  },
2962
2963
  Argument: {
2963
- leave: ({ name, value }) => name + ": " + value
2964
+ leave: ({ name: name2, value }) => name2 + ": " + value
2964
2965
  },
2965
2966
  // Fragments
2966
2967
  FragmentSpread: {
2967
- leave: ({ name, directives }) => "..." + name + wrap(" ", join(directives, " "))
2968
+ leave: ({ name: name2, directives }) => "..." + name2 + wrap(" ", join(directives, " "))
2968
2969
  },
2969
2970
  InlineFragment: {
2970
2971
  leave: ({ typeCondition, directives, selectionSet }) => join(
@@ -2978,9 +2979,9 @@ var printDocASTReducer = {
2978
2979
  )
2979
2980
  },
2980
2981
  FragmentDefinition: {
2981
- leave: ({ name, typeCondition, variableDefinitions, directives, selectionSet }) => (
2982
+ leave: ({ name: name2, typeCondition, variableDefinitions, directives, selectionSet }) => (
2982
2983
  // or removed in the future.
2983
- `fragment ${name}${wrap("(", join(variableDefinitions, ", "), ")")} on ${typeCondition} ${wrap("", join(directives, " "), " ")}` + selectionSet
2984
+ `fragment ${name2}${wrap("(", join(variableDefinitions, ", "), ")")} on ${typeCondition} ${wrap("", join(directives, " "), " ")}` + selectionSet
2984
2985
  )
2985
2986
  },
2986
2987
  // Value
@@ -3009,15 +3010,15 @@ var printDocASTReducer = {
3009
3010
  leave: ({ fields }) => "{" + join(fields, ", ") + "}"
3010
3011
  },
3011
3012
  ObjectField: {
3012
- leave: ({ name, value }) => name + ": " + value
3013
+ leave: ({ name: name2, value }) => name2 + ": " + value
3013
3014
  },
3014
3015
  // Directive
3015
3016
  Directive: {
3016
- leave: ({ name, arguments: args }) => "@" + name + wrap("(", join(args, ", "), ")")
3017
+ leave: ({ name: name2, arguments: args }) => "@" + name2 + wrap("(", join(args, ", "), ")")
3017
3018
  },
3018
3019
  // Type
3019
3020
  NamedType: {
3020
- leave: ({ name }) => name
3021
+ leave: ({ name: name2 }) => name2
3021
3022
  },
3022
3023
  ListType: {
3023
3024
  leave: ({ type }) => "[" + type + "]"
@@ -3033,13 +3034,13 @@ var printDocASTReducer = {
3033
3034
  leave: ({ operation, type }) => operation + ": " + type
3034
3035
  },
3035
3036
  ScalarTypeDefinition: {
3036
- leave: ({ description, name, directives }) => wrap("", description, "\n") + join(["scalar", name, join(directives, " ")], " ")
3037
+ leave: ({ description, name: name2, directives }) => wrap("", description, "\n") + join(["scalar", name2, join(directives, " ")], " ")
3037
3038
  },
3038
3039
  ObjectTypeDefinition: {
3039
- leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") + join(
3040
+ leave: ({ description, name: name2, interfaces, directives, fields }) => wrap("", description, "\n") + join(
3040
3041
  [
3041
3042
  "type",
3042
- name,
3043
+ name2,
3043
3044
  wrap("implements ", join(interfaces, " & ")),
3044
3045
  join(directives, " "),
3045
3046
  block(fields)
@@ -3048,19 +3049,19 @@ var printDocASTReducer = {
3048
3049
  )
3049
3050
  },
3050
3051
  FieldDefinition: {
3051
- leave: ({ description, name, arguments: args, type, directives }) => wrap("", description, "\n") + name + (hasMultilineItems(args) ? wrap("(\n", indent(join(args, "\n")), "\n)") : wrap("(", join(args, ", "), ")")) + ": " + type + wrap(" ", join(directives, " "))
3052
+ leave: ({ description, name: name2, arguments: args, type, directives }) => wrap("", description, "\n") + name2 + (hasMultilineItems(args) ? wrap("(\n", indent(join(args, "\n")), "\n)") : wrap("(", join(args, ", "), ")")) + ": " + type + wrap(" ", join(directives, " "))
3052
3053
  },
3053
3054
  InputValueDefinition: {
3054
- leave: ({ description, name, type, defaultValue, directives }) => wrap("", description, "\n") + join(
3055
- [name + ": " + type, wrap("= ", defaultValue), join(directives, " ")],
3055
+ leave: ({ description, name: name2, type, defaultValue, directives }) => wrap("", description, "\n") + join(
3056
+ [name2 + ": " + type, wrap("= ", defaultValue), join(directives, " ")],
3056
3057
  " "
3057
3058
  )
3058
3059
  },
3059
3060
  InterfaceTypeDefinition: {
3060
- leave: ({ description, name, interfaces, directives, fields }) => wrap("", description, "\n") + join(
3061
+ leave: ({ description, name: name2, interfaces, directives, fields }) => wrap("", description, "\n") + join(
3061
3062
  [
3062
3063
  "interface",
3063
- name,
3064
+ name2,
3064
3065
  wrap("implements ", join(interfaces, " & ")),
3065
3066
  join(directives, " "),
3066
3067
  block(fields)
@@ -3069,22 +3070,22 @@ var printDocASTReducer = {
3069
3070
  )
3070
3071
  },
3071
3072
  UnionTypeDefinition: {
3072
- leave: ({ description, name, directives, types }) => wrap("", description, "\n") + join(
3073
- ["union", name, join(directives, " "), wrap("= ", join(types, " | "))],
3073
+ leave: ({ description, name: name2, directives, types }) => wrap("", description, "\n") + join(
3074
+ ["union", name2, join(directives, " "), wrap("= ", join(types, " | "))],
3074
3075
  " "
3075
3076
  )
3076
3077
  },
3077
3078
  EnumTypeDefinition: {
3078
- leave: ({ description, name, directives, values }) => wrap("", description, "\n") + join(["enum", name, join(directives, " "), block(values)], " ")
3079
+ leave: ({ description, name: name2, directives, values }) => wrap("", description, "\n") + join(["enum", name2, join(directives, " "), block(values)], " ")
3079
3080
  },
3080
3081
  EnumValueDefinition: {
3081
- leave: ({ description, name, directives }) => wrap("", description, "\n") + join([name, join(directives, " ")], " ")
3082
+ leave: ({ description, name: name2, directives }) => wrap("", description, "\n") + join([name2, join(directives, " ")], " ")
3082
3083
  },
3083
3084
  InputObjectTypeDefinition: {
3084
- leave: ({ description, name, directives, fields }) => wrap("", description, "\n") + join(["input", name, join(directives, " "), block(fields)], " ")
3085
+ leave: ({ description, name: name2, directives, fields }) => wrap("", description, "\n") + join(["input", name2, join(directives, " "), block(fields)], " ")
3085
3086
  },
3086
3087
  DirectiveDefinition: {
3087
- leave: ({ description, name, arguments: args, repeatable, locations }) => wrap("", description, "\n") + "directive @" + name + (hasMultilineItems(args) ? wrap("(\n", indent(join(args, "\n")), "\n)") : wrap("(", join(args, ", "), ")")) + (repeatable ? " repeatable" : "") + " on " + join(locations, " | ")
3088
+ leave: ({ description, name: name2, arguments: args, repeatable, locations }) => wrap("", description, "\n") + "directive @" + name2 + (hasMultilineItems(args) ? wrap("(\n", indent(join(args, "\n")), "\n)") : wrap("(", join(args, ", "), ")")) + (repeatable ? " repeatable" : "") + " on " + join(locations, " | ")
3088
3089
  },
3089
3090
  SchemaExtension: {
3090
3091
  leave: ({ directives, operationTypes }) => join(
@@ -3093,13 +3094,13 @@ var printDocASTReducer = {
3093
3094
  )
3094
3095
  },
3095
3096
  ScalarTypeExtension: {
3096
- leave: ({ name, directives }) => join(["extend scalar", name, join(directives, " ")], " ")
3097
+ leave: ({ name: name2, directives }) => join(["extend scalar", name2, join(directives, " ")], " ")
3097
3098
  },
3098
3099
  ObjectTypeExtension: {
3099
- leave: ({ name, interfaces, directives, fields }) => join(
3100
+ leave: ({ name: name2, interfaces, directives, fields }) => join(
3100
3101
  [
3101
3102
  "extend type",
3102
- name,
3103
+ name2,
3103
3104
  wrap("implements ", join(interfaces, " & ")),
3104
3105
  join(directives, " "),
3105
3106
  block(fields)
@@ -3108,10 +3109,10 @@ var printDocASTReducer = {
3108
3109
  )
3109
3110
  },
3110
3111
  InterfaceTypeExtension: {
3111
- leave: ({ name, interfaces, directives, fields }) => join(
3112
+ leave: ({ name: name2, interfaces, directives, fields }) => join(
3112
3113
  [
3113
3114
  "extend interface",
3114
- name,
3115
+ name2,
3115
3116
  wrap("implements ", join(interfaces, " & ")),
3116
3117
  join(directives, " "),
3117
3118
  block(fields)
@@ -3120,10 +3121,10 @@ var printDocASTReducer = {
3120
3121
  )
3121
3122
  },
3122
3123
  UnionTypeExtension: {
3123
- leave: ({ name, directives, types }) => join(
3124
+ leave: ({ name: name2, directives, types }) => join(
3124
3125
  [
3125
3126
  "extend union",
3126
- name,
3127
+ name2,
3127
3128
  join(directives, " "),
3128
3129
  wrap("= ", join(types, " | "))
3129
3130
  ],
@@ -3131,10 +3132,10 @@ var printDocASTReducer = {
3131
3132
  )
3132
3133
  },
3133
3134
  EnumTypeExtension: {
3134
- leave: ({ name, directives, values }) => join(["extend enum", name, join(directives, " "), block(values)], " ")
3135
+ leave: ({ name: name2, directives, values }) => join(["extend enum", name2, join(directives, " "), block(values)], " ")
3135
3136
  },
3136
3137
  InputObjectTypeExtension: {
3137
- leave: ({ name, directives, fields }) => join(["extend input", name, join(directives, " "), block(fields)], " ")
3138
+ leave: ({ name: name2, directives, fields }) => join(["extend input", name2, join(directives, " "), block(fields)], " ")
3138
3139
  }
3139
3140
  };
3140
3141
  function join(maybeArray, separator = "") {
@@ -3270,7 +3271,7 @@ var extras = {
3270
3271
  gql["default"] = gql;
3271
3272
  var lib_default = gql;
3272
3273
 
3273
- // ../../packages/sdk/dist/chunk-DLMDDEWF.mjs
3274
+ // ../../packages/sdk/dist/chunk-WJKSPJSS.mjs
3274
3275
  var GetBlobsDocument = lib_default`
3275
3276
  query getBlobs($where: blobs_bool_exp, $orderBy: [blobs_order_by!], $limit: Int, $offset: Int) {
3276
3277
  blobs(where: $where, order_by: $orderBy, limit: $limit, offset: $offset) {
@@ -3306,6 +3307,24 @@ var GetBlobActivitiesDocument = lib_default`
3306
3307
  }
3307
3308
  }
3308
3309
  `;
3310
+ var GetBlobsCountDocument = lib_default`
3311
+ query getBlobsCount($where: blobs_bool_exp) {
3312
+ blobs_aggregate(where: $where) {
3313
+ aggregate {
3314
+ count
3315
+ }
3316
+ }
3317
+ }
3318
+ `;
3319
+ var GetBlobActivitiesCountDocument = lib_default`
3320
+ query getBlobActivitiesCount($where: blob_activities_bool_exp) {
3321
+ blob_activities_aggregate(where: $where) {
3322
+ aggregate {
3323
+ count
3324
+ }
3325
+ }
3326
+ }
3327
+ `;
3309
3328
  var defaultWrapper = (action, _operationName, _operationType, _variables) => action();
3310
3329
  function getSdk(client, withWrapper = defaultWrapper) {
3311
3330
  return {
@@ -3314,11 +3333,17 @@ function getSdk(client, withWrapper = defaultWrapper) {
3314
3333
  },
3315
3334
  getBlobActivities(variables, requestHeaders, signal) {
3316
3335
  return withWrapper((wrappedRequestHeaders) => client.request({ document: GetBlobActivitiesDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getBlobActivities", "query", variables);
3336
+ },
3337
+ getBlobsCount(variables, requestHeaders, signal) {
3338
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetBlobsCountDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getBlobsCount", "query", variables);
3339
+ },
3340
+ getBlobActivitiesCount(variables, requestHeaders, signal) {
3341
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetBlobActivitiesCountDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getBlobActivitiesCount", "query", variables);
3317
3342
  }
3318
3343
  };
3319
3344
  }
3320
3345
 
3321
- // ../../packages/sdk/dist/chunk-VPT45MTZ.mjs
3346
+ // ../../packages/sdk/dist/chunk-HFGEQP5N.mjs
3322
3347
  import { Network as Network3 } from "@aptos-labs/ts-sdk";
3323
3348
 
3324
3349
  // ../../node_modules/.pnpm/graphql-request@7.2.0_graphql@16.11.0/node_modules/graphql-request/build/legacy/classes/ClientError.js
@@ -3354,9 +3379,9 @@ var HeadersInitToPlainObject = (headers) => {
3354
3379
  if (headers instanceof Headers) {
3355
3380
  oHeaders = HeadersInstanceToPlainObject(headers);
3356
3381
  } else if (Array.isArray(headers)) {
3357
- headers.forEach(([name, value]) => {
3358
- if (name && value !== void 0) {
3359
- oHeaders[name] = value;
3382
+ headers.forEach(([name2, value]) => {
3383
+ if (name2 && value !== void 0) {
3384
+ oHeaders[name2] = value;
3360
3385
  }
3361
3386
  });
3362
3387
  } else if (headers) {
@@ -3620,8 +3645,8 @@ var createFetcher = (method) => async (params) => {
3620
3645
  initResolved = initNew;
3621
3646
  }
3622
3647
  if (searchParams) {
3623
- searchParams.forEach((value, name) => {
3624
- url.searchParams.append(name, value);
3648
+ searchParams.forEach((value, name2) => {
3649
+ url.searchParams.append(name2, value);
3625
3650
  });
3626
3651
  }
3627
3652
  const $fetch = params.fetch ?? fetch;
@@ -3833,7 +3858,7 @@ var parseRequestArgs = (documentOrOptions, variables, requestHeaders) => {
3833
3858
  };
3834
3859
  };
3835
3860
 
3836
- // ../../packages/sdk/dist/chunk-VPT45MTZ.mjs
3861
+ // ../../packages/sdk/dist/chunk-HFGEQP5N.mjs
3837
3862
  function createShelbyIndexerClient(baseUrl, options) {
3838
3863
  const graphqlClient = new GraphQLClient(baseUrl, options);
3839
3864
  return getSdk(graphqlClient);
@@ -3866,7 +3891,7 @@ function getShelbyIndexerClient(config) {
3866
3891
  });
3867
3892
  }
3868
3893
 
3869
- // ../../packages/sdk/dist/chunk-KBUWZXFA.mjs
3894
+ // ../../packages/sdk/dist/chunk-4JZO2D7T.mjs
3870
3895
  import { Hex as Hex2 } from "@aptos-labs/ts-sdk";
3871
3896
  async function* readInChunks(input, chunkSize) {
3872
3897
  let idx = 0;
@@ -3945,12 +3970,16 @@ function isReadableStream(value) {
3945
3970
  function toUint8Array(view) {
3946
3971
  return view instanceof Uint8Array ? view : new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
3947
3972
  }
3948
- function buildRequestUrl(path6, baseUrl) {
3973
+ function buildRequestUrl(path7, baseUrl) {
3949
3974
  const baseHasSlash = baseUrl.endsWith("/");
3950
3975
  const safeBase = baseHasSlash ? baseUrl : `${baseUrl}/`;
3951
- const safePath = path6.replace(/^\/+/, "");
3976
+ const safePath = path7.replace(/^\/+/, "");
3952
3977
  return new URL(safePath, safeBase);
3953
3978
  }
3979
+ function getBlobNameSuffix(blobName) {
3980
+ const parts = blobName.split("/");
3981
+ return parts.slice(1).join("/") || "";
3982
+ }
3954
3983
 
3955
3984
  // ../../packages/sdk/dist/chunk-ZPW742E7.mjs
3956
3985
  var ERASURE_CODE_PARAMS = {
@@ -4134,11 +4163,11 @@ function buildClayConfig(input) {
4134
4163
  // ../../packages/sdk/dist/chunk-FIFKKWXV.mjs
4135
4164
  import { AccountAddress as AccountAddress2 } from "@aptos-labs/ts-sdk";
4136
4165
  import { z } from "zod";
4137
- var BlobNameSchema = z.string().min(1, "Blob name path parameter cannot be empty.").max(1024, "Blob name cannot exceed 1024 characters.").refine((name) => !name.endsWith("/"), {
4166
+ var BlobNameSchema = z.string().min(1, "Blob name path parameter cannot be empty.").max(1024, "Blob name cannot exceed 1024 characters.").refine((name2) => !name2.endsWith("/"), {
4138
4167
  message: "Blob name cannot end with a slash"
4139
4168
  });
4140
4169
 
4141
- // ../../packages/sdk/dist/chunk-TEDFWEY6.mjs
4170
+ // ../../packages/sdk/dist/chunk-7P3P3D3X.mjs
4142
4171
  import { AccountAddress as AccountAddress3 } from "@aptos-labs/ts-sdk";
4143
4172
  function encodeURIComponentKeepSlashes(str) {
4144
4173
  return encodeURIComponent(str).replace(/%2F/g, "/");
@@ -4408,7 +4437,7 @@ var createBlobKey = (params) => {
4408
4437
  return `@${AccountAddress4.from(params.account).toStringLongWithoutPrefix()}/${params.blobName}`;
4409
4438
  };
4410
4439
 
4411
- // ../../packages/sdk/dist/chunk-LTV26KU4.mjs
4440
+ // ../../packages/sdk/dist/chunk-PCNLFNAT.mjs
4412
4441
  import { z as z2 } from "zod";
4413
4442
  var ChunksetCommitmentSchema = z2.object({
4414
4443
  // Chunkset root (vector commitment of child chunks)
@@ -4530,7 +4559,7 @@ function validatePrePaddedChunkset(chunkset, expectedSize, chunksetIdx) {
4530
4559
  return chunkset;
4531
4560
  }
4532
4561
 
4533
- // ../../packages/sdk/dist/chunk-MEINKPI3.mjs
4562
+ // ../../packages/sdk/dist/chunk-HDYY6NS4.mjs
4534
4563
  import {
4535
4564
  AccountAddress as AccountAddress5,
4536
4565
  Aptos as Aptos2,
@@ -4595,7 +4624,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4595
4624
  try {
4596
4625
  const rawMetadata = await this.aptos.view({
4597
4626
  payload: {
4598
- function: `${this.deployer.toString()}::global_metadata::get_blob_metadata`,
4627
+ function: `${this.deployer.toString()}::blob_metadata::get_blob_metadata`,
4599
4628
  functionArguments: [
4600
4629
  createBlobKey({
4601
4630
  account: params.account,
@@ -4626,6 +4655,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4626
4655
  ).toUint8Array(),
4627
4656
  owner: AccountAddress5.fromString(metadata.owner),
4628
4657
  name: params.name,
4658
+ blobNameSuffix: getBlobNameSuffix(params.name),
4629
4659
  size: Number(metadata.blob_size),
4630
4660
  encoding,
4631
4661
  expirationMicros: metadata.expiration_micros,
@@ -4658,13 +4688,14 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4658
4688
  * ```
4659
4689
  */
4660
4690
  getAccountBlobs(params) {
4691
+ const { where, ...rest } = params;
4661
4692
  return this.getBlobs({
4662
4693
  where: {
4663
- ...params.where,
4694
+ ...where ?? {},
4664
4695
  owner: { _eq: AccountAddress5.from(params.account).toString() }
4665
4696
  },
4666
- pagination: params.pagination,
4667
- orderBy: params.orderBy
4697
+ pagination: rest.pagination,
4698
+ orderBy: rest.orderBy
4668
4699
  });
4669
4700
  }
4670
4701
  /**
@@ -4686,8 +4717,14 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4686
4717
  async getBlobs(params = {}) {
4687
4718
  const { limit, offset } = params.pagination ?? {};
4688
4719
  const { orderBy, where } = params;
4720
+ const currentMicros = Date.now() * 1e3;
4721
+ const defaultActiveFilter = {
4722
+ expires_at: { _gte: currentMicros },
4723
+ is_deleted: { _eq: "0" }
4724
+ };
4725
+ const finalWhere = where !== void 0 ? { ...defaultActiveFilter, ...where } : defaultActiveFilter;
4689
4726
  const { blobs } = await this.indexer.getBlobs({
4690
- where,
4727
+ where: finalWhere,
4691
4728
  limit,
4692
4729
  offset,
4693
4730
  orderBy
@@ -4696,6 +4733,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4696
4733
  (blob) => ({
4697
4734
  owner: AccountAddress5.from(blob.owner),
4698
4735
  name: blob.blob_name,
4736
+ blobNameSuffix: getBlobNameSuffix(blob.blob_name),
4699
4737
  blobMerkleRoot: Hex3.fromHexInput(blob.blob_commitment).toUint8Array(),
4700
4738
  size: Number(blob.size),
4701
4739
  // TODO: Add encoding when supported in NCI
@@ -4720,10 +4758,10 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4720
4758
  orderBy
4721
4759
  });
4722
4760
  const activityTypeMapping = {
4723
- [`${this.deployer.toStringLong()}::global_metadata::BlobRegisteredEvent`]: "register_blob",
4724
- [`${this.deployer.toStringLong()}::global_metadata::BlobDeletedEvent`]: "delete_blob",
4725
- [`${this.deployer.toStringLong()}::global_metadata::BlobExpirationExtendedEvent`]: "extend_blob_expiration",
4726
- [`${this.deployer.toStringLong()}::global_metadata::BlobWrittenEvent`]: "write_blob"
4761
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobRegisteredEvent`]: "register_blob",
4762
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobDeletedEvent`]: "delete_blob",
4763
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobExpirationExtendedEvent`]: "extend_blob_expiration",
4764
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobWrittenEvent`]: "write_blob"
4727
4765
  };
4728
4766
  return blob_activities.map(
4729
4767
  (activity) => ({
@@ -4741,28 +4779,36 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4741
4779
  );
4742
4780
  }
4743
4781
  /**
4744
- * Retrieves the blob chunks for a given blob from the blockchain. The blob chunk will contain
4745
- * the commitment, the storage provider location, and the status of the chunk (stored or pending).
4746
- *
4747
- * @deprecated Will need to get reworked when we are acking blobs from storage providers.
4782
+ * Retrieves the total number of blobs from the blockchain.
4748
4783
  *
4749
- * @param params.account - The account namespace the blob is stored in (e.g. "0x1")
4750
- * @param params.name - The name of the blob (e.g. "foo/bar")
4751
- * @returns The chunks that make up the blob.
4784
+ * @param params.where (optional) - The where clause to filter the blobs by.
4785
+ * @returns The total number of blobs.
4752
4786
  *
4753
4787
  * @example
4754
4788
  * ```typescript
4755
- * // BlobChunk[]
4756
- * const chunks = await client.getBlobChunks({
4757
- * account: AccountAddress.fromString("0x1"),
4758
- * name: "foo/bar.txt",
4759
- * });
4789
+ * const count = await client.getBlobsCount();
4790
+ * ```
4791
+ */
4792
+ async getBlobsCount(params) {
4793
+ const { where } = params;
4794
+ const { blobs_aggregate } = await this.indexer.getBlobsCount({ where });
4795
+ return blobs_aggregate?.aggregate?.count ?? 0;
4796
+ }
4797
+ /**
4798
+ * Retrieves the total number of blob activities from the blockchain.
4760
4799
  *
4761
- * const isStored = chunks.every((c) => c.location.variant === "stored");
4800
+ * @param params.where (optional) - The where clause to filter the blob activities by.
4801
+ * @returns The total number of blob activities.
4802
+ *
4803
+ * @example
4804
+ * ```typescript
4805
+ * const count = await client.getBlobActivitiesCount();
4762
4806
  * ```
4763
4807
  */
4764
- getBlobChunks(_params) {
4765
- throw new Error("Not implemented");
4808
+ async getBlobActivitiesCount(params) {
4809
+ const { where } = params;
4810
+ const { blob_activities_aggregate } = await this.indexer.getBlobActivitiesCount({ where });
4811
+ return blob_activities_aggregate?.aggregate?.count ?? 0;
4766
4812
  }
4767
4813
  /**
4768
4814
  * Registers a blob on the blockchain by writing its merkle root and metadata.
@@ -4814,6 +4860,63 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4814
4860
  })
4815
4861
  };
4816
4862
  }
4863
+ /**
4864
+ * Registers multiple blobs on the blockchain by writing their merkle roots and metadata.
4865
+ *
4866
+ * @param params.account - The account that is signing and paying for the transaction.
4867
+ * @param params.expirationMicros - The expiration time of the blobs in microseconds.
4868
+ * @param params.blobs - The blobs to register.
4869
+ * @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
4870
+ * @param params.blobs.blobSize - The size of the blob in bytes.
4871
+ * @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
4872
+ * @param params.options - Optional transaction building options.
4873
+ * @param params.options.chunksetSizeBytes - Custom chunkset size (defaults to DEFAULT_CHUNKSET_SIZE_BYTES).
4874
+ * @param params.options.build - Additional Aptos transaction building options.
4875
+ *
4876
+ * @returns An object containing the pending transaction.
4877
+ *
4878
+ * @example
4879
+ * ```typescript
4880
+ * const provider = await ClayErasureCodingProvider.create();
4881
+ * const blobCommitments = await generateCommitments(provider, data);
4882
+ *
4883
+ * const { transaction } = await client.batchRegisterBlobs({
4884
+ * account: signer,
4885
+ * expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
4886
+ * blobs: [
4887
+ * {
4888
+ * blobName: "foo/bar.txt",
4889
+ * blobSize: data.length,
4890
+ * blobMerkleRoot: blobCommitments.blob_merkle_root,
4891
+ * },
4892
+ * ],
4893
+ * });
4894
+ * ```
4895
+ */
4896
+ async batchRegisterBlobs(params) {
4897
+ const chunksetSize = params.options?.chunksetSizeBytes ?? DEFAULT_CHUNKSET_SIZE_BYTES;
4898
+ const transaction = await this.aptos.transaction.build.simple({
4899
+ ...params.options?.build,
4900
+ sender: params.account.accountAddress,
4901
+ data: _ShelbyBlobClient.createBatchRegisterBlobsPayload({
4902
+ deployer: this.deployer,
4903
+ account: params.account.accountAddress,
4904
+ expirationMicros: params.expirationMicros,
4905
+ blobs: params.blobs.map((blob) => ({
4906
+ blobName: blob.blobName,
4907
+ blobSize: blob.blobSize,
4908
+ blobMerkleRoot: blob.blobMerkleRoot,
4909
+ numChunksets: expectedTotalChunksets(blob.blobSize, chunksetSize)
4910
+ }))
4911
+ })
4912
+ });
4913
+ return {
4914
+ transaction: await this.aptos.signAndSubmitTransaction({
4915
+ signer: params.account,
4916
+ transaction
4917
+ })
4918
+ };
4919
+ }
4817
4920
  /**
4818
4921
  * Creates a transaction payload to register a blob on the blockchain.
4819
4922
  * This is a static helper method for constructing the Move function call payload.
@@ -4832,7 +4935,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4832
4935
  */
4833
4936
  static createRegisterBlobPayload(params) {
4834
4937
  return {
4835
- function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::global_metadata::register_blob`,
4938
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::register_blob`,
4836
4939
  functionArguments: [
4837
4940
  params.blobName,
4838
4941
  params.expirationMicros,
@@ -4876,7 +4979,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4876
4979
  blobSizes.push(blob.blobSize);
4877
4980
  });
4878
4981
  return {
4879
- function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::global_metadata::register_multiple_blobs`,
4982
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::register_multiple_blobs`,
4880
4983
  functionArguments: [
4881
4984
  blobNames,
4882
4985
  params.expirationMicros,
@@ -4889,12 +4992,168 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
4889
4992
  ]
4890
4993
  };
4891
4994
  }
4995
+ /**
4996
+ * Creates a transaction payload to delete a blob on the blockchain.
4997
+ * This is a static helper method for constructing the Move function call payload.
4998
+ *
4999
+ * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
5000
+ * @param params.blobNameSuffix - The blob name suffix (e.g. "bar.txt").
5001
+ *
5002
+ * @returns An Aptos transaction payload data object for the delete_blob Move function.
5003
+ *
5004
+ * @see https://github.com/shelby/shelby/blob/64e9d7b4f0005e586faeb1e4085c79159234b6b6/move/shelby_contract/sources/global_metadata.move#L616
5005
+ */
5006
+ static createDeleteBlobPayload(params) {
5007
+ return {
5008
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_blob`,
5009
+ functionArguments: [params.blobNameSuffix]
5010
+ };
5011
+ }
4892
5012
  };
4893
5013
 
4894
- // ../../packages/sdk/dist/chunk-2Y3ZLUYT.mjs
5014
+ // ../../packages/sdk/dist/chunk-CQZZRXA6.mjs
4895
5015
  import {
4896
5016
  Aptos as Aptos3
4897
5017
  } from "@aptos-labs/ts-sdk";
5018
+
5019
+ // ../../node_modules/.pnpm/yocto-queue@1.2.1/node_modules/yocto-queue/index.js
5020
+ var Node = class {
5021
+ value;
5022
+ next;
5023
+ constructor(value) {
5024
+ this.value = value;
5025
+ }
5026
+ };
5027
+ var Queue = class {
5028
+ #head;
5029
+ #tail;
5030
+ #size;
5031
+ constructor() {
5032
+ this.clear();
5033
+ }
5034
+ enqueue(value) {
5035
+ const node = new Node(value);
5036
+ if (this.#head) {
5037
+ this.#tail.next = node;
5038
+ this.#tail = node;
5039
+ } else {
5040
+ this.#head = node;
5041
+ this.#tail = node;
5042
+ }
5043
+ this.#size++;
5044
+ }
5045
+ dequeue() {
5046
+ const current = this.#head;
5047
+ if (!current) {
5048
+ return;
5049
+ }
5050
+ this.#head = this.#head.next;
5051
+ this.#size--;
5052
+ return current.value;
5053
+ }
5054
+ peek() {
5055
+ if (!this.#head) {
5056
+ return;
5057
+ }
5058
+ return this.#head.value;
5059
+ }
5060
+ clear() {
5061
+ this.#head = void 0;
5062
+ this.#tail = void 0;
5063
+ this.#size = 0;
5064
+ }
5065
+ get size() {
5066
+ return this.#size;
5067
+ }
5068
+ *[Symbol.iterator]() {
5069
+ let current = this.#head;
5070
+ while (current) {
5071
+ yield current.value;
5072
+ current = current.next;
5073
+ }
5074
+ }
5075
+ *drain() {
5076
+ while (this.#head) {
5077
+ yield this.dequeue();
5078
+ }
5079
+ }
5080
+ };
5081
+
5082
+ // ../../node_modules/.pnpm/p-limit@7.1.1/node_modules/p-limit/index.js
5083
+ function pLimit(concurrency) {
5084
+ validateConcurrency(concurrency);
5085
+ const queue = new Queue();
5086
+ let activeCount = 0;
5087
+ const resumeNext = () => {
5088
+ if (activeCount < concurrency && queue.size > 0) {
5089
+ activeCount++;
5090
+ queue.dequeue()();
5091
+ }
5092
+ };
5093
+ const next = () => {
5094
+ activeCount--;
5095
+ resumeNext();
5096
+ };
5097
+ const run = async (function_, resolve3, arguments_) => {
5098
+ const result = (async () => function_(...arguments_))();
5099
+ resolve3(result);
5100
+ try {
5101
+ await result;
5102
+ } catch {
5103
+ }
5104
+ next();
5105
+ };
5106
+ const enqueue = (function_, resolve3, arguments_) => {
5107
+ new Promise((internalResolve) => {
5108
+ queue.enqueue(internalResolve);
5109
+ }).then(run.bind(void 0, function_, resolve3, arguments_));
5110
+ if (activeCount < concurrency) {
5111
+ resumeNext();
5112
+ }
5113
+ };
5114
+ const generator = (function_, ...arguments_) => new Promise((resolve3) => {
5115
+ enqueue(function_, resolve3, arguments_);
5116
+ });
5117
+ Object.defineProperties(generator, {
5118
+ activeCount: {
5119
+ get: () => activeCount
5120
+ },
5121
+ pendingCount: {
5122
+ get: () => queue.size
5123
+ },
5124
+ clearQueue: {
5125
+ value() {
5126
+ queue.clear();
5127
+ }
5128
+ },
5129
+ concurrency: {
5130
+ get: () => concurrency,
5131
+ set(newConcurrency) {
5132
+ validateConcurrency(newConcurrency);
5133
+ concurrency = newConcurrency;
5134
+ queueMicrotask(() => {
5135
+ while (activeCount < concurrency && queue.size > 0) {
5136
+ resumeNext();
5137
+ }
5138
+ });
5139
+ }
5140
+ },
5141
+ map: {
5142
+ async value(array, function_) {
5143
+ const promises = array.map((value, index) => this(function_, value, index));
5144
+ return Promise.all(promises);
5145
+ }
5146
+ }
5147
+ });
5148
+ return generator;
5149
+ }
5150
+ function validateConcurrency(concurrency) {
5151
+ if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
5152
+ throw new TypeError("Expected `concurrency` to be a number from 1 and up");
5153
+ }
5154
+ }
5155
+
5156
+ // ../../packages/sdk/dist/chunk-CQZZRXA6.mjs
4898
5157
  var ShelbyClient = class {
4899
5158
  /**
4900
5159
  * The coordination client is used to interact with the Aptos blockchain which handles the commitments
@@ -5024,6 +5283,89 @@ var ShelbyClient = class {
5024
5283
  blobData: params.blobData
5025
5284
  });
5026
5285
  }
5286
+ /**
5287
+ * Uploads a batch of blobs to the Shelby network.
5288
+ * This method handles the complete upload flow including commitment generation,
5289
+ * blockchain registration, and storage upload.
5290
+ *
5291
+ * @param params.blobs - The blobs to upload.
5292
+ * @param params.blobs.blobData - The raw data to upload as a Uint8Array.
5293
+ * @param params.blobs.blobName - The name/path of the blob (e.g. "folder/file.txt").
5294
+ * @param params.expirationMicros - The expiration time in microseconds since Unix epoch.
5295
+ * @param params.signer - The account that signs and pays for the transaction.
5296
+ * @param params.options - Optional upload configuration.
5297
+ * @param params.options.chunksetSizeBytes - Custom chunkset size.
5298
+ * @param params.options.build - Additional Aptos transaction options.
5299
+ *
5300
+ * @returns The transaction and generated blob commitments (when implemented).
5301
+ *
5302
+ * @example
5303
+ * ```typescript
5304
+ * await client.batchUpload({
5305
+ * blobs: [
5306
+ * { blobData: Buffer.from("Hello, World!"), blobName: "hello.txt" },
5307
+ * { blobData: Buffer.from("Hello, World 2!"), blobName: "hello2.txt" },
5308
+ * ],
5309
+ * expirationMicros: Date.now() * 1000 + 86400_000_000 // 24 hours from now
5310
+ * });
5311
+ * ```
5312
+ */
5313
+ async batchUpload(params) {
5314
+ const existingBlobs = await this.coordination.getBlobs({
5315
+ where: {
5316
+ blob_name: {
5317
+ _in: params.blobs.map(
5318
+ (blob) => createBlobKey({
5319
+ account: params.signer.accountAddress,
5320
+ blobName: blob.blobName
5321
+ })
5322
+ )
5323
+ }
5324
+ }
5325
+ });
5326
+ const blobsToRegister = params.blobs.filter(
5327
+ (blob) => !existingBlobs.some(
5328
+ (existingBlob) => existingBlob.name === createBlobKey({
5329
+ account: params.signer.accountAddress,
5330
+ blobName: blob.blobName
5331
+ })
5332
+ )
5333
+ );
5334
+ if (blobsToRegister.length > 0) {
5335
+ const provider = await this.getProvider();
5336
+ const blobCommitments = await Promise.all(
5337
+ blobsToRegister.map(
5338
+ async (blob) => generateCommitments(provider, blob.blobData)
5339
+ )
5340
+ );
5341
+ const { transaction: pendingRegisterBlobTransaction } = await this.coordination.batchRegisterBlobs({
5342
+ account: params.signer,
5343
+ expirationMicros: params.expirationMicros,
5344
+ blobs: blobsToRegister.map((blob, index) => ({
5345
+ blobName: blob.blobName,
5346
+ blobSize: blob.blobData.length,
5347
+ blobMerkleRoot: blobCommitments[index].blob_merkle_root
5348
+ })),
5349
+ options: params.options
5350
+ });
5351
+ await this.coordination.aptos.waitForTransaction({
5352
+ transactionHash: pendingRegisterBlobTransaction.hash,
5353
+ options: { waitForIndexer: true }
5354
+ });
5355
+ }
5356
+ const limit = pLimit(3);
5357
+ await Promise.all(
5358
+ params.blobs.map(
5359
+ (blob) => limit(
5360
+ () => this.rpc.putBlob({
5361
+ account: params.signer.accountAddress,
5362
+ blobName: blob.blobName,
5363
+ blobData: blob.blobData
5364
+ })
5365
+ )
5366
+ )
5367
+ );
5368
+ }
5027
5369
  /**
5028
5370
  * Downloads a blob from the Shelby RPC node.
5029
5371
  *
@@ -5046,15 +5388,15 @@ var ShelbyClient = class {
5046
5388
  }
5047
5389
  };
5048
5390
 
5049
- // ../../packages/sdk/dist/chunk-X56YUBBI.mjs
5391
+ // ../../packages/sdk/dist/chunk-2JMRK5PM.mjs
5050
5392
  var ShelbyNodeClient = class extends ShelbyClient {
5051
5393
  };
5052
5394
 
5053
5395
  // ../../packages/sdk/dist/chunk-7P6ASYW6.mjs
5054
5396
  var __defProp = Object.defineProperty;
5055
5397
  var __export = (target, all) => {
5056
- for (var name in all)
5057
- __defProp(target, name, { get: all[name], enumerable: true });
5398
+ for (var name2 in all)
5399
+ __defProp(target, name2, { get: all[name2], enumerable: true });
5058
5400
  };
5059
5401
 
5060
5402
  // ../../packages/sdk/dist/chunk-A4IG6GSE.mjs
@@ -5153,9 +5495,10 @@ var reed_solomon_erasure_bg_default = __toBinaryNode("AGFzbQEAAAAB/oCAgAASYAJ/fw
5153
5495
  var DEFAULT_CHUNK_SIZE_BYTES2 = 2 * 1024 * 1024;
5154
5496
 
5155
5497
  // src/commands/account.tsx
5156
- import chalk from "chalk";
5498
+ import chalk2 from "chalk";
5499
+ import { filesize } from "filesize";
5157
5500
  import { render } from "ink";
5158
- import { z as z9 } from "zod";
5501
+ import { z as z10 } from "zod";
5159
5502
 
5160
5503
  // src/components/AccountWizard.tsx
5161
5504
  import { Box, Text } from "ink";
@@ -5326,10 +5669,10 @@ function saveConfig(config, configPath = "~/.shelby/config.yaml") {
5326
5669
  fs.writeFileSync(resolvedPath, YAML.stringify(config), "utf8");
5327
5670
  }
5328
5671
  function getCurrentContext(config, contextName) {
5329
- const name = contextName || config.default_context;
5330
- const context = config.contexts[name];
5672
+ const name2 = contextName || config.default_context;
5673
+ const context = config.contexts[name2];
5331
5674
  if (!context) {
5332
- throw new Error(`Context '${name}' not found in config`);
5675
+ throw new Error(`Context '${name2}' not found in config`);
5333
5676
  }
5334
5677
  return {
5335
5678
  api_key: context.api_key,
@@ -5338,19 +5681,19 @@ function getCurrentContext(config, contextName) {
5338
5681
  };
5339
5682
  }
5340
5683
  function getCurrentAccount(config, accountName) {
5341
- const name = accountName || config.default_account;
5342
- if (!name) {
5343
- throw new Error(`Account with name '${name}' not found in config`);
5684
+ const name2 = accountName || config.default_account;
5685
+ if (!name2) {
5686
+ throw new Error(`Account with name '${name2}' not found in config`);
5344
5687
  }
5345
- const account = config.accounts[name];
5688
+ const account = config.accounts[name2];
5346
5689
  if (!account) {
5347
- throw new Error(`Account '${name}' not found in config`);
5690
+ throw new Error(`Account '${name2}' not found in config`);
5348
5691
  }
5349
5692
  let privateKey;
5350
5693
  if (account.private_key) {
5351
5694
  privateKey = account.private_key;
5352
5695
  } else {
5353
- throw new Error(`No private key found for account '${name}'`);
5696
+ throw new Error(`No private key found for account '${name2}'`);
5354
5697
  }
5355
5698
  return {
5356
5699
  address: account.address,
@@ -5361,11 +5704,11 @@ function getCurrentAccount(config, accountName) {
5361
5704
  };
5362
5705
  }
5363
5706
  function getAptosSettingsFromContext(context) {
5364
- const { name, api_key, ...options } = context.aptos_network;
5707
+ const { name: name2, api_key, ...options } = context.aptos_network;
5365
5708
  const activeApiKey = api_key || context.api_key;
5366
5709
  return {
5367
5710
  ...options,
5368
- network: NetworkToNetworkName[name],
5711
+ network: NetworkToNetworkName[name2],
5369
5712
  clientConfig: { API_KEY: activeApiKey }
5370
5713
  };
5371
5714
  }
@@ -5402,13 +5745,13 @@ function getCurrentShelbyConfig(config, opts = { context: config.default_context
5402
5745
  }
5403
5746
 
5404
5747
  // src/utils/account.ts
5405
- function validateAccountName(name, config) {
5406
- const parsed = AccountNameSchema.safeParse(name);
5407
- if (!parsed.success || name.length === 0) {
5748
+ function validateAccountName(name2, config) {
5749
+ const parsed = AccountNameSchema.safeParse(name2);
5750
+ if (!parsed.success || name2.length === 0) {
5408
5751
  return parsed.error?.errors[0]?.message || "Account name must be a non-empty string containing only letters, numbers, underscores, or hyphens.";
5409
5752
  }
5410
- if (config?.accounts[name]) {
5411
- return `Account '${name}' already exists. Choose a different name.`;
5753
+ if (config?.accounts[name2]) {
5754
+ return `Account '${name2}' already exists. Choose a different name.`;
5412
5755
  }
5413
5756
  return void 0;
5414
5757
  }
@@ -5453,33 +5796,33 @@ var AccountWizard = ({
5453
5796
  const [step, setStep] = useState(
5454
5797
  initialName ? "address" : "name"
5455
5798
  );
5456
- const [name, setName] = useState(initialName || "");
5799
+ const [name2, setName] = useState(initialName || "");
5457
5800
  const [nameError, setNameError] = useState(null);
5458
5801
  const [address, setAddress] = useState("");
5459
5802
  const [privateKey, setPrivateKey] = useState("");
5460
5803
  useEffect(() => {
5461
5804
  if (step === "done") {
5462
5805
  onComplete({
5463
- name,
5806
+ name: name2,
5464
5807
  address: address || void 0,
5465
5808
  privateKey
5466
5809
  });
5467
5810
  }
5468
- }, [onComplete, step, name, address, privateKey]);
5811
+ }, [onComplete, step, name2, address, privateKey]);
5469
5812
  if (step === "name") {
5470
5813
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
5471
5814
  /* @__PURE__ */ jsx(Text, { children: "Account name?" }),
5472
5815
  /* @__PURE__ */ jsx(
5473
5816
  TextInput,
5474
5817
  {
5475
- value: name,
5818
+ value: name2,
5476
5819
  onChange: (value) => {
5477
5820
  setName(value);
5478
5821
  const error = validateAccountName(value, config);
5479
5822
  setNameError(error || null);
5480
5823
  },
5481
5824
  onSubmit: () => {
5482
- const error = validateAccountName(name, config);
5825
+ const error = validateAccountName(name2, config);
5483
5826
  if (error) {
5484
5827
  setNameError(error);
5485
5828
  return;
@@ -5563,7 +5906,7 @@ function AptosNetworkNameSelector({
5563
5906
  onSelect
5564
5907
  }) {
5565
5908
  const items = [
5566
- ...shelbyNetworks.map((name) => ({ label: name, value: name })),
5909
+ ...shelbyNetworks.map((name2) => ({ label: name2, value: name2 })),
5567
5910
  ...additionalItems
5568
5911
  ];
5569
5912
  return /* @__PURE__ */ jsx3(
@@ -5599,9 +5942,9 @@ var APTOS_CONFIG_FIELDS = [
5599
5942
  type: "select",
5600
5943
  key: "name",
5601
5944
  label: "Network Name",
5602
- items: shelbyNetworks.map((name) => ({
5603
- label: name,
5604
- value: name
5945
+ items: shelbyNetworks.map((name2) => ({
5946
+ label: name2,
5947
+ value: name2
5605
5948
  }))
5606
5949
  },
5607
5950
  {
@@ -6000,7 +6343,7 @@ var CreateContextWizard = ({
6000
6343
  onComplete
6001
6344
  }) => {
6002
6345
  const [step, setStep] = useState4("name");
6003
- const [name, setName] = useState4("");
6346
+ const [name2, setName] = useState4("");
6004
6347
  const [apiKey, setApiKey] = useState4("");
6005
6348
  const [shelbyNetwork, setShelbyNetwork] = useState4(
6006
6349
  {}
@@ -6011,12 +6354,12 @@ var CreateContextWizard = ({
6011
6354
  const validatedAptosNetwork = AptosNetworkSchema.parse(aptosNetwork);
6012
6355
  const validatedShelbyNetwork = ShelbyNetworkSchema.parse(shelbyNetwork);
6013
6356
  onComplete({
6014
- name,
6357
+ name: name2,
6015
6358
  apiKey: apiKey || void 0,
6016
6359
  shelbyNetwork: validatedShelbyNetwork,
6017
6360
  aptosNetwork: validatedAptosNetwork
6018
6361
  });
6019
- }, [step, name, apiKey, shelbyNetwork, aptosNetwork, onComplete]);
6362
+ }, [step, name2, apiKey, shelbyNetwork, aptosNetwork, onComplete]);
6020
6363
  if (step === "name") {
6021
6364
  return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
6022
6365
  /* @__PURE__ */ jsx6(Text5, { children: "Context name?" }),
@@ -6025,7 +6368,7 @@ var CreateContextWizard = ({
6025
6368
  {
6026
6369
  placeholder: "Enter context name",
6027
6370
  required: true,
6028
- value: name,
6371
+ value: name2,
6029
6372
  onChange: setName,
6030
6373
  onSubmit: () => setStep("api-key")
6031
6374
  }
@@ -6255,6 +6598,158 @@ function assetTypeToString(asset) {
6255
6598
  return AccountAddress7.from(asset).toString();
6256
6599
  }
6257
6600
 
6601
+ // src/utils/cache.ts
6602
+ import path2 from "path";
6603
+ import fs2 from "fs-extra";
6604
+ var Cache = class {
6605
+ cachePath;
6606
+ schema;
6607
+ constructor(cacheFileName, schema) {
6608
+ this.cachePath = resolveConfigPath(`~/.shelby/${cacheFileName}`);
6609
+ this.schema = schema;
6610
+ }
6611
+ /**
6612
+ * Read data from cache
6613
+ * Returns null if cache doesn't exist or fails validation
6614
+ */
6615
+ read() {
6616
+ try {
6617
+ if (!fs2.existsSync(this.cachePath)) {
6618
+ return null;
6619
+ }
6620
+ const data = fs2.readFileSync(this.cachePath, "utf-8");
6621
+ const parsed = JSON.parse(data);
6622
+ const result = this.schema.safeParse(parsed);
6623
+ if (!result.success) {
6624
+ return null;
6625
+ }
6626
+ return result.data;
6627
+ } catch {
6628
+ return null;
6629
+ }
6630
+ }
6631
+ /**
6632
+ * Write data to cache
6633
+ * Data is validated before writing
6634
+ */
6635
+ write(data) {
6636
+ try {
6637
+ const validated = this.schema.parse(data);
6638
+ const cacheDir = path2.dirname(this.cachePath);
6639
+ fs2.mkdirpSync(cacheDir);
6640
+ fs2.writeFileSync(
6641
+ this.cachePath,
6642
+ JSON.stringify(validated, null, 2),
6643
+ "utf-8"
6644
+ );
6645
+ return true;
6646
+ } catch {
6647
+ return false;
6648
+ }
6649
+ }
6650
+ /**
6651
+ * Delete the cache file
6652
+ */
6653
+ clear() {
6654
+ try {
6655
+ if (fs2.existsSync(this.cachePath)) {
6656
+ fs2.unlinkSync(this.cachePath);
6657
+ }
6658
+ return true;
6659
+ } catch {
6660
+ return false;
6661
+ }
6662
+ }
6663
+ /**
6664
+ * Check if cache exists
6665
+ */
6666
+ exists() {
6667
+ return fs2.existsSync(this.cachePath);
6668
+ }
6669
+ /**
6670
+ * Get the resolved cache file path
6671
+ */
6672
+ getPath() {
6673
+ return this.cachePath;
6674
+ }
6675
+ };
6676
+
6677
+ // src/utils/check-version.ts
6678
+ import boxen from "boxen";
6679
+ import chalk from "chalk";
6680
+ import { getLatestVersion } from "fast-npm-meta";
6681
+ import * as semver from "semver";
6682
+ import { z as z9 } from "zod";
6683
+ var CHECK_INTERVAL = 1e3 * 60 * 60 * 24;
6684
+ var NOTIFY_INTERVAL = CHECK_INTERVAL;
6685
+ var VersionCacheSchema = z9.object({
6686
+ lastChecked: z9.number(),
6687
+ latestVersion: z9.string(),
6688
+ lastNotified: z9.number().optional()
6689
+ });
6690
+ var versionCache = new Cache("version-check.json", VersionCacheSchema);
6691
+ async function fetchLatestVersion() {
6692
+ try {
6693
+ const result = await getLatestVersion(name, { throw: false });
6694
+ if ("error" in result) {
6695
+ return null;
6696
+ }
6697
+ return result.version;
6698
+ } catch {
6699
+ return null;
6700
+ }
6701
+ }
6702
+ function displayUpdateNotification(latestVersion) {
6703
+ const message = [
6704
+ `Update available ${chalk.dim(version)} \u2192 ${chalk.green(
6705
+ latestVersion
6706
+ )}`,
6707
+ "",
6708
+ `Run ${chalk.cyan(`npm install -g ${name}`)} to update`
6709
+ ].join("\n");
6710
+ console.log(
6711
+ "\n" + boxen(message, {
6712
+ padding: 1,
6713
+ margin: 1,
6714
+ borderStyle: "round",
6715
+ borderColor: "yellow"
6716
+ }) + "\n"
6717
+ );
6718
+ }
6719
+ async function checkForUpdates(force = false) {
6720
+ try {
6721
+ const now = Date.now();
6722
+ const cache = versionCache.read();
6723
+ const shouldUseCache = cache && !force && now - cache.lastChecked < CHECK_INTERVAL;
6724
+ if (shouldUseCache) {
6725
+ if (semver.gt(cache.latestVersion, version)) {
6726
+ const shouldNotify = !cache.lastNotified || now - cache.lastNotified >= NOTIFY_INTERVAL;
6727
+ if (shouldNotify) {
6728
+ displayUpdateNotification(cache.latestVersion);
6729
+ versionCache.write({ ...cache, lastNotified: now });
6730
+ }
6731
+ }
6732
+ return;
6733
+ }
6734
+ const latestVersion = await fetchLatestVersion();
6735
+ if (!latestVersion) return;
6736
+ const isUpdateAvailable = semver.gt(latestVersion, version);
6737
+ versionCache.write({
6738
+ lastChecked: now,
6739
+ latestVersion,
6740
+ lastNotified: isUpdateAvailable ? now : cache?.lastNotified
6741
+ });
6742
+ if (isUpdateAvailable) {
6743
+ displayUpdateNotification(latestVersion);
6744
+ }
6745
+ } catch (err) {
6746
+ console.error("Unable to check for updates", err);
6747
+ }
6748
+ }
6749
+ async function checkForUpdatesAsync() {
6750
+ await checkForUpdates();
6751
+ }
6752
+
6258
6753
  // src/utils/erasure.ts
6259
6754
  var providerPromise;
6260
6755
  function getErasureCodingProvider() {
@@ -6265,7 +6760,10 @@ function getErasureCodingProvider() {
6265
6760
  }
6266
6761
 
6267
6762
  // src/utils/paths.ts
6268
- import path2 from "path";
6763
+ import path3 from "path";
6764
+ function endsWithDirectorySeparator(filePath) {
6765
+ return filePath.endsWith("/") || filePath.endsWith("\\") || filePath.endsWith(path3.sep);
6766
+ }
6269
6767
  function normBlobName(pathModule, inputDirectoryName, filename, blobPrefix) {
6270
6768
  const blobNameWithoutInputDir = pathModule.relative(
6271
6769
  inputDirectoryName,
@@ -6277,7 +6775,7 @@ function normBlobName(pathModule, inputDirectoryName, filename, blobPrefix) {
6277
6775
  );
6278
6776
  const blobNameNormalized = pathModule.normalize(blobNameWithPrefix);
6279
6777
  const parts = blobNameNormalized.split(pathModule.sep);
6280
- return path2.posix.join(...parts);
6778
+ return path3.posix.join(...parts);
6281
6779
  }
6282
6780
  function denormBlobName(pathModule, blobPrefix, blobName, outputPrefix) {
6283
6781
  if (!pathModule.isAbsolute(outputPrefix)) {
@@ -6511,7 +7009,7 @@ function createResponsiveTable(options) {
6511
7009
 
6512
7010
  // src/utils/version.ts
6513
7011
  import { execSync } from "child_process";
6514
- import semver from "semver";
7012
+ import semver2 from "semver";
6515
7013
  var MIN_APTOS_CLI_VERSION = "7.8.0";
6516
7014
  var MIN_NODE_VERSION = "22.0.0";
6517
7015
  function getNodeVersion() {
@@ -6519,7 +7017,7 @@ function getNodeVersion() {
6519
7017
  }
6520
7018
  function getNodeVersionInfo(minVersion = MIN_NODE_VERSION) {
6521
7019
  const version2 = getNodeVersion();
6522
- const meetsRequirement = semver.gte(version2, minVersion);
7020
+ const meetsRequirement = semver2.gte(version2, minVersion);
6523
7021
  return { version: version2, meetsRequirement };
6524
7022
  }
6525
7023
  function getAptosCliVersion() {
@@ -6535,7 +7033,7 @@ function getAptosCliVersion() {
6535
7033
  }
6536
7034
  function getAptosCliVersionInfo(minVersion = MIN_APTOS_CLI_VERSION) {
6537
7035
  const version2 = getAptosCliVersion();
6538
- const meetsRequirement = version2 ? semver.gte(version2, minVersion) : false;
7036
+ const meetsRequirement = version2 ? semver2.gte(version2, minVersion) : false;
6539
7037
  return { version: version2, meetsRequirement };
6540
7038
  }
6541
7039
 
@@ -7017,10 +7515,10 @@ var handleError = (error) => {
7017
7515
 
7018
7516
  // src/commands/account.tsx
7019
7517
  import { jsx as jsx10 } from "react/jsx-runtime";
7020
- var CreateAccountOptionsSchema = z9.object({
7021
- name: z9.string().optional(),
7022
- privateKey: z9.string().optional(),
7023
- address: z9.string().optional(),
7518
+ var CreateAccountOptionsSchema = z10.object({
7519
+ name: z10.string().optional(),
7520
+ privateKey: z10.string().optional(),
7521
+ address: z10.string().optional(),
7024
7522
  scheme: SignatureSchemeSchema.optional()
7025
7523
  });
7026
7524
  var allSchemes = SignatureSchemeSchema.options.join(", ");
@@ -7029,10 +7527,10 @@ function askQuestion(question) {
7029
7527
  input: process.stdin,
7030
7528
  output: process.stdout
7031
7529
  });
7032
- return new Promise((resolve2) => {
7530
+ return new Promise((resolve3) => {
7033
7531
  rl.question(question, (answer) => {
7034
7532
  rl.close();
7035
- resolve2(answer.trim());
7533
+ resolve3(answer.trim());
7036
7534
  });
7037
7535
  });
7038
7536
  }
@@ -7047,12 +7545,12 @@ async function promptForAccountName(config) {
7047
7545
  return answer;
7048
7546
  }
7049
7547
  }
7050
- var ListAccountOptionsSchema = z9.object({});
7051
- var UseAccountOptionsSchema = z9.object({
7052
- accountName: z9.string()
7548
+ var ListAccountOptionsSchema = z10.object({});
7549
+ var UseAccountOptionsSchema = z10.object({
7550
+ accountName: z10.string()
7053
7551
  });
7054
- var DeleteAccountOptionsSchema = z9.object({
7055
- accountName: z9.string()
7552
+ var DeleteAccountOptionsSchema = z10.object({
7553
+ accountName: z10.string()
7056
7554
  });
7057
7555
  function accountCommand(program) {
7058
7556
  const account = program.command("account").description("Manage signing accounts (addresses & keys)");
@@ -7064,7 +7562,7 @@ function accountCommand(program) {
7064
7562
  "Aptos account address (hex-encoded)"
7065
7563
  ).action(async (options) => {
7066
7564
  CreateAccountOptionsSchema.parse(options);
7067
- const { name, privateKey, address, scheme } = options;
7565
+ const { name: name2, privateKey, address, scheme } = options;
7068
7566
  const configPath = program.opts().configFile;
7069
7567
  let config;
7070
7568
  try {
@@ -7123,20 +7621,20 @@ function accountCommand(program) {
7123
7621
  /* @__PURE__ */ jsx10(
7124
7622
  AccountWizard,
7125
7623
  {
7126
- initialName: name,
7624
+ initialName: name2,
7127
7625
  config,
7128
7626
  onComplete: ({
7129
- name: name2,
7627
+ name: name3,
7130
7628
  address: address2,
7131
7629
  privateKey: privateKey2
7132
7630
  }) => {
7133
- config.accounts[name2] = {
7631
+ config.accounts[name3] = {
7134
7632
  private_key: privateKey2,
7135
7633
  address: address2
7136
7634
  };
7137
7635
  saveConfig(config, configPath);
7138
7636
  console.log(
7139
- `\u2705 Account ${name2} saved to ${resolveConfigPath(configPath)}`
7637
+ `\u2705 Account ${name3} saved to ${resolveConfigPath(configPath)}`
7140
7638
  );
7141
7639
  unmount();
7142
7640
  }
@@ -7172,9 +7670,9 @@ function accountCommand(program) {
7172
7670
  padding: 12
7173
7671
  // Account for borders (4) + cell padding (6) + margin
7174
7672
  });
7175
- for (const [name, { address, private_key }] of accounts) {
7176
- const isDefault = name === config.default_account ? " (default)" : "";
7177
- const displayName = name + isDefault;
7673
+ for (const [name2, { address, private_key }] of accounts) {
7674
+ const isDefault = name2 === config.default_account ? " (default)" : "";
7675
+ const displayName = name2 + isDefault;
7178
7676
  const maskedKey = private_key ? `${private_key.slice(0, 20)}...` : "";
7179
7677
  const row = [displayName, address || "", maskedKey];
7180
7678
  table.push(row.map((cell, i) => wrapCell(cell, i)));
@@ -7235,25 +7733,33 @@ function accountCommand(program) {
7235
7733
  });
7236
7734
  const activeAccount = getCurrentAccount(config, accountName).account;
7237
7735
  const shelbyClient = new ShelbyNodeClient(shelbyConfig);
7238
- console.log(
7239
- `\u{1F50D} Retrieving blobs for ${accountName} (${activeAccount.accountAddress.toString()})`
7736
+ console.log(`\u{1F50D} Retrieving blobs for ${accountName}`);
7737
+ console.log(`\u{1F464} Address: ${activeAccount.accountAddress.toString()}`);
7738
+ const shelbyExplorerUrl = getShelbyAccountExplorerUrl(
7739
+ shelbyConfig.network,
7740
+ activeAccount.accountAddress.toString()
7240
7741
  );
7742
+ console.log(`\u{1F5C2}\uFE0F Shelby Explorer: ${shelbyExplorerUrl}`);
7241
7743
  const blobs = await shelbyClient.coordination.getBlobs({
7242
7744
  where: {
7243
7745
  owner: { _eq: activeAccount.accountAddress.toString() }
7244
7746
  }
7245
7747
  });
7246
7748
  console.log(
7247
- `\u2705 Retrieved ${blobs.length} blob${blobs.length === 1 ? "" : "s"} for ${accountName} (${activeAccount.accountAddress.toString()})`
7749
+ `
7750
+ \u2705 Retrieved ${blobs.length} blob${blobs.length === 1 ? "" : "s"}`
7248
7751
  );
7752
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
7249
7753
  if (blobs.length === 0) {
7250
7754
  console.log("No blobs found.");
7755
+ console.log("\u2728 Done!");
7251
7756
  return;
7252
7757
  }
7758
+ console.log("\u{1F4E6} Stored Blobs");
7253
7759
  const { table, wrapCell } = createResponsiveTable({
7254
7760
  columns: [
7255
7761
  { header: "Name", width: 30, flex: true },
7256
- { header: "Size (bytes)", width: 15 },
7762
+ { header: "Size", width: 12 },
7257
7763
  { header: "Expires", width: 25 }
7258
7764
  ],
7259
7765
  padding: 12
@@ -7262,14 +7768,20 @@ function accountCommand(program) {
7262
7768
  const expirationDate = new Date(blob.expirationMicros / 1e3);
7263
7769
  const blobNameMatch = blob.name.match(/@[^/]+\/(.+)/);
7264
7770
  const displayName = blobNameMatch ? blobNameMatch[1] : blob.name;
7265
- const row = [
7266
- displayName,
7267
- blob.size.toString(),
7268
- expirationDate.toLocaleString()
7269
- ];
7771
+ const formattedSize = filesize(blob.size, { standard: "jedec" });
7772
+ const formattedDate = expirationDate.toLocaleDateString("en-US", {
7773
+ month: "short",
7774
+ day: "numeric",
7775
+ year: "numeric",
7776
+ hour: "numeric",
7777
+ minute: "2-digit",
7778
+ hour12: true
7779
+ });
7780
+ const row = [displayName, formattedSize, formattedDate];
7270
7781
  table.push(row.map((cell, i) => wrapCell(cell, i)));
7271
7782
  }
7272
7783
  console.log(table.toString());
7784
+ console.log("\u2728 Done!");
7273
7785
  } catch (error) {
7274
7786
  let displayMessage;
7275
7787
  if (error instanceof Error && error.message.includes("GraphQL Error (Code: 401)")) {
@@ -7344,16 +7856,16 @@ function accountCommand(program) {
7344
7856
  console.log("\n\u{1F464} Account Information");
7345
7857
  console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
7346
7858
  if (!addressArg && accountName) {
7347
- console.log(`\u{1F3F7}\uFE0F Alias: ${chalk.cyan(accountName)}`);
7859
+ console.log(`\u{1F3F7}\uFE0F Alias: ${chalk2.cyan(accountName)}`);
7348
7860
  }
7349
- console.log(`\u{1F310} Context: ${chalk.magenta(contextName)}`);
7861
+ console.log(`\u{1F310} Context: ${chalk2.magenta(contextName)}`);
7350
7862
  console.log("");
7351
- console.log(`\u{1F511} Address: ${chalk.dim(targetAddress)}`);
7863
+ console.log(`\u{1F511} Address: ${chalk2.dim(targetAddress)}`);
7352
7864
  console.log(
7353
- `\u{1F517} Aptos Explorer: ${chalk.blueBright.underline(aptosExplorerUrl)}`
7865
+ `\u{1F517} Aptos Explorer: ${chalk2.blueBright.underline(aptosExplorerUrl)}`
7354
7866
  );
7355
7867
  console.log(
7356
- `\u{1F5C2}\uFE0F Shelby Explorer: ${chalk.blueBright.underline(shelbyExplorerUrl)}`
7868
+ `\u{1F5C2}\uFE0F Shelby Explorer: ${chalk2.blueBright.underline(shelbyExplorerUrl)}`
7357
7869
  );
7358
7870
  console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
7359
7871
  console.log("\n\u{1F4B0} Balance:\n");
@@ -7403,21 +7915,21 @@ function accountCommand(program) {
7403
7915
  }
7404
7916
 
7405
7917
  // src/commands/commitment.ts
7406
- import * as fs2 from "fs";
7918
+ import * as fs3 from "fs";
7407
7919
  import * as fsP from "fs/promises";
7408
7920
  import { Readable } from "stream";
7409
- import { z as z10 } from "zod";
7410
- var CommitmentOptionsSchema = z10.object({
7411
- input: z10.string().nonempty("`--input` is required").refine(
7412
- async (path6) => {
7413
- const stat4 = await fsP.stat(path6);
7921
+ import { z as z11 } from "zod";
7922
+ var CommitmentOptionsSchema = z11.object({
7923
+ input: z11.string().nonempty("`--input` is required").refine(
7924
+ async (path7) => {
7925
+ const stat4 = await fsP.stat(path7);
7414
7926
  return stat4.isFile();
7415
7927
  },
7416
7928
  {
7417
7929
  message: "`--input` must be a file"
7418
7930
  }
7419
7931
  ),
7420
- output: z10.string().nonempty("`--output` is required")
7932
+ output: z11.string().nonempty("`--output` is required")
7421
7933
  });
7422
7934
  function commitmentCommand(program) {
7423
7935
  program.command("commitment <input> <output>").description(
@@ -7427,7 +7939,7 @@ function commitmentCommand(program) {
7427
7939
  input,
7428
7940
  output
7429
7941
  });
7430
- const inputFile = fs2.createReadStream(validatedOptions.input);
7942
+ const inputFile = fs3.createReadStream(validatedOptions.input);
7431
7943
  const provider = await getErasureCodingProvider();
7432
7944
  const commitment = await generateCommitments(
7433
7945
  provider,
@@ -7439,29 +7951,29 @@ function commitmentCommand(program) {
7439
7951
 
7440
7952
  // src/commands/context.tsx
7441
7953
  import { render as render2 } from "ink";
7442
- import { z as z12 } from "zod";
7954
+ import { z as z13 } from "zod";
7443
7955
 
7444
7956
  // src/utils/commands.ts
7445
- import z11 from "zod";
7446
- var AptosCommandOptionsSchema = z11.object({
7447
- aptosNetwork: z11.string().optional(),
7957
+ import z12 from "zod";
7958
+ var AptosCommandOptionsSchema = z12.object({
7959
+ aptosNetwork: z12.string().optional(),
7448
7960
  // predefined network name
7449
- aptosFullnode: z11.string().url().optional(),
7450
- aptosFaucet: z11.string().url().optional(),
7451
- aptosIndexer: z11.string().url().optional(),
7452
- aptosPepper: z11.string().url().optional(),
7453
- aptosProver: z11.string().url().optional(),
7454
- aptosApiKey: z11.string().optional()
7961
+ aptosFullnode: z12.string().url().optional(),
7962
+ aptosFaucet: z12.string().url().optional(),
7963
+ aptosIndexer: z12.string().url().optional(),
7964
+ aptosPepper: z12.string().url().optional(),
7965
+ aptosProver: z12.string().url().optional(),
7966
+ aptosApiKey: z12.string().optional()
7455
7967
  });
7456
7968
  var addAptosCommandOptions = (context) => context.option(
7457
7969
  "--aptos-network <network>",
7458
7970
  `Aptos network (${shelbyNetworks.join(", ")})`
7459
7971
  ).option("--aptos-fullnode <url>", "Aptos fullnode URL").option("--aptos-faucet <url>", "Aptos faucet URL").option("--aptos-indexer <url>", "Aptos indexer URL").option("--aptos-pepper <url>", "Aptos pepper URL").option("--aptos-prover <url>", "Aptos prover URL").option("--aptos-api-key <key>", "Aptos API key");
7460
- var ShelbyCommandOptionsSchema = z11.object({
7972
+ var ShelbyCommandOptionsSchema = z12.object({
7461
7973
  shelbyRpcEndpoint: EndpointSchema.optional(),
7462
7974
  shelbyIndexerEndpoint: EndpointSchema.optional(),
7463
- shelbyRpcApiKey: z11.string().optional(),
7464
- shelbyIndexerApiKey: z11.string().optional()
7975
+ shelbyRpcApiKey: z12.string().optional(),
7976
+ shelbyIndexerApiKey: z12.string().optional()
7465
7977
  });
7466
7978
  var addShelbyCommandOptions = (context) => context.option("--shelby-rpc-endpoint <url>", "Shelby RPC endpoint").option("--shelby-indexer-endpoint <url>", "Shelby indexer endpoint").option("--shelby-rpc-api-key <key>", "Shelby RPC API key").option("--shelby-indexer-api-key <key>", "Shelby indexer API key");
7467
7979
 
@@ -7498,13 +8010,13 @@ function getShelbyNetworkFromOptions(options) {
7498
8010
  indexer_api_key: options.shelbyIndexerApiKey
7499
8011
  };
7500
8012
  }
7501
- var CreateContextOptionsSchema = z12.object({ name: z12.string().optional() }).merge(AptosCommandOptionsSchema).merge(ShelbyCommandOptionsSchema);
7502
- var UpdateContextOptionsSchema = z12.object({}).merge(ShelbyCommandOptionsSchema).merge(AptosCommandOptionsSchema);
8013
+ var CreateContextOptionsSchema = z13.object({ name: z13.string().optional() }).merge(AptosCommandOptionsSchema).merge(ShelbyCommandOptionsSchema);
8014
+ var UpdateContextOptionsSchema = z13.object({}).merge(ShelbyCommandOptionsSchema).merge(AptosCommandOptionsSchema);
7503
8015
  function contextCommand(program) {
7504
8016
  const context = program.command("context").description("Manage network contexts (Shelby RPC & Aptos endpoints)");
7505
8017
  addShelbyCommandOptions(addAptosCommandOptions(context.command("create"))).description("Create a new context").option("--name <context-name>", "Name of the context").action((options) => {
7506
8018
  CreateContextOptionsSchema.parse(options);
7507
- const { name } = options;
8019
+ const { name: name2 } = options;
7508
8020
  const aptosNetwork = getAptosNetworkFromOptions(options);
7509
8021
  const shelbyNetwork = getShelbyNetworkFromOptions(options);
7510
8022
  const configPath = program.opts().configFile;
@@ -7515,7 +8027,7 @@ function contextCommand(program) {
7515
8027
  config = {
7516
8028
  contexts: {},
7517
8029
  accounts: {},
7518
- default_context: name || "",
8030
+ default_context: name2 || "",
7519
8031
  default_account: "default_account"
7520
8032
  };
7521
8033
  }
@@ -7525,10 +8037,10 @@ function contextCommand(program) {
7525
8037
  const hasAptosNetworkChanges = Object.values(aptosNetwork).some(
7526
8038
  (value) => value !== void 0
7527
8039
  );
7528
- if (name && (hasAptosNetworkChanges || hasShelbyNetworkChanges)) {
8040
+ if (name2 && (hasAptosNetworkChanges || hasShelbyNetworkChanges)) {
7529
8041
  const validatedAptosNetwork = AptosNetworkSchema.parse(aptosNetwork);
7530
8042
  const validatedShelbyNetwork = ShelbyNetworkSchema.parse(shelbyNetwork);
7531
- config.contexts[name] = {
8043
+ config.contexts[name2] = {
7532
8044
  shelby_network: {
7533
8045
  ...validatedShelbyNetwork,
7534
8046
  // This is to ensure there are no trailing slashes
@@ -7540,7 +8052,7 @@ function contextCommand(program) {
7540
8052
  aptos_network: validatedAptosNetwork
7541
8053
  };
7542
8054
  saveConfig(config, configPath);
7543
- console.log(`\u2705 Context '${name}' created successfully`);
8055
+ console.log(`\u2705 Context '${name2}' created successfully`);
7544
8056
  return;
7545
8057
  }
7546
8058
  const { unmount } = render2(
@@ -7548,18 +8060,18 @@ function contextCommand(program) {
7548
8060
  CreateContextWizard,
7549
8061
  {
7550
8062
  onComplete: ({
7551
- name: name2,
8063
+ name: name3,
7552
8064
  apiKey,
7553
8065
  shelbyNetwork: shelbyNetwork2,
7554
8066
  aptosNetwork: aptosNetwork2
7555
8067
  }) => {
7556
- config.contexts[name2] = {
8068
+ config.contexts[name3] = {
7557
8069
  api_key: apiKey,
7558
8070
  shelby_network: shelbyNetwork2,
7559
8071
  aptos_network: aptosNetwork2
7560
8072
  };
7561
8073
  saveConfig(config, configPath);
7562
- console.log(`\u2705 Context '${name2}' created successfully`);
8074
+ console.log(`\u2705 Context '${name3}' created successfully`);
7563
8075
  unmount();
7564
8076
  process.exit(0);
7565
8077
  }
@@ -7769,59 +8281,106 @@ function contextCommand(program) {
7769
8281
 
7770
8282
  // src/commands/download.tsx
7771
8283
  import * as fsS from "fs";
7772
- import * as fs3 from "fs/promises";
7773
- import * as path3 from "path";
8284
+ import * as fs4 from "fs/promises";
8285
+ import * as path4 from "path";
7774
8286
  import { Readable as Readable2, Transform } from "stream";
7775
8287
  import { pipeline } from "stream/promises";
7776
8288
  import ora from "ora";
7777
- import { z as z13 } from "zod";
7778
- var denormBlobName2 = (a, b, c) => denormBlobName(path3, a, b, c);
7779
- var endsWithDirectorySeparator = (filePath) => {
7780
- return filePath.endsWith("/") || filePath.endsWith("\\") || filePath.endsWith(path3.sep);
7781
- };
7782
- var DownloadOptionsSchema = z13.object({
7783
- src: z13.string().min(1, "`src`must be a valid blob name or directory prefix").describe("Blob name or directory prefix to download"),
7784
- dst: z13.string().min(1, "`dst` must be a valid filepath").describe("Local path where to save the downloaded content"),
7785
- recursive: z13.boolean().default(false).describe("Download assuming canonical directory layout and recurse"),
7786
- force: z13.boolean().default(false).describe("Overwrite the dst if it already exists")
8289
+ import { z as z14 } from "zod";
8290
+ var denormBlobName2 = (a, b, c) => denormBlobName(path4, a, b, c);
8291
+ var DownloadOptionsSchema = z14.object({
8292
+ source: z14.string({
8293
+ required_error: "\n\u274C Missing Required Argument\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\u26A0\uFE0F Missing source blob name or prefix (first argument)\n\n\u{1F4A1} Usage:\n shelby download <source-blob-name> <destination-path> [options]\n\n\u{1F4DD} Examples:\n shelby download my-blob.txt ./myfile.txt\n shelby download my-folder/ ./my-folder/ -r\n"
8294
+ }).min(1, "Source blob name or directory prefix is required").describe("Blob name or directory prefix to download"),
8295
+ destination: z14.string({
8296
+ required_error: "\n\u274C Missing Required Argument\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\u26A0\uFE0F Missing destination path (second argument)\n\n\u{1F4A1} Usage:\n shelby download <source-blob-name> <destination-path> [options]\n\n\u{1F4DD} Example:\n shelby download my-blob.txt ./myfile.txt\n"
8297
+ }).min(1, "`destination` must be a valid filepath").describe("Local path where to save the downloaded content"),
8298
+ recursive: z14.boolean().default(false).describe("Download assuming canonical directory layout and recurse"),
8299
+ force: z14.boolean().default(false).describe("Overwrite the destination if it already exists")
7787
8300
  }).refine(
7788
8301
  (data) => {
7789
8302
  if (data.recursive) {
7790
- if (!data.src.endsWith("/") || !endsWithDirectorySeparator(data.dst))
8303
+ if (!data.source.endsWith("/") || !endsWithDirectorySeparator(data.destination))
7791
8304
  return false;
7792
8305
  return true;
7793
8306
  }
7794
8307
  return true;
7795
8308
  },
7796
- {
7797
- message: "Recursive downloads require src prefix and dst name to end in directory separator ('/' or '\\')"
7798
- }
8309
+ (data) => ({
8310
+ message: `
8311
+ \u274C Invalid Download Options
8312
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
8313
+
8314
+ \u26A0\uFE0F Recursive downloads require:
8315
+ - The source prefix must end with '/'
8316
+ - The destination path must end with '/' or '\\'
8317
+
8318
+ \u{1F9FE} Received:
8319
+ Source: ${data.source}
8320
+ Destination: ${data.destination}
8321
+
8322
+ \u{1F4A1} Tip: Add trailing slashes to both paths:
8323
+ \u{1F449} shelby download --recursive ${data.source.endsWith("/") ? data.source : `${data.source}/`} ${endsWithDirectorySeparator(data.destination) ? data.destination : `${data.destination}/`}
8324
+ `
8325
+ })
7799
8326
  ).refine(
7800
8327
  (data) => {
7801
8328
  if (!data.recursive) {
7802
- if (!BlobNameSchema.safeParse(data.src).success) return false;
7803
- if (endsWithDirectorySeparator(data.dst)) return false;
8329
+ if (!BlobNameSchema.safeParse(data.source).success) return false;
8330
+ if (endsWithDirectorySeparator(data.destination)) return false;
7804
8331
  return true;
7805
8332
  }
7806
8333
  return true;
7807
8334
  },
7808
- {
7809
- message: "Blob downloads, non-recursive, require that src blob name and dst path not end in directory separator ('/' or '\\')"
8335
+ (data) => {
8336
+ const sourceEndsWithSlash = data.source.endsWith("/") || data.source.endsWith("\\");
8337
+ const destEndsWithSlash = endsWithDirectorySeparator(data.destination);
8338
+ let tipMessage = "";
8339
+ if (sourceEndsWithSlash && destEndsWithSlash) {
8340
+ tipMessage = `\u{1F4A1} Tip: For downloading a directory, use the --recursive flag:
8341
+ \u{1F449} shelby download --recursive ${data.source} ${data.destination}`;
8342
+ } else if (sourceEndsWithSlash && !destEndsWithSlash) {
8343
+ tipMessage = `\u{1F4A1} Tip: For downloading a directory, both paths need trailing slashes:
8344
+ \u{1F449} shelby download --recursive ${data.source} ${data.destination}/`;
8345
+ } else if (!sourceEndsWithSlash && destEndsWithSlash) {
8346
+ tipMessage = `\u{1F4A1} Choose one of the following:
8347
+
8348
+ To download a single blob (remove trailing slash from destination):
8349
+ \u{1F449} shelby download ${data.source} ${data.destination.replace(/[\\/]+$/, "")}
8350
+
8351
+ To download a directory recursively (add trailing slash to source):
8352
+ \u{1F449} shelby download --recursive ${data.source}/ ${data.destination}`;
8353
+ }
8354
+ return {
8355
+ message: `
8356
+ \u274C Invalid Download Options
8357
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
8358
+
8359
+ \u26A0\uFE0F Blob downloads (non-recursive) require:
8360
+ - The source blob name must NOT end with '/' or '\\'
8361
+ - The destination path must NOT end with '/' or '\\'
8362
+
8363
+ \u{1F9FE} Received:
8364
+ Source: ${data.source}
8365
+ Destination: ${data.destination}
8366
+
8367
+ ` + tipMessage + "\n"
8368
+ };
7810
8369
  }
7811
8370
  );
7812
8371
  async function validateOutput(options) {
7813
- const parentDir = path3.dirname(options.dst);
8372
+ const parentDir = path4.dirname(options.destination);
7814
8373
  try {
7815
- const parentStats = await fs3.stat(parentDir);
8374
+ const parentStats = await fs4.stat(parentDir);
7816
8375
  if (!parentStats.isDirectory()) {
7817
8376
  throw new Error(
7818
- `Parent path '${parentDir}' exists but is not a directory. Cannot create dst ${options.recursive ? "directory" : "file"} '${options.dst}'.`
8377
+ `Parent path '${parentDir}' exists but is not a directory. Cannot create destination ${options.recursive ? "directory" : "file"} '${options.destination}'.`
7819
8378
  );
7820
8379
  }
7821
8380
  } catch (error) {
7822
8381
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
7823
8382
  throw new Error(
7824
- `Parent directory '${parentDir}' of dst '${options.dst}' does not exist. Create it first or use a different dst path.`
8383
+ `Parent directory '${parentDir}' of destination '${options.destination}' does not exist. Create it first or use a different destination path.`
7825
8384
  );
7826
8385
  }
7827
8386
  throw error;
@@ -7829,7 +8388,7 @@ async function validateOutput(options) {
7829
8388
  if (options.force) return;
7830
8389
  let outputStats;
7831
8390
  try {
7832
- outputStats = await fs3.stat(options.dst);
8391
+ outputStats = await fs4.stat(options.destination);
7833
8392
  } catch (error) {
7834
8393
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
7835
8394
  return;
@@ -7839,64 +8398,73 @@ async function validateOutput(options) {
7839
8398
  const isDirectory = outputStats.isDirectory();
7840
8399
  if (!options.recursive && isDirectory) {
7841
8400
  throw new Error(
7842
- `dst path '${options.dst}' is a directory but expected a file path to download a single blob (--recursive not provided).`
8401
+ `destination path '${options.destination}' is a directory but expected a file path to download a single blob (--recursive not provided).`
7843
8402
  );
7844
8403
  }
7845
8404
  if (options.recursive && !isDirectory) {
7846
8405
  throw new Error(
7847
- `dst path '${options.dst}' exists but is not a directory. Directory downloads require a directory path.`
8406
+ `destination path '${options.destination}' exists but is not a directory. Directory downloads require a directory path.`
7848
8407
  );
7849
8408
  }
7850
8409
  if (options.recursive) {
7851
- const entries = await fs3.readdir(options.dst);
8410
+ const entries = await fs4.readdir(options.destination);
7852
8411
  if (entries.length > 0) {
7853
8412
  throw new Error(
7854
- `Directory '${options.dst}' exists and is not empty. Use --force to overwrite or choose an empty directory.`
8413
+ `Directory '${options.destination}' exists and is not empty. Use --force to overwrite or choose an empty directory.`
7855
8414
  );
7856
8415
  }
7857
8416
  } else {
7858
8417
  throw new Error(
7859
- `File '${options.dst}' already exists. Use --force to overwrite.`
8418
+ `File '${options.destination}' already exists. Use --force to overwrite.`
7860
8419
  );
7861
8420
  }
7862
8421
  }
7863
8422
  async function createFileList(options, nodeClient, account) {
7864
8423
  const matchingBlobList = [];
8424
+ const stripAccountPrefix = (fullName) => {
8425
+ const blobNameMatch = fullName.match(/^@[^/]+\/(.+)$/);
8426
+ return blobNameMatch ? blobNameMatch[1] : fullName;
8427
+ };
7865
8428
  if (options.recursive) {
7866
- const allBlobs = await nodeClient.coordination.getAccountBlobs({
8429
+ const activeBlobs = await nodeClient.coordination.getAccountBlobs({
7867
8430
  account
7868
8431
  });
7869
- for (const blobMd of allBlobs) {
7870
- const blobNameWithoutAccount = blobMd.name.slice(1 + 64 + 1);
7871
- if (!blobNameWithoutAccount.startsWith(options.src)) continue;
8432
+ for (const blobMd of activeBlobs) {
8433
+ const blobNameWithoutAccount = stripAccountPrefix(blobMd.name);
8434
+ if (!blobNameWithoutAccount.startsWith(options.source)) continue;
7872
8435
  matchingBlobList.push(blobMd);
7873
8436
  }
7874
8437
  if (matchingBlobList.length === 0) {
7875
8438
  throw new Error(
7876
- `No blobs matching prefix ${options.src} were found in account ${account}`
8439
+ `No active blobs matching prefix '${options.source}' were found for account ${account.toString()}. They may have expired or been deleted.`
7877
8440
  );
7878
8441
  }
7879
8442
  } else {
7880
- const md = await nodeClient.coordination.getBlobMetadata({
7881
- account,
7882
- name: options.src
8443
+ const activeBlobs = await nodeClient.coordination.getAccountBlobs({
8444
+ account
7883
8445
  });
7884
- if (md === void 0) {
7885
- throw new Error(`Could not find a blob with name ${options.src}`);
8446
+ const md = activeBlobs.find(
8447
+ (blob) => stripAccountPrefix(blob.name) === options.source
8448
+ );
8449
+ if (!md) {
8450
+ throw new Error(
8451
+ `No active blob named '${options.source}' was found for account ${account.toString()}. It may have expired or been deleted.
8452
+ `
8453
+ );
7886
8454
  }
7887
8455
  matchingBlobList.push(md);
7888
8456
  }
7889
8457
  const ret = [];
7890
8458
  for (const blobMd of matchingBlobList) {
7891
- let blobname;
7892
- if (options.recursive) {
7893
- blobname = blobMd.name.slice(1 + 64 + 1);
7894
- } else {
7895
- blobname = blobMd.name;
7896
- }
8459
+ const blobNameWithoutAccount = stripAccountPrefix(blobMd.name);
7897
8460
  const entry = {
7898
- filename: denormBlobName2(options.src, blobname, options.dst),
7899
- blobname,
8461
+ filename: denormBlobName2(
8462
+ options.source,
8463
+ blobNameWithoutAccount,
8464
+ options.destination
8465
+ ),
8466
+ blobname: blobNameWithoutAccount,
8467
+ // FIXME this is nasty
7900
8468
  sizeBytes: blobMd.size
7901
8469
  };
7902
8470
  ret.push(entry);
@@ -7906,12 +8474,12 @@ async function createFileList(options, nodeClient, account) {
7906
8474
  async function createOutputDirectories(fileList) {
7907
8475
  const uniqueDirectories = /* @__PURE__ */ new Set();
7908
8476
  for (const fileEntry of fileList) {
7909
- const parentDir = path3.dirname(fileEntry.filename);
8477
+ const parentDir = path4.dirname(fileEntry.filename);
7910
8478
  uniqueDirectories.add(parentDir);
7911
8479
  }
7912
8480
  for (const dir of uniqueDirectories) {
7913
8481
  try {
7914
- await fs3.mkdir(dir, { recursive: true });
8482
+ await fs4.mkdir(dir, { recursive: true });
7915
8483
  } catch (error) {
7916
8484
  throw new Error(
7917
8485
  `Failed to create directory '${dir}': ${error instanceof Error ? error.message : error}`
@@ -7935,96 +8503,170 @@ function createProgressTransform(totalBytes, reporter) {
7935
8503
  });
7936
8504
  }
7937
8505
  function downloadCommand(program) {
7938
- program.command("download <src> <dst>").description("Download a file or directory from Shelby RPC").option(
8506
+ program.command("download").description("Download a file or directory from Shelby RPC").argument("[source]", "Source blob name or prefix").argument("[destination]", "Destination path").option(
7939
8507
  "-r, --recursive",
7940
8508
  "Download assuming canonical directory layout using '/' as separators. Produces a directory."
7941
- ).option("-f, --force", "Overwrite the dst").action(
7942
- async (src, dst, rawOptions) => {
7943
- const options = DownloadOptionsSchema.parse({
7944
- ...rawOptions,
7945
- src,
7946
- dst
7947
- });
7948
- options.dst = path3.resolve(options.dst);
7949
- await validateOutput(options);
7950
- if (options.recursive) {
7951
- console.log(
7952
- `Downloading directory: ${options.src} -> ${options.dst}`
7953
- );
7954
- } else {
7955
- console.log(`Downloading blob: ${options.src} -> ${options.dst}`);
7956
- }
7957
- const configPath = program.opts().configFile;
7958
- let config;
8509
+ ).option("-f, --force", "Overwrite the destination").action(
8510
+ async (source, destination, rawOptions) => {
8511
+ let options;
7959
8512
  try {
7960
- config = loadConfig(configPath);
8513
+ options = DownloadOptionsSchema.parse({
8514
+ ...rawOptions,
8515
+ source,
8516
+ destination
8517
+ });
7961
8518
  } catch (error) {
7962
- console.error(`Error: ${error.message}`);
8519
+ if (error instanceof z14.ZodError) {
8520
+ const firstIssue = error.issues[0];
8521
+ if (firstIssue) {
8522
+ console.log(firstIssue.message);
8523
+ } else {
8524
+ console.error("\u26A0\uFE0F Invalid download options provided");
8525
+ }
8526
+ } else {
8527
+ console.error(
8528
+ `\u26A0\uFE0F ${error instanceof Error ? error.message : String(error)}`
8529
+ );
8530
+ }
7963
8531
  process.exit(1);
7964
8532
  }
7965
- const shelbyConfig = getCurrentShelbyConfig(config, {
7966
- context: program.opts().context
7967
- });
7968
- const activeAccount = getCurrentAccount(
7969
- config,
7970
- program.opts().account
7971
- ).account;
7972
- const nodeClient = new ShelbyNodeClient(shelbyConfig);
7973
- const fileList = await createFileList(
7974
- options,
7975
- nodeClient,
7976
- activeAccount.accountAddress
7977
- );
7978
- for (const fileEntry of fileList) {
7979
- console.log(
7980
- `Downloading ${fileEntry.blobname} -> ${fileEntry.filename}`
7981
- );
7982
- }
7983
- if (options.force) {
7984
- console.log(`--force was set, so deleting ${options.dst}`);
7985
- await fs3.rm(options.dst, { recursive: true, force: true });
7986
- }
8533
+ options.destination = path4.resolve(options.destination);
8534
+ let config;
8535
+ let spinner;
7987
8536
  const handleSigint = () => {
7988
- spinner.fail("Quitting due to ctrl-C / SIGINT...");
8537
+ spinner?.fail("Quitting due to ctrl-C / SIGINT...");
7989
8538
  process.exit(1);
7990
8539
  };
7991
- process.removeAllListeners("SIGINT");
7992
- process.on("SIGINT", handleSigint);
7993
- const spinner = ora({
7994
- text: "Creating dst directory tree...",
7995
- discardStdin: false
7996
- }).start();
7997
- await createOutputDirectories(fileList);
7998
- let totalSize = 0;
7999
- for (const fileEntry of fileList) totalSize += fileEntry.sizeBytes;
8000
- const startTime = performance.now();
8001
- let amountDownloaded = 0;
8002
- const formatProgressPercent = () => (100 * (amountDownloaded / totalSize)).toFixed(2);
8003
- const formatProgressRate = () => {
8004
- const mib = amountDownloaded / 1024 / 1024;
8005
- const sec = (performance.now() - startTime) / 1e3;
8006
- return (mib / sec).toFixed(2);
8007
- };
8008
- for (const fileEntry of fileList) {
8009
- const out = fsS.createWriteStream(fileEntry.filename);
8010
- const { readable } = await nodeClient.rpc.getBlob({
8011
- account: activeAccount.accountAddress,
8012
- blobName: fileEntry.blobname
8540
+ try {
8541
+ const configPath = program.opts().configFile;
8542
+ config = loadConfig(configPath);
8543
+ const shelbyConfig = getCurrentShelbyConfig(config, {
8544
+ context: program.opts().context
8013
8545
  });
8014
- const reporter = (filePercent, rateMiB) => {
8015
- spinner.text = `Downloading ${fileEntry.blobname}, ${filePercent}% at ${rateMiB} MiB/s .. (Overall: ${formatProgressPercent()}%, ${formatProgressRate()} MiB/s)`;
8016
- };
8017
- const nodeStream = Readable2.fromWeb(readable);
8018
- await pipeline(
8019
- nodeStream,
8020
- createProgressTransform(fileEntry.sizeBytes, reporter),
8021
- out
8546
+ const activeAccount = getCurrentAccount(
8547
+ config,
8548
+ program.opts().account
8549
+ ).account;
8550
+ const nodeClient = new ShelbyNodeClient(shelbyConfig);
8551
+ const fileList = await createFileList(
8552
+ options,
8553
+ nodeClient,
8554
+ activeAccount.accountAddress
8555
+ );
8556
+ await validateOutput(options);
8557
+ console.log(`
8558
+ \u{1F4E5} Downloading Files (${fileList.length} total)`);
8559
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
8560
+ for (let i = 0; i < fileList.length; i++) {
8561
+ const fileEntry = fileList[i];
8562
+ const blobBaseName = path4.basename(fileEntry.blobname);
8563
+ console.log(`${i + 1}. ${blobBaseName} \u2192 ${fileEntry.filename}`);
8564
+ }
8565
+ console.log();
8566
+ if (options.force) {
8567
+ console.log(`--force was set, so deleting ${options.destination}`);
8568
+ await fs4.rm(options.destination, { recursive: true, force: true });
8569
+ }
8570
+ process.removeAllListeners("SIGINT");
8571
+ process.on("SIGINT", handleSigint);
8572
+ spinner = ora({
8573
+ text: "Creating destination directory tree...",
8574
+ discardStdin: false
8575
+ }).start();
8576
+ await createOutputDirectories(fileList);
8577
+ let totalSize = 0;
8578
+ for (const fileEntry of fileList) totalSize += fileEntry.sizeBytes;
8579
+ const startTime = performance.now();
8580
+ let amountDownloaded = 0;
8581
+ let filesDownloaded = 0;
8582
+ const isSingleFile = fileList.length === 1;
8583
+ const formatProgressPercent = () => totalSize > 0 ? (100 * (amountDownloaded / totalSize)).toFixed(2) : "0.00";
8584
+ for (const fileEntry of fileList) {
8585
+ const out = fsS.createWriteStream(fileEntry.filename);
8586
+ const fileName = path4.basename(fileEntry.blobname);
8587
+ const { readable } = await nodeClient.rpc.getBlob({
8588
+ account: activeAccount.accountAddress,
8589
+ blobName: fileEntry.blobname
8590
+ });
8591
+ const reporter = (filePercent, _rateMiB) => {
8592
+ if (spinner) {
8593
+ if (isSingleFile) {
8594
+ spinner.text = `Downloading ${fileName}... (${filePercent}%)`;
8595
+ } else {
8596
+ spinner.text = `Downloading ${fileName}... (${filesDownloaded}/${fileList.length} files, ${formatProgressPercent()}%)`;
8597
+ }
8598
+ }
8599
+ };
8600
+ const nodeStream = Readable2.fromWeb(readable);
8601
+ await pipeline(
8602
+ nodeStream,
8603
+ createProgressTransform(fileEntry.sizeBytes, reporter),
8604
+ out
8605
+ );
8606
+ amountDownloaded += fileEntry.sizeBytes;
8607
+ filesDownloaded++;
8608
+ }
8609
+ const totalTime = (performance.now() - startTime) / 1e3;
8610
+ spinner?.stop();
8611
+ console.log(
8612
+ `
8613
+ \u2705 All downloads complete \u2014 took ${totalTime.toFixed(1)} seconds`
8022
8614
  );
8023
- amountDownloaded += fileEntry.sizeBytes;
8615
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
8616
+ console.log("\u2728 Done!");
8617
+ } catch (error) {
8618
+ spinner?.stop();
8619
+ console.log("\n\u274C Download Failed");
8620
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
8621
+ if (options.recursive) {
8622
+ console.log(`\u{1F9FE} Directory: ${options.source}`);
8623
+ } else {
8624
+ console.log(`\u{1F9FE} File: ${options.source}`);
8625
+ }
8626
+ if (config) {
8627
+ const activeAccount = getCurrentAccount(
8628
+ config,
8629
+ program.opts().account
8630
+ ).account;
8631
+ console.log(
8632
+ `\u{1F464} Account: ${activeAccount.accountAddress.toString()}`
8633
+ );
8634
+ }
8635
+ console.log();
8636
+ if (error instanceof Error) {
8637
+ if (error.message.includes("GraphQL Error (Code: 401)")) {
8638
+ const contextName = program.opts().context || config?.default_context;
8639
+ console.error("\u26A0\uFE0F Authentication required.");
8640
+ console.error(
8641
+ " Please add an indexer API key to your context configuration."
8642
+ );
8643
+ console.error();
8644
+ console.error("\u{1F4A1} Tip: Update your context with an API key:");
8645
+ console.error(
8646
+ ` \u{1F449} shelby context update ${contextName ?? "default"} --indexer-api-key YOUR_KEY`
8647
+ );
8648
+ } else if (error.message.includes("No active blob") || error.message.includes("may have expired or been deleted")) {
8649
+ const blobName = options.source;
8650
+ console.error(
8651
+ `\u26A0\uFE0F No active blob${options.recursive ? "s" : ""} named '${blobName}' ${options.recursive ? "were" : "was"} found.`
8652
+ );
8653
+ console.error(" It may have expired or been deleted.");
8654
+ console.error();
8655
+ console.error(
8656
+ "\u{1F4A1} Tip: Try listing available blobs before downloading:"
8657
+ );
8658
+ console.error(" \u{1F449} shelby account blobs");
8659
+ } else {
8660
+ console.error(`\u26A0\uFE0F ${error.message}`);
8661
+ }
8662
+ } else {
8663
+ console.error(`\u26A0\uFE0F ${String(error)}`);
8664
+ }
8665
+ console.log("\n");
8666
+ process.exit(1);
8667
+ } finally {
8668
+ process.removeListener("SIGINT", handleSigint);
8024
8669
  }
8025
- const totalTime = (performance.now() - startTime) / 1e3;
8026
- const totalRate = amountDownloaded / 1024 / 1024 / totalTime;
8027
- spinner.succeed(`Final rate ${totalRate.toFixed(2)} MiB/s`);
8028
8670
  }
8029
8671
  );
8030
8672
  }
@@ -8032,10 +8674,10 @@ function downloadCommand(program) {
8032
8674
  // src/commands/faucet.tsx
8033
8675
  import { Network as Network9 } from "@aptos-labs/ts-sdk";
8034
8676
  import { execaSync } from "execa";
8035
- import { z as z14 } from "zod";
8036
- var FaucetOptionsSchema = z14.object({
8037
- network: z14.enum([Network9.SHELBYNET]).optional(),
8038
- open: z14.boolean().optional().default(true)
8677
+ import { z as z15 } from "zod";
8678
+ var FaucetOptionsSchema = z15.object({
8679
+ network: z15.enum([Network9.SHELBYNET]).optional(),
8680
+ open: z15.boolean().optional().default(true)
8039
8681
  });
8040
8682
  function faucetCommand(program) {
8041
8683
  program.command("faucet").description("Open the Shelby faucet web page to request tokens").option("--network <network>", "Network to request tokens for (shelbynet)").option("--no-open", "Don't automatically open browser, just print the URL").action((options) => {
@@ -8106,9 +8748,9 @@ function openBrowser(url) {
8106
8748
  }
8107
8749
 
8108
8750
  // src/commands/init.tsx
8109
- import path4 from "path";
8751
+ import path5 from "path";
8110
8752
  import { Network as Network10 } from "@aptos-labs/ts-sdk";
8111
- import fs4 from "fs-extra";
8753
+ import fs5 from "fs-extra";
8112
8754
  import { render as render3 } from "ink";
8113
8755
  import { jsx as jsx12 } from "react/jsx-runtime";
8114
8756
  function initCommand(program) {
@@ -8237,22 +8879,72 @@ function cloneContexts(contexts) {
8237
8879
  return JSON.parse(JSON.stringify(contexts));
8238
8880
  }
8239
8881
  function ensureConfigDir(resolvedPath) {
8240
- fs4.mkdirpSync(path4.dirname(resolvedPath));
8882
+ fs5.mkdirpSync(path5.dirname(resolvedPath));
8241
8883
  }
8242
8884
 
8243
8885
  // src/commands/upload.tsx
8244
- import * as fs5 from "fs/promises";
8245
- import * as path5 from "path";
8886
+ import * as fs6 from "fs/promises";
8887
+ import * as path6 from "path";
8246
8888
  import { Aptos as Aptos5, AptosConfig as AptosConfig4 } from "@aptos-labs/ts-sdk";
8247
8889
  import * as chrono from "chrono-node";
8248
8890
  import { glob } from "glob";
8891
+ import ignore from "ignore";
8249
8892
  import { Box as Box7, render as render4, Text as Text7 } from "ink";
8250
8893
  import SelectInput4 from "ink-select-input";
8251
8894
  import ora2 from "ora";
8252
- import { z as z15 } from "zod";
8895
+ import { z as z16 } from "zod";
8896
+
8897
+ // src/utils/commander-helpers.ts
8898
+ function createExitOverrideHandler(commandName, requiredArgs, requiredOptions, exampleUsage, warningMessage) {
8899
+ return (err) => {
8900
+ if (err.code === "commander.helpDisplayed") {
8901
+ process.exit(0);
8902
+ }
8903
+ const args = process.argv.slice(process.argv.indexOf(commandName) + 1);
8904
+ const hasArguments = args.some((arg) => !arg.startsWith("-"));
8905
+ if (err.code === "commander.missingMandatoryOptionValue") {
8906
+ if (!hasArguments && requiredOptions) {
8907
+ console.error("\n\u274C Missing Required Arguments");
8908
+ console.error("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
8909
+ const warning = warningMessage || "Missing required arguments or options";
8910
+ console.error(`\u26A0\uFE0F ${warning}
8911
+ `);
8912
+ console.error("\u{1F4A1} Usage:");
8913
+ console.error(
8914
+ ` shelby ${commandName} ${requiredArgs} ${requiredOptions}
8915
+ `
8916
+ );
8917
+ if (exampleUsage) {
8918
+ console.error("\u{1F4DD} Examples:");
8919
+ console.error(` ${exampleUsage}`);
8920
+ }
8921
+ console.error("\n");
8922
+ } else {
8923
+ console.error(err.message);
8924
+ }
8925
+ process.exit(1);
8926
+ }
8927
+ if (err.code === "commander.optionMissingArgument") {
8928
+ console.error("\n\u274C Missing Option Value");
8929
+ console.error("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
8930
+ const cleanMessage = err.message.replace(/^error:\s*/i, "");
8931
+ console.error(`\u26A0\uFE0F ${cleanMessage}
8932
+ `);
8933
+ if (exampleUsage) {
8934
+ console.error("\u{1F4A1} Example:");
8935
+ console.error(` ${exampleUsage}`);
8936
+ }
8937
+ console.error("\n");
8938
+ process.exit(1);
8939
+ }
8940
+ throw err;
8941
+ };
8942
+ }
8943
+
8944
+ // src/commands/upload.tsx
8253
8945
  import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
8254
- var normBlobName2 = (i, f, b) => normBlobName(path5, i, f, b);
8255
- var flexibleDateSchema = z15.string().transform((val) => {
8946
+ var normBlobName2 = (i, f, b) => normBlobName(path6, i, f, b);
8947
+ var flexibleDateSchema = z16.string().transform((val, ctx) => {
8256
8948
  const now = /* @__PURE__ */ new Date();
8257
8949
  let parsedDate = null;
8258
8950
  if (/^\d+$/.test(val)) {
@@ -8274,77 +8966,207 @@ var flexibleDateSchema = z15.string().transform((val) => {
8274
8966
  }
8275
8967
  }
8276
8968
  if (!parsedDate || Number.isNaN(parsedDate.getTime())) {
8277
- throw new Error(
8278
- `Invalid date format: "${val}". Try formats like "tomorrow", "in 2 days", "next Friday", "2025-12-31", or a UNIX timestamp.`
8279
- );
8969
+ ctx.addIssue({
8970
+ code: z16.ZodIssueCode.custom,
8971
+ message: `
8972
+ \u274C Upload Failed
8973
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
8974
+
8975
+ \u26A0\uFE0F Invalid date format: "${val}"
8976
+
8977
+ \u{1F4A1} Try formats like:
8978
+ \u2022 "tomorrow", "in 2 days", "next Friday"
8979
+ \u2022 "2025-12-31"
8980
+ \u2022 UNIX timestamp
8981
+
8982
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`
8983
+ });
8984
+ return z16.NEVER;
8280
8985
  }
8281
8986
  if (parsedDate.getTime() <= now.getTime()) {
8282
- throw new Error(
8283
- `Expiration date must be in the future. "${val}" resolves to ${parsedDate.toLocaleString()} which is in the past.`
8284
- );
8987
+ ctx.addIssue({
8988
+ code: z16.ZodIssueCode.custom,
8989
+ message: `
8990
+ \u274C Upload Failed
8991
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
8992
+
8993
+ \u26A0\uFE0F Expiration date must be in the future
8994
+
8995
+ \u{1F4C5} "${val}" resolves to ${parsedDate.toLocaleString()}
8996
+ which is in the past.
8997
+
8998
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`
8999
+ });
9000
+ return z16.NEVER;
8285
9001
  }
8286
9002
  return parsedDate;
8287
9003
  });
8288
- var UploadOptionsSchema = z15.object({
8289
- src: z15.string().nonempty("`src` positional arg is required"),
8290
- dst: z15.string().nonempty("`dst` position arg is required"),
9004
+ var UploadOptionsSchema = z16.object({
9005
+ source: z16.string({
9006
+ required_error: '\n\u274C Missing Required Argument\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\u26A0\uFE0F Missing source file or directory path (first argument)\n\n\u{1F4A1} Usage:\n shelby upload <source-file-or-directory> <destination-blob-name> [options]\n\n\u{1F4DD} Examples:\n shelby upload ./myfile.txt my-blob.txt -e tomorrow\n shelby upload ./my-folder/ my-folder/ -r -e "next week"\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500'
9007
+ }).min(1, "Source file or directory path is required"),
9008
+ destination: z16.string({
9009
+ required_error: "\n\u274C Missing Required Argument\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\u26A0\uFE0F Missing destination blob name (second argument)\n\n\u{1F4A1} Usage:\n shelby upload <source-file-or-directory> <destination-blob-name> [options]\n\n\u{1F4DD} Example:\n shelby upload ./myfile.txt files/my-blob.txt -e tomorrow\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
9010
+ }).min(1, "Destination blob name is required"),
8291
9011
  expiration: flexibleDateSchema,
8292
- recursive: z15.boolean().optional().default(false),
8293
- assumeYes: z15.boolean().optional().default(false),
8294
- outputCommitments: z15.string().optional()
9012
+ recursive: z16.boolean().optional().default(false),
9013
+ assumeYes: z16.boolean().optional().default(false),
9014
+ outputCommitments: z16.string().optional()
8295
9015
  }).superRefine(async (data, ctx) => {
8296
- const stats = await fs5.stat(data.src);
9016
+ const stats = await fs6.stat(data.source);
8297
9017
  if (!stats.isFile() && !stats.isDirectory()) {
8298
9018
  ctx.addIssue({
8299
- code: z15.ZodIssueCode.custom,
8300
- message: "`src` must be a file or a directory",
8301
- path: ["src"]
9019
+ code: z16.ZodIssueCode.custom,
9020
+ message: "\n\u274C Upload Failed\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n\u26A0\uFE0F Source path must be a file or directory\n\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
9021
+ path: ["source"]
8302
9022
  });
8303
9023
  return;
8304
9024
  }
8305
9025
  if (stats.isDirectory()) {
8306
- if (!data.dst.endsWith("/")) {
9026
+ if (!data.destination.endsWith("/")) {
8307
9027
  ctx.addIssue({
8308
- code: z15.ZodIssueCode.custom,
8309
- message: "When src is a directory, dst must end with '/'",
8310
- path: ["dst"]
9028
+ code: z16.ZodIssueCode.custom,
9029
+ message: `
9030
+ \u274C Upload Failed
9031
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
9032
+
9033
+ \u26A0\uFE0F When source is a directory, destination must end with '/'
9034
+
9035
+ \u{1F4A1} Tip: When uploading a directory, add a trailing slash:
9036
+ \u{1F449} shelby upload -r ${data.source} ${data.destination}/
9037
+
9038
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`,
9039
+ path: ["destination"]
8311
9040
  });
8312
9041
  }
8313
9042
  } else if (stats.isFile()) {
8314
- const blobNameResult = BlobNameSchema.safeParse(data.dst);
9043
+ const blobNameResult = BlobNameSchema.safeParse(data.destination);
8315
9044
  if (!blobNameResult.success) {
8316
9045
  ctx.addIssue({
8317
- code: z15.ZodIssueCode.custom,
8318
- message: "When src is a file, dst must be a valid blob name (cannot end with '/')",
8319
- path: ["dst"]
9046
+ code: z16.ZodIssueCode.custom,
9047
+ message: `
9048
+ \u274C Upload Failed
9049
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
9050
+
9051
+ \u26A0\uFE0F When source is a file, destination must be a valid blob name (cannot end with '/')
9052
+
9053
+ \u{1F4A1} Tip: When uploading a file, remove the trailing slash:
9054
+ \u{1F449} shelby upload ${data.source} ${data.destination.replace(/\/$/, "")}
9055
+
9056
+ \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`,
9057
+ path: ["destination"]
8320
9058
  });
8321
9059
  }
8322
9060
  }
8323
9061
  });
9062
+ async function buildGitignoreMap(root) {
9063
+ const resolvedRoot = path6.resolve(root);
9064
+ const gitignoreMap = /* @__PURE__ */ new Map();
9065
+ const ensureMatcher = (dir) => {
9066
+ const existing = gitignoreMap.get(dir);
9067
+ if (existing) {
9068
+ return existing;
9069
+ }
9070
+ const instance = ignore();
9071
+ gitignoreMap.set(dir, instance);
9072
+ return instance;
9073
+ };
9074
+ ensureMatcher(resolvedRoot).add(".git/");
9075
+ const gitignoreFiles = await glob("**/.gitignore", {
9076
+ cwd: resolvedRoot,
9077
+ dot: true,
9078
+ absolute: true,
9079
+ nodir: true
9080
+ });
9081
+ for (const gitignorePath of gitignoreFiles) {
9082
+ try {
9083
+ const contents = await fs6.readFile(gitignorePath, "utf8");
9084
+ const directory = path6.dirname(gitignorePath);
9085
+ ensureMatcher(directory).add(contents);
9086
+ } catch (error) {
9087
+ if (error instanceof Error && Object.hasOwn(error, "code") && // biome-ignore lint/suspicious/noExplicitAny: node fs error type
9088
+ error.code === "ENOENT") {
9089
+ continue;
9090
+ }
9091
+ throw error;
9092
+ }
9093
+ }
9094
+ return gitignoreMap;
9095
+ }
9096
+ function collectDirectoriesFromRoot(root, filePath) {
9097
+ const directories = [];
9098
+ let current = path6.dirname(filePath);
9099
+ while (true) {
9100
+ directories.push(current);
9101
+ if (current === root) {
9102
+ break;
9103
+ }
9104
+ const parent = path6.dirname(current);
9105
+ if (parent === current) {
9106
+ break;
9107
+ }
9108
+ current = parent;
9109
+ }
9110
+ return directories.reverse();
9111
+ }
9112
+ function shouldIgnorePath(gitignoreMap, root, filePath) {
9113
+ const directories = collectDirectoriesFromRoot(root, filePath);
9114
+ let ignored = false;
9115
+ for (const directory of directories) {
9116
+ const matcher = gitignoreMap.get(directory);
9117
+ if (!matcher) {
9118
+ continue;
9119
+ }
9120
+ const relative2 = path6.relative(directory, filePath).split(path6.sep).join("/");
9121
+ const result = matcher.test(relative2);
9122
+ if (result.ignored) {
9123
+ ignored = true;
9124
+ }
9125
+ if (result.unignored) {
9126
+ ignored = false;
9127
+ }
9128
+ }
9129
+ return ignored;
9130
+ }
8324
9131
  async function createFilelist(options) {
8325
- const stats = await fs5.stat(options.src);
9132
+ const stats = await fs6.stat(options.source);
8326
9133
  if (stats.isFile()) {
8327
- const blobname = normBlobName2(options.src, options.src, options.dst);
9134
+ const blobname = normBlobName2(
9135
+ options.source,
9136
+ options.source,
9137
+ options.destination
9138
+ );
8328
9139
  const blobNameValidation = BlobNameSchema.safeParse(blobname);
8329
9140
  if (!blobNameValidation.success) {
8330
9141
  throw new Error(
8331
- `File ${options.src} as blobname ${blobname} would form an invalid blob name: ${blobNameValidation.error.message}`
9142
+ `File ${options.source} as blobname ${blobname} would form an invalid blob name: ${blobNameValidation.error.message}`
8332
9143
  );
8333
9144
  }
8334
- return [{ filename: options.src, blobname, sizeBytes: stats.size }];
9145
+ return [{ filename: options.source, blobname, sizeBytes: stats.size }];
8335
9146
  }
8336
9147
  if (!options.recursive) {
8337
9148
  throw new Error(
8338
- `${options.src} is a directory. Use --recursive to upload directories.`
9149
+ `${options.source} is a directory. Use --recursive to upload directories.`
8339
9150
  );
8340
9151
  }
9152
+ const sourceRoot = path6.resolve(options.source);
9153
+ const gitignoreMap = await buildGitignoreMap(sourceRoot);
8341
9154
  const fileList = [];
8342
- const result = await glob(path5.join(options.src, "**", "*"), {
8343
- nodir: true
9155
+ const result = await glob("**/*", {
9156
+ cwd: sourceRoot,
9157
+ absolute: true,
9158
+ nodir: true,
9159
+ dot: true
8344
9160
  });
8345
9161
  for await (const file of result) {
8346
- const stats2 = await fs5.stat(file);
8347
- const blobname = normBlobName2(options.src, file, options.dst);
9162
+ if (shouldIgnorePath(gitignoreMap, sourceRoot, file)) {
9163
+ continue;
9164
+ }
9165
+ const stats2 = await fs6.stat(file);
9166
+ if (!stats2.isFile()) {
9167
+ continue;
9168
+ }
9169
+ const blobname = normBlobName2(sourceRoot, file, options.destination);
8348
9170
  const blobNameValidation = BlobNameSchema.safeParse(blobname);
8349
9171
  if (!blobNameValidation.success) {
8350
9172
  throw new Error(
@@ -8360,7 +9182,7 @@ async function createFilelist(options) {
8360
9182
  return fileList;
8361
9183
  }
8362
9184
  function uploadCommand(program) {
8363
- program.command("upload <src> <dst>").description("Upload a file or directory to the shelby RPC in the config.").requiredOption(
9185
+ const uploadCmd = program.command("upload").description("Upload a file or directory to the shelby RPC in the config.").argument("[source]", "Source file or directory path").argument("[destination]", "Destination blob name").requiredOption(
8364
9186
  "-e, --expiration <datetime>",
8365
9187
  'Expiration date/time (required). Examples: "tomorrow", "in 2 days", "next Friday", "2025-12-31", UNIX timestamp'
8366
9188
  ).option("-r, --recursive", "If uploading a directory, recurse").option(
@@ -8369,205 +9191,227 @@ function uploadCommand(program) {
8369
9191
  ).option(
8370
9192
  "--output-commitments <filename>",
8371
9193
  "Location to store commitments computed as as part of the upload"
8372
- ).action(async (src, dst, options) => {
8373
- let validatedOptions;
8374
- try {
8375
- validatedOptions = await UploadOptionsSchema.parseAsync({
8376
- ...options,
8377
- src,
8378
- dst
8379
- });
8380
- } catch (error) {
8381
- const { displayMessage } = handleError(error);
8382
- console.error(`\u274C ${displayMessage}`);
8383
- process.exit(1);
8384
- }
8385
- const configPath = program.opts().configFile;
8386
- let config;
8387
- try {
8388
- config = loadConfig(configPath);
8389
- } catch (error) {
8390
- console.error(`Error: ${error.message}`);
8391
- process.exit(1);
8392
- }
8393
- const start = performance.now();
8394
- const filelist = await createFilelist(validatedOptions);
8395
- const timeToCreateFilelist = ((performance.now() - start) / 1e3).toFixed(
8396
- 5
8397
- );
8398
- console.log("\n\u{1F680} Upload Summary");
8399
- console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
8400
- if (filelist.length === 1) {
8401
- console.log(`\u{1F4E6} File: ${filelist[0].filename}`);
8402
- console.log(`\u{1F4C1} Blob Name: ${filelist[0].blobname}`);
8403
- } else {
8404
- console.log(`\u{1F4E6} Files: ${filelist.length} files`);
9194
+ ).configureOutput({
9195
+ writeErr: (_str) => {
8405
9196
  }
8406
- console.log("");
8407
- console.log(
8408
- `\u{1F9EE} Filelist created (${filelist.length} ${filelist.length === 1 ? "entry" : "entries"})`
8409
- );
8410
- console.log(`\u23F1\uFE0F Took: ${timeToCreateFilelist}s`);
8411
- if (validatedOptions.assumeYes) {
8412
- console.log("\u2699\uFE0F Flag: --assume-yes (auto-confirmed)");
8413
- }
8414
- if (!validatedOptions.assumeYes) {
8415
- const shouldContinue = await new Promise((resolve2) => {
8416
- const { unmount } = render4(
8417
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
8418
- /* @__PURE__ */ jsx13(Text7, { children: "Continue?" }),
8419
- /* @__PURE__ */ jsx13(
8420
- SelectInput4,
8421
- {
8422
- items: [
8423
- { label: "Yes", value: true },
8424
- { label: "No", value: false }
8425
- ],
8426
- onSelect: (item) => {
8427
- unmount();
8428
- resolve2(item.value);
8429
- }
8430
- }
8431
- )
8432
- ] })
8433
- );
8434
- });
8435
- if (!shouldContinue) {
8436
- console.log("Upload cancelled.");
8437
- process.exit(0);
8438
- }
8439
- }
8440
- const shelbyConfig = getCurrentShelbyConfig(config, {
8441
- context: program.opts().context
8442
- });
8443
- const activeAccount = getCurrentAccount(
8444
- config,
8445
- program.opts().account
8446
- ).account;
8447
- const aptos = new Aptos5(new AptosConfig4(shelbyConfig.aptos));
8448
- const shelbyClient = new ShelbyNodeClient(shelbyConfig);
8449
- const handleSigint = () => {
8450
- spinner.fail("Quitting due to ctrl-C / SIGINT...");
8451
- process.exit(1);
8452
- };
8453
- process.removeAllListeners("SIGINT");
8454
- process.on("SIGINT", handleSigint);
8455
- const expireUsec = validatedOptions.expiration.getTime() * 1e3;
8456
- const expirationDate = new Date(expireUsec / 1e3);
8457
- const formattedExpiration = expirationDate.toLocaleDateString("en-US", {
8458
- year: "numeric",
8459
- month: "short",
8460
- day: "numeric",
8461
- hour: "numeric",
8462
- minute: "2-digit",
8463
- second: "2-digit",
8464
- hour12: true
8465
- });
8466
- console.log("");
8467
- console.log(`\u{1F552} Expires: ${formattedExpiration}`);
8468
- const spinner = ora2({
8469
- text: "Uploading...",
8470
- discardStdin: false
8471
- }).start();
8472
- const startTime = performance.now();
8473
- let totalSize = 0;
8474
- let amountUploaded = 0;
8475
- const outputCommitments = {};
8476
- let firstTransactionHash;
8477
- const formatProgressPercent = () => (100 * (amountUploaded / totalSize)).toFixed(2);
8478
- for (const entry of filelist) {
8479
- totalSize += entry.sizeBytes;
8480
- }
8481
- let hasUploadedBlob = false;
8482
- for (const entry of filelist) {
8483
- const fileName = path5.basename(entry.filename);
8484
- spinner.text = `\u{1F4D6} Reading ${fileName}... (${formatProgressPercent()}%)`;
9197
+ });
9198
+ uploadCmd.exitOverride(
9199
+ createExitOverrideHandler(
9200
+ "upload",
9201
+ "<source> <destination>",
9202
+ "-e, --expiration <datetime>",
9203
+ 'shelby upload ./file.txt myblob -e "in 2 days"\n shelby upload ./my-folder/ my-folder/ -r -e tomorrow',
9204
+ "Missing source, destination, and expiration"
9205
+ )
9206
+ );
9207
+ uploadCmd.action(
9208
+ async (source, destination, options) => {
9209
+ let validatedOptions;
8485
9210
  try {
8486
- const blobData = await fs5.readFile(entry.filename);
8487
- if (blobData.length !== entry.sizeBytes) {
8488
- throw new Error(
8489
- `Size of file ${entry.filename} changed after initial scan. Original size was ${entry.sizeBytes} but it is now ${blobData.length}`
8490
- );
8491
- }
8492
- spinner.text = `\u{1F517} Checking if blob exists... (${formatProgressPercent()}%)`;
8493
- const existingBlobMetadata = await shelbyClient.coordination.getBlobMetadata({
8494
- account: activeAccount.accountAddress,
8495
- name: entry.blobname
9211
+ validatedOptions = await UploadOptionsSchema.parseAsync({
9212
+ ...options,
9213
+ source,
9214
+ destination
8496
9215
  });
8497
- if (existingBlobMetadata) {
8498
- spinner.fail(
8499
- `Blob '${entry.blobname}' already exists. Please use a different name or delete the existing blob first.`
8500
- );
8501
- process.exit(1);
8502
- }
8503
- spinner.text = `\u{1F517} Generating commitments for ${fileName}... (${formatProgressPercent()}%)`;
8504
- const provider = await getErasureCodingProvider();
8505
- const blobCommitments = await generateCommitments(provider, blobData);
8506
- if (validatedOptions.outputCommitments) {
8507
- outputCommitments[entry.filename] = blobCommitments;
8508
- }
8509
- spinner.text = `\u{1F517} Registering ${fileName} on L1... (${formatProgressPercent()}%)`;
8510
- const { transaction: pendingRegisterBlobTransaction } = await shelbyClient.coordination.registerBlob({
8511
- account: activeAccount,
8512
- blobName: entry.blobname,
8513
- blobMerkleRoot: blobCommitments.blob_merkle_root,
8514
- size: blobData.length,
8515
- expirationMicros: validatedOptions.expiration.getTime() * 1e3
8516
- });
8517
- const registerTransactionHash = pendingRegisterBlobTransaction.hash;
8518
- if (!firstTransactionHash) {
8519
- firstTransactionHash = registerTransactionHash;
9216
+ } catch (error) {
9217
+ if (error instanceof z16.ZodError) {
9218
+ const firstIssue = error.issues[0];
9219
+ if (firstIssue) {
9220
+ console.log(firstIssue.message);
9221
+ } else {
9222
+ console.error("\u26A0\uFE0F Invalid options provided");
9223
+ }
9224
+ } else {
9225
+ const { displayMessage } = handleError(error);
9226
+ console.error(`\u26A0\uFE0F ${displayMessage}`);
8520
9227
  }
8521
- await aptos.waitForTransaction({
8522
- transactionHash: pendingRegisterBlobTransaction.hash
8523
- });
8524
- spinner.text = `\u{1F4E4} Uploading ${fileName} to Shelby RPC... (${formatProgressPercent()}%)`;
8525
- await shelbyClient.rpc.putBlob({
8526
- account: activeAccount.accountAddress,
8527
- blobName: entry.blobname,
8528
- blobData
8529
- });
8530
- hasUploadedBlob = true;
8531
- amountUploaded += blobData.length;
9228
+ process.exit(1);
9229
+ }
9230
+ const configPath = program.opts().configFile;
9231
+ let config;
9232
+ try {
9233
+ config = loadConfig(configPath);
8532
9234
  } catch (error) {
8533
- const { displayMessage } = handleError(error);
8534
- spinner.fail(displayMessage);
9235
+ console.error(`Error: ${error.message}`);
8535
9236
  process.exit(1);
8536
9237
  }
8537
- }
8538
- if (validatedOptions.outputCommitments) {
8539
- await fs5.writeFile(
8540
- validatedOptions.outputCommitments,
8541
- JSON.stringify(outputCommitments)
9238
+ const start = performance.now();
9239
+ const filelist = await createFilelist(validatedOptions);
9240
+ const timeToCreateFilelist = ((performance.now() - start) / 1e3).toFixed(
9241
+ 5
8542
9242
  );
8543
- }
8544
- if (hasUploadedBlob) {
9243
+ console.log("\n\u{1F680} Upload Summary");
9244
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
9245
+ if (filelist.length === 1) {
9246
+ console.log(`\u{1F4E6} File: ${filelist[0].filename}`);
9247
+ console.log(`\u{1F4C1} Blob Name: ${filelist[0].blobname}`);
9248
+ } else {
9249
+ console.log(`\u{1F4E6} Files: ${filelist.length} files`);
9250
+ }
9251
+ console.log("");
9252
+ console.log(
9253
+ `\u{1F9EE} Filelist created (${filelist.length} ${filelist.length === 1 ? "entry" : "entries"})`
9254
+ );
9255
+ console.log(`\u23F1\uFE0F Took: ${timeToCreateFilelist}s`);
9256
+ if (validatedOptions.assumeYes) {
9257
+ console.log("\u2699\uFE0F Flag: --assume-yes (auto-confirmed)");
9258
+ }
9259
+ if (!validatedOptions.assumeYes) {
9260
+ const shouldContinue = await new Promise((resolve3) => {
9261
+ const { unmount } = render4(
9262
+ /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
9263
+ /* @__PURE__ */ jsx13(Text7, { children: "Continue?" }),
9264
+ /* @__PURE__ */ jsx13(
9265
+ SelectInput4,
9266
+ {
9267
+ items: [
9268
+ { label: "Yes", value: true },
9269
+ { label: "No", value: false }
9270
+ ],
9271
+ onSelect: (item) => {
9272
+ unmount();
9273
+ resolve3(item.value);
9274
+ }
9275
+ }
9276
+ )
9277
+ ] })
9278
+ );
9279
+ });
9280
+ if (!shouldContinue) {
9281
+ console.log("Upload cancelled.");
9282
+ process.exit(0);
9283
+ }
9284
+ }
9285
+ const shelbyConfig = getCurrentShelbyConfig(config, {
9286
+ context: program.opts().context
9287
+ });
9288
+ const activeAccount = getCurrentAccount(
9289
+ config,
9290
+ program.opts().account
9291
+ ).account;
9292
+ const aptos = new Aptos5(new AptosConfig4(shelbyConfig.aptos));
9293
+ const shelbyClient = new ShelbyNodeClient(shelbyConfig);
9294
+ const handleSigint = () => {
9295
+ spinner.fail("Quitting due to ctrl-C / SIGINT...");
9296
+ process.exit(1);
9297
+ };
9298
+ process.removeAllListeners("SIGINT");
9299
+ process.on("SIGINT", handleSigint);
9300
+ const expireUsec = validatedOptions.expiration.getTime() * 1e3;
9301
+ const expirationDate = new Date(expireUsec / 1e3);
9302
+ const formattedExpiration = expirationDate.toLocaleDateString("en-US", {
9303
+ year: "numeric",
9304
+ month: "short",
9305
+ day: "numeric",
9306
+ hour: "numeric",
9307
+ minute: "2-digit",
9308
+ second: "2-digit",
9309
+ hour12: true
9310
+ });
9311
+ console.log("");
9312
+ console.log(`\u{1F552} Expires: ${formattedExpiration}`);
9313
+ const spinner = ora2({
9314
+ text: "Uploading...",
9315
+ discardStdin: false
9316
+ }).start();
9317
+ const startTime = performance.now();
9318
+ let totalSize = 0;
9319
+ let amountUploaded = 0;
9320
+ const outputCommitments = {};
9321
+ let firstTransactionHash;
9322
+ for (const entry of filelist) {
9323
+ totalSize += entry.sizeBytes;
9324
+ }
9325
+ const isSingleFile = filelist.length === 1;
9326
+ const formatProgressPercent = () => totalSize > 0 ? (100 * (amountUploaded / totalSize)).toFixed(2) : "0.00";
9327
+ let filesProcessed = 0;
9328
+ for (const entry of filelist) {
9329
+ const fileName = path6.basename(entry.filename);
9330
+ const fileProgress = isSingleFile ? `(${formatProgressPercent()}%)` : `(${filesProcessed}/${filelist.length} files, ${formatProgressPercent()}%)`;
9331
+ spinner.text = `\u{1F4D6} Reading ${fileName}... ${fileProgress}`;
9332
+ try {
9333
+ const blobData = await fs6.readFile(entry.filename);
9334
+ if (blobData.length !== entry.sizeBytes) {
9335
+ throw new Error(
9336
+ `Size of file ${entry.filename} changed after initial scan. Original size was ${entry.sizeBytes} but it is now ${blobData.length}`
9337
+ );
9338
+ }
9339
+ spinner.text = `\u{1F517} Checking if blob exists... ${fileProgress}`;
9340
+ const existingBlobMetadata = await shelbyClient.coordination.getBlobMetadata({
9341
+ account: activeAccount.accountAddress,
9342
+ name: entry.blobname
9343
+ });
9344
+ if (existingBlobMetadata) {
9345
+ spinner.fail(
9346
+ `Blob '${entry.blobname}' already exists. Please use a different name or delete the existing blob first.`
9347
+ );
9348
+ process.exit(1);
9349
+ }
9350
+ spinner.text = `\u{1F517} Generating commitments for ${fileName}... ${fileProgress}`;
9351
+ const provider = await getErasureCodingProvider();
9352
+ const blobCommitments = await generateCommitments(provider, blobData);
9353
+ if (validatedOptions.outputCommitments) {
9354
+ outputCommitments[entry.filename] = blobCommitments;
9355
+ }
9356
+ spinner.text = `\u{1F517} Registering ${fileName} on L1... ${fileProgress}`;
9357
+ const { transaction: pendingRegisterBlobTransaction } = await shelbyClient.coordination.registerBlob({
9358
+ account: activeAccount,
9359
+ blobName: entry.blobname,
9360
+ blobMerkleRoot: blobCommitments.blob_merkle_root,
9361
+ size: blobData.length,
9362
+ expirationMicros: validatedOptions.expiration.getTime() * 1e3
9363
+ });
9364
+ const registerTransactionHash = pendingRegisterBlobTransaction.hash;
9365
+ if (!firstTransactionHash) {
9366
+ firstTransactionHash = registerTransactionHash;
9367
+ }
9368
+ await aptos.waitForTransaction({
9369
+ transactionHash: pendingRegisterBlobTransaction.hash
9370
+ });
9371
+ spinner.text = `\u{1F4E4} Uploading ${fileName} to Shelby RPC... ${fileProgress}`;
9372
+ await shelbyClient.rpc.putBlob({
9373
+ account: activeAccount.accountAddress,
9374
+ blobName: entry.blobname,
9375
+ blobData
9376
+ });
9377
+ amountUploaded += blobData.length;
9378
+ filesProcessed++;
9379
+ } catch (error) {
9380
+ const { displayMessage } = handleError(error);
9381
+ spinner.fail(displayMessage);
9382
+ process.exit(1);
9383
+ }
9384
+ }
9385
+ if (validatedOptions.outputCommitments) {
9386
+ await fs6.writeFile(
9387
+ validatedOptions.outputCommitments,
9388
+ JSON.stringify(outputCommitments)
9389
+ );
9390
+ }
8545
9391
  const elapsedSec = ((performance.now() - startTime) / 1e3).toFixed(2);
8546
9392
  spinner.succeed(`Upload complete \u2014 took ${elapsedSec}s`);
8547
- } else {
8548
- spinner.succeed("Skipped upload, blob has already been uploaded.");
8549
- }
8550
- console.log("");
8551
- if (firstTransactionHash) {
8552
- const explorerUrl = getAptosTransactionExplorerUrl(
9393
+ console.log("");
9394
+ if (firstTransactionHash) {
9395
+ const explorerUrl = getAptosTransactionExplorerUrl(
9396
+ shelbyConfig.network,
9397
+ firstTransactionHash
9398
+ );
9399
+ console.log("\u{1F310} Aptos Explorer:");
9400
+ console.log(` ${explorerUrl}`);
9401
+ console.log("");
9402
+ }
9403
+ const shelbyExplorerUrl = getShelbyAccountExplorerUrl(
8553
9404
  shelbyConfig.network,
8554
- firstTransactionHash
9405
+ activeAccount.accountAddress.toString()
8555
9406
  );
8556
- console.log("\u{1F310} Aptos Explorer:");
8557
- console.log(` ${explorerUrl}`);
9407
+ console.log("\u{1F5C2}\uFE0F Shelby Explorer:");
9408
+ console.log(` ${shelbyExplorerUrl}`);
9409
+ console.log("");
9410
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
9411
+ console.log("\u2728 Done!");
8558
9412
  console.log("");
8559
9413
  }
8560
- const shelbyExplorerUrl = getShelbyAccountExplorerUrl(
8561
- shelbyConfig.network,
8562
- activeAccount.accountAddress.toString()
8563
- );
8564
- console.log("\u{1F5C2}\uFE0F Shelby Explorer:");
8565
- console.log(` ${shelbyExplorerUrl}`);
8566
- console.log("");
8567
- console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
8568
- console.log("\u2728 Done!");
8569
- console.log("");
8570
- });
9414
+ );
8571
9415
  }
8572
9416
 
8573
9417
  // src/cli.tsx
@@ -8608,6 +9452,7 @@ function createProgram() {
8608
9452
 
8609
9453
  // src/entry.ts
8610
9454
  function main() {
9455
+ checkForUpdatesAsync();
8611
9456
  const rawArgs = process.argv.slice(2);
8612
9457
  const normalizedArgs = rawArgs[0] === "--" ? rawArgs.slice(1) : rawArgs;
8613
9458
  createProgram().parse([process.argv[0], process.argv[1], ...normalizedArgs]);