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
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Web3ClientFactory } from '
|
|
2
|
-
import { BlockchainExplorerFactory } from '
|
|
3
|
-
import { Erc4337Service } from '
|
|
4
|
-
import { UserOperation } from '
|
|
5
|
-
import { $address } from '
|
|
6
|
-
import { $erc4337 } from '
|
|
1
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
2
|
+
import { BlockchainExplorerFactory } from 'dequanto/explorer/BlockchainExplorerFactory';
|
|
3
|
+
import { Erc4337Service } from 'dequanto/erc4337/Erc4337Service';
|
|
4
|
+
import { UserOperation } from 'dequanto/erc4337/models/UserOperation';
|
|
5
|
+
import { $address } from 'dequanto/utils/$address';
|
|
6
|
+
import { $erc4337 } from 'dequanto/erc4337/utils/$erc4337';
|
|
7
|
+
import { $require } from 'dequanto/utils/$require';
|
|
7
8
|
|
|
8
9
|
UTest({
|
|
9
10
|
async 'hash a UserOperation and create an ERC-4337 service' () {
|
|
@@ -28,10 +29,11 @@ UTest({
|
|
|
28
29
|
paymasterAndData: '0x',
|
|
29
30
|
signature: '0x'
|
|
30
31
|
};
|
|
32
|
+
const entryPointAddress = '0xc6e7df5e7b4f2a278906862b61205850344d4e7d';
|
|
33
|
+
const chainId = 1;
|
|
34
|
+
const hash = $erc4337.hash(op,entryPointAddress , chainId);
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
has_(hash, /^0x[a-fA-F0-9]{64}$/);
|
|
35
|
-
notEq_(service, null);
|
|
36
|
+
$require.match(/^0x[a-fA-F0-9]{64}$/, hash);
|
|
37
|
+
$require.notNull(service);
|
|
36
38
|
}
|
|
37
|
-
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BlockchainExplorerFactory } from 'dequanto/explorer/BlockchainExplorerFactory';
|
|
2
|
+
import { $address } from 'dequanto/utils/$address';
|
|
3
|
+
import { $require } from 'dequanto/utils/$require';
|
|
4
|
+
|
|
5
|
+
UTest({
|
|
6
|
+
async 'fetch stable USDC ABI and source from configured Ethereum explorer' () {
|
|
7
|
+
const explorer = await BlockchainExplorerFactory.getAsync('eth');
|
|
8
|
+
const address = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
|
|
9
|
+
|
|
10
|
+
const { abi, implementation } = await explorer.getContractAbi(address);
|
|
11
|
+
const source = await explorer.getContractSource(implementation);
|
|
12
|
+
const creation = await explorer.getContractCreation(address);
|
|
13
|
+
|
|
14
|
+
$require.AddressNotEmpty(implementation);
|
|
15
|
+
$require.True($address.eq(implementation, address) === false, `USDC is Proxy: ${implementation} != ${address}`);
|
|
16
|
+
$require.gt(JSON.parse(abi).length, 0);
|
|
17
|
+
$require.match(/FiatToken|Proxy|USDC/i, source.ContractName);
|
|
18
|
+
$require.AddressNotEmpty(creation.creator);
|
|
19
|
+
$require.TxHash(creation.txHash);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { Generator } from '
|
|
1
|
+
import { Generator } from 'dequanto/gen/Generator';
|
|
2
|
+
import { $require } from 'dequanto/utils/$require';
|
|
2
3
|
import { File } from 'atma-io';
|
|
3
4
|
|
|
5
|
+
// Generator is the low-level API for creating contract classes programmatically.
|
|
6
|
+
// Prefer 0xweb install for third-party contracts and @0xweb/hardhat for local Hardhat contracts.
|
|
4
7
|
UTest({
|
|
5
|
-
async 'generate a typed contract
|
|
8
|
+
async 'generate a typed contract class from a fixture artifact' () {
|
|
6
9
|
const output = './test/tmp/ai-examples/hardhat/';
|
|
7
10
|
const gen = new Generator({
|
|
8
11
|
name: 'AnyERC20',
|
|
@@ -16,7 +19,7 @@ UTest({
|
|
|
16
19
|
const result = await gen.generate();
|
|
17
20
|
const source = await File.readAsync<string>(result.main, { skipHooks: true });
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
$require.has('class AnyERC20', source);
|
|
23
|
+
$require.has('ContractBase', source);
|
|
21
24
|
}
|
|
22
25
|
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
2
|
+
import { $require } from 'dequanto/utils/$require';
|
|
3
|
+
|
|
4
|
+
UTest({
|
|
5
|
+
async 'change balances, storage, and time on Hardhat and roll back'() {
|
|
6
|
+
const client = await Web3ClientFactory.getAsync('hh:memory');
|
|
7
|
+
const address = '0x0000000000000000000000000000000000001234';
|
|
8
|
+
const balanceBefore = await client.getBalance(address);
|
|
9
|
+
const storageBefore = await client.getStorageAt(address, 0);
|
|
10
|
+
const blockBefore = await client.getBlockNumber();
|
|
11
|
+
const id = await client.debug.snapshot();
|
|
12
|
+
|
|
13
|
+
await client.debug.setBalance(address, 10n ** 18n);
|
|
14
|
+
$require.eq(await client.getBalance(address), 10n ** 18n);
|
|
15
|
+
|
|
16
|
+
// The same operation writes a known slot at any contract address.
|
|
17
|
+
await client.debug.setStorageAt(address, 0, '0x2a');
|
|
18
|
+
$require.eq(BigInt(await client.getStorageAt(address, 0)), 42n);
|
|
19
|
+
|
|
20
|
+
await client.debug.mine('5days');
|
|
21
|
+
$require.eq(await client.getBlockNumber(), blockBefore + 432_000);
|
|
22
|
+
|
|
23
|
+
await client.debug.revert(id);
|
|
24
|
+
|
|
25
|
+
$require.eq(await client.getBalance(address), balanceBefore);
|
|
26
|
+
$require.eq(await client.getStorageAt(address, 0), storageBefore);
|
|
27
|
+
$require.eq(await client.getBlockNumber(), blockBefore);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
2
|
+
import { ERC20 } from 'dequanto/prebuilt/openzeppelin/ERC20';
|
|
3
|
+
import { $erc20 } from 'dequanto/utils/$erc20';
|
|
4
|
+
import { $require } from 'dequanto/utils/$require';
|
|
5
|
+
|
|
6
|
+
UTest({
|
|
7
|
+
async 'set an ERC20 balance and transfer from an impersonated account on a fork' () {
|
|
8
|
+
// Requires an accessible Ethereum RPC from the dequanto configuration.
|
|
9
|
+
const client = await Web3ClientFactory.getAsync('hh:memory:eth');
|
|
10
|
+
// To use an already running local Ethereum fork, use getAsync('hh:eth').
|
|
11
|
+
const usdc = new ERC20('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', client);
|
|
12
|
+
const account = {
|
|
13
|
+
address: '0x0000000000000000000000000000000000001234',
|
|
14
|
+
type: 'impersonated'
|
|
15
|
+
} as const;
|
|
16
|
+
const to = '0x0000000000000000000000000000000000005678';
|
|
17
|
+
const amount = 1_000_000n; // 1 USDC (6 decimals).
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
await client.debug.setBalance(account.address, 10n ** 18n);
|
|
21
|
+
await $erc20.setBalanceAny(client, usdc.address, account.address, amount);
|
|
22
|
+
$require.eq(await usdc.balanceOf(account.address), amount);
|
|
23
|
+
|
|
24
|
+
const recipientBalance = await usdc.balanceOf(to);
|
|
25
|
+
const writer = await usdc.$receipt().transfer(account, to, amount);
|
|
26
|
+
|
|
27
|
+
$require.Hex(writer.receipt.transactionHash);
|
|
28
|
+
$require.eq(await usdc.balanceOf(account.address), 0n);
|
|
29
|
+
$require.eq(await usdc.balanceOf(to), recipientBalance + amount);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { Web3ClientFactory } from '
|
|
2
|
-
import { EventsIndexer } from '
|
|
3
|
-
import { ERC20 } from '
|
|
1
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
2
|
+
import { EventsIndexer } from 'dequanto/indexer/EventsIndexer';
|
|
3
|
+
import { ERC20 } from 'dequanto/prebuilt/openzeppelin/ERC20';
|
|
4
|
+
import { $require } from 'dequanto/utils/$require';
|
|
4
5
|
|
|
5
6
|
UTest({
|
|
6
7
|
async 'index stable USDC Transfer logs from live Ethereum RPC' () {
|
|
7
8
|
const client = await Web3ClientFactory.getAsync('eth');
|
|
8
9
|
const usdc = new ERC20('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', client);
|
|
9
10
|
|
|
11
|
+
// EventsIndexer stores fetched logs in the local cache directory, so later runs can reuse cached ranges.
|
|
10
12
|
const indexer = new EventsIndexer(usdc, {
|
|
11
13
|
name: 'USDCTransfersAiExample',
|
|
12
14
|
fs: {
|
|
@@ -19,9 +21,9 @@ UTest({
|
|
|
19
21
|
toBlock: 18_000_010
|
|
20
22
|
});
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
$require.gt(logs.length, 0);
|
|
25
|
+
$require.gte(infos.fetched + infos.cached, logs.length);
|
|
26
|
+
$require.eq(logs[0].event, 'Transfer');
|
|
27
|
+
$require.TxHash(logs[0].transactionHash);
|
|
26
28
|
}
|
|
27
|
-
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
2
|
+
import { BlockDateResolver } from 'dequanto/blocks/BlockDateResolver';
|
|
3
|
+
import { Config } from 'dequanto/config/Config';
|
|
4
|
+
import { $date } from 'dequanto/utils/$date';
|
|
5
|
+
import { $require } from 'dequanto/utils/$require';
|
|
6
|
+
|
|
7
|
+
UTest({
|
|
8
|
+
async 'read common RPC data via Web3Client directly' () {
|
|
9
|
+
const cfg = await Config.fetch();
|
|
10
|
+
|
|
11
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
12
|
+
|
|
13
|
+
const chainId = await client.getChainId();
|
|
14
|
+
const latest = await client.getBlockNumber();
|
|
15
|
+
const block = await client.getBlock('latest');
|
|
16
|
+
const balance = await client.getBalance('0x0000000000000000000000000000000000000000');
|
|
17
|
+
|
|
18
|
+
$require.eq(chainId, 1);
|
|
19
|
+
$require.gt(Number(latest), 0);
|
|
20
|
+
$require.gt(Number(block.timestamp), 0);
|
|
21
|
+
$require.gte(balance, 0n);
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
async 'call low-level RPC methods from the generated Rpc client' () {
|
|
25
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
26
|
+
// getRpc exposes the full generated RPC method list from OpenRPC specs, including eth, core-geth, MetaMask, and Flashbots methods.
|
|
27
|
+
const rpc = await client.getRpc();
|
|
28
|
+
|
|
29
|
+
const latest = await rpc.eth_blockNumber();
|
|
30
|
+
const block = await rpc.eth_getBlockByNumber('latest', false);
|
|
31
|
+
const balance = await rpc.eth_getBalance('0x0000000000000000000000000000000000000000', 'latest');
|
|
32
|
+
|
|
33
|
+
$require.gt(Number(latest), 0);
|
|
34
|
+
$require.gt(Number(block.timestamp), 0);
|
|
35
|
+
$require.gte(balance, 0n);
|
|
36
|
+
|
|
37
|
+
// Use rpc.request for custom or not-yet-generated RPC methods.
|
|
38
|
+
const response = await rpc.request({
|
|
39
|
+
method: 'eth_blockNumber',
|
|
40
|
+
params: []
|
|
41
|
+
});
|
|
42
|
+
$require.gt(Number(response), 0);
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
async 'resolve a block number and timestamp from a date' () {
|
|
46
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
47
|
+
const resolver = new BlockDateResolver(client);
|
|
48
|
+
const date = new Date('2026-03-03T10:20:00Z');
|
|
49
|
+
|
|
50
|
+
const blockNumber = await resolver.getBlockNumberFor(date);
|
|
51
|
+
const info = await resolver.getBlockInfoFor(date);
|
|
52
|
+
const blockDate = await resolver.getDate(blockNumber);
|
|
53
|
+
|
|
54
|
+
$require.eq(blockNumber, 24576295);
|
|
55
|
+
$require.eq(blockNumber, 24576295);
|
|
56
|
+
$require.lte(Math.abs($date.toUnixTimestamp(date) - info.timestamp), 1);
|
|
57
|
+
$require.eq(blockDate.toISOString(), new Date('2026-03-03T10:19:59Z').toISOString());
|
|
58
|
+
}
|
|
59
|
+
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { HardhatProvider } from '
|
|
2
|
-
import { InMemoryServiceTransport } from '
|
|
3
|
-
import { SafeTx } from '
|
|
4
|
-
import { $address } from '
|
|
5
|
-
import {
|
|
1
|
+
import { HardhatProvider } from 'dequanto/hardhat/HardhatProvider';
|
|
2
|
+
import { InMemoryServiceTransport } from 'dequanto/safe/transport/InMemoryServiceTransport';
|
|
3
|
+
import { SafeTx } from 'dequanto/safe/SafeTx';
|
|
4
|
+
import { $address } from 'dequanto/utils/$address';
|
|
5
|
+
import { $require } from 'dequanto/utils/$require';
|
|
6
|
+
import { SafeAccount } from 'dequanto/models/TAccount';
|
|
6
7
|
|
|
7
8
|
UTest({
|
|
8
9
|
async 'build a Safe batch from generated tx data' () {
|
|
@@ -45,11 +46,11 @@ UTest({
|
|
|
45
46
|
await token.$data().transfer(safeAccount, owner2.address, 50n)
|
|
46
47
|
];
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
$require.eq(txs.length, 2);
|
|
49
50
|
txs.forEach(tx => {
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
$require.True($address.eq(tx.to, token.address));
|
|
52
|
+
$require.match(/^0x[a-fA-F0-9]+$/, tx.data);
|
|
52
53
|
});
|
|
53
|
-
|
|
54
|
+
$require.notNull(safeTx);
|
|
54
55
|
}
|
|
55
56
|
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
2
|
+
import { TxDataBuilder } from 'dequanto/txs/TxDataBuilder';
|
|
3
|
+
import { TxWriter } from 'dequanto/txs/TxWriter';
|
|
4
|
+
import { $account } from 'dequanto/utils/$account';
|
|
5
|
+
import { $address } from 'dequanto/utils/$address';
|
|
6
|
+
import { $number } from 'dequanto/utils/$number';
|
|
7
|
+
import { $require } from 'dequanto/utils/$require';
|
|
8
|
+
|
|
9
|
+
UTest({
|
|
10
|
+
async 'build native transfer tx data with gas fields' () {
|
|
11
|
+
const client = await Web3ClientFactory.getAsync('hh:memory');
|
|
12
|
+
const alice = $account.generate('alice');
|
|
13
|
+
await client.debug.setBalance(alice.address, 1e18);
|
|
14
|
+
const bob = $account.generate('bob');
|
|
15
|
+
|
|
16
|
+
const builder = new TxDataBuilder(client, alice, {
|
|
17
|
+
to: bob.address
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
builder.setValue(0.05);
|
|
21
|
+
await builder.setGas({ gasEstimation: false, gasLimit: 21_000 });
|
|
22
|
+
|
|
23
|
+
$require.True($address.eq(builder.data.to, bob.address));
|
|
24
|
+
$require.eq(builder.data.value, $number.toHex(5e16));
|
|
25
|
+
$require.eq(Number(builder.data.gas), 21_000);
|
|
26
|
+
$require.notNull(builder.data.maxFeePerGas ?? builder.data.gasPrice);
|
|
27
|
+
|
|
28
|
+
const writer = TxWriter.create(client, builder, alice);
|
|
29
|
+
const tx = await writer.send();
|
|
30
|
+
const receipt = await tx.wait();
|
|
31
|
+
$require.TxHash(receipt.transactionHash);
|
|
32
|
+
$require.eq(await client.getBalance(bob.address), BigInt(5e16));
|
|
33
|
+
}
|
|
34
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { AavePool } from '../../../0xc/eth/AavePool/AavePool';
|
|
2
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
3
|
+
import { HardhatProvider } from 'dequanto/hardhat/HardhatProvider';
|
|
4
|
+
import { SlotsParser } from 'dequanto/solidity/SlotsParser';
|
|
5
|
+
import { SlotsStorage } from 'dequanto/solidity/SlotsStorage';
|
|
6
|
+
import { $require } from 'dequanto/utils/$require';
|
|
7
|
+
|
|
8
|
+
// Generated classes include the storage layout: use instance.storage.$set(name, value).
|
|
9
|
+
// SlotsParser and SlotsStorage provide the low-level alternative for Solidity source.
|
|
10
|
+
UTest({
|
|
11
|
+
async 'read and set AavePool storage by variable name on an Ethereum fork' () {
|
|
12
|
+
const client = await Web3ClientFactory.getAsync('hh:memory:eth');
|
|
13
|
+
const pool = new AavePool(undefined, client);
|
|
14
|
+
const premiumBefore = await pool.FLASHLOAN_PREMIUM_TOTAL();
|
|
15
|
+
const packedNeighborBefore = await pool.storage.__DEPRECATED_flashLoanPremiumToProtocol();
|
|
16
|
+
const id = await client.debug.snapshot();
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const premium = premiumBefore + 1n;
|
|
20
|
+
await pool.storage.$set('_flashLoanPremium', premium);
|
|
21
|
+
|
|
22
|
+
$require.eq(await pool.storage._flashLoanPremium(), premium);
|
|
23
|
+
$require.eq(await pool.FLASHLOAN_PREMIUM_TOTAL(), premium);
|
|
24
|
+
// Both uint128 fields share slot 58; preserve the neighboring field.
|
|
25
|
+
$require.eq(await pool.storage.__DEPRECATED_flashLoanPremiumToProtocol(), packedNeighborBefore);
|
|
26
|
+
} finally {
|
|
27
|
+
await client.debug.revert(id);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
$require.eq(await pool.FLASHLOAN_PREMIUM_TOTAL(), premiumBefore);
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
async 'read and write Solidity storage with SlotsParser and SlotsStorage' () {
|
|
34
|
+
const code = `
|
|
35
|
+
contract Vault {
|
|
36
|
+
uint256 public count = 123;
|
|
37
|
+
mapping(address => uint256) balances;
|
|
38
|
+
|
|
39
|
+
constructor () {
|
|
40
|
+
balances[address(0x1000000000000000000000000000000000000001)] = 7;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
const hh = new HardhatProvider();
|
|
45
|
+
const client = await Web3ClientFactory.getAsync('hh:memory');
|
|
46
|
+
const { contract } = await hh.deployCode(code, { client });
|
|
47
|
+
|
|
48
|
+
const slots = await SlotsParser.slots({ path: '', code }, 'Vault');
|
|
49
|
+
const storage = SlotsStorage.createWithClient(client, contract.address, slots);
|
|
50
|
+
|
|
51
|
+
$require.eq(await storage.get('count'), 123n);
|
|
52
|
+
$require.eq(await storage.get('balances["0x1000000000000000000000000000000000000001"]'), 7n);
|
|
53
|
+
|
|
54
|
+
// Direct storage writes require a debug network such as Hardhat.
|
|
55
|
+
await storage.set('count', 500n);
|
|
56
|
+
$require.eq(await storage.get('count'), 500n);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
2
|
+
import { ERC20 } from 'dequanto/prebuilt/openzeppelin/ERC20';
|
|
3
|
+
import { $account } from 'dequanto/utils/$account';
|
|
4
|
+
import { $erc20 } from 'dequanto/utils/$erc20';
|
|
5
|
+
import { $require } from 'dequanto/utils/$require';
|
|
6
|
+
|
|
7
|
+
const USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' as const;
|
|
8
|
+
const INITIAL_SENDER_BALANCE = 100_000_000n;
|
|
9
|
+
const TRANSFER_AMOUNT = 42_000_000n;
|
|
10
|
+
|
|
11
|
+
UTest({
|
|
12
|
+
async 'transfer USDC with a prebuilt ERC20 contract class' () {
|
|
13
|
+
const client = await Web3ClientFactory.getAsync('hh:memory:eth');
|
|
14
|
+
const sender = $account.generate('sender');
|
|
15
|
+
const recipient = $account.generate('recipient');
|
|
16
|
+
const usdc = new ERC20(USDC, client);
|
|
17
|
+
|
|
18
|
+
// Test-only fork setup: fund the sender with native gas and USDC balance.
|
|
19
|
+
await client.debug.setBalance(sender.address, 1e18);
|
|
20
|
+
await $erc20.setBalanceAny(client, usdc.address, sender.address, 100);
|
|
21
|
+
|
|
22
|
+
$require.eq(await usdc.symbol(), 'USDC');
|
|
23
|
+
$require.eq(await usdc.decimals(), 6);
|
|
24
|
+
$require.eq(await usdc.balanceOf(sender.address), INITIAL_SENDER_BALANCE);
|
|
25
|
+
|
|
26
|
+
await usdc.$receipt().transfer(sender, recipient.address, TRANSFER_AMOUNT);
|
|
27
|
+
$require.eq(await usdc.balanceOf(recipient.address), TRANSFER_AMOUNT);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { $abi } from 'dequanto/abi/$abi';
|
|
2
|
+
import { $contract } from 'dequanto/utils/$contract';
|
|
3
|
+
import { $date } from 'dequanto/utils/$date';
|
|
4
|
+
import { $hex } from 'dequanto/utils/$hex';
|
|
5
|
+
import { $promise } from 'dequanto/utils/$promise';
|
|
6
|
+
import { $require } from 'dequanto/utils/$require';
|
|
7
|
+
import { $sig } from 'dequanto/utils/$sig';
|
|
8
|
+
|
|
9
|
+
const ACCOUNT = '0x0000000000000000000000000000000000000002';
|
|
10
|
+
|
|
11
|
+
UTest({
|
|
12
|
+
'encode and decode ABI values and calldata' () {
|
|
13
|
+
const encoded = $abi.encode(['address', 'uint256'], [ACCOUNT, 5n]);
|
|
14
|
+
const [account, amount] = $abi.decode(['address', 'uint256'], encoded);
|
|
15
|
+
const calldata = $abi.encodeCall(
|
|
16
|
+
'function transfer(address to, uint256 amount)',
|
|
17
|
+
[ACCOUNT, 5n]
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
$require.eq(account, ACCOUNT);
|
|
21
|
+
$require.eq(amount, 5n);
|
|
22
|
+
$require.eq(
|
|
23
|
+
calldata,
|
|
24
|
+
'0xa9059cbb00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000005'
|
|
25
|
+
);
|
|
26
|
+
$require.eq(
|
|
27
|
+
$abi.decodeReturn<bigint>(
|
|
28
|
+
'function totalSupply() view returns (uint256)',
|
|
29
|
+
$abi.encode('uint256', 10n)
|
|
30
|
+
),
|
|
31
|
+
10n
|
|
32
|
+
);
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
'hash Solidity values and manipulate hex' () {
|
|
36
|
+
const topic = $contract.keccak256('Transfer(address,address,uint256)');
|
|
37
|
+
const payload = $hex.concat([$hex.ensure('1234'), $hex.toHexBuffer(5)]);
|
|
38
|
+
|
|
39
|
+
$require.eq(topic, '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef');
|
|
40
|
+
$require.eq(payload, '0x123405');
|
|
41
|
+
$require.eq($hex.padBytes('0x2a', 4), '0x0000002a');
|
|
42
|
+
$require.eq($hex.getBytes(payload, 0, 2), '0x1234');
|
|
43
|
+
$require.eq($hex.getBytesLength(payload), 3);
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
async 'validate values, dates, signatures, and promise results' () {
|
|
47
|
+
$require.eq($date.parseTimespan('5days', { get: 's' }), 432_000);
|
|
48
|
+
$require.AddressNotEmpty(ACCOUNT);
|
|
49
|
+
$require.BigInt(5n, 'Expected an amount', { min: 1n });
|
|
50
|
+
|
|
51
|
+
const signer = $sig.$account.generate();
|
|
52
|
+
const signature = await $sig.signMessage('Hello dequanto', signer);
|
|
53
|
+
$require.eq($sig.recoverMessage('Hello dequanto', signature), signer.address);
|
|
54
|
+
|
|
55
|
+
const success = await $promise.caught(Promise.resolve(42));
|
|
56
|
+
const failure = await $promise.caught(Promise.reject(new Error('Expected failure')));
|
|
57
|
+
|
|
58
|
+
$require.eq(success.result, 42);
|
|
59
|
+
$require.Null(success.error);
|
|
60
|
+
$require.notNull(failure.error);
|
|
61
|
+
$require.eq(failure.error.message, 'Expected failure');
|
|
62
|
+
}
|
|
63
|
+
});
|
|
@@ -48,7 +48,7 @@ const balance = await token.balanceOf(account);
|
|
|
48
48
|
For ad hoc reads without a generated class:
|
|
49
49
|
|
|
50
50
|
```ts
|
|
51
|
-
import { ContractReader } from '
|
|
51
|
+
import { ContractReader } from 'dequanto/contracts/ContractReader';
|
|
52
52
|
|
|
53
53
|
const reader = new ContractReader(client);
|
|
54
54
|
const symbol = await reader.readAsync<string>(
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Use `HardhatProvider` for compile/deploy helper flows and `Deployments` for idempotent deployments, deployment storage, bytecode checks, proxy upgrades, beacon proxies, and verification.
|
|
4
4
|
|
|
5
|
+
See [Hardhat development and forking](hardhat.md) for creating development networks and live-contract forks, impersonating accounts, changing balances/storage, and restoring snapshots.
|
|
6
|
+
|
|
5
7
|
Key source files:
|
|
6
8
|
|
|
7
9
|
- `src/hardhat/HardhatProvider.ts`
|
|
@@ -21,7 +23,7 @@ Useful tests:
|
|
|
21
23
|
## HardhatProvider
|
|
22
24
|
|
|
23
25
|
```ts
|
|
24
|
-
import { HardhatProvider } from '
|
|
26
|
+
import { HardhatProvider } from 'dequanto/hardhat/HardhatProvider';
|
|
25
27
|
|
|
26
28
|
const hh = new HardhatProvider();
|
|
27
29
|
const client = hh.client();
|
|
@@ -43,7 +45,7 @@ Common methods:
|
|
|
43
45
|
## Idempotent Deployments
|
|
44
46
|
|
|
45
47
|
```ts
|
|
46
|
-
import { Deployments } from '
|
|
48
|
+
import { Deployments } from 'dequanto/contracts/deploy/Deployments';
|
|
47
49
|
|
|
48
50
|
const deployments = new Deployments(client, deployer, {
|
|
49
51
|
directory: './deployments/',
|
|
@@ -34,7 +34,7 @@ Use `'*'` for all events, or an event-name array for multiple events.
|
|
|
34
34
|
## EventsIndexer
|
|
35
35
|
|
|
36
36
|
```ts
|
|
37
|
-
import { EventsIndexer } from '
|
|
37
|
+
import { EventsIndexer } from 'dequanto/indexer/EventsIndexer';
|
|
38
38
|
|
|
39
39
|
const indexer = new EventsIndexer(contract, {
|
|
40
40
|
name: 'TokenTransfers',
|
|
@@ -19,7 +19,7 @@ Useful tests:
|
|
|
19
19
|
## Create Explorer
|
|
20
20
|
|
|
21
21
|
```ts
|
|
22
|
-
import { BlockchainExplorerFactory } from '
|
|
22
|
+
import { BlockchainExplorerFactory } from 'dequanto/explorer/BlockchainExplorerFactory';
|
|
23
23
|
|
|
24
24
|
const explorer = BlockchainExplorerFactory.get('eth');
|
|
25
25
|
```
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
TypeScript class generation is a core dequanto workflow. Prefer generated contract classes over raw ABI calls: generated classes let application code call contracts as ordinary TypeScript classes, with no direct web3-specific ABI encoding, decoding, or JSON-RPC plumbing.
|
|
4
4
|
|
|
5
|
-
Before generating a contract, check whether dequanto already ships a prebuilt class. The package includes OpenZeppelin contract classes under `dequanto/prebuilt/**` /
|
|
5
|
+
Before generating a contract, check whether dequanto already ships a prebuilt class. The package includes OpenZeppelin contract classes under `dequanto/prebuilt/**` / `dequanto/prebuilt/openzeppelin/**`. Class names match the OpenZeppelin contract names, for example `ERC20`, `ERC721`, `Ownable`, or `TimelockController`.
|
|
6
6
|
|
|
7
7
|
For standard OpenZeppelin contracts, do not generate a new class. Import the prebuilt class and pass the target contract address plus a chain client loaded by platform/chain abbreviation:
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
|
-
import { Web3ClientFactory } from '
|
|
11
|
-
import { ERC20 } from '
|
|
10
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
11
|
+
import { ERC20 } from 'dequanto/prebuilt/openzeppelin/ERC20';
|
|
12
12
|
|
|
13
13
|
const platform = 'eth';
|
|
14
14
|
const address = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
|
|
@@ -21,8 +21,8 @@ const decimals = await token.decimals();
|
|
|
21
21
|
|
|
22
22
|
Use the high-level generation tools when no prebuilt class exists:
|
|
23
23
|
|
|
24
|
-
- For deployed and explorer-verified contracts, use
|
|
25
|
-
- For
|
|
24
|
+
- For deployed and explorer-verified third-party contracts, use `0xweb install` as the primary generation workflow.
|
|
25
|
+
- For local contract development, use `@0xweb/contract` / `@0xweb/hardhat` so local Solidity contracts generate TypeScript classes from the normal compile flow.
|
|
26
26
|
- Use the low-level `Generator` API only when the task needs custom generation inside TypeScript code.
|
|
27
27
|
|
|
28
28
|
Key source files:
|
|
@@ -41,25 +41,37 @@ Useful tests:
|
|
|
41
41
|
- `test/generate/slotreader.spec.ts`
|
|
42
42
|
- `test/hardhat/deployments/deployments.spec.ts`
|
|
43
43
|
|
|
44
|
-
## Install
|
|
44
|
+
## Install Third-Party Contracts With 0xweb
|
|
45
45
|
|
|
46
|
-
Use `0xweb install` for
|
|
46
|
+
Use `0xweb install` as the primary tool for generating classes from deployed third-party contracts. When the contract is verified on an Etherscan-compatible explorer, `0xweb` downloads the ABI and source, follows standard proxy patterns, and generates the class for the current implementation.
|
|
47
47
|
|
|
48
48
|
```bash
|
|
49
49
|
npm i 0xweb -g
|
|
50
|
-
0xweb install <address> --
|
|
50
|
+
0xweb install <address> --name <contractClassName> --chain <chainAbbr>
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Example:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
0xweb install 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 --
|
|
56
|
+
0xweb install 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 --name USDC --chain eth
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If the target contract is a proxy but the implementation cannot be detected automatically, pass the implementation address explicitly:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
0xweb install <proxyAddress> --implementation <implementationAddress> --name SomeName --chain eth
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
By default, `0xweb install` saves the downloaded Solidity sources next to the generated class. Use `--save-sources false` when the project should keep only the generated contract class:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
0xweb install <address> --name SomeName --chain eth --save-sources false
|
|
57
69
|
```
|
|
58
70
|
|
|
59
71
|
The generated class can then be imported and used like a normal TypeScript class:
|
|
60
72
|
|
|
61
73
|
```ts
|
|
62
|
-
import { Web3ClientFactory } from '
|
|
74
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
63
75
|
import { USDC } from './0xc/eth/USDC/USDC';
|
|
64
76
|
|
|
65
77
|
const client = await Web3ClientFactory.getAsync('eth');
|
|
@@ -69,6 +81,17 @@ const symbol = await usdc.symbol();
|
|
|
69
81
|
const decimals = await usdc.decimals();
|
|
70
82
|
```
|
|
71
83
|
|
|
84
|
+
## Install From ABI JSON Or Solidity Source
|
|
85
|
+
|
|
86
|
+
`0xweb install` also accepts a local ABI JSON artifact or Solidity source file instead of an address:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
0xweb install test/fixtures/artifacts/AnyERC20/AnyERC20.json --name AnyERC20 --chain eth
|
|
90
|
+
0xweb install contracts/AnyERC20.sol --name AnyERC20 --chain eth
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Use this for ad hoc class generation from explicit local inputs. For ongoing local contract development, prefer the Hardhat integration so the generated classes stay in sync with `hardhat compile`.
|
|
94
|
+
|
|
72
95
|
## Hardhat Projects
|
|
73
96
|
|
|
74
97
|
Use `@0xweb/hardhat` in Hardhat projects. The plugin hooks into the Hardhat compile flow and generates TypeScript classes for local `*.sol` contracts whenever the project is compiled.
|
|
@@ -93,12 +116,12 @@ Use the generated classes in tests, scripts, and app code instead of raw ABI obj
|
|
|
93
116
|
|
|
94
117
|
## Low-Level Generator API
|
|
95
118
|
|
|
96
|
-
Use `Generator` directly only for custom generation tasks, test fixtures, non-Hardhat toolchains, or agent code that must generate classes from explicit ABI arrays, ABI JSON, compiled artifacts, Solidity files, or explorer-verified source by address.
|
|
119
|
+
Use `Generator` directly only for custom generation tasks, test fixtures, non-Hardhat toolchains, or agent code that must generate classes from explicit ABI arrays, ABI JSON, compiled artifacts, Solidity files, or explorer-verified source by address. For normal third-party contracts, prefer `0xweb install`; for local Hardhat projects, prefer `@0xweb/hardhat`.
|
|
97
120
|
|
|
98
121
|
### Generate From Compiled Artifact
|
|
99
122
|
|
|
100
123
|
```ts
|
|
101
|
-
import { Generator } from '
|
|
124
|
+
import { Generator } from 'dequanto/gen/Generator';
|
|
102
125
|
|
|
103
126
|
const gen = new Generator({
|
|
104
127
|
name: 'AnyERC20',
|
|
@@ -157,7 +180,7 @@ When a contract is generated from verified on-chain source, such as with `0xweb
|
|
|
157
180
|
Use `GeneratorStorageReader` when the task needs generated storage accessors without generating the full contract class.
|
|
158
181
|
|
|
159
182
|
```ts
|
|
160
|
-
import { GeneratorStorageReader } from '
|
|
183
|
+
import { GeneratorStorageReader } from 'dequanto/gen/GeneratorStorageReader';
|
|
161
184
|
|
|
162
185
|
const gen = new GeneratorStorageReader();
|
|
163
186
|
const result = await gen.generate({
|