dequanto 0.2.49 → 0.2.51

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 (179) hide show
  1. package/contracts/oz/Proxy.sol +1 -0
  2. package/lib/cjs/abi/$abi.js +33 -0
  3. package/lib/cjs/abi/$abi.js.map +1 -1
  4. package/lib/cjs/blocks/BlockDateResolver.js.map +1 -1
  5. package/lib/cjs/clients/Web3Client.js +43 -2
  6. package/lib/cjs/clients/Web3Client.js.map +1 -1
  7. package/lib/cjs/clients/Web3ClientFactory.js +26 -4
  8. package/lib/cjs/clients/Web3ClientFactory.js.map +1 -1
  9. package/lib/cjs/clients/debug/ClientDebugMethods.js +4 -0
  10. package/lib/cjs/clients/debug/ClientDebugMethods.js.map +1 -1
  11. package/lib/cjs/clients/utils/$web3Abi.js +1 -1
  12. package/lib/cjs/clients/utils/$web3Abi.js.map +1 -1
  13. package/lib/cjs/config/Config.js +28 -6
  14. package/lib/cjs/config/Config.js.map +1 -1
  15. package/lib/cjs/config/ConfigDefaults.js +6 -2
  16. package/lib/cjs/config/ConfigDefaults.js.map +1 -1
  17. package/lib/cjs/config/ConfigProvider.js +5 -0
  18. package/lib/cjs/config/ConfigProvider.js.map +1 -1
  19. package/lib/cjs/config/DefaultFactory.js +27 -0
  20. package/lib/cjs/config/DefaultFactory.js.map +1 -0
  21. package/lib/cjs/contracts/ContractBase.js +6 -2
  22. package/lib/cjs/contracts/ContractBase.js.map +1 -1
  23. package/lib/cjs/contracts/ContractReader.js +1 -35
  24. package/lib/cjs/contracts/ContractReader.js.map +1 -1
  25. package/lib/cjs/explorer/BlockchainExplorer.js +9 -9
  26. package/lib/cjs/explorer/BlockchainExplorer.js.map +1 -1
  27. package/lib/cjs/explorer/BlockchainExplorerFactory.js +1 -1
  28. package/lib/cjs/explorer/BlockchainExplorerFactory.js.map +1 -1
  29. package/lib/cjs/explorer/BlockchainExplorerProvider.js +1 -1
  30. package/lib/cjs/explorer/BlockchainExplorerProvider.js.map +1 -1
  31. package/lib/cjs/explorer/BlockchainExplorerStorage.js +2 -2
  32. package/lib/cjs/explorer/BlockchainExplorerStorage.js.map +1 -1
  33. package/lib/cjs/explorer/ContractVerifier.js +10 -10
  34. package/lib/cjs/explorer/ContractVerifier.js.map +1 -1
  35. package/lib/cjs/explorer/verifiers/FsHtmlVerifier.js +1 -1
  36. package/lib/cjs/explorer/verifiers/FsHtmlVerifier.js.map +1 -1
  37. package/lib/cjs/rpc/RpcContract.js +4 -32
  38. package/lib/cjs/rpc/RpcContract.js.map +1 -1
  39. package/lib/cjs/utils/$account.js +5 -0
  40. package/lib/cjs/utils/$account.js.map +1 -1
  41. package/lib/cjs/utils/$config.js +4 -5
  42. package/lib/cjs/utils/$config.js.map +1 -1
  43. package/lib/cjs/utils/$erc20.js +47 -0
  44. package/lib/cjs/utils/$erc20.js.map +1 -0
  45. package/lib/cjs/utils/$require.js +2 -2
  46. package/lib/cjs/utils/$require.js.map +1 -1
  47. package/lib/esm/abi/$abi.js.map +1 -1
  48. package/lib/esm/abi/$abi.mjs +33 -0
  49. package/lib/esm/blocks/BlockDateResolver.js.map +1 -1
  50. package/lib/esm/clients/Web3Client.js.map +1 -1
  51. package/lib/esm/clients/Web3Client.mjs +43 -2
  52. package/lib/esm/clients/Web3ClientFactory.js.map +1 -1
  53. package/lib/esm/clients/Web3ClientFactory.mjs +26 -4
  54. package/lib/esm/clients/debug/ClientDebugMethods.js.map +1 -1
  55. package/lib/esm/clients/debug/ClientDebugMethods.mjs +4 -0
  56. package/lib/esm/clients/utils/$web3Abi.js.map +1 -1
  57. package/lib/esm/clients/utils/$web3Abi.mjs +1 -1
  58. package/lib/esm/config/Config.js.map +1 -1
  59. package/lib/esm/config/Config.mjs +28 -6
  60. package/lib/esm/config/ConfigDefaults.js.map +1 -1
  61. package/lib/esm/config/ConfigDefaults.mjs +6 -2
  62. package/lib/esm/config/ConfigProvider.js.map +1 -1
  63. package/lib/esm/config/ConfigProvider.mjs +5 -0
  64. package/lib/esm/config/DefaultFactory.js.map +1 -0
  65. package/lib/esm/config/DefaultFactory.mjs +23 -0
  66. package/lib/esm/contracts/ContractBase.js.map +1 -1
  67. package/lib/esm/contracts/ContractBase.mjs +6 -2
  68. package/lib/esm/contracts/ContractReader.js.map +1 -1
  69. package/lib/esm/contracts/ContractReader.mjs +1 -35
  70. package/lib/esm/explorer/BlockchainExplorer.js.map +1 -1
  71. package/lib/esm/explorer/BlockchainExplorer.mjs +9 -9
  72. package/lib/esm/explorer/BlockchainExplorerFactory.js.map +1 -1
  73. package/lib/esm/explorer/BlockchainExplorerFactory.mjs +1 -1
  74. package/lib/esm/explorer/BlockchainExplorerProvider.js.map +1 -1
  75. package/lib/esm/explorer/BlockchainExplorerProvider.mjs +1 -1
  76. package/lib/esm/explorer/BlockchainExplorerStorage.js.map +1 -1
  77. package/lib/esm/explorer/BlockchainExplorerStorage.mjs +2 -2
  78. package/lib/esm/explorer/ContractVerifier.js.map +1 -1
  79. package/lib/esm/explorer/ContractVerifier.mjs +10 -10
  80. package/lib/esm/explorer/verifiers/FsHtmlVerifier.js.map +1 -1
  81. package/lib/esm/explorer/verifiers/FsHtmlVerifier.mjs +1 -1
  82. package/lib/esm/rpc/RpcContract.js.map +1 -1
  83. package/lib/esm/rpc/RpcContract.mjs +4 -32
  84. package/lib/esm/utils/$account.js.map +1 -1
  85. package/lib/esm/utils/$account.mjs +5 -0
  86. package/lib/esm/utils/$config.js.map +1 -1
  87. package/lib/esm/utils/$config.mjs +4 -5
  88. package/lib/esm/utils/$erc20.js.map +1 -0
  89. package/lib/esm/utils/$erc20.mjs +41 -0
  90. package/lib/esm/utils/$require.js.map +1 -1
  91. package/lib/esm/utils/$require.mjs +2 -2
  92. package/lib/types/abi/$abi.d.ts +3 -1
  93. package/lib/types/blocks/BlockDateResolver.d.ts +1 -1
  94. package/lib/types/clients/Web3Client.d.ts +1 -1
  95. package/lib/types/clients/Web3ClientFactory.d.ts +10 -2
  96. package/lib/types/clients/debug/ClientDebugMethods.d.ts +1 -1
  97. package/lib/types/config/AConfigBase.d.ts +3 -0
  98. package/lib/types/config/Config.d.ts +2 -1
  99. package/lib/types/config/DefaultFactory.d.ts +2 -0
  100. package/lib/types/config/interface/IConfigData.d.ts +14 -2
  101. package/lib/types/contracts/ContractReader.d.ts +1 -1
  102. package/lib/types/explorer/BlockchainExplorerFactory.d.ts +1 -1
  103. package/lib/types/explorer/IBlockchainExplorer.d.ts +6 -0
  104. package/lib/types/models/TPlatform.d.ts +1 -1
  105. package/lib/types/utils/$account.d.ts +1 -0
  106. package/lib/types/utils/$erc20.d.ts +5 -0
  107. package/lib/types/utils/$require.d.ts +2 -2
  108. package/package.json +1 -1
  109. package/skills/README.md +45 -0
  110. package/{docs/ai → skills/dequanto}/INDEX.md +16 -5
  111. package/skills/dequanto/SKILL.md +73 -0
  112. package/skills/dequanto/examples/config.spec.ts +113 -0
  113. package/skills/dequanto/examples/contract-read.spec.ts +112 -0
  114. package/skills/dequanto/examples/contract-write.spec.ts +68 -0
  115. package/skills/dequanto/examples/deploy-contract.spec.ts +69 -0
  116. package/{docs/ai → skills/dequanto}/examples/erc4337-userop.spec.ts +13 -11
  117. package/skills/dequanto/examples/explorer-abi.spec.ts +21 -0
  118. package/{docs/ai/examples/generate-client.spec.ts → skills/dequanto/examples/generate-contract-class.spec.ts} +7 -4
  119. package/skills/dequanto/examples/hardhat-debug.spec.ts +29 -0
  120. package/skills/dequanto/examples/hardhat-fork.spec.ts +31 -0
  121. package/{docs/ai → skills/dequanto}/examples/index-events.spec.ts +10 -8
  122. package/skills/dequanto/examples/rpc-read.spec.ts +59 -0
  123. package/{docs/ai → skills/dequanto}/examples/safe-batch.spec.ts +10 -9
  124. package/skills/dequanto/examples/send-transaction.spec.ts +34 -0
  125. package/skills/dequanto/examples/storage.spec.ts +58 -0
  126. package/skills/dequanto/examples/token-transfer.spec.ts +29 -0
  127. package/skills/dequanto/examples/utils.spec.ts +63 -0
  128. package/{docs/ai → skills/dequanto}/references/contracts.md +1 -1
  129. package/{docs/ai → skills/dequanto}/references/deployments.md +4 -2
  130. package/{docs/ai → skills/dequanto}/references/events-indexing.md +1 -1
  131. package/{docs/ai → skills/dequanto}/references/explorer.md +1 -1
  132. package/{docs/ai → skills/dequanto}/references/generation.md +36 -13
  133. package/skills/dequanto/references/hardhat.md +113 -0
  134. package/{docs/ai → skills/dequanto}/references/rpc-clients.md +25 -5
  135. package/{docs/ai → skills/dequanto}/references/safe-erc4337.md +2 -2
  136. package/skills/dequanto/references/storage.md +122 -0
  137. package/{docs/ai → skills/dequanto}/references/tokens-accounts.md +12 -6
  138. package/{docs/ai → skills/dequanto}/references/transactions.md +6 -4
  139. package/skills/dequanto/references/utils.md +131 -0
  140. package/src/abi/$abi.ts +34 -1
  141. package/src/blocks/BlockDateResolver.ts +1 -1
  142. package/src/clients/Web3Client.ts +48 -3
  143. package/src/clients/Web3ClientFactory.ts +33 -5
  144. package/src/clients/debug/ClientDebugMethods.ts +5 -1
  145. package/src/clients/utils/$web3Abi.ts +2 -2
  146. package/src/config/AConfigBase.ts +4 -0
  147. package/src/config/Config.ts +30 -8
  148. package/src/config/ConfigDefaults.ts +6 -2
  149. package/src/config/ConfigProvider.ts +5 -1
  150. package/src/config/DefaultFactory.ts +26 -0
  151. package/src/config/interface/IConfigData.ts +15 -2
  152. package/src/contracts/ContractBase.ts +6 -2
  153. package/src/contracts/ContractReader.ts +3 -40
  154. package/src/explorer/BlockchainExplorer.ts +9 -9
  155. package/src/explorer/BlockchainExplorerFactory.ts +1 -2
  156. package/src/explorer/BlockchainExplorerProvider.ts +1 -1
  157. package/src/explorer/BlockchainExplorerStorage.ts +2 -2
  158. package/src/explorer/ContractVerifier.ts +10 -10
  159. package/src/explorer/IBlockchainExplorer.ts +4 -0
  160. package/src/explorer/verifiers/FsHtmlVerifier.ts +1 -1
  161. package/src/models/TPlatform.ts +1 -0
  162. package/src/rpc/RpcContract.ts +5 -33
  163. package/src/utils/$account.ts +5 -0
  164. package/src/utils/$config.ts +4 -6
  165. package/src/utils/$erc20.ts +53 -0
  166. package/src/utils/$require.ts +4 -4
  167. package/tsconfig.json +3 -3
  168. package/tsconfig.umd.json +1 -2
  169. package/docs/ai/examples/contract-read.spec.ts +0 -44
  170. package/docs/ai/examples/contract-write.spec.ts +0 -16
  171. package/docs/ai/examples/deploy-contract.spec.ts +0 -32
  172. package/docs/ai/examples/explorer-abi.spec.ts +0 -18
  173. package/docs/ai/examples/rpc-read.spec.ts +0 -15
  174. package/docs/ai/examples/send-transaction.spec.ts +0 -22
  175. package/docs/ai/examples/storage-read.spec.ts +0 -27
  176. package/docs/ai/examples/token-transfer.spec.ts +0 -22
  177. package/docs/ai/references/storage.md +0 -93
  178. package/docs/ai/skill/dequanto/SKILL.md +0 -59
  179. /package/{docs/ai → skills/dequanto}/references/migration-from-ethers-viem.md +0 -0
@@ -7,6 +7,7 @@ import { EvmWeb3Client } from './EvmWeb3Client';
7
7
  import { $require } from '@dequanto/utils/$require';
8
8
  import { $config } from '@dequanto/utils/$config';
9
9
  import type { HardhatWeb3Client } from '@dequanto/hardhat/HardhatWeb3Client';
10
+ import { IConfigData } from '@dequanto/config/interface/IConfigData';
10
11
 
11
12
  export namespace Web3ClientFactory {
12
13
 
@@ -14,9 +15,23 @@ export namespace Web3ClientFactory {
14
15
  TClient extends EvmWeb3Client | HardhatWeb3Client = EvmWeb3Client
15
16
  > (platform: TPlatform | number, opts?: IWeb3EndpointOptions): TClient {
16
17
  if (typeof platform === 'string' && (platform === 'hardhat' || platform.startsWith('hh:'))) {
17
- let client = di.resolve(HardhatProvider).client('localhost', opts);
18
- if (platform.startsWith('hh:')) {
19
- client.configureFork(platform.slice(3));
18
+ // hardhat - local hardhat network
19
+ // hh:eth - local hardhat network (which runs as a fork)
20
+ // hh:memory - in-memory hardhat network
21
+ // hh:memory:eth - getAsync only: in-memory forked hardhat network
22
+ if (platform.startsWith('hh:memory:')) {
23
+ throw new Error(`use getAsync to resolve forked "${platform}" client`);
24
+ }
25
+
26
+ let network = platform.startsWith('hh:')
27
+ ? platform.slice(3)
28
+ : null;
29
+ let hh = network === 'memory'
30
+ ? 'hardhat' as const
31
+ : 'localhost' as const;
32
+ let client = di.resolve(HardhatProvider).client(hh, opts);
33
+ if (network != null && network !== 'memory') {
34
+ client.configureFork(network);
20
35
  }
21
36
  return client as TClient;
22
37
  }
@@ -29,11 +44,24 @@ export namespace Web3ClientFactory {
29
44
  }) as TClient;
30
45
  }
31
46
 
47
+ type HHInMemoryForkData = {
48
+ block?: number
49
+ url?: string
50
+ }
32
51
  /** Same as the sync variant, but ensures the config is fetched */
33
52
  export async function getAsync <
34
53
  TClient extends EvmWeb3Client | HardhatWeb3Client = EvmWeb3Client
35
- > (platform: TPlatform | string | number, opts?: IWeb3EndpointOptions): Promise<TClient> {
36
- let cfg = await Config.get();
54
+ > (platform: TPlatform | string | number, opts?: IWeb3EndpointOptions & HHInMemoryForkData & { config?: Partial<IConfigData>}): Promise<TClient> {
55
+ let cfg = await Config.get(opts?.config);
56
+ if (typeof platform === 'string' && platform.startsWith('hh:memory:')) {
57
+ let network = platform.replace('hh:memory:', '');
58
+ let client = await di.resolve(HardhatProvider).forked({
59
+ platform: network,
60
+ block: opts?.block,
61
+ url: opts?.url,
62
+ });
63
+ return client as TClient;
64
+ }
37
65
  return get<TClient>(platform, opts);
38
66
  }
39
67
  }
@@ -7,6 +7,7 @@ import { $hex } from '@dequanto/utils/$hex';
7
7
  import { TEth } from '@dequanto/models/TEth';
8
8
  import { $array } from '@dequanto/utils/$array';
9
9
  import { $date } from '@dequanto/utils/$date';
10
+ import { $number } from '@dequanto/utils/$number';
10
11
 
11
12
 
12
13
  export class ClientDebugMethods {
@@ -53,10 +54,13 @@ export class ClientDebugMethods {
53
54
  return this.call('mine', ...args);
54
55
  }
55
56
 
56
- setBalance (address: TAddress, amount: bigint | string) {
57
+ setBalance (address: TAddress, amount: bigint | number | string) {
57
58
  if (typeof amount === 'bigint') {
58
59
  amount = $bigint.toHex(amount);
59
60
  }
61
+ if (typeof amount === 'number') {
62
+ amount = $number.toHex(amount);
63
+ }
60
64
  return this.call('setBalance', address, amount);
61
65
  }
62
66
 
@@ -8,13 +8,13 @@ export namespace $web3Abi {
8
8
  let arr: TAbiItem[];
9
9
  if (typeof abi === 'string') {
10
10
  arr = [ $abiParser.parseMethod(abi) ];
11
- } else if (Array.isArray(abi)) {
11
+ } else if (Array.isArray(abi)) {
12
12
  arr = abi;
13
13
  } else {
14
14
  arr = [ abi ];
15
15
  }
16
16
 
17
- let first = abi[0];
17
+ let first = arr[0];
18
18
  if (first.outputs == null || first.outputs.length === 0) {
19
19
  // Normalize outputs to read at least bytes if nothing is set
20
20
  first.outputs = [
@@ -5,6 +5,10 @@ import { TEth } from '@dequanto/models/TEth'
5
5
 
6
6
  type TConfigParamsBase = {
7
7
  config?: Partial<IConfigData>
8
+ // alias for config.web3.platform.endpoints
9
+ rpc?: {
10
+ [platform: string]: string | string[] | IConfigData['web3']['']['endpoints']
11
+ }
8
12
  }
9
13
 
10
14
  export type TConfigParamsNode = TConfigParamsBase & {
@@ -12,6 +12,27 @@ export class Config {
12
12
  static async fetch (parameters?: TConfigParamsNode | TConfigParamsBrowser): Promise<Appcfg<IConfigData> & IConfigData> {
13
13
  singleton ??= new class_Dfr();
14
14
 
15
+ if (parameters?.rpc) {
16
+ parameters.config ??= {};
17
+ parameters.config.web3 ??= {};
18
+ for (let platform in parameters.rpc) {
19
+ parameters.config.web3[platform] ??= {} as any;
20
+ parameters.config.web3[platform].endpoints = [];
21
+ let val = parameters.rpc[platform];
22
+ if (typeof val === 'string') {
23
+ parameters.config.web3[platform].endpoints.push({
24
+ url: val
25
+ });
26
+ continue;
27
+ }
28
+ if (Array.isArray(val) && typeof val[0] === 'string') {
29
+ parameters.config.web3[platform].endpoints.push(...val.map(url => ({url})));
30
+ continue;
31
+ }
32
+ parameters.config.web3[platform].endpoints = val as any;
33
+ }
34
+ }
35
+
15
36
  let cfg = await provider.fetch(parameters);
16
37
 
17
38
  obj_extend(config, cfg);
@@ -28,21 +49,22 @@ export class Config {
28
49
  }
29
50
 
30
51
  /** Will return a config that was previously loaded by fetch with any parameters or will trigger fetch with default parameters */
31
- static async get (): Promise<Appcfg<IConfigData> & IConfigData> {
32
- if (singleton != null) {
52
+ static async get (config?: Partial<IConfigData>): Promise<Appcfg<IConfigData> & IConfigData> {
53
+ if (singleton != null && config == null) {
33
54
  return singleton;
34
55
  }
35
- return Config.fetch();
56
+ return Config.fetch({ config });
36
57
  }
37
58
 
38
- // static async getExplorerConfig (platform: TPlatform | number): Promise<TExplorer> {
39
- // let config = await Config.get();
40
-
41
- // }
42
-
43
59
  static async extend (json) {
44
60
  await provider.extend(json);
45
61
  }
62
+
63
+ static clean (): Config {
64
+ memd.fn.clearMemoized(Config.fetch);
65
+ singleton = null;
66
+ return Config;
67
+ }
46
68
  }
47
69
 
48
70
  export const config = { } as IConfigData;
@@ -1,5 +1,6 @@
1
1
  import { IConfigData } from './interface/IConfigData';
2
- export const ConfigDefaults = <IConfigData> {
2
+ import { DefaultFactory } from './DefaultFactory';
3
+ export const ConfigDefaults = DefaultFactory({
3
4
  "accounts": null,
4
5
  "settings": {
5
6
  "generate": {
@@ -116,6 +117,9 @@ export const ConfigDefaults = <IConfigData> {
116
117
  "chainId": 1,
117
118
  "chainToken": "ETH",
118
119
  "endpoints": [
120
+ {
121
+ "url": "https://ethereum-rpc.publicnode.com"
122
+ },
119
123
  {
120
124
  "url": "https://eth.drpc.org",
121
125
  "rateLimit": "2000/5m"
@@ -504,4 +508,4 @@ export const ConfigDefaults = <IConfigData> {
504
508
  "base": "0x00000000000D6FFc74A8feb35aF5827bf57f6786",
505
509
  "linea": "0x00000000000D6FFc74A8feb35aF5827bf57f6786"
506
510
  }
507
- };
511
+ });
@@ -33,7 +33,6 @@ export class ConfigProvider implements IConfigProvider {
33
33
  ;
34
34
 
35
35
  let cfg = await AppConfig.fetch<IConfigData>(sources);
36
-
37
36
  if (this.config != null) {
38
37
  this.config.$extend(cfg.toJSON());
39
38
  } else {
@@ -102,6 +101,11 @@ export class ConfigProvider implements IConfigProvider {
102
101
  parameters?.dotenv ? {
103
102
  dotenv: true
104
103
  } : null,
104
+ parameters?.config ? {
105
+ sync: true,
106
+ extendArrays: false,
107
+ config: parameters.config
108
+ } : null,
105
109
  ];
106
110
  }
107
111
 
@@ -0,0 +1,26 @@
1
+ import { IConfigData } from './interface/IConfigData';
2
+
3
+ export function DefaultFactory (config: IConfigData): IConfigData {
4
+
5
+ if (typeof process !== 'undefined' && process.env != null) {
6
+ for (let key in process.env) {
7
+ if (key.startsWith('RPC_') === false) {
8
+ continue;
9
+ }
10
+ const platform = key.replace('RPC_', '').toLowerCase();
11
+ if (platform in config.web3 === false) {
12
+ continue;
13
+ }
14
+
15
+ const url = process.env[key];
16
+ if (/^(http|ws)/.test(url) === false) {
17
+ continue;
18
+ }
19
+ config.web3[platform].endpoints = [
20
+ { url: url }
21
+ ];
22
+ }
23
+ }
24
+
25
+ return config;
26
+ }
@@ -4,6 +4,7 @@ import { TAddress } from '@dequanto/models/TAddress';
4
4
  import { TPlatform } from '@dequanto/models/TPlatform';
5
5
  import { IRpcConfig } from '@dequanto/clients/ClientPool';
6
6
  import { TChain } from '@dequanto/models/TChain';
7
+ import { TEth } from '@dequanto/models/TEth';
7
8
 
8
9
 
9
10
  export interface IConfigData {
@@ -28,10 +29,10 @@ export interface IConfigData {
28
29
 
29
30
  blockchainExplorer: {
30
31
  [platform in TPlatform]: {
31
- key: string;
32
+ key?: string;
32
33
  host?: string;
33
34
  api?: string
34
- wwww?: string
35
+ www?: string
35
36
  };
36
37
  };
37
38
 
@@ -77,4 +78,16 @@ export interface IConfigData {
77
78
  [platform in TPlatform]: TAddress
78
79
  };
79
80
 
81
+ ns: {
82
+ [service: string]: {
83
+ [platform: string]: {
84
+ registry: TEth.Address
85
+ resolver?: TEth.Address
86
+ }
87
+ }
88
+ }
89
+
90
+ oracles: {
91
+ [service: string]: any
92
+ }
80
93
  }
@@ -299,14 +299,18 @@ export abstract class ContractBase {
299
299
 
300
300
  protected $read(abi: string | TAbiItem, ...params) {
301
301
  if (this.builderConfig?.send === 'manual') {
302
+ let abiJson = typeof abi === 'string'
303
+ ? $abiParser.parseMethod(abi)
304
+ : abi;
302
305
  let req = <ContractReaderUtils.IContractReadParams>{
303
306
  address: this.address,
304
- abi,
307
+ abi: abiJson,
305
308
  params: params,
306
309
  blockNumber: this.blockNumber ?? this.blockDate,
307
310
  options: {
308
311
  from: this.builderConfig?.from
309
- }
312
+ },
313
+ method: abiJson.name
310
314
  };
311
315
  return req;
312
316
  }
@@ -302,9 +302,9 @@ export class ContractReader implements IContractReader {
302
302
  return filters as RpcTypes.Filter;
303
303
  }
304
304
 
305
- static async read (client: Web3Client, address: TAddress, methodAbi: string){
305
+ static async read <TResult = any> (client: Web3Client, address: TAddress, methodAbi: string){
306
306
  let reader = new ContractReader(client);
307
- return reader.readAsync(address, methodAbi);
307
+ return reader.readAsync<TResult>(address, methodAbi);
308
308
  }
309
309
  }
310
310
 
@@ -357,43 +357,6 @@ export namespace ContractReaderUtils {
357
357
  export async function readAsyncBatch(client: Web3Client, requests: (IContractReadParams | null)[], options?: {
358
358
  allowErrors?: boolean
359
359
  }) {
360
-
361
- let rpcRequests = await alot(requests).map(async request => {
362
- if (request == null) {
363
- return null;
364
- }
365
- let abi = request.abi;
366
- if (typeof abi === 'string') {
367
- abi = $abiParser.parseMethod(abi);
368
- }
369
- let blockNumber = request.blockNumber;
370
- if (blockNumber instanceof Date) {
371
- let resolver = di.resolve(BlockDateResolver, client);
372
- blockNumber = await resolver.getBlockNumberFor(blockNumber);
373
- }
374
- return {
375
- address: request.address,
376
- abi: [ abi ],
377
- method: abi.name,
378
- params: request.params,
379
- blockNumber: blockNumber,
380
- options: request.options
381
- } as TRpcContractCall;
382
- }).toArrayAsync();
383
-
384
- let mapped = [];
385
- let rpcRequestsNotEmpty = [];
386
- for (let i = 0; i < rpcRequests.length; i++) {
387
- if (rpcRequests[i] == null) {
388
- continue;
389
- }
390
- let idx = rpcRequestsNotEmpty.push(rpcRequests[i]) - 1;
391
- mapped[i] = idx;
392
- }
393
-
394
- let outputs = await client.readContractBatch(rpcRequestsNotEmpty, options);
395
- return rpcRequests.map((_, i) => {
396
- return outputs[mapped[i]] ?? null;
397
- });
360
+ return await client.readContractBatch(requests, options);
398
361
  }
399
362
  }
@@ -175,10 +175,10 @@ export class BlockchainExplorer implements IBlockchainExplorer {
175
175
  try {
176
176
  abi = await this.client.get(url);
177
177
  } catch (err) {
178
- $logger.log(`Blockchain explorer request filed "${url}": ${err.message}`);
178
+ $logger.log(`Blockchain explorer request failed for "${url}": ${err.message}`);
179
179
  let addressByByteCode = await this.getSimilarContract(address);
180
180
  if (addressByByteCode != null) {
181
- $logger.log(`Found similar byte code address: ${addressByByteCode}`);
181
+ $logger.log(`Found similar bytecode address: ${addressByByteCode}`);
182
182
  return this.getContractAbi(addressByByteCode);
183
183
  }
184
184
  throw err;
@@ -195,7 +195,7 @@ export class BlockchainExplorer implements IBlockchainExplorer {
195
195
  let hex = $address.fromBytes32(uin256Hex);
196
196
  return this.getContractAbi(hex)
197
197
  }
198
- throw new Error(`Implement ${params.implementation} support`);
198
+ throw new Error(`Implementation lookup is not supported for ${params.implementation}`);
199
199
  }
200
200
  if (isOpenZeppelinProxy(abiJson) || mightBeProxy(abiJson)) {
201
201
  let web3 = this.getWeb3(this.platform);
@@ -384,12 +384,12 @@ export class BlockchainExplorer implements IBlockchainExplorer {
384
384
  try {
385
385
  return JSON.parse(str)
386
386
  } catch (error) {
387
- // etherscan returns code wrapped into {{}}
387
+ // Etherscan can return source code wrapped in {{...}}
388
388
  }
389
389
  str = str
390
390
  .replace(/^\s*\{\{/g, '{')
391
391
  .replace(/\}\}\s*$/g, '}');
392
- // @TODO check etherscan serialized jsons. Does it always has "{{...}}" wrappings
392
+ // @TODO Check Etherscan serialized JSON. Does it always use "{{...}}" wrapping?
393
393
 
394
394
  return JSON.parse(str)
395
395
  }
@@ -555,7 +555,7 @@ function hasMethod(abi: TAbiItem[], name: string) {
555
555
  function ensureDefaults(opts: TExplorerDefinition) {
556
556
 
557
557
  let platform = opts.platform;
558
- $require.notNull(platform, `Generic Blockchain Explorer Config should contain platform name`);
558
+ $require.notNull(platform, `Generic blockchain explorer config must include a platform name`);
559
559
 
560
560
  opts.ABI_CACHE ??= `./cache/${$platform.toPath(platform)}/abis.json`
561
561
  opts.CONTRACTS ??= [];
@@ -594,7 +594,7 @@ class HttpClient {
594
594
  async getHtml(url: string) {
595
595
  let resp = await $http.get(url);
596
596
  if (resp.status !== 200) {
597
- throw new Error(`${url} not loaded with status ${resp.status}.`);
597
+ throw new Error(`${url} failed to load with status ${resp.status}.`);
598
598
  }
599
599
  return resp.data;
600
600
  }
@@ -644,7 +644,7 @@ class HttpClient {
644
644
  throw error;
645
645
  }
646
646
  if (data.result == null) {
647
- $logger.warn(`Blockchain "${url}" explorer returned empty result`, data);
647
+ $logger.warn(`Blockchain explorer "${url}" returned an empty result`, data);
648
648
  }
649
649
  return data.result as TOut;
650
650
  }
@@ -669,7 +669,7 @@ class HttpClient {
669
669
  throw new Error(str);
670
670
  }
671
671
  if (data.result == null) {
672
- $logger.warn(`Blockchain "${url}" explorer returned empty result`, data);
672
+ $logger.warn(`Blockchain explorer "${url}" returned an empty result`, data);
673
673
  }
674
674
  return data.result;
675
675
  }
@@ -50,7 +50,7 @@ export namespace BlockchainExplorerFactory {
50
50
  return new BlockchainExplorer(params);
51
51
  }
52
52
 
53
- /** Same as sync variation, but ensures the config is being fetched */
53
+ /** Same as the synchronous variant, but ensures the config has been fetched */
54
54
  export async function getAsync (platform: TPlatform, opts?: IBlockchainExplorerFactoryParams): Promise<IBlockchainExplorer> {
55
55
  await Config.get();
56
56
  return get(platform, opts);
@@ -58,7 +58,6 @@ export namespace BlockchainExplorerFactory {
58
58
 
59
59
  /** @obsolete Create instance directly with the get/getAsync method */
60
60
  export function create (opts: IBlockchainExplorerFactoryParams): Constructor<IBlockchainExplorer> {
61
-
62
61
  return class extends BlockchainExplorer {
63
62
  constructor (config?: IBlockchainExplorerFactoryParams) {
64
63
  super(config ?? opts);
@@ -26,7 +26,7 @@ export namespace BlockchainExplorerProvider {
26
26
  if (cfg != null) {
27
27
  return new BlockchainExplorer({ platform, ...cfg });
28
28
  }
29
- throw new Error(`Unsupported platform ${platform} for block chain explorer`);
29
+ throw new Error(`Unsupported platform ${platform} for blockchain explorer`);
30
30
  }
31
31
  }
32
32
 
@@ -82,7 +82,7 @@ export class BlockchainExplorerStorage implements IBlockchainExplorer {
82
82
  let $address = opts?.implementation ?? address;
83
83
  let $contract = this.contracts[$address.toLowerCase()];
84
84
  $require.notNull($contract, `Contract "${$address}" not found`);
85
- // @TODO: L1: return abi as json (means in *scan providers we must serialize it earlier)
85
+ // @TODO: L1: Return ABI as JSON. *scan providers should serialize it earlier.
86
86
  return {
87
87
  implementation: $address,
88
88
  abi: JSON.stringify($contract.abi)
@@ -92,7 +92,7 @@ export class BlockchainExplorerStorage implements IBlockchainExplorer {
92
92
  let _address = address;
93
93
  let _contract = this.contracts[_address.toLowerCase()];
94
94
  $require.notNull(_contract, `Contract "${_address}" not found`);
95
- // @TODO: L1: return abi as json (means in *scan providers we must serialize it earlier)
95
+ // @TODO: L1: Return ABI as JSON. *scan providers should serialize it earlier.
96
96
  return {
97
97
  SourceCode: {
98
98
  contractName: _contract.name,
@@ -42,7 +42,7 @@ export class ContractVerifier {
42
42
  }
43
43
 
44
44
  async ensure (Ctor: TContractInfo, opts: TSubmissionOptions = {}): Promise<void> {
45
- this.logger.log(`Submit sources for ${typeof Ctor === 'string' ? Ctor : Ctor.name}`);
45
+ this.logger.log(`Submitting sources for ${typeof Ctor === 'string' ? Ctor : Ctor.name}`);
46
46
 
47
47
  let status = await this.submit(Ctor, opts);
48
48
  await this.waitForVerification(status, opts);
@@ -66,7 +66,7 @@ export class ContractVerifier {
66
66
  } catch (e) {
67
67
  let message = e.message;
68
68
  if (/verified/i.test(message)) {
69
- // was already verified
69
+ // Already verified.
70
70
  return true;
71
71
  }
72
72
  if (/(pending|queue)/i.test(message)) {
@@ -100,13 +100,13 @@ export class ContractVerifier {
100
100
  }
101
101
 
102
102
  try {
103
- this.logger.log(`Checking if already verified ${address}`);
103
+ this.logger.log(`Checking whether contract ${address} is already verified`);
104
104
  let currentSources = await this.explorer.getContractSource(address);
105
105
  if ($is.notEmpty(currentSources?.ContractName)) {
106
106
  return { status:'verified' };
107
107
  }
108
108
  } catch (error) {
109
- // ignore any pre-check error and continue with the verification
109
+ // Ignore pre-check errors and continue with verification.
110
110
  }
111
111
 
112
112
  let deployedBytecode = await client.getCode(address);
@@ -140,7 +140,7 @@ export class ContractVerifier {
140
140
  }
141
141
 
142
142
  let jsonMetaPath = info.ctx.source.path;
143
- $require.notEmpty(jsonMetaPath, `Deployment should return a path to compilation JSON`);
143
+ $require.notEmpty(jsonMetaPath, `Deployment should return a path to the compilation JSON`);
144
144
  $require.True(await File.existsAsync(jsonMetaPath) , `${jsonMetaPath} does not exist`);
145
145
 
146
146
  let jsonMeta = await File.readAsync<{ sourceName: string, contractName: string }>(jsonMetaPath);
@@ -150,7 +150,7 @@ export class ContractVerifier {
150
150
  let jsonMetaDbg = await File.readAsync<{ buildInfo: string }>(jsonMetaDbgPath);
151
151
 
152
152
  let jsonMetaBuildInfoPath = jsonMetaDbg.buildInfo;
153
- $require.notEmpty(jsonMetaPath, `${jsonMetaDbgPath} should contain the path to the buildInfo json file`);
153
+ $require.notEmpty(jsonMetaPath, `${jsonMetaDbgPath} should contain the path to the build info JSON file`);
154
154
 
155
155
  let buildInfoPath = new class_Uri(new class_Uri(jsonMetaPath).toDir()).combine(jsonMetaBuildInfoPath).toString();
156
156
  $require.True(await File.existsAsync(buildInfoPath) , `${buildInfoPath} does not exist`);
@@ -170,7 +170,7 @@ export class ContractVerifier {
170
170
  }
171
171
  let buildInfo = await File.readAsync<TBuildInfo>(buildInfoPath);
172
172
 
173
- $require.notNull(buildInfo.solcLongVersion, `${buildInfoPath} should contain the "solcLongVersion" information`);
173
+ $require.notNull(buildInfo.solcLongVersion, `${buildInfoPath} should contain the "solcLongVersion" value`);
174
174
 
175
175
  let sources = await this.getSources(jsonMeta.sourceName);
176
176
  let sourcesSerialized = JSON.stringify({
@@ -181,7 +181,7 @@ export class ContractVerifier {
181
181
 
182
182
  let sourcesSerializedWrapped = `${sourcesSerialized}`;
183
183
 
184
- this.logger.log(`Submit ${jsonMeta.sourceName}:${jsonMeta.contractName} and dependencies to verify ${address} contract`);
184
+ this.logger.log(`Submitting ${jsonMeta.sourceName}:${jsonMeta.contractName} and dependencies to verify contract ${address}`);
185
185
 
186
186
  try {
187
187
  let guid = await this.explorer.submitContractVerification({
@@ -243,7 +243,7 @@ export class ContractVerifier {
243
243
 
244
244
  await crawlSourceFile(new SourceFile(main));
245
245
 
246
- this.logger.log(`Found ${Object.keys(sources).length} source files: `, Object.keys(sources));
246
+ this.logger.log(`Found ${Object.keys(sources).length} source files:`, Object.keys(sources));
247
247
  return sources;
248
248
  }
249
249
 
@@ -284,7 +284,7 @@ export class ContractVerifier {
284
284
  } catch (e) {
285
285
  let message = e.message;
286
286
  if (/verified|success/i.test(message)) {
287
- // was already verified
287
+ // Already verified.
288
288
  return true;
289
289
  }
290
290
  if (/(pending|queue)/i.test(message)) {
@@ -3,9 +3,13 @@ import { IAbiProvider } from './IAbiProvider';
3
3
  import { TEth } from '@dequanto/models/TEth';
4
4
  import { TAddress } from '@dequanto/models/TAddress';
5
5
  import { IVerifier } from './verifiers/IVerifier';
6
+ import { TExplorerDefinition } from '@dequanto/models/TExplorer';
6
7
 
7
8
 
8
9
  export interface IBlockchainExplorer extends IAbiProvider, IVerifier {
10
+ config?: {
11
+ api?: { url?: string; key?: string }
12
+ }
9
13
  inMemoryDb: IContractDetails[]
10
14
  getContractMeta(q: string): Promise<IContractDetails>;
11
15
  getContractCreation(address: TEth.Address): Promise<{ creator: TEth.Address, txHash: TEth.Hex }>;
@@ -115,7 +115,7 @@ export class FsHtmlVerifier implements IVerifier {
115
115
 
116
116
 
117
117
  if (contractData.contractName.includes('Utils/Proxy')) {
118
- // fix Proxy, rename contract duplicates
118
+ // Rename duplicate Proxy contracts before writing the verification form.
119
119
  html = html.replaceAll('contracts/Utils/Proxy.sol:Proxy', 'contracts/Utils/TUProxy.sol:TUProxy');
120
120
  html = html.replace('Utils/Proxy.sol":', 'Utils/TUProxy.sol":');
121
121
  html = html.replace('contract Proxy is ', 'contract TUProxy is ');
@@ -14,5 +14,6 @@ export type TPlatform = 'eth'
14
14
  | 'hardhat'
15
15
  | 'optimism'
16
16
  | 'avalanche'
17
+ | 'hh:memory'
17
18
  | `hh:${string}`
18
19
  | string;