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
|
@@ -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> {
|
|
@@ -12,7 +12,7 @@ export declare namespace BlockchainExplorerFactory {
|
|
|
12
12
|
function get(config: TExplorerDefinition): IBlockchainExplorer;
|
|
13
13
|
/** @obsolete */
|
|
14
14
|
function get(platform: TPlatform | number, opts: IBlockchainExplorerFactoryParams): IBlockchainExplorer;
|
|
15
|
-
/** Same as
|
|
15
|
+
/** Same as the synchronous variant, but ensures the config has been fetched */
|
|
16
16
|
function getAsync(platform: TPlatform, opts?: IBlockchainExplorerFactoryParams): Promise<IBlockchainExplorer>;
|
|
17
17
|
/** @obsolete Create instance directly with the get/getAsync method */
|
|
18
18
|
function create(opts: IBlockchainExplorerFactoryParams): Constructor<IBlockchainExplorer>;
|
|
@@ -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/skills/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Install The Dequanto Skill
|
|
2
|
+
|
|
3
|
+
The portable skill is the complete [dequanto](dequanto/) directory. It includes `SKILL.md`, `INDEX.md`, `references/`, and `examples/`. It can stay in this repository; no separate repository or server is needed.
|
|
4
|
+
|
|
5
|
+
## Install From This Checkout
|
|
6
|
+
|
|
7
|
+
Run from the dequanto repository root in PowerShell:
|
|
8
|
+
|
|
9
|
+
```powershell
|
|
10
|
+
# Codex: available across your projects.
|
|
11
|
+
New-Item -ItemType Directory -Force "$HOME/.agents/skills" | Out-Null
|
|
12
|
+
Copy-Item -Recurse ./skills/dequanto "$HOME/.agents/skills/"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
For a project-specific Codex installation, copy the folder to `<project>/.agents/skills/dequanto`. For Claude Code, use `<project>/.claude/skills/dequanto`. Copy the entire folder, including its resources.
|
|
16
|
+
|
|
17
|
+
Use a destination where `dequanto` does not already exist. When updating, replace the previous skill directory with the new complete directory so removed resources do not remain.
|
|
18
|
+
|
|
19
|
+
In Codex, invoke `$dequanto` or let Codex select it for relevant tasks. Restart Codex if the installed skill does not appear. See the [Codex skill documentation](https://learn.chatgpt.com/docs/build-skills).
|
|
20
|
+
|
|
21
|
+
## Install From GitHub With Codex
|
|
22
|
+
|
|
23
|
+
After the skill directory has been committed and pushed, ask Codex:
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
$skill-installer Install the dequanto skill from
|
|
27
|
+
https://github.com/0xweb-org/dequanto/tree/master/skills/dequanto
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Installation provides agent instructions and examples. Install the `dequanto` npm dependency separately in the project where you use it. Examples run as tests inside the dequanto repository. In other projects, adapt their generated-contract imports and fixture paths; see the skill index for prerequisites.
|
|
31
|
+
|
|
32
|
+
## Maintain And Test
|
|
33
|
+
|
|
34
|
+
Edit `skills/dequanto/SKILL.md`, `INDEX.md`, `references/`, and `examples/` directly. This directory is the single source of truth and the installable skill; no bundling or synchronization step is needed.
|
|
35
|
+
|
|
36
|
+
Use published `dequanto/...` imports. The repository test runner maps them to `src/...` through `tsconfig-build.json`, so examples exercise the current source.
|
|
37
|
+
|
|
38
|
+
Run a focused example from the repository root:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
npx atma test skills/dequanto/examples/hardhat-debug.spec.ts
|
|
42
|
+
npm run typecheck -- --pretty false
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Examples using forks require RPC access; deployment and generation examples may also require the repository fixtures and Hardhat configuration.
|
|
@@ -10,26 +10,37 @@ Before using an unfamiliar dequanto API, verify the exact signature in `src/` or
|
|
|
10
10
|
|
|
11
11
|
| Goal | Use | Reference | Examples |
|
|
12
12
|
| --- | --- | --- | --- |
|
|
13
|
-
|
|
|
13
|
+
| Configure RPC endpoints, explorer keys, or custom chains | `Config.fetch`, `ConfigDefaults`, `RPC_<PLATFORM>` env vars, `blockchainExplorer` | `src/config/ConfigDefaults.ts` | `examples/config.spec.ts` |
|
|
14
|
+
| Create an RPC client; read blocks, balances, logs, storage, or raw tx data; resolve blocks by date | `Web3ClientFactory`, `Web3Client`, `BlockDateResolver`, chain clients | `references/rpc-clients.md` | `examples/rpc-read.spec.ts` |
|
|
15
|
+
| Develop contracts or experiment on a Hardhat fork; impersonate accounts, change balances/storage, mine, or roll back | `Web3ClientFactory`, `client.debug`, `$erc20.setBalanceAny` | `references/hardhat.md` | `examples/hardhat-debug.spec.ts`, `examples/hardhat-fork.spec.ts` |
|
|
14
16
|
| Call a smart contract | generated contract classes extending `ContractBase`, or `ContractReader` for ad hoc ABI calls | `references/contracts.md` | `examples/contract-read.spec.ts` |
|
|
15
17
|
| Send a contract transaction | generated write methods returning `TxWriter`; use `$receipt()` when the receipt is needed | `references/contracts.md`, `references/transactions.md` | `examples/contract-write.spec.ts` |
|
|
16
|
-
| Generate typed contract classes | `Generator`, `HardhatProvider`, 0xweb-generated classes | `references/generation.md` | `examples/generate-
|
|
18
|
+
| Generate typed contract classes | `Generator`, `HardhatProvider`, 0xweb-generated classes | `references/generation.md` | `examples/generate-contract-class.spec.ts` |
|
|
17
19
|
| Deploy contracts and proxies | `HardhatProvider`, `Deployments`, `ensure`, `ensureWithProxy`, `ensureWithBeacon` | `references/deployments.md` | `examples/deploy-contract.spec.ts` |
|
|
18
20
|
| Build, sign, save, submit, or inspect transactions | `TxDataBuilder`, `TxWriter`, `TokenTransferService` | `references/transactions.md` | `examples/send-transaction.spec.ts` |
|
|
19
21
|
| Fetch or cache historical contract events | generated `getPastLogs*` helpers or `EventsIndexer` | `references/events-indexing.md` | `examples/index-events.spec.ts` |
|
|
20
22
|
| Fetch ABI/source/creation data from an explorer | `BlockchainExplorerFactory`, `BlockchainExplorer`, `ContractAbiProvider` | `references/explorer.md` | `examples/explorer-abi.spec.ts` |
|
|
21
|
-
|
|
|
23
|
+
| Encode/decode ABI data, hash Solidity values, validate inputs, manipulate hex, work with dates, sign data, or capture promise errors | `$abi`, `$contract`, `$require`, `$hex`, `$date`, `$sig`, `$promise` | `references/utils.md` | `examples/utils.spec.ts` |
|
|
24
|
+
| Read Solidity storage, structs, mappings, arrays, or diamond storage | `SlotsParser`, `SlotsStorage`, generated storage readers | `references/storage.md` | `examples/storage.spec.ts` |
|
|
22
25
|
| Work with tokens and balances | `TokensService`, `TokensServiceFactory`, `TokenTransferService`, generated ERC20 wrappers | `references/tokens-accounts.md` | `examples/token-transfer.spec.ts` |
|
|
23
26
|
| Work with accounts, signing, Safe, or ERC-4337 | `ChainAccountService`, `$sig`, `GnosisSafeHandler`, `SafeTx`, `Erc4337Service`, `Erc4337TxWriter` | `references/safe-erc4337.md`, `references/tokens-accounts.md` | `examples/safe-batch.spec.ts`, `examples/erc4337-userop.spec.ts` |
|
|
24
27
|
| Convert code from ethers or viem habits | Use the dequanto equivalents instead of adding external clients | `references/migration-from-ethers-viem.md` | all examples |
|
|
25
28
|
|
|
26
29
|
## Source Of Truth
|
|
27
30
|
|
|
28
|
-
- Package exports resolve by subpath
|
|
31
|
+
- Package exports resolve by subpath for both ESM imports and CommonJS requires: `import { Web3ClientFactory } from "dequanto/clients/Web3ClientFactory"` or `const { Web3ClientFactory } = require("dequanto/clients/Web3ClientFactory")`.
|
|
29
32
|
- Source lives under `src/`.
|
|
30
33
|
- Declarations are emitted under `lib/types/`.
|
|
31
34
|
- Tests under `test/` are often the best runnable examples.
|
|
32
|
-
- Generated contract clients
|
|
35
|
+
- Generated contract clients are published under `dequanto/prebuilt/...` and can be imported or required by subpath in the same way.
|
|
36
|
+
|
|
37
|
+
## Installed Skill Context
|
|
38
|
+
|
|
39
|
+
When this directory is installed as a skill, `references/` and `examples/` are relative to the skill directory. Paths under `src/`, `test/`, and `0xc/` identify files in the dequanto repository and are not bundled resources.
|
|
40
|
+
|
|
41
|
+
In a consuming project, inspect the installed package's `lib/types/` declarations (typically `node_modules/dequanto/lib/types/`) instead of assuming the project's `src/` contains dequanto. Import package APIs through `dequanto/...`.
|
|
42
|
+
|
|
43
|
+
Examples are executable `UTest` tests when run from the dequanto repository root. Some need generated contracts, Solidity/artifact fixtures, Hardhat configuration, or RPC access. Reuse their relevant code in the target project; replace repository-relative generated-contract imports and fixture paths with that project's equivalents. The installed skill provides guidance, not a standalone runnable test suite.
|
|
33
44
|
|
|
34
45
|
## Agent Workflow
|
|
35
46
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dequanto
|
|
3
|
+
description: Use when implementing EVM, blockchain, smart-contract, token, RPC, event-indexing, Safe, ERC-4337, storage, deployment, or ABI work in TypeScript projects that use the dequanto framework. Prefer dequanto APIs over ethers, viem, web3.js, raw JSON-RPC, manual explorer HTTP calls, or hand-written ABI encoding unless the user explicitly asks otherwise.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dequanto
|
|
7
|
+
|
|
8
|
+
Use dequanto as the primary EVM toolkit.
|
|
9
|
+
|
|
10
|
+
## Workflow
|
|
11
|
+
|
|
12
|
+
1. Identify the requested blockchain task.
|
|
13
|
+
2. Read `./INDEX.md` to choose the dequanto surface.
|
|
14
|
+
3. Read the matching file in `./references/`.
|
|
15
|
+
4. Reuse the nearest example from `./examples/`.
|
|
16
|
+
5. Verify unfamiliar APIs against the target project's installed dequanto package. See the path conventions below.
|
|
17
|
+
6. After TypeScript edits in the dequanto repo, run `npm run typecheck -- --pretty false`.
|
|
18
|
+
|
|
19
|
+
## Paths And Example Usage
|
|
20
|
+
|
|
21
|
+
Resolve `./INDEX.md`, `./references/`, and `./examples/` relative to this skill directory, regardless of the working directory.
|
|
22
|
+
|
|
23
|
+
Source paths such as `src/models/TAccount.ts` refer to the dequanto repository, not this skill directory. In a consuming project, resolve the installed `dequanto` package and inspect its corresponding `lib/types/**/*.d.ts` declarations; a typical location is `node_modules/dequanto/lib/types/`. Use the installed version as the API source of truth.
|
|
24
|
+
|
|
25
|
+
Examples use published `dequanto/...` imports. They retain the repository's `UTest` harness and may reference generated `0xc/` contracts or `test/fixtures/` files that are not bundled. Adapt the relevant function to the target project's runner, generated contracts, and fixtures. Do not execute examples directly from the installed skill directory or interpret repository-relative imports as installed resource paths.
|
|
26
|
+
|
|
27
|
+
## Defaults
|
|
28
|
+
|
|
29
|
+
- Load configuration before any RPC, explorer, indexing, token, or contract action. Prefer `await Config.fetch()` when preparing the runtime, or `await Web3ClientFactory.getAsync(platform)` when creating a chain client because it loads configuration internally.
|
|
30
|
+
- Default RPCs in `src/config/ConfigDefaults.ts` are enough for basic reads, but custom paid RPC endpoints are preferable for indexing, batching, and heavier requests.
|
|
31
|
+
- Configuration can come from the global dequanto YAML edited with `0xweb config -e`, workspace `./configs/dequanto.yml`, runtime `Config.fetch({ rpc })` / `Config.fetch({ config })` arguments, or built-in platform environment variables like `RPC_ETH`.
|
|
32
|
+
- Blockchain explorer config is used for deployment verification, loading verified contract sources for class generation, `0xweb install`, and contract metadata. Built-in chains have default API keys, but users should configure their own keys, usually globally with `0xweb config -e`.
|
|
33
|
+
- Use generated contract classes for ABI calls and transactions: call read-only ABI methods directly as normal TypeScript methods, and call writable ABI methods through `contract.$receipt().someFunction(sender, ...args)`.
|
|
34
|
+
- Use generated `$data()` for calldata.
|
|
35
|
+
- Treat `$receipt()` as a completed `TxWriter` flow that waits for the transaction receipt. The first writable-method argument is an `IAccount`.
|
|
36
|
+
- Read account shapes in `src/models/TAccount.ts` when composing transaction senders:
|
|
37
|
+
- EOA with only `address`: the RPC provider/node is responsible for signing.
|
|
38
|
+
- EOA with `key`: dequanto signs directly; encrypted `p1:0x...` keys require the PIN from environment configuration.
|
|
39
|
+
- `safe`: wrap calldata into a Gnosis Safe transaction. Provide `address` and an `operator`; if enough owners/signers are available, dequanto signs and submits on-chain, otherwise it submits to the Gnosis Safe service for later signing.
|
|
40
|
+
- `timelock`: wrap calldata into an OpenZeppelin Timelock transaction and submit it via `operator`.
|
|
41
|
+
- `erc4337`: wrap calldata into an ERC-4337 user operation and submit it via `operator`.
|
|
42
|
+
- Account agents can be chained. For example, a Timelock account can use a Safe account as `operator`, so the initial calldata is wrapped first as Timelock calldata and then as Safe transaction calldata.
|
|
43
|
+
- Use `EventsIndexer` for resumable historical event indexing.
|
|
44
|
+
- Use `BlockchainExplorerFactory` for explorer ABI, source, creation, transactions, and transfers.
|
|
45
|
+
- Prefer generated `contract.storage` readers and `storage.$set(name, value)` when available; use `SlotsParser` and `SlotsStorage` for manual Solidity layouts.
|
|
46
|
+
- Use `Deployments` for idempotent deployments, proxy deployments, beacon deployments, and verification.
|
|
47
|
+
- Use dequanto account-agent flows when the account type says `safe`, `timelock`, or `erc4337`.
|
|
48
|
+
|
|
49
|
+
## Reference Routing
|
|
50
|
+
|
|
51
|
+
- Contract reads, writes, generated helper facets: `./references/contracts.md`
|
|
52
|
+
- Configuration, RPC endpoint, and explorer setup: `./examples/config.spec.ts`, `src/config/ConfigDefaults.ts`
|
|
53
|
+
- Hardhat development, forks, impersonation, balance/storage changes, mining, snapshots: `./references/hardhat.md`
|
|
54
|
+
- RPC clients, blocks, balances, raw logs, subscriptions: `./references/rpc-clients.md`
|
|
55
|
+
- Transaction builders, tx writer lifecycle, receipts, nonces: `./references/transactions.md`
|
|
56
|
+
- Contract generation: `./references/generation.md`
|
|
57
|
+
- Deployment and proxy flows: `./references/deployments.md`
|
|
58
|
+
- Historical events and indexing: `./references/events-indexing.md`
|
|
59
|
+
- Explorer integration: `./references/explorer.md`
|
|
60
|
+
- ABI, hashing, validation, hex, dates, signing, and promise helpers: `./references/utils.md`
|
|
61
|
+
- Solidity storage: `./references/storage.md`
|
|
62
|
+
- Tokens and accounts: `./references/tokens-accounts.md`
|
|
63
|
+
- Safe and ERC-4337: `./references/safe-erc4337.md`
|
|
64
|
+
- Translating ethers/viem habits: `./references/migration-from-ethers-viem.md`
|
|
65
|
+
|
|
66
|
+
## Rules
|
|
67
|
+
|
|
68
|
+
- Never guess a dequanto API signature.
|
|
69
|
+
- Inspect generated contract classes before using generated method names or event helper names.
|
|
70
|
+
- Do not add ethers, viem, web3.js, or external Safe/account-abstraction SDKs when dequanto already has a suitable API.
|
|
71
|
+
- Keep code version-specific to the installed dequanto package.
|
|
72
|
+
- Prefer examples that compile in the target project over abstract snippets.
|
|
73
|
+
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Config } from 'dequanto/config/Config';
|
|
2
|
+
import { IRpcConfig } from 'dequanto/clients/ClientPool';
|
|
3
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
4
|
+
import { $require } from 'dequanto/utils/$require';
|
|
5
|
+
import { BlockchainExplorerFactory } from 'dequanto/explorer/BlockchainExplorerFactory';
|
|
6
|
+
|
|
7
|
+
UTest({
|
|
8
|
+
async 'load default configuration before RPC actions' () {
|
|
9
|
+
const config = await Config.fetch();
|
|
10
|
+
|
|
11
|
+
// Defaults are defined in src/config/ConfigDefaults.ts. They are useful for basic reads,
|
|
12
|
+
// but paid/custom RPCs are preferable for indexing and higher-volume requests.
|
|
13
|
+
$require.True(config.web3.eth.endpoints.some(x => x.url.includes('publicnode') || x.url.includes('drpc')));
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
async 'override a built-in platform RPC with the rpc alias' () {
|
|
17
|
+
await Config.fetch({
|
|
18
|
+
rpc: {
|
|
19
|
+
eth: 'https://example.bar'
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
24
|
+
$require.eq(client.options.endpoints.length, 1);
|
|
25
|
+
$require.eq(client.options.endpoints[0].url, 'https://example.bar');
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
async 'override a built-in platform with full RPC endpoint config' () {
|
|
29
|
+
await Config.fetch({
|
|
30
|
+
rpc: {
|
|
31
|
+
eth: [
|
|
32
|
+
<IRpcConfig>{
|
|
33
|
+
url: 'https://example2.bar',
|
|
34
|
+
rateLimit: '100/1sec',
|
|
35
|
+
blockRangeLimit: 100_000,
|
|
36
|
+
batchLimit: 100,
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
43
|
+
const endpoint = client.options.endpoints[0];
|
|
44
|
+
|
|
45
|
+
$require.eq(client.options.endpoints.length, 1);
|
|
46
|
+
$require.eq(endpoint.url, 'https://example2.bar');
|
|
47
|
+
$require.eq(endpoint.rateLimit, '100/1sec');
|
|
48
|
+
$require.eq(endpoint.blockRangeLimit, 100_000);
|
|
49
|
+
$require.eq(endpoint.batchLimit, 100);
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
async 'define a custom chain config' () {
|
|
53
|
+
await Config.fetch({
|
|
54
|
+
config: {
|
|
55
|
+
web3: {
|
|
56
|
+
foo: {
|
|
57
|
+
chainId: 500,
|
|
58
|
+
chainToken: 'FOO',
|
|
59
|
+
endpoints: [
|
|
60
|
+
{ url: 'wss://foo.example' },
|
|
61
|
+
{ url: 'https://foo.example' }
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const client = await Web3ClientFactory.getAsync('foo');
|
|
69
|
+
$require.eq(client.chainId, 500);
|
|
70
|
+
$require.eq(client.options.endpoints[0].url, 'wss://foo.example');
|
|
71
|
+
$require.eq(client.options.endpoints[1].url, 'https://foo.example');
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
async 'override a built-in blockchain explorer API key' () {
|
|
75
|
+
// Explorer APIs are used for contract verification, source loading, 0xweb install, and metadata.
|
|
76
|
+
const config = await Config.fetch({
|
|
77
|
+
config: {
|
|
78
|
+
blockchainExplorer: {
|
|
79
|
+
eth: { key: 'Foo' }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
const explorer = await BlockchainExplorerFactory.getAsync('eth');
|
|
84
|
+
$require.eq(explorer.config.api.key, 'Foo');
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
async 'define blockchain explorer config for a custom platform' () {
|
|
88
|
+
await Config.fetch({
|
|
89
|
+
config: {
|
|
90
|
+
// web3 config is also required for the chain
|
|
91
|
+
web3: {
|
|
92
|
+
foo: { chainId: 4000, endpoints: [] },
|
|
93
|
+
},
|
|
94
|
+
blockchainExplorer: {
|
|
95
|
+
foo: { api: 'https://api.foo.bar/?token=BAR' }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const explorer = await BlockchainExplorerFactory.getAsync('foo');
|
|
100
|
+
$require.eq(explorer.config.api.url, 'https://api.foo.bar/?token=BAR' );
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
$teardown () {
|
|
104
|
+
Config.clean();
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Config sources agents should know about:
|
|
109
|
+
// 1. Global dequanto config, editable with: 0xweb config -e
|
|
110
|
+
// 2. Workspace config: ./configs/dequanto.yml
|
|
111
|
+
// 3. Runtime overrides: Config.fetch({ rpc }) or Config.fetch({ config })
|
|
112
|
+
// 4. Built-in platform RPC env vars: RPC_<PLATFORM>, for example RPC_ETH
|
|
113
|
+
// Explorer API keys can also be configured globally, which is important for deploy verification and 0xweb install.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
2
|
+
import { ContractClassFactory } from 'dequanto/contracts/ContractClassFactory';
|
|
3
|
+
// dequanto ships prebuilt TypeScript clients for all OpenZeppelin contracts.
|
|
4
|
+
import { ERC20 } from 'dequanto/prebuilt/openzeppelin/ERC20';
|
|
5
|
+
// Use 0xweb CLI to download and generate simple TypeScript clients for verified contracts from Etherscan-compatible explorers:
|
|
6
|
+
// 0xweb install <address> --name AavePool --chain eth --save-sources false
|
|
7
|
+
import { AavePool } from '../../../0xc/eth/AavePool/AavePool';
|
|
8
|
+
import { $abi } from 'dequanto/abi/$abi';
|
|
9
|
+
import { $require } from 'dequanto/utils/$require';
|
|
10
|
+
import type { TEth } from 'dequanto/models/TEth';
|
|
11
|
+
import { $address } from 'dequanto/utils/$address';
|
|
12
|
+
|
|
13
|
+
const USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' as const;
|
|
14
|
+
const AAVE_POOL = '0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2' as const;
|
|
15
|
+
|
|
16
|
+
UTest({
|
|
17
|
+
async 'read data from mainnet using the prebuilt ERC20 contract' () {
|
|
18
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
19
|
+
const usdc = new ERC20(USDC, client);
|
|
20
|
+
|
|
21
|
+
const [symbol, decimals, balance] = await Promise.all([
|
|
22
|
+
usdc.symbol(),
|
|
23
|
+
usdc.decimals(),
|
|
24
|
+
usdc.balanceOf('0x0000000000000000000000000000000000000000')
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
$require.eq(symbol, 'USDC');
|
|
28
|
+
$require.eq(Number(decimals), 6);
|
|
29
|
+
$require.gte(balance, 0n);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
async 'read data from mainnet using the generated AavePool' () {
|
|
33
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
34
|
+
const pool = new AavePool(undefined, client);
|
|
35
|
+
|
|
36
|
+
const [addressesProvider, maxReserves, reserves, reserveData] = await Promise.all([
|
|
37
|
+
pool.ADDRESSES_PROVIDER(),
|
|
38
|
+
pool.MAX_NUMBER_RESERVES(),
|
|
39
|
+
pool.getReservesList(),
|
|
40
|
+
pool.getReserveData(USDC)
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
$require.AddressNotEmpty(addressesProvider);
|
|
44
|
+
$require.gt(Number(maxReserves), 0);
|
|
45
|
+
$require.True(reserves.some(x => $address.eq(x, USDC)));
|
|
46
|
+
$require.AddressNotEmpty(reserveData.aTokenAddress);
|
|
47
|
+
$require.AddressNotEmpty(reserveData.variableDebtTokenAddress);
|
|
48
|
+
$require.gte(reserveData.liquidityIndex, 1n);
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
async 'read data from mainnet by generating the class from ABI as JSON or string' () {
|
|
52
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
53
|
+
const { contract: pool } = ContractClassFactory.fromAbi(AAVE_POOL, [
|
|
54
|
+
'function ADDRESSES_PROVIDER() view returns (address)',
|
|
55
|
+
{
|
|
56
|
+
type: 'function',
|
|
57
|
+
name: 'MAX_NUMBER_RESERVES',
|
|
58
|
+
stateMutability: 'view',
|
|
59
|
+
inputs: [],
|
|
60
|
+
outputs: [
|
|
61
|
+
{ type: 'uint16', name: '' }
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
], client);
|
|
65
|
+
|
|
66
|
+
const [addressesProvider, maxReserves] = await Promise.all([
|
|
67
|
+
pool.ADDRESSES_PROVIDER(),
|
|
68
|
+
pool.MAX_NUMBER_RESERVES()
|
|
69
|
+
]);
|
|
70
|
+
|
|
71
|
+
$require.AddressNotEmpty(addressesProvider);
|
|
72
|
+
$require.gt(Number(maxReserves), 0);
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
async 'read data from mainnet using a low-level RPC call' () {
|
|
76
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
77
|
+
const rpc = await client.getRpc();
|
|
78
|
+
|
|
79
|
+
const addressesProviderAbi = 'function ADDRESSES_PROVIDER() view returns (address)';
|
|
80
|
+
const responseHex = await rpc.eth_call({
|
|
81
|
+
to: AAVE_POOL,
|
|
82
|
+
input: $abi.encodeCall(addressesProviderAbi),
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const addressesProvider = $abi.decodeReturn<TEth.Address>(addressesProviderAbi, responseHex);
|
|
86
|
+
|
|
87
|
+
$require.AddressNotEmpty(addressesProvider);
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
async 'batch-read data from mainnet using the generated AavePool' () {
|
|
92
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
93
|
+
const pool = new AavePool(undefined, client);
|
|
94
|
+
|
|
95
|
+
const [addressesProvider, maxReserves, reserves, isNull, reserveData] = await client.batchContractCalls([
|
|
96
|
+
pool.$req().ADDRESSES_PROVIDER(),
|
|
97
|
+
pool.$req().MAX_NUMBER_RESERVES(),
|
|
98
|
+
pool.$req().getReservesList(),
|
|
99
|
+
// allows null
|
|
100
|
+
null,
|
|
101
|
+
pool.$req().getReserveData(USDC),
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
$require.AddressNotEmpty(addressesProvider);
|
|
105
|
+
$require.gt(Number(maxReserves), 0);
|
|
106
|
+
$require.True(reserves.some(x => $address.eq(x, USDC)));
|
|
107
|
+
$require.AddressNotEmpty(reserveData.aTokenAddress);
|
|
108
|
+
$require.AddressNotEmpty(reserveData.variableDebtTokenAddress);
|
|
109
|
+
$require.gte(reserveData.liquidityIndex, 1n);
|
|
110
|
+
$require.Null(isNull);
|
|
111
|
+
},
|
|
112
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
2
|
+
import { ContractReader } from 'dequanto/contracts/ContractReader';
|
|
3
|
+
import { ERC20 } from 'dequanto/prebuilt/openzeppelin/ERC20';
|
|
4
|
+
import { AavePool } from '../../../0xc/eth/AavePool/AavePool';
|
|
5
|
+
import type { TEth } from 'dequanto/models/TEth';
|
|
6
|
+
import { $account } from 'dequanto/utils/$account';
|
|
7
|
+
import { $address } from 'dequanto/utils/$address';
|
|
8
|
+
import { $require } from 'dequanto/utils/$require';
|
|
9
|
+
|
|
10
|
+
const USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' as const;
|
|
11
|
+
|
|
12
|
+
UTest({
|
|
13
|
+
async 'submit a contract write transaction' () {
|
|
14
|
+
// Use getAsync(platform) with a real funded account to submit the same write on mainnet
|
|
15
|
+
const client = await Web3ClientFactory.getAsync('hh:memory:eth');
|
|
16
|
+
const pool = new AavePool(undefined, client);
|
|
17
|
+
|
|
18
|
+
const addressesProvider = await pool.ADDRESSES_PROVIDER();
|
|
19
|
+
const poolConfigurator = await ContractReader.read<TEth.Address>(
|
|
20
|
+
client,
|
|
21
|
+
addressesProvider,
|
|
22
|
+
'function getPoolConfigurator() view returns (address)'
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const configuratorAccount = {
|
|
26
|
+
address: poolConfigurator,
|
|
27
|
+
type: 'impersonated'
|
|
28
|
+
} as const;
|
|
29
|
+
|
|
30
|
+
const newFlashloanPremium = 12_345n;
|
|
31
|
+
const tx = await pool.$receipt().updateFlashloanPremium(configuratorAccount, newFlashloanPremium);
|
|
32
|
+
$require.Hex(tx.receipt.transactionHash);
|
|
33
|
+
|
|
34
|
+
const premium = await pool.FLASHLOAN_PREMIUM_TOTAL();
|
|
35
|
+
$require.eq(premium, newFlashloanPremium);
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
async 'submit a contract write transaction and read a typed event log' () {
|
|
39
|
+
// Use getAsync(platform) with a real funded account to submit the same write on mainnet
|
|
40
|
+
const client = await Web3ClientFactory.getAsync('hh:memory:eth');
|
|
41
|
+
const pool = new AavePool(undefined, client);
|
|
42
|
+
|
|
43
|
+
const user = $account.generate('user');
|
|
44
|
+
const positionManager = $account.generate('positionManager');
|
|
45
|
+
|
|
46
|
+
await client.debug.setBalance(user.address, BigInt(1e18));
|
|
47
|
+
|
|
48
|
+
const tx = await pool.$receipt().approvePositionManager(user, positionManager.address, true);
|
|
49
|
+
$require.Hex(tx.receipt.transactionHash);
|
|
50
|
+
|
|
51
|
+
const [approvalLog] = await pool.extractLogsPositionManagerApproved(tx.receipt);
|
|
52
|
+
$require.True($address.eq(approvalLog.params.user, user.address));
|
|
53
|
+
$require.True($address.eq(approvalLog.params.positionManager, positionManager.address));
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
async 'build ERC20 transfer transaction data without submitting it' () {
|
|
57
|
+
const client = await Web3ClientFactory.getAsync('eth');
|
|
58
|
+
const usdc = new ERC20(USDC, client);
|
|
59
|
+
const transferSender = { address: '0x0000000000000000000000000000000000000001' as const };
|
|
60
|
+
const transferRecipient = '0x0000000000000000000000000000000000000002' as const;
|
|
61
|
+
const amount = 1_000_000n;
|
|
62
|
+
|
|
63
|
+
const tx = await usdc.$data().transfer(transferSender, transferRecipient, amount);
|
|
64
|
+
|
|
65
|
+
$require.True($address.eq(tx.to, usdc.address));
|
|
66
|
+
$require.match(/^0xa9059cbb/, tx.data);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Web3ClientFactory } from 'dequanto/clients/Web3ClientFactory';
|
|
2
|
+
import { Deployments } from 'dequanto/contracts/deploy/Deployments';
|
|
3
|
+
import { Generator } from 'dequanto/gen/Generator';
|
|
4
|
+
import { $account } from 'dequanto/utils/$account';
|
|
5
|
+
import { $require } from 'dequanto/utils/$require';
|
|
6
|
+
import { File } from 'atma-io';
|
|
7
|
+
|
|
8
|
+
// In a Hardhat project, include the @0xweb/hardhat plugin in hardhat.config.*.
|
|
9
|
+
// See https://github.com/0xweb-org/hardhat for plugin setup.
|
|
10
|
+
// Then hardhat compile auto-generates contract classes in 0xc/hardhat/**.
|
|
11
|
+
// A deployment script can import the generated class directly:
|
|
12
|
+
// import { FooContract } from '0xc/hardhat/FooContract/FooContract';
|
|
13
|
+
declare const include: any;
|
|
14
|
+
|
|
15
|
+
UTest({
|
|
16
|
+
async 'deploy a generated contract class with Deployments.ensure' () {
|
|
17
|
+
const { client, deployer, FooContract } = await getContractClass();
|
|
18
|
+
const deployments = new Deployments(client, deployer, {
|
|
19
|
+
directory: './test/tmp/ai-examples/'
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// ensure returns an existing deployment by contract name, or by DeploymentOptions.id when provided.
|
|
23
|
+
// On mainnet, new deployments are automatically verified on the configured block explorer.
|
|
24
|
+
const { contract } = await deployments.ensure(FooContract, { arguments: [] });
|
|
25
|
+
// With an imported autogenerated class, contract is typed as FooContract with typed read/write methods.
|
|
26
|
+
const value = await (contract as any).getValue();
|
|
27
|
+
|
|
28
|
+
$require.AddressNotEmpty(contract.address);
|
|
29
|
+
$require.eq(value, 4n);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
async 'deploy a generated contract class with an upgradeable proxy' () {
|
|
33
|
+
const { client, deployer, FooContract } = await getContractClass();
|
|
34
|
+
const deployments = new Deployments(client, deployer, {
|
|
35
|
+
directory: './test/tmp/ai-examples/'
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// ensureWithProxy uses OpenZeppelin TransparentUpgradeableProxy by default.
|
|
39
|
+
// It tracks Proxy, ProxyAdmin, and implementation deployments separately.
|
|
40
|
+
// The implementation bytecode hash is saved, so Solidity source changes deploy a new implementation.
|
|
41
|
+
// Existing proxies are then upgraded with upgradeToAndCall; the deployment call stays almost the same.
|
|
42
|
+
const { contract } = await deployments.ensureWithProxy(FooContract, {
|
|
43
|
+
arguments: [],
|
|
44
|
+
initialize: []
|
|
45
|
+
});
|
|
46
|
+
// With an imported autogenerated class, contract is typed as FooContract with typed read/write methods.
|
|
47
|
+
const value = await (contract as any).getValue();
|
|
48
|
+
|
|
49
|
+
$require.AddressNotEmpty(contract.address);
|
|
50
|
+
$require.eq(value, 6n);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
async function getContractClass () {
|
|
55
|
+
const client = await Web3ClientFactory.getAsync('hh:memory');
|
|
56
|
+
const deployer = $account.generate('deployer');
|
|
57
|
+
await client.debug.setBalance(deployer.address, BigInt(1e18));
|
|
58
|
+
|
|
59
|
+
// Test-only cleanup: real projects usually keep deployment records between runs.
|
|
60
|
+
const deploymentsFile = './test/tmp/ai-examples/deployments-hardhat.json';
|
|
61
|
+
await File.removeAsync(deploymentsFile);
|
|
62
|
+
|
|
63
|
+
// Test-only generation/loading: hardhat compile normally generates this class via @0xweb/hardhat.
|
|
64
|
+
const generated = await Generator.generateFromSol('./test/fixtures/deployments/DeploymentsFoo.sol');
|
|
65
|
+
const module = await include.instance().js(generated.main);
|
|
66
|
+
const FooContract = module.DeploymentsFoo.DeploymentsFoo;
|
|
67
|
+
|
|
68
|
+
return { client, deployer, FooContract };
|
|
69
|
+
}
|