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.
- package/contracts/oz/Proxy.sol +1 -0
- package/docs/ai/INDEX.md +4 -3
- package/docs/ai/examples/config.spec.ts +113 -0
- package/docs/ai/examples/contract-read.spec.ts +81 -13
- package/docs/ai/examples/contract-write.spec.ts +61 -9
- package/docs/ai/examples/deploy-contract.spec.ts +53 -16
- package/docs/ai/examples/erc4337-userop.spec.ts +7 -5
- package/docs/ai/examples/explorer-abi.spec.ts +9 -6
- package/docs/ai/examples/{generate-client.spec.ts → generate-contract-class.spec.ts} +6 -3
- package/docs/ai/examples/index-events.spec.ts +8 -6
- package/docs/ai/examples/rpc-read.spec.ts +32 -5
- package/docs/ai/examples/safe-batch.spec.ts +5 -4
- package/docs/ai/examples/send-transaction.spec.ts +23 -11
- package/docs/ai/examples/storage-read.spec.ts +15 -7
- package/docs/ai/examples/token-transfer.spec.ts +22 -15
- package/docs/ai/references/generation.md +30 -7
- package/docs/ai/skill/dequanto/SKILL.md +5 -1
- package/lib/cjs/abi/$abi.js +33 -0
- package/lib/cjs/abi/$abi.js.map +1 -1
- package/lib/cjs/blocks/BlockDateResolver.js.map +1 -1
- package/lib/cjs/clients/Web3Client.js +43 -2
- package/lib/cjs/clients/Web3Client.js.map +1 -1
- package/lib/cjs/clients/Web3ClientFactory.js +26 -4
- package/lib/cjs/clients/Web3ClientFactory.js.map +1 -1
- package/lib/cjs/clients/debug/ClientDebugMethods.js +4 -0
- package/lib/cjs/clients/debug/ClientDebugMethods.js.map +1 -1
- package/lib/cjs/clients/utils/$web3Abi.js +1 -1
- package/lib/cjs/clients/utils/$web3Abi.js.map +1 -1
- package/lib/cjs/config/Config.js +28 -6
- package/lib/cjs/config/Config.js.map +1 -1
- package/lib/cjs/config/ConfigDefaults.js +6 -2
- package/lib/cjs/config/ConfigDefaults.js.map +1 -1
- package/lib/cjs/config/ConfigProvider.js +5 -0
- package/lib/cjs/config/ConfigProvider.js.map +1 -1
- package/lib/cjs/config/DefaultFactory.js +27 -0
- package/lib/cjs/config/DefaultFactory.js.map +1 -0
- package/lib/cjs/contracts/ContractBase.js +6 -2
- package/lib/cjs/contracts/ContractBase.js.map +1 -1
- package/lib/cjs/contracts/ContractReader.js +1 -35
- package/lib/cjs/contracts/ContractReader.js.map +1 -1
- package/lib/cjs/explorer/BlockchainExplorerFactory.js.map +1 -1
- package/lib/cjs/rpc/RpcContract.js +4 -32
- package/lib/cjs/rpc/RpcContract.js.map +1 -1
- package/lib/cjs/utils/$account.js +5 -0
- package/lib/cjs/utils/$account.js.map +1 -1
- package/lib/cjs/utils/$config.js +4 -5
- package/lib/cjs/utils/$config.js.map +1 -1
- package/lib/cjs/utils/$erc20.js +47 -0
- package/lib/cjs/utils/$erc20.js.map +1 -0
- package/lib/cjs/utils/$require.js +2 -2
- package/lib/cjs/utils/$require.js.map +1 -1
- package/lib/esm/abi/$abi.js.map +1 -1
- package/lib/esm/abi/$abi.mjs +33 -0
- package/lib/esm/blocks/BlockDateResolver.js.map +1 -1
- package/lib/esm/clients/Web3Client.js.map +1 -1
- package/lib/esm/clients/Web3Client.mjs +43 -2
- package/lib/esm/clients/Web3ClientFactory.js.map +1 -1
- package/lib/esm/clients/Web3ClientFactory.mjs +26 -4
- package/lib/esm/clients/debug/ClientDebugMethods.js.map +1 -1
- package/lib/esm/clients/debug/ClientDebugMethods.mjs +4 -0
- package/lib/esm/clients/utils/$web3Abi.js.map +1 -1
- package/lib/esm/clients/utils/$web3Abi.mjs +1 -1
- package/lib/esm/config/Config.js.map +1 -1
- package/lib/esm/config/Config.mjs +28 -6
- package/lib/esm/config/ConfigDefaults.js.map +1 -1
- package/lib/esm/config/ConfigDefaults.mjs +6 -2
- package/lib/esm/config/ConfigProvider.js.map +1 -1
- package/lib/esm/config/ConfigProvider.mjs +5 -0
- package/lib/esm/config/DefaultFactory.js.map +1 -0
- package/lib/esm/config/DefaultFactory.mjs +23 -0
- package/lib/esm/contracts/ContractBase.js.map +1 -1
- package/lib/esm/contracts/ContractBase.mjs +6 -2
- package/lib/esm/contracts/ContractReader.js.map +1 -1
- package/lib/esm/contracts/ContractReader.mjs +1 -35
- package/lib/esm/explorer/BlockchainExplorerFactory.js.map +1 -1
- package/lib/esm/rpc/RpcContract.js.map +1 -1
- package/lib/esm/rpc/RpcContract.mjs +4 -32
- package/lib/esm/utils/$account.js.map +1 -1
- package/lib/esm/utils/$account.mjs +5 -0
- package/lib/esm/utils/$config.js.map +1 -1
- package/lib/esm/utils/$config.mjs +4 -5
- package/lib/esm/utils/$erc20.js.map +1 -0
- package/lib/esm/utils/$erc20.mjs +41 -0
- package/lib/esm/utils/$require.js.map +1 -1
- package/lib/esm/utils/$require.mjs +2 -2
- package/lib/types/abi/$abi.d.ts +3 -1
- package/lib/types/blocks/BlockDateResolver.d.ts +1 -1
- package/lib/types/clients/Web3Client.d.ts +1 -1
- package/lib/types/clients/Web3ClientFactory.d.ts +10 -2
- package/lib/types/clients/debug/ClientDebugMethods.d.ts +1 -1
- package/lib/types/config/AConfigBase.d.ts +3 -0
- package/lib/types/config/Config.d.ts +2 -1
- package/lib/types/config/DefaultFactory.d.ts +2 -0
- package/lib/types/config/interface/IConfigData.d.ts +14 -2
- package/lib/types/contracts/ContractReader.d.ts +1 -1
- package/lib/types/explorer/IBlockchainExplorer.d.ts +6 -0
- package/lib/types/models/TPlatform.d.ts +1 -1
- package/lib/types/utils/$account.d.ts +1 -0
- package/lib/types/utils/$erc20.d.ts +5 -0
- package/lib/types/utils/$require.d.ts +2 -2
- package/package.json +1 -1
- package/src/abi/$abi.ts +34 -1
- package/src/blocks/BlockDateResolver.ts +1 -1
- package/src/clients/Web3Client.ts +48 -3
- package/src/clients/Web3ClientFactory.ts +33 -5
- package/src/clients/debug/ClientDebugMethods.ts +5 -1
- package/src/clients/utils/$web3Abi.ts +2 -2
- package/src/config/AConfigBase.ts +4 -0
- package/src/config/Config.ts +30 -8
- package/src/config/ConfigDefaults.ts +6 -2
- package/src/config/ConfigProvider.ts +5 -1
- package/src/config/DefaultFactory.ts +26 -0
- package/src/config/interface/IConfigData.ts +15 -2
- package/src/contracts/ContractBase.ts +6 -2
- package/src/contracts/ContractReader.ts +3 -40
- package/src/explorer/BlockchainExplorerFactory.ts +0 -1
- package/src/explorer/IBlockchainExplorer.ts +4 -0
- package/src/models/TPlatform.ts +1 -0
- package/src/rpc/RpcContract.ts +5 -33
- package/src/utils/$account.ts +5 -0
- package/src/utils/$config.ts +4 -6
- package/src/utils/$erc20.ts +53 -0
- package/src/utils/$require.ts +4 -4
- package/tsconfig.json +1 -2
- 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;
|
|
@@ -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
|
|
28
|
+
key?: string;
|
|
28
29
|
host?: string;
|
|
29
30
|
api?: string;
|
|
30
|
-
|
|
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<
|
|
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
|
}
|
|
@@ -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
|
|
21
|
-
function Null<T>(val: T, message
|
|
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
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
|
-
|
|
116
|
-
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
11
|
+
} else if (Array.isArray(abi)) {
|
|
12
12
|
arr = abi;
|
|
13
13
|
} else {
|
|
14
14
|
arr = [ abi ];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
let first =
|
|
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 & {
|
package/src/config/Config.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
32
|
+
key?: string;
|
|
32
33
|
host?: string;
|
|
33
34
|
api?: string
|
|
34
|
-
|
|
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 }>;
|