dequanto 0.2.49 → 0.2.50

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 (125) hide show
  1. package/contracts/oz/Proxy.sol +1 -0
  2. package/docs/ai/INDEX.md +4 -3
  3. package/docs/ai/examples/config.spec.ts +113 -0
  4. package/docs/ai/examples/contract-read.spec.ts +81 -13
  5. package/docs/ai/examples/contract-write.spec.ts +61 -9
  6. package/docs/ai/examples/deploy-contract.spec.ts +53 -16
  7. package/docs/ai/examples/erc4337-userop.spec.ts +7 -5
  8. package/docs/ai/examples/explorer-abi.spec.ts +9 -6
  9. package/docs/ai/examples/{generate-client.spec.ts → generate-contract-class.spec.ts} +6 -3
  10. package/docs/ai/examples/index-events.spec.ts +8 -6
  11. package/docs/ai/examples/rpc-read.spec.ts +32 -5
  12. package/docs/ai/examples/safe-batch.spec.ts +5 -4
  13. package/docs/ai/examples/send-transaction.spec.ts +23 -11
  14. package/docs/ai/examples/storage-read.spec.ts +15 -7
  15. package/docs/ai/examples/token-transfer.spec.ts +22 -15
  16. package/docs/ai/references/generation.md +30 -7
  17. package/docs/ai/skill/dequanto/SKILL.md +5 -1
  18. package/lib/cjs/abi/$abi.js +33 -0
  19. package/lib/cjs/abi/$abi.js.map +1 -1
  20. package/lib/cjs/blocks/BlockDateResolver.js.map +1 -1
  21. package/lib/cjs/clients/Web3Client.js +43 -2
  22. package/lib/cjs/clients/Web3Client.js.map +1 -1
  23. package/lib/cjs/clients/Web3ClientFactory.js +26 -4
  24. package/lib/cjs/clients/Web3ClientFactory.js.map +1 -1
  25. package/lib/cjs/clients/debug/ClientDebugMethods.js +4 -0
  26. package/lib/cjs/clients/debug/ClientDebugMethods.js.map +1 -1
  27. package/lib/cjs/clients/utils/$web3Abi.js +1 -1
  28. package/lib/cjs/clients/utils/$web3Abi.js.map +1 -1
  29. package/lib/cjs/config/Config.js +28 -6
  30. package/lib/cjs/config/Config.js.map +1 -1
  31. package/lib/cjs/config/ConfigDefaults.js +6 -2
  32. package/lib/cjs/config/ConfigDefaults.js.map +1 -1
  33. package/lib/cjs/config/ConfigProvider.js +5 -0
  34. package/lib/cjs/config/ConfigProvider.js.map +1 -1
  35. package/lib/cjs/config/DefaultFactory.js +27 -0
  36. package/lib/cjs/config/DefaultFactory.js.map +1 -0
  37. package/lib/cjs/contracts/ContractBase.js +6 -2
  38. package/lib/cjs/contracts/ContractBase.js.map +1 -1
  39. package/lib/cjs/contracts/ContractReader.js +1 -35
  40. package/lib/cjs/contracts/ContractReader.js.map +1 -1
  41. package/lib/cjs/explorer/BlockchainExplorerFactory.js.map +1 -1
  42. package/lib/cjs/rpc/RpcContract.js +4 -32
  43. package/lib/cjs/rpc/RpcContract.js.map +1 -1
  44. package/lib/cjs/utils/$account.js +5 -0
  45. package/lib/cjs/utils/$account.js.map +1 -1
  46. package/lib/cjs/utils/$config.js +4 -5
  47. package/lib/cjs/utils/$config.js.map +1 -1
  48. package/lib/cjs/utils/$erc20.js +47 -0
  49. package/lib/cjs/utils/$erc20.js.map +1 -0
  50. package/lib/cjs/utils/$require.js +2 -2
  51. package/lib/cjs/utils/$require.js.map +1 -1
  52. package/lib/esm/abi/$abi.js.map +1 -1
  53. package/lib/esm/abi/$abi.mjs +33 -0
  54. package/lib/esm/blocks/BlockDateResolver.js.map +1 -1
  55. package/lib/esm/clients/Web3Client.js.map +1 -1
  56. package/lib/esm/clients/Web3Client.mjs +43 -2
  57. package/lib/esm/clients/Web3ClientFactory.js.map +1 -1
  58. package/lib/esm/clients/Web3ClientFactory.mjs +26 -4
  59. package/lib/esm/clients/debug/ClientDebugMethods.js.map +1 -1
  60. package/lib/esm/clients/debug/ClientDebugMethods.mjs +4 -0
  61. package/lib/esm/clients/utils/$web3Abi.js.map +1 -1
  62. package/lib/esm/clients/utils/$web3Abi.mjs +1 -1
  63. package/lib/esm/config/Config.js.map +1 -1
  64. package/lib/esm/config/Config.mjs +28 -6
  65. package/lib/esm/config/ConfigDefaults.js.map +1 -1
  66. package/lib/esm/config/ConfigDefaults.mjs +6 -2
  67. package/lib/esm/config/ConfigProvider.js.map +1 -1
  68. package/lib/esm/config/ConfigProvider.mjs +5 -0
  69. package/lib/esm/config/DefaultFactory.js.map +1 -0
  70. package/lib/esm/config/DefaultFactory.mjs +23 -0
  71. package/lib/esm/contracts/ContractBase.js.map +1 -1
  72. package/lib/esm/contracts/ContractBase.mjs +6 -2
  73. package/lib/esm/contracts/ContractReader.js.map +1 -1
  74. package/lib/esm/contracts/ContractReader.mjs +1 -35
  75. package/lib/esm/explorer/BlockchainExplorerFactory.js.map +1 -1
  76. package/lib/esm/rpc/RpcContract.js.map +1 -1
  77. package/lib/esm/rpc/RpcContract.mjs +4 -32
  78. package/lib/esm/utils/$account.js.map +1 -1
  79. package/lib/esm/utils/$account.mjs +5 -0
  80. package/lib/esm/utils/$config.js.map +1 -1
  81. package/lib/esm/utils/$config.mjs +4 -5
  82. package/lib/esm/utils/$erc20.js.map +1 -0
  83. package/lib/esm/utils/$erc20.mjs +41 -0
  84. package/lib/esm/utils/$require.js.map +1 -1
  85. package/lib/esm/utils/$require.mjs +2 -2
  86. package/lib/types/abi/$abi.d.ts +3 -1
  87. package/lib/types/blocks/BlockDateResolver.d.ts +1 -1
  88. package/lib/types/clients/Web3Client.d.ts +1 -1
  89. package/lib/types/clients/Web3ClientFactory.d.ts +10 -2
  90. package/lib/types/clients/debug/ClientDebugMethods.d.ts +1 -1
  91. package/lib/types/config/AConfigBase.d.ts +3 -0
  92. package/lib/types/config/Config.d.ts +2 -1
  93. package/lib/types/config/DefaultFactory.d.ts +2 -0
  94. package/lib/types/config/interface/IConfigData.d.ts +14 -2
  95. package/lib/types/contracts/ContractReader.d.ts +1 -1
  96. package/lib/types/explorer/IBlockchainExplorer.d.ts +6 -0
  97. package/lib/types/models/TPlatform.d.ts +1 -1
  98. package/lib/types/utils/$account.d.ts +1 -0
  99. package/lib/types/utils/$erc20.d.ts +5 -0
  100. package/lib/types/utils/$require.d.ts +2 -2
  101. package/package.json +1 -1
  102. package/src/abi/$abi.ts +34 -1
  103. package/src/blocks/BlockDateResolver.ts +1 -1
  104. package/src/clients/Web3Client.ts +48 -3
  105. package/src/clients/Web3ClientFactory.ts +33 -5
  106. package/src/clients/debug/ClientDebugMethods.ts +5 -1
  107. package/src/clients/utils/$web3Abi.ts +2 -2
  108. package/src/config/AConfigBase.ts +4 -0
  109. package/src/config/Config.ts +30 -8
  110. package/src/config/ConfigDefaults.ts +6 -2
  111. package/src/config/ConfigProvider.ts +5 -1
  112. package/src/config/DefaultFactory.ts +26 -0
  113. package/src/config/interface/IConfigData.ts +15 -2
  114. package/src/contracts/ContractBase.ts +6 -2
  115. package/src/contracts/ContractReader.ts +3 -40
  116. package/src/explorer/BlockchainExplorerFactory.ts +0 -1
  117. package/src/explorer/IBlockchainExplorer.ts +4 -0
  118. package/src/models/TPlatform.ts +1 -0
  119. package/src/rpc/RpcContract.ts +5 -33
  120. package/src/utils/$account.ts +5 -0
  121. package/src/utils/$config.ts +4 -6
  122. package/src/utils/$erc20.ts +53 -0
  123. package/src/utils/$require.ts +4 -4
  124. package/tsconfig.json +1 -2
  125. package/tsconfig.umd.json +1 -2
@@ -15,7 +15,7 @@ export declare class ClientDebugMethods {
15
15
  * @param intervalSeconds Default: 1 block in 1 second
16
16
  */
17
17
  mine(blocks?: number | bigint | string, intervalSeconds?: number | bigint): Promise<any>;
18
- setBalance(address: TAddress, amount: bigint | string): Promise<any>;
18
+ setBalance(address: TAddress, amount: bigint | number | string): Promise<any>;
19
19
  reset(params?: {
20
20
  forking?: {
21
21
  jsonRpcUrl?: any;
@@ -1,6 +1,9 @@
1
1
  import { IConfigData } from './interface/IConfigData';
2
2
  type TConfigParamsBase = {
3
3
  config?: Partial<IConfigData>;
4
+ rpc?: {
5
+ [platform: string]: string | string[] | IConfigData['web3']['']['endpoints'];
6
+ };
4
7
  };
5
8
  export type TConfigParamsNode = TConfigParamsBase & {
6
9
  dotenv?: boolean;
@@ -4,7 +4,8 @@ import { IConfigData } from './interface/IConfigData';
4
4
  export declare class Config {
5
5
  static fetch(parameters?: TConfigParamsNode | TConfigParamsBrowser): Promise<Appcfg<IConfigData> & IConfigData>;
6
6
  /** Will return a config that was previously loaded by fetch with any parameters or will trigger fetch with default parameters */
7
- static get(): Promise<Appcfg<IConfigData> & IConfigData>;
7
+ static get(config?: Partial<IConfigData>): Promise<Appcfg<IConfigData> & IConfigData>;
8
8
  static extend(json: any): Promise<void>;
9
+ static clean(): Config;
9
10
  }
10
11
  export declare const config: IConfigData;
@@ -0,0 +1,2 @@
1
+ import { IConfigData } from './interface/IConfigData';
2
+ export declare function DefaultFactory(config: IConfigData): IConfigData;
@@ -4,6 +4,7 @@ import { TAddress } from '../../models/TAddress';
4
4
  import { TPlatform } from '../../models/TPlatform';
5
5
  import { IRpcConfig } from '../../clients/ClientPool';
6
6
  import { TChain } from '../../models/TChain';
7
+ import { TEth } from '../../models/TEth';
7
8
  export interface IConfigData {
8
9
  settings: {
9
10
  /** Root path of the dequanto library */
@@ -24,10 +25,10 @@ export interface IConfigData {
24
25
  tokens: ITokenGlob[];
25
26
  blockchainExplorer: {
26
27
  [platform in TPlatform]: {
27
- key: string;
28
+ key?: string;
28
29
  host?: string;
29
30
  api?: string;
30
- wwww?: string;
31
+ www?: string;
31
32
  };
32
33
  };
33
34
  chains: TChain[];
@@ -69,4 +70,15 @@ export interface IConfigData {
69
70
  spotPriceAggregator?: {
70
71
  [platform in TPlatform]: TAddress;
71
72
  };
73
+ ns: {
74
+ [service: string]: {
75
+ [platform: string]: {
76
+ registry: TEth.Address;
77
+ resolver?: TEth.Address;
78
+ };
79
+ };
80
+ };
81
+ oracles: {
82
+ [service: string]: any;
83
+ };
72
84
  }
@@ -48,7 +48,7 @@ export declare class ContractReader implements IContractReader {
48
48
  [key: string]: any;
49
49
  } | any[];
50
50
  }): Promise<RpcTypes.Filter>;
51
- static read(client: Web3Client, address: TAddress, methodAbi: string): Promise<any>;
51
+ static read<TResult = any>(client: Web3Client, address: TAddress, methodAbi: string): Promise<TResult>;
52
52
  }
53
53
  export declare namespace ContractReaderUtils {
54
54
  class DeferredRequest<T = any> {
@@ -4,6 +4,12 @@ import { TEth } from '../models/TEth';
4
4
  import { TAddress } from '../models/TAddress';
5
5
  import { IVerifier } from './verifiers/IVerifier';
6
6
  export interface IBlockchainExplorer extends IAbiProvider, IVerifier {
7
+ config?: {
8
+ api?: {
9
+ url?: string;
10
+ key?: string;
11
+ };
12
+ };
7
13
  inMemoryDb: IContractDetails[];
8
14
  getContractMeta(q: string): Promise<IContractDetails>;
9
15
  getContractCreation(address: TEth.Address): Promise<{
@@ -1 +1 @@
1
- export type TPlatform = 'eth' | 'eth:goerli' | 'bsc' | 'polygon' | 'arbitrum' | 'xdai' | 'boba' | 'hardhat' | 'optimism' | 'avalanche' | `hh:${string}` | string;
1
+ export type TPlatform = 'eth' | 'eth:goerli' | 'bsc' | 'polygon' | 'arbitrum' | 'xdai' | 'boba' | 'hardhat' | 'optimism' | 'avalanche' | 'hh:memory' | `hh:${string}` | string;
@@ -4,4 +4,5 @@ export declare namespace $account {
4
4
  function isSafe(account: TAccount): account is SafeAccount;
5
5
  function isErc4337(account: TAccount): account is Erc4337Account;
6
6
  function isTimelock(account: TAccount): account is TimelockAccount;
7
+ function generate(name: string): EoAccount;
7
8
  }
@@ -0,0 +1,5 @@
1
+ import { TEth } from '../models/TEth';
2
+ import { Web3Client } from '../clients/Web3Client';
3
+ export declare namespace $erc20 {
4
+ function setBalanceAny(client: Web3Client, token: TEth.Address, account: TEth.Address, amount: bigint | number): Promise<void>;
5
+ }
@@ -17,8 +17,8 @@ export declare namespace $require {
17
17
  function Function<T>(val: T, message: string): NonNullable<T>;
18
18
  function Array<T>(val: T, message: string): NonNullable<T>;
19
19
  function String<T>(val: T, message: string): NonNullable<T>;
20
- function notNull<T>(val: T, message: string, ...logs: any[]): NonNullable<T>;
21
- function Null<T>(val: T, message: string, ...logs: any[]): T;
20
+ function notNull<T>(val: T, message?: string, ...logs: any[]): NonNullable<T>;
21
+ function Null<T>(val: T, message?: string, ...logs: any[]): T;
22
22
  function notEmpty<T extends string | Array<any> | {
23
23
  length: number;
24
24
  }>(val: T, message: string): NonNullable<T>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dequanto",
3
- "version": "0.2.49",
3
+ "version": "0.2.50",
4
4
  "author": {
5
5
  "name": "Alex Kit",
6
6
  "email": "alex.kit@atmajs.com"
package/src/abi/$abi.ts CHANGED
@@ -1,7 +1,9 @@
1
- import { TAbiInput } from '@dequanto/types/TAbi';
1
+ import { TAbiInput, TAbiItem, TAbiOutput } from '@dequanto/types/TAbi';
2
2
  import { ParamType } from './fragments';
3
3
  import { TEth } from '@dequanto/models/TEth';
4
4
  import { $abiCoder } from './$abiCoder';
5
+ import { $abiUtils } from '@dequanto/utils/$abiUtils';
6
+ import { $abiParser } from '@dequanto/utils/$abiParser';
5
7
 
6
8
  export namespace $abi {
7
9
  type TAbiType = string | ParamType | TAbiInput;
@@ -29,6 +31,37 @@ export namespace $abi {
29
31
  return isSingle ? result[0] : result;
30
32
  }
31
33
 
34
+ export function encodeCall(abi: string | TAbiItem, params?: any[]): TEth.Hex {
35
+ return $abiUtils.serializeMethodCallData(abi, params);
36
+ }
37
+
38
+ export function decodeReturn<T = any>(abi: string | TAbiItem | TAbiOutput[], hex: string): T {
39
+ let outputs = typeof abi === 'string'
40
+ ? ($abiParser.parseMethod(abi).outputs ?? [])
41
+ : (Array.isArray(abi) ? abi : abi.outputs ?? []);
42
+ let returnAbi = outputs;
43
+ let isDynamic: boolean = null;
44
+ if (outputs.length > 1) {
45
+ let isNamedTuple = outputs.every(x => x.name != null && x.name !== '');
46
+ if (isNamedTuple) {
47
+ returnAbi = [{ type: 'tuple', components: outputs, name: null }];
48
+ isDynamic = false;
49
+ }
50
+ }
51
+
52
+ try {
53
+ let arr = $abiCoder.decode(returnAbi as any, hex, {
54
+ dynamic: isDynamic
55
+ });
56
+ return returnAbi.length === 1 ? arr[0] : arr;
57
+ } catch (error) {
58
+ if (outputs.length === 1 && returnAbi.length === 1) {
59
+ return $abiCoder.decodeSingle(returnAbi[0], hex);
60
+ }
61
+ throw error;
62
+ }
63
+ }
64
+
32
65
  function ensureTypes (types: TAbiType | TAbiType[]): TAbiType[] {
33
66
  let arr = Array.isArray(types) ? types : [ types ];
34
67
  return arr.map($abiCoder.normalizeType);
@@ -1,9 +1,9 @@
1
1
  import alot from 'alot';
2
2
  import memd from 'memd';
3
- import { Web3Client } from '@dequanto/clients/Web3Client';
4
3
  import { TEth } from '@dequanto/models/TEth';
5
4
  import { $block } from '@dequanto/utils/$block';
6
5
  import { $date } from '@dequanto/utils/$date';
6
+ import type { Web3Client } from '@dequanto/clients/Web3Client';
7
7
 
8
8
  export class BlockDateResolver {
9
9
  private AVG_INITIAL = {
@@ -32,6 +32,8 @@ import { DataLike } from '@dequanto/utils/types';
32
32
  import { ErrorCode } from './ClientPoolStats';
33
33
  import { $date } from '@dequanto/utils/$date';
34
34
  import { WalletClient } from './WalletClient';
35
+ import alot from 'alot';
36
+ import { $abiParser } from '@dequanto/utils/$abiParser';
35
37
 
36
38
  export abstract class Web3Client implements IWeb3Client {
37
39
 
@@ -108,12 +110,55 @@ export abstract class Web3Client implements IWeb3Client {
108
110
  }
109
111
 
110
112
  // Submit contract calls in a batch and decode the responses.
111
- async batchContractCalls(requests: TRpcContractCall[], options?: {
113
+ async batchContractCalls(requests: TRpcContractCall[] | Promise<TRpcContractCall>[], options?: {
112
114
  allowErrors?: boolean
113
115
  }) {
114
116
  let reader = new RpcContract(this);
115
- let result = await reader.batch(requests, options);
116
- return result;
117
+
118
+ let requestsArrRaw = await Promise.all(requests);
119
+ let requestsArr = await alot(requestsArrRaw).mapAsync(async request => {
120
+ if (request == null) {
121
+ return null;
122
+ }
123
+ let abi = typeof request.abi === 'string'
124
+ ? [ $abiParser.parseMethod(request.abi) ]
125
+ : (Array.isArray(request.abi) ? request.abi : [ request.abi ])
126
+
127
+ let blockNumber = request.blockNumber;
128
+ if (blockNumber instanceof Date) {
129
+ let resolver = di.resolve(BlockDateResolver, this);
130
+ blockNumber = await resolver.getBlockNumberFor(blockNumber);
131
+ }
132
+ let method = request.method;
133
+ if (method == null) {
134
+ $require.eq(abi.length, 1, `No function method is provided, the single ABI item expected`);
135
+ method = abi[0].name;
136
+ }
137
+ return {
138
+ address: request.address,
139
+ abi: abi,
140
+ method: method,
141
+ params: request.params,
142
+ blockNumber: blockNumber,
143
+ options: options
144
+ } as TRpcContractCall;
145
+ }).toArrayAsync();
146
+
147
+ // Skip NULL request: mirror later as the NULL result
148
+ let mapped = [];
149
+ let rpcRequestsNotEmpty = [];
150
+ for (let i = 0; i < requestsArr.length; i++) {
151
+ if (requestsArr[i] == null) {
152
+ continue;
153
+ }
154
+ let idx = rpcRequestsNotEmpty.push(requestsArr[i]) - 1;
155
+ mapped[i] = idx;
156
+ }
157
+
158
+ let outputs = await reader.batch(rpcRequestsNotEmpty, options);
159
+ return requestsArr.map((_, i) => {
160
+ return outputs[mapped[i]] ?? null;
161
+ });
117
162
  }
118
163
 
119
164
  getEventStream(address: TEth.Address, abi: TAbiItem[], event: string) {
@@ -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
  }
@@ -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);
@@ -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 }>;
@@ -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;