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.
- package/contracts/oz/Proxy.sol +1 -0
- 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/BlockchainExplorer.js +9 -9
- package/lib/cjs/explorer/BlockchainExplorer.js.map +1 -1
- package/lib/cjs/explorer/BlockchainExplorerFactory.js +1 -1
- package/lib/cjs/explorer/BlockchainExplorerFactory.js.map +1 -1
- package/lib/cjs/explorer/BlockchainExplorerProvider.js +1 -1
- package/lib/cjs/explorer/BlockchainExplorerProvider.js.map +1 -1
- package/lib/cjs/explorer/BlockchainExplorerStorage.js +2 -2
- package/lib/cjs/explorer/BlockchainExplorerStorage.js.map +1 -1
- package/lib/cjs/explorer/ContractVerifier.js +10 -10
- package/lib/cjs/explorer/ContractVerifier.js.map +1 -1
- package/lib/cjs/explorer/verifiers/FsHtmlVerifier.js +1 -1
- package/lib/cjs/explorer/verifiers/FsHtmlVerifier.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/BlockchainExplorer.js.map +1 -1
- package/lib/esm/explorer/BlockchainExplorer.mjs +9 -9
- package/lib/esm/explorer/BlockchainExplorerFactory.js.map +1 -1
- package/lib/esm/explorer/BlockchainExplorerFactory.mjs +1 -1
- package/lib/esm/explorer/BlockchainExplorerProvider.js.map +1 -1
- package/lib/esm/explorer/BlockchainExplorerProvider.mjs +1 -1
- package/lib/esm/explorer/BlockchainExplorerStorage.js.map +1 -1
- package/lib/esm/explorer/BlockchainExplorerStorage.mjs +2 -2
- package/lib/esm/explorer/ContractVerifier.js.map +1 -1
- package/lib/esm/explorer/ContractVerifier.mjs +10 -10
- package/lib/esm/explorer/verifiers/FsHtmlVerifier.js.map +1 -1
- package/lib/esm/explorer/verifiers/FsHtmlVerifier.mjs +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/BlockchainExplorerFactory.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/skills/README.md +45 -0
- package/{docs/ai → skills/dequanto}/INDEX.md +16 -5
- package/skills/dequanto/SKILL.md +73 -0
- package/skills/dequanto/examples/config.spec.ts +113 -0
- package/skills/dequanto/examples/contract-read.spec.ts +112 -0
- package/skills/dequanto/examples/contract-write.spec.ts +68 -0
- package/skills/dequanto/examples/deploy-contract.spec.ts +69 -0
- package/{docs/ai → skills/dequanto}/examples/erc4337-userop.spec.ts +13 -11
- package/skills/dequanto/examples/explorer-abi.spec.ts +21 -0
- package/{docs/ai/examples/generate-client.spec.ts → skills/dequanto/examples/generate-contract-class.spec.ts} +7 -4
- package/skills/dequanto/examples/hardhat-debug.spec.ts +29 -0
- package/skills/dequanto/examples/hardhat-fork.spec.ts +31 -0
- package/{docs/ai → skills/dequanto}/examples/index-events.spec.ts +10 -8
- package/skills/dequanto/examples/rpc-read.spec.ts +59 -0
- package/{docs/ai → skills/dequanto}/examples/safe-batch.spec.ts +10 -9
- package/skills/dequanto/examples/send-transaction.spec.ts +34 -0
- package/skills/dequanto/examples/storage.spec.ts +58 -0
- package/skills/dequanto/examples/token-transfer.spec.ts +29 -0
- package/skills/dequanto/examples/utils.spec.ts +63 -0
- package/{docs/ai → skills/dequanto}/references/contracts.md +1 -1
- package/{docs/ai → skills/dequanto}/references/deployments.md +4 -2
- package/{docs/ai → skills/dequanto}/references/events-indexing.md +1 -1
- package/{docs/ai → skills/dequanto}/references/explorer.md +1 -1
- package/{docs/ai → skills/dequanto}/references/generation.md +36 -13
- package/skills/dequanto/references/hardhat.md +113 -0
- package/{docs/ai → skills/dequanto}/references/rpc-clients.md +25 -5
- package/{docs/ai → skills/dequanto}/references/safe-erc4337.md +2 -2
- package/skills/dequanto/references/storage.md +122 -0
- package/{docs/ai → skills/dequanto}/references/tokens-accounts.md +12 -6
- package/{docs/ai → skills/dequanto}/references/transactions.md +6 -4
- package/skills/dequanto/references/utils.md +131 -0
- 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/BlockchainExplorer.ts +9 -9
- package/src/explorer/BlockchainExplorerFactory.ts +1 -2
- package/src/explorer/BlockchainExplorerProvider.ts +1 -1
- package/src/explorer/BlockchainExplorerStorage.ts +2 -2
- package/src/explorer/ContractVerifier.ts +10 -10
- package/src/explorer/IBlockchainExplorer.ts +4 -0
- package/src/explorer/verifiers/FsHtmlVerifier.ts +1 -1
- 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 +3 -3
- package/tsconfig.umd.json +1 -2
- package/docs/ai/examples/contract-read.spec.ts +0 -44
- package/docs/ai/examples/contract-write.spec.ts +0 -16
- package/docs/ai/examples/deploy-contract.spec.ts +0 -32
- package/docs/ai/examples/explorer-abi.spec.ts +0 -18
- package/docs/ai/examples/rpc-read.spec.ts +0 -15
- package/docs/ai/examples/send-transaction.spec.ts +0 -22
- package/docs/ai/examples/storage-read.spec.ts +0 -27
- package/docs/ai/examples/token-transfer.spec.ts +0 -22
- package/docs/ai/references/storage.md +0 -93
- package/docs/ai/skill/dequanto/SKILL.md +0 -59
- /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
|
-
|
|
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
|
}
|
|
@@ -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
|
|
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
|
|
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(`
|
|
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
|
-
//
|
|
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
|
|
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
|
|
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}
|
|
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}"
|
|
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}"
|
|
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
|
|
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
|
|
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:
|
|
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:
|
|
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(`
|
|
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
|
-
//
|
|
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
|
|
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
|
-
//
|
|
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
|
|
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"
|
|
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(`
|
|
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
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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 ');
|