@sparkdotfi/abi-cli 0.2.0-20250808.efecd1d6 → 0.2.0-20250811.13be5bb5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import { NodeContext, NodeRuntime } from '@effect/platform-node';
2
- import { Effect, Layer } from 'effect';
2
+ import { Effect, Layer, Logger } from 'effect';
3
3
  import { configLayer } from './config/Config';
4
4
  import { abiFetcherLayer } from './fetch/AbiFetcher';
5
5
  import { blockchainClientRepositoryLayer } from './fetch/BlockchainClientRepository';
6
6
  import { main } from './main';
7
+ import { AbiCliLogger } from './services/AbiCliLogger';
7
8
  import { progressBarLayer } from './services/ProgressBar';
8
9
  const blockchainClientRepository = Layer.provide(blockchainClientRepositoryLayer, configLayer);
9
10
  const abiFetcher = Layer.provide(abiFetcherLayer, [blockchainClientRepository, configLayer]);
11
+ const logger = Logger.replace(Logger.defaultLogger, AbiCliLogger);
10
12
  const mainDeps = Layer.mergeAll(configLayer, blockchainClientRepository, abiFetcher, NodeContext.layer, progressBarLayer);
11
- main.pipe(Effect.provide(mainDeps), Effect.withSpan('cli'), NodeRuntime.runMain);
13
+ main.pipe(Effect.provide(mainDeps), Effect.provide(logger), Effect.withSpan('cli'), NodeRuntime.runMain({ disablePrettyLogger: true }));
@@ -1 +1 @@
1
- {"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../../src/config/Config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,YAAY,EAAgB,MAAM,UAAU,CAAA;;;;AAErD,qBAAa,gBAAiB,SAAQ,sBAAqC,YAAY,CAAC;CAAG;AAE3F,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;CACtD;;AASD,qBAAa,SAAU,SAAQ,cAAuD;CAAG;AAEzF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC,CAE3F;AAED,eAAO,MAAM,WAAW,8DASmB,CAAA"}
1
+ {"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../../src/config/Config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,YAAY,EAAgB,MAAM,UAAU,CAAA;;;;AAErD,qBAAa,gBAAiB,SAAQ,sBAAqC,YAAY,CAAC;CAAG;AAE3F,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;CACtD;;AASD,qBAAa,SAAU,SAAQ,cAAuD;CAAG;AAEzF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC,CAE3F;AAED,eAAO,MAAM,WAAW,8DAamB,CAAA"}
@@ -15,7 +15,7 @@ export function configLayerFromConfig(cfg) {
15
15
  }
16
16
  export const configLayer = Layer.effect(CliConfig, Effect.gen(function* () {
17
17
  const config = yield* loadRawConfigFromFile;
18
- const decodedConfig = yield* Schema.decodeUnknownEither(configSchema)(config);
18
+ const decodedConfig = yield* Schema.decodeUnknownEither(configSchema, { onExcessProperty: 'error' })(config);
19
19
  yield* Effect.logInfo('Config loaded');
20
20
  return yield* make(decodedConfig);
21
21
  }).pipe(Effect.withSpan('configLayer')));
@@ -1,29 +1,9 @@
1
1
  import { Schema } from 'effect';
2
- declare const addressesSchema: Schema.SchemaClass<{
3
- readonly mainnet?: (`0x${string}` & {
4
- readonly __TAG__: "CheckedAddress";
5
- }) | undefined;
6
- readonly base?: (`0x${string}` & {
7
- readonly __TAG__: "CheckedAddress";
8
- }) | undefined;
9
- readonly gnosis?: (`0x${string}` & {
10
- readonly __TAG__: "CheckedAddress";
11
- }) | undefined;
12
- readonly arbitrum?: (`0x${string}` & {
13
- readonly __TAG__: "CheckedAddress";
14
- }) | undefined;
15
- readonly optimism?: (`0x${string}` & {
16
- readonly __TAG__: "CheckedAddress";
17
- }) | undefined;
18
- readonly worldchain?: (`0x${string}` & {
19
- readonly __TAG__: "CheckedAddress";
20
- }) | undefined;
21
- readonly unichain?: (`0x${string}` & {
22
- readonly __TAG__: "CheckedAddress";
23
- }) | undefined;
24
- }, {
25
- readonly [x: string]: string | undefined;
26
- }, never>;
2
+ declare const addressesSchema: Schema.Record$<typeof Schema.String, Schema.transform<typeof Schema.String, Schema.declare<`0x${string}` & {
3
+ readonly __TAG__: "CheckedAddress";
4
+ }, `0x${string}` & {
5
+ readonly __TAG__: "CheckedAddress";
6
+ }, readonly [], never>>>;
27
7
  export declare const configSchema: Schema.Struct<{
28
8
  out: typeof Schema.String;
29
9
  secrets: Schema.Struct<{
@@ -33,60 +13,24 @@ export declare const configSchema: Schema.Struct<{
33
13
  }>;
34
14
  eoa: Schema.PropertySignature<":", {
35
15
  readonly [x: string]: {
36
- readonly mainnet?: (`0x${string}` & {
16
+ readonly [x: string]: `0x${string}` & {
37
17
  readonly __TAG__: "CheckedAddress";
38
- }) | undefined;
39
- readonly base?: (`0x${string}` & {
40
- readonly __TAG__: "CheckedAddress";
41
- }) | undefined;
42
- readonly gnosis?: (`0x${string}` & {
43
- readonly __TAG__: "CheckedAddress";
44
- }) | undefined;
45
- readonly arbitrum?: (`0x${string}` & {
46
- readonly __TAG__: "CheckedAddress";
47
- }) | undefined;
48
- readonly optimism?: (`0x${string}` & {
49
- readonly __TAG__: "CheckedAddress";
50
- }) | undefined;
51
- readonly worldchain?: (`0x${string}` & {
52
- readonly __TAG__: "CheckedAddress";
53
- }) | undefined;
54
- readonly unichain?: (`0x${string}` & {
55
- readonly __TAG__: "CheckedAddress";
56
- }) | undefined;
18
+ };
57
19
  };
58
20
  }, never, "?:", {
59
21
  readonly [x: string]: {
60
- readonly [x: string]: string | undefined;
22
+ readonly [x: string]: string;
61
23
  };
62
24
  }, false, never>;
63
25
  contracts: Schema.PropertySignature<":", {
64
26
  readonly [x: string]: {
65
- readonly mainnet?: (`0x${string}` & {
66
- readonly __TAG__: "CheckedAddress";
67
- }) | undefined;
68
- readonly base?: (`0x${string}` & {
69
- readonly __TAG__: "CheckedAddress";
70
- }) | undefined;
71
- readonly gnosis?: (`0x${string}` & {
72
- readonly __TAG__: "CheckedAddress";
73
- }) | undefined;
74
- readonly arbitrum?: (`0x${string}` & {
27
+ readonly [x: string]: `0x${string}` & {
75
28
  readonly __TAG__: "CheckedAddress";
76
- }) | undefined;
77
- readonly optimism?: (`0x${string}` & {
78
- readonly __TAG__: "CheckedAddress";
79
- }) | undefined;
80
- readonly worldchain?: (`0x${string}` & {
81
- readonly __TAG__: "CheckedAddress";
82
- }) | undefined;
83
- readonly unichain?: (`0x${string}` & {
84
- readonly __TAG__: "CheckedAddress";
85
- }) | undefined;
29
+ };
86
30
  };
87
31
  }, never, "?:", {
88
32
  readonly [x: string]: {
89
- readonly [x: string]: string | undefined;
33
+ readonly [x: string]: string;
90
34
  };
91
35
  }, false, never>;
92
36
  interfaces: Schema.PropertySignature<":", {
@@ -94,33 +38,15 @@ export declare const configSchema: Schema.Struct<{
94
38
  readonly methods?: readonly string[] | undefined;
95
39
  readonly events?: readonly string[] | undefined;
96
40
  readonly addresses: {
97
- readonly mainnet?: (`0x${string}` & {
98
- readonly __TAG__: "CheckedAddress";
99
- }) | undefined;
100
- readonly base?: (`0x${string}` & {
101
- readonly __TAG__: "CheckedAddress";
102
- }) | undefined;
103
- readonly gnosis?: (`0x${string}` & {
104
- readonly __TAG__: "CheckedAddress";
105
- }) | undefined;
106
- readonly arbitrum?: (`0x${string}` & {
107
- readonly __TAG__: "CheckedAddress";
108
- }) | undefined;
109
- readonly optimism?: (`0x${string}` & {
110
- readonly __TAG__: "CheckedAddress";
111
- }) | undefined;
112
- readonly worldchain?: (`0x${string}` & {
113
- readonly __TAG__: "CheckedAddress";
114
- }) | undefined;
115
- readonly unichain?: (`0x${string}` & {
41
+ readonly [x: string]: `0x${string}` & {
116
42
  readonly __TAG__: "CheckedAddress";
117
- }) | undefined;
43
+ };
118
44
  };
119
45
  };
120
46
  }, never, "?:", {
121
47
  readonly [x: string]: {
122
48
  readonly addresses: {
123
- readonly [x: string]: string | undefined;
49
+ readonly [x: string]: string;
124
50
  };
125
51
  readonly methods?: readonly string[] | undefined;
126
52
  readonly events?: readonly string[] | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,MAAM,EAAE,MAAM,QAAQ,CAAA;AAWvC,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;SAOpB,CAAA;AAgBD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBvB,CAAA;AAGF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,YAAY,CAAC,CAAA;AACrE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,YAAY,CAAC,CAAA;AAElE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,eAAe,CAAC,CAAA;AAExE,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,MAAM,EAAE,MAAM,QAAQ,CAAA;AAWvC,QAAA,MAAM,eAAe;;;;wBAKnB,CAAA;AAgBF,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBvB,CAAA;AAGF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,YAAY,CAAC,CAAA;AACrE,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,YAAY,CAAC,CAAA;AAElE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,eAAe,CAAC,CAAA;AAExE,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA"}
@@ -1,16 +1,16 @@
1
- import { CheckedAddress, allSparkDomains } from '@sparkdotfi/common-universal';
1
+ import { CheckedAddress } from '@sparkdotfi/common-universal';
2
2
  import { Option, Schema } from 'effect';
3
3
  const CheckedAddressSchema = Schema.declare((input) => input === CheckedAddress(input));
4
4
  const StringToCheckedAddress = Schema.transform(Schema.String, CheckedAddressSchema, {
5
5
  decode: (fromA) => CheckedAddress(fromA),
6
6
  encode: (address) => address.toString(),
7
7
  });
8
- const addressesSchema = Schema.partial(Schema.Record({
9
- key: Schema.String.pipe(Schema.filter(isSparkDomain)).annotations({ message: () => 'Must be valid spark domain' }),
8
+ const addressesSchema = Schema.Record({
9
+ key: Schema.String,
10
10
  value: StringToCheckedAddress.annotations({
11
11
  message: () => 'Must be valid address',
12
12
  }),
13
- }));
13
+ });
14
14
  const interfaceSchema = Schema.Record({
15
15
  key: Schema.String,
16
16
  value: Schema.Struct({
@@ -32,17 +32,14 @@ export const configSchema = Schema.Struct({
32
32
  }),
33
33
  eoa: Schema.optionalToRequired(contractsMapSchema, contractsMapSchema, {
34
34
  decode: (o) => (Option.isNone(o) ? {} : o.value),
35
- encode: (ti) => Option.some(ti),
35
+ encode: (_) => Option.none(),
36
36
  }),
37
37
  contracts: Schema.optionalToRequired(contractsMapSchema, contractsMapSchema, {
38
38
  decode: (o) => (Option.isNone(o) ? {} : o.value),
39
- encode: (ti) => Option.some(ti),
39
+ encode: (_) => Option.none(),
40
40
  }),
41
41
  interfaces: Schema.optionalToRequired(interfaceSchema, interfaceSchema, {
42
42
  decode: (o) => (Option.isNone(o) ? {} : o.value),
43
- encode: (ti) => Option.some(ti),
43
+ encode: (_) => Option.none(),
44
44
  }),
45
45
  });
46
- function isSparkDomain(data) {
47
- return allSparkDomains.includes(data);
48
- }
@@ -1 +1 @@
1
- {"version":3,"file":"AbiFetcher.d.ts","sourceRoot":"","sources":["../../src/fetch/AbiFetcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAmB,MAAM,8BAA8B,CAAA;AAC9E,OAAO,EAAE,OAAO,EAAkB,MAAM,EAAE,KAAK,EAAY,MAAM,QAAQ,CAAA;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;;AAExG,qBAAa,UAAW,SAAQ,eAA0D;CAAG;AAE7F,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,CACjB,QAAQ,EAAE,aAAa,KACpB,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,eAAe,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,6BAA6B,CAAC,CAAA;CAC/G;;;;AAED,qBAAa,gBAAiB,SAAQ,sBAAqC;IACzE,OAAO,EAAE,cAAc,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAC;CAAG;;;;AACL,qBAAa,eAAgB,SAAQ,qBAAoC,YAAY,CAAC;CAAG;AAyBzF,eAAO,MAAM,eAAe,wEAAiC,CAAA"}
1
+ {"version":3,"file":"AbiFetcher.d.ts","sourceRoot":"","sources":["../../src/fetch/AbiFetcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAiC,MAAM,8BAA8B,CAAA;AAC5F,OAAO,EAAE,OAAO,EAAkB,MAAM,EAAE,KAAK,EAAY,MAAM,QAAQ,CAAA;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;;AAExG,qBAAa,UAAW,SAAQ,eAA0D;CAAG;AAE7F,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,CACjB,QAAQ,EAAE,aAAa,KACpB,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,eAAe,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,6BAA6B,CAAC,CAAA;CAC/G;;;;AAED,qBAAa,gBAAiB,SAAQ,sBAAqC;IACzE,OAAO,EAAE,cAAc,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAC;CAAG;;;;AACL,qBAAa,eAAgB,SAAQ,qBAAoC,YAAY,CAAC;CAAG;AAkCzF,eAAO,MAAM,eAAe,wEAAiC,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { whatsabi } from '@shazow/whatsabi';
2
- import { domainToChainId } from '@sparkdotfi/common-universal';
2
+ import { chainIdToDomain } from '@sparkdotfi/common-universal';
3
3
  import { Context, Data, Duration, Effect, Layer, Schedule } from 'effect';
4
4
  import { CliConfig } from '../config/Config';
5
5
  import { BlockchainClientRepository } from './BlockchainClientRepository';
@@ -13,15 +13,21 @@ const make = Effect.gen(function* () {
13
13
  const blockchainClientRepository = yield* BlockchainClientRepository;
14
14
  const config = yield* (yield* CliConfig).getConfig();
15
15
  const fetchAbi = (contract) => Effect.gen(function* () {
16
- const { address, domain } = contract;
16
+ const { address, chainId } = contract;
17
+ const domain = chainIdToDomain[chainId];
18
+ if (!domain) {
19
+ return yield* Effect.fail(new AbiFetcherError({
20
+ message: `ChainId ${chainId} not supported`,
21
+ }));
22
+ }
17
23
  const client = yield* blockchainClientRepository.getClientForDomain(domain);
18
24
  return yield* whatsAbiFetchEffect({
19
25
  address,
20
- chainId: domainToChainId[domain],
26
+ chainId: Number(chainId),
21
27
  etherscanApiKey: config.secrets.etherscanApiKey,
22
28
  client,
23
29
  });
24
- });
30
+ }).pipe(Effect.withSpan('fetchAbi'));
25
31
  return {
26
32
  fetchAbi,
27
33
  };
@@ -51,7 +57,7 @@ const whatsAbiFetchEffect = (args) => {
51
57
  message: 'WhatsABI failure',
52
58
  });
53
59
  },
54
- }).pipe(Effect.timeout('10 seconds'), Effect.retry(Schedule.intersect(Schedule.exponential(Duration.millis(250), 1.5), Schedule.recurs(3))), Effect.andThen((data) => {
60
+ }).pipe(Effect.timeout('10 seconds'), Effect.retry(Schedule.intersect(Schedule.exponential(Duration.millis(250), 1.5), Schedule.recurs(5))), Effect.andThen((data) => {
55
61
  if (data.abi.length === 0) {
56
62
  return Effect.fail(new AbiNotFoundError({ address, chainId }));
57
63
  }
@@ -59,5 +65,5 @@ const whatsAbiFetchEffect = (args) => {
59
65
  return Effect.fail(new AbiNotFoundError({ address, chainId }));
60
66
  }
61
67
  return Effect.succeed(data.abi);
62
- }));
68
+ }), Effect.withSpan('whatsAbiFetchEffect'));
63
69
  };
@@ -2,7 +2,7 @@ import { Effect } from 'effect';
2
2
  import { CliConfig } from '../config/Config';
3
3
  import { ProgressBar } from '../services/ProgressBar';
4
4
  import { AbiFetcher } from './AbiFetcher';
5
- export declare const fetchAbis: Effect.Effect<Partial<Record<"mainnet" | "base" | "gnosis" | "arbitrum" | "optimism" | "worldchain" | "unichain", Record<`0x${string}` & {
5
+ export declare const fetchAbis: Effect.Effect<Partial<Record<string, Record<`0x${string}` & {
6
6
  readonly __TAG__: "CheckedAddress";
7
7
  }, import("../types").ContractMetadata>>>, import("./BlockchainClientRepository").BlockchainClientNotFoundError | import("./AbiFetcher").AbiFetcherError | import("./AbiFetcher").AbiNotFoundError | import("effect/Cause").TimeoutException | import("../services/ProgressBar").ProgressBarError, CliConfig | AbiFetcher | ProgressBar>;
8
8
  //# sourceMappingURL=fetchAbis.d.ts.map
@@ -17,22 +17,30 @@ export const fetchAbis = Effect.gen(function* () {
17
17
  }).pipe(Effect.withSpan('fetchAbis'));
18
18
  function getContractsToFetch(config) {
19
19
  const contractsPart = entries(config.contracts).flatMap(([name, chainAddresses]) => {
20
- return entries(chainAddresses).map(([domain, address]) => ({ domain, address, name }));
20
+ return entries(chainAddresses).map(([chainId, address]) => ({
21
+ chainId,
22
+ address,
23
+ name,
24
+ }));
21
25
  });
22
26
  const interfacesPart = entries(config.interfaces || {}).flatMap(([name, interfaceConfig]) => {
23
- return entries(interfaceConfig.addresses).map(([domain, address]) => ({ domain, address, name }));
27
+ return entries(interfaceConfig.addresses).map(([chainId, address]) => ({
28
+ chainId,
29
+ address,
30
+ name,
31
+ }));
24
32
  });
25
- return uniqueBy(contractsPart.concat(interfacesPart), (c) => `${c.domain}-${c.address}`);
33
+ return uniqueBy(contractsPart.concat(interfacesPart), (c) => `${c.chainId}-${c.address}`);
26
34
  }
27
35
  // @todo this should be possible to replace with nested usage of remeda's groupBy
28
36
  function getMetadataStore(downloadedAbis) {
29
37
  return downloadedAbis.reduce((acc, data) => {
30
- const domain = data.contract.domain;
38
+ const chainId = data.contract.chainId;
31
39
  const address = data.contract.address;
32
- if (!acc[domain]) {
33
- acc[domain] = {};
40
+ if (!acc[chainId]) {
41
+ acc[chainId] = {};
34
42
  }
35
- acc[domain][address] = { abi: data.abi };
43
+ acc[chainId][address] = { abi: data.abi };
36
44
  return acc;
37
45
  }, {});
38
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/generate/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAO,qBAAqB,EAAa,yBAAyB,EAAsB,MAAM,UAAU,CAAA;AAI/G,eAAO,MAAM,QAAQ,kBAAmB,qBAAqB,UAAU,YAAY,yIAWL,CAAA;AAE9E;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC,CAM/E;AAiBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,CAE1E"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/generate/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAO,qBAAqB,EAAa,yBAAyB,EAAsB,MAAM,UAAU,CAAA;AAI/G,eAAO,MAAM,QAAQ,kBAAmB,qBAAqB,UAAU,YAAY,yIAUL,CAAA;AAE9E;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC,CAM/E;AAiBD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,CAE1E"}
@@ -4,10 +4,9 @@ import { entries, fromEntries } from 'remeda';
4
4
  import { preprocess } from './dataProcessing';
5
5
  import { format } from './formatOutput';
6
6
  export const generate = (metadataStore, config) => Effect.gen(function* () {
7
- yield* Effect.logInfo('Validating ...');
8
7
  const fs = yield* FileSystem.FileSystem;
9
8
  const data = preprocess(metadataStore, config);
10
- yield* Effect.logInfo('Writing ...');
9
+ yield* Effect.logInfo(`Writing to "${config.out}"`);
11
10
  const module = yield* Effect.tryPromise(() => generateModule(data));
12
11
  yield* fs.writeFileString(config.out, module);
13
12
  }).pipe(Effect.withSpan('generate'));
@@ -33,7 +32,7 @@ function contractSection(data) {
33
32
  `;
34
33
  }
35
34
  export function getOrderedAddresses(data) {
36
- return fromEntries(entries(data).sort(([a], [b]) => a.localeCompare(b)));
35
+ return fromEntries(entries(data).sort(([a], [b]) => Number(a) - Number(b)));
37
36
  }
38
37
  function header(name, type) {
39
38
  return `
@@ -0,0 +1,3 @@
1
+ import { Logger } from 'effect';
2
+ export declare const AbiCliLogger: Logger.Logger<unknown, void>;
3
+ //# sourceMappingURL=AbiCliLogger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AbiCliLogger.d.ts","sourceRoot":"","sources":["../../src/services/AbiCliLogger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,eAAO,MAAM,YAAY,8BAiBvB,CAAA"}
@@ -0,0 +1,18 @@
1
+ import { Logger } from 'effect';
2
+ export const AbiCliLogger = Logger.make(({ message, logLevel }) => {
3
+ const logLevelLabel = logLevel.label;
4
+ switch (logLevelLabel) {
5
+ case 'FATAL':
6
+ case 'ERROR':
7
+ return globalThis.console.error(`${message}`);
8
+ case 'WARN':
9
+ return globalThis.console.warn(`${message}`);
10
+ case 'INFO':
11
+ return globalThis.console.info(`${message}`);
12
+ case 'DEBUG':
13
+ case 'TRACE':
14
+ return globalThis.console.debug(`${message}`);
15
+ default:
16
+ globalThis.console.info(`${message}`);
17
+ }
18
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"ProgressBar.d.ts","sourceRoot":"","sources":["../../src/services/ProgressBar.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;;;;AAExC,qBAAa,gBAAiB,SAAQ,sBAAqC,YAAY,CAAC;CAAG;AAE3F,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAA;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAA;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAA;CAC9D;;AA4BD,qBAAa,WAAY,SAAQ,gBAA6D;CAAG;AAEjG,eAAO,MAAM,gBAAgB,wCAAoC,CAAA;AASjE,eAAO,MAAM,oBAAoB,wCAAwC,CAAA"}
1
+ {"version":3,"file":"ProgressBar.d.ts","sourceRoot":"","sources":["../../src/services/ProgressBar.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;;;;AAExC,qBAAa,gBAAiB,SAAQ,sBAAqC,YAAY,CAAC;CAAG;AAE3F,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAA;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAA;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAA;CAC9D;;AAiCD,qBAAa,WAAY,SAAQ,gBAA6D;CAAG;AAEjG,eAAO,MAAM,gBAAgB,wCAAoC,CAAA;AASjE,eAAO,MAAM,oBAAoB,wCAAwC,CAAA"}
@@ -3,7 +3,9 @@ import { Context, Data, Effect, Layer } from 'effect';
3
3
  export class ProgressBarError extends Data.TaggedError('ProgressBarError') {
4
4
  }
5
5
  const effect = Effect.gen(function* () {
6
- const bar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
6
+ const bar = new cliProgress.SingleBar({
7
+ clearOnComplete: true,
8
+ }, cliProgress.Presets.shades_classic);
7
9
  const create = (total) => Effect.try({
8
10
  try: () => bar.start(total, 0),
9
11
  catch: (error) => new ProgressBarError({ message: 'Failed to create progress bar', cause: error }),
package/dist/types.d.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import { whatsabi } from '@shazow/whatsabi';
2
- import { CheckedAddress, SparkDomain } from '@sparkdotfi/common-universal';
2
+ import { CheckedAddress } from '@sparkdotfi/common-universal';
3
3
  import { AddressesConfig } from './config/schema';
4
4
  export type Abi = whatsabi.abi.ABI;
5
5
  export interface ContractIndex {
6
6
  address: CheckedAddress;
7
- domain: SparkDomain;
7
+ chainId: string;
8
8
  }
9
9
  export interface ContractMetadata {
10
10
  abi: Abi;
11
11
  }
12
- export type ContractMetadataStore = Partial<Record<SparkDomain, Record<CheckedAddress, ContractMetadata>>>;
12
+ export type ContractMetadataStore = Partial<Record<string, Record<CheckedAddress, ContractMetadata>>>;
13
13
  export interface PreprocessedEntity {
14
14
  name: string;
15
15
  abi: Abi;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAA;AAElC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,cAAc,CAAA;IACvB,MAAM,EAAE,WAAW,CAAA;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,GAAG,CAAA;CACT;AAED,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;AAE1G,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,GAAG,CAAA;IACR,SAAS,EAAE,eAAe,CAAA;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,eAAe,CAAA;CAC3B;AACD,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,kBAAkB,EAAE,CAAA;IAC/B,UAAU,EAAE,kBAAkB,EAAE,CAAA;IAChC,IAAI,EAAE,SAAS,EAAE,CAAA;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAA;AAElC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,cAAc,CAAA;IACvB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,GAAG,CAAA;CACT;AAED,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;AAErG,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,GAAG,CAAA;IACR,SAAS,EAAE,eAAe,CAAA;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,eAAe,CAAA;CAC3B;AACD,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,kBAAkB,EAAE,CAAA;IAC/B,UAAU,EAAE,kBAAkB,EAAE,CAAA;IAChC,IAAI,EAAE,SAAS,EAAE,CAAA;CAClB"}
@@ -2,6 +2,14 @@ import { Effect } from 'effect';
2
2
  import { GlobalConfig } from '../config/schema';
3
3
  import { ContractMetadataStore } from '../types';
4
4
  export declare const verify: (store: ContractMetadataStore, config: GlobalConfig) => Effect.Effect<void, ValidationError, never>;
5
+ /**
6
+ * @internal
7
+ */
8
+ export declare const hasAddresses: (config: GlobalConfig) => Effect.Effect<undefined, ValidationError, never>;
9
+ /**
10
+ * @internal
11
+ */
12
+ export declare const hasMatchingAbis: (config: GlobalConfig, store: ContractMetadataStore) => Effect.Effect<undefined, ValidationError, never>;
5
13
  declare const ValidationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
6
14
  readonly _tag: "ValidationError";
7
15
  } & Readonly<A>;
@@ -1 +1 @@
1
- {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/verify/verify.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAA;AAErC,OAAO,EAAmB,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAEhD,eAAO,MAAM,MAAM,UAAW,qBAAqB,UAAU,YAAY,gDAIrE,CAAA;;;;AAwCJ,qBAAa,eAAgB,SAAQ,qBAAoC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;CAAG"}
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/verify/verify.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAA;AAErC,OAAO,EAAmB,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAEhD,eAAO,MAAM,MAAM,UAAW,qBAAqB,UAAU,YAAY,gDAMrE,CAAA;AAEJ;;GAEG;AACH,eAAO,MAAM,YAAY,WAAY,YAAY,qDAcP,CAAA;AAE1C;;GAEG;AACH,eAAO,MAAM,eAAe,WAAY,YAAY,SAAS,qBAAqB,qDAarC,CAAA;;;;AAa7C,qBAAa,eAAgB,SAAQ,qBAAoC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;CAAG"}
@@ -2,25 +2,34 @@ import { assert } from '@sparkdotfi/common-universal';
2
2
  import { Data, Effect } from 'effect';
3
3
  import { entries } from 'remeda';
4
4
  export const verify = (store, config) => Effect.gen(function* () {
5
+ yield* Effect.logInfo('Validating');
5
6
  yield* hasAddresses(config);
6
7
  yield* hasMatchingAbis(config, store);
7
8
  });
8
- const hasAddresses = (config) => Effect.gen(function* () {
9
+ /**
10
+ * @internal
11
+ */
12
+ export const hasAddresses = (config) => Effect.gen(function* () {
9
13
  const contracts = Object.entries(config.contracts);
10
14
  const emptyAddresses = contracts.filter(([_name, addresses]) => {
11
15
  return Object.keys(addresses).length === 0;
12
16
  });
13
17
  if (emptyAddresses.length > 0) {
14
- return yield* Effect.fail(new ValidationError({ message: `Found empty addresses definitions: ${emptyAddresses.map((e) => e[0])}` }));
18
+ return yield* Effect.fail(new ValidationError({
19
+ message: `Found empty addresses definitions: ${emptyAddresses.map((e) => e[0]).join(', ')}`,
20
+ }));
15
21
  }
16
22
  }).pipe(Effect.withSpan('hasAddresses'));
17
- const hasMatchingAbis = (config, store) => Effect.gen(function* () {
23
+ /**
24
+ * @internal
25
+ */
26
+ export const hasMatchingAbis = (config, store) => Effect.gen(function* () {
18
27
  const contracts = Object.entries(config.contracts);
19
28
  const result = contracts.filter(([_name, addresses]) => {
20
29
  return !validateAbisAreTheSame(addresses, store);
21
30
  });
22
31
  if (result.length > 0) {
23
- return yield* Effect.fail(new ValidationError({ message: `Found not matching abis: ${result.map((e) => e[0])}` }));
32
+ return yield* Effect.fail(new ValidationError({ message: `Found not matching abis: ${result.map((e) => e[0]).join(', ')}` }));
24
33
  }
25
34
  }).pipe(Effect.withSpan('hasMatchingAbis'));
26
35
  const validateAbisAreTheSame = (addresses, store) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sparkdotfi/abi-cli",
3
- "version": "0.2.0-20250808.efecd1d6",
3
+ "version": "0.2.0-20250811.13be5bb5",
4
4
  "engines": {
5
5
  "node": ">=22.0.0"
6
6
  },