Skip to content

Commit 3700887

Browse files
authored
viem examples (#910)
* wip * basic example works * add doc and polish
1 parent 08c1a2f commit 3700887

File tree

11 files changed

+1461
-34
lines changed

11 files changed

+1461
-34
lines changed

examples/viem/.gitignore

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
node_modules
2+
.env
3+
4+
# Hardhat files
5+
/cache
6+
/artifacts
7+
8+
# TypeChain files
9+
/typechain
10+
/typechain-types
11+
12+
# solidity-coverage files
13+
/coverage
14+
/coverage.json
15+
16+
node_modules
17+
.env
18+
19+
# Hardhat files
20+
/cache
21+
/artifacts
22+
23+
# TypeChain files
24+
/typechain
25+
/typechain-types
26+
27+
# solidity-coverage files
28+
/coverage
29+
/coverage.json
30+
31+
node_modules
32+
.env
33+
34+
# Hardhat files
35+
/cache
36+
/artifacts
37+
38+
# TypeChain files
39+
/typechain
40+
/typechain-types
41+
42+
# solidity-coverage files
43+
/coverage
44+
/coverage.json

examples/viem/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Acala EVM+ Examples - Viem
2+
This example demonstrate how to use viem to interact with Acala EVM+. It deploys and interacts with the Echo contracts.
3+
4+
This tutorial will focus on using **vanilla viem**, which is compatible across node and broswer. Hardhat will only be used to compile contract and run tests. If your code doesn't run on broswer, and you hope to make use of some hardhat wrappers over viem, check out the [hardhat-viem](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-viem) plugin.
5+
6+
## Start a Local Development Stack
7+
clean up docker containers
8+
```
9+
docker compose down -v
10+
```
11+
12+
start the local development stack
13+
```
14+
docker compose up
15+
```
16+
17+
once you see logs like this, the local development stack is ready. It's ok if there are some warnings/errors in the logs, since there is no transaction in the node yet.
18+
```
19+
--------------------------------------------
20+
🚀 SERVER STARTED 🚀
21+
--------------------------------------------
22+
version : bodhi.js/eth-rpc-adapter/2.7.16
23+
endpoint url : ws://mandala-node:9944
24+
subquery url : http://graphql-engine:3001
25+
listening to : 8545
26+
max blockCache : 200
27+
max batchSize : 50
28+
max storageSize : 5000
29+
safe mode : false
30+
local mode : true
31+
rich mode : false
32+
http only : false
33+
verbose : true
34+
--------------------------------------------
35+
```
36+
37+
For more information about the local development stack, please refer to the [doc](https://evmdocs.acala.network/network/network-setup/local-development-network).
38+
39+
## Run the Example
40+
- install deps
41+
```
42+
yarn install
43+
```
44+
45+
- compile the contract
46+
```
47+
yarn build
48+
```
49+
50+
- run tests on local mandala
51+
```
52+
yarn test
53+
```

examples/viem/contracts/Echo.sol

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
pragma solidity =0.8.9;
2+
3+
contract Echo{
4+
string public echo;
5+
uint echoCount;
6+
7+
event NewEcho(string message, uint count);
8+
9+
constructor() {
10+
echo = "Deployed successfully!";
11+
}
12+
13+
function scream(string memory message) public returns(string memory){
14+
echo = message;
15+
echoCount += 1;
16+
emit NewEcho(message, echoCount);
17+
return message;
18+
}
19+
}

examples/viem/docker-compose.yml

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
services:
2+
mandala-node:
3+
image: ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4
4+
container_name: mandala-node
5+
ports:
6+
- 9944:9944
7+
command:
8+
- --dev
9+
- -levm=debug
10+
- --rpc-external
11+
- --rpc-cors=all
12+
- --rpc-methods=unsafe
13+
- --pruning=archive
14+
- --instant-sealing
15+
16+
postgres:
17+
image: postgres:12-alpine
18+
container_name: postgres
19+
ports:
20+
- 5432:5432
21+
environment:
22+
POSTGRES_PASSWORD: postgres
23+
24+
subquery-node:
25+
image: acala/evm-subql:2.7.16
26+
container_name: subquery-node
27+
ports:
28+
- 3000:3000
29+
depends_on:
30+
- mandala-node
31+
- postgres
32+
restart: always
33+
extra_hosts:
34+
- host.docker.internal:host-gateway
35+
environment:
36+
DB_USER: postgres
37+
DB_PASS: postgres
38+
DB_DATABASE: postgres
39+
DB_HOST: host.docker.internal
40+
DB_PORT: 5432
41+
command:
42+
- -f=project.yaml # local mandala
43+
- --network-endpoint=ws://mandala-node:9944
44+
- --db-schema=acala_evm
45+
- --log-level=debug
46+
- --unsafe
47+
- --disable-historical
48+
49+
graphql-engine:
50+
image: onfinality/subql-query:v1.4.0
51+
container_name: graphql-engine
52+
ports:
53+
- 3001:3001
54+
depends_on:
55+
- subquery-node
56+
restart: always
57+
extra_hosts:
58+
- host.docker.internal:host-gateway
59+
environment:
60+
DB_USER: postgres
61+
DB_PASS: postgres
62+
DB_DATABASE: postgres
63+
DB_HOST: host.docker.internal
64+
DB_PORT: 5432
65+
PORT: 3001
66+
command:
67+
- --name=acala_evm
68+
- --playground
69+
- --indexer=http://subquery-node:3000
70+
71+
eth-rpc-adapter-server:
72+
image: acala/eth-rpc-adapter:2.7.16
73+
container_name: eth-rpc-adapter-server
74+
restart: always
75+
depends_on:
76+
- mandala-node
77+
- graphql-engine
78+
ports:
79+
- 8545:8545
80+
extra_hosts:
81+
- host.docker.internal:host-gateway
82+
environment:
83+
- SUBQL_URL=http://graphql-engine:3001
84+
- ENDPOINT_URL=ws://mandala-node:9944
85+
- LOCAL_MODE=1
86+
command: yarn start

examples/viem/hardhat.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { HardhatUserConfig } from 'hardhat/config';
2+
3+
const config: HardhatUserConfig = {
4+
solidity: '0.8.9',
5+
};
6+
7+
export default config;

examples/viem/package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "evm-examples-viem",
3+
"version": "1.0.0",
4+
"main": "src/index.ts",
5+
"scripts": {
6+
"build": "hardhat compile",
7+
"test": "hardhat test"
8+
},
9+
"devDependencies": {
10+
"@types/node": "^20.10.5",
11+
"hardhat": "^2.19.4",
12+
"typescript": "^5.3.3",
13+
"viem": "^1.21.0"
14+
}
15+
}

examples/viem/test/echo.test.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { expect } from 'chai';
2+
import { createWalletClient, http, getContractAddress, publicActions } from 'viem'
3+
import { mnemonicToAccount } from 'viem/accounts'
4+
5+
import EchoJson from '../artifacts/contracts/Echo.sol/Echo.json';
6+
7+
const TEST_MNEMONIC = 'fox sight canyon orphan hotel grow hedgehog build bless august weather swarm';
8+
const account = mnemonicToAccount(TEST_MNEMONIC)
9+
const client = createWalletClient({
10+
account,
11+
chain: { // TODO: support public mandala after PR is merged
12+
name: 'local',
13+
id: 595,
14+
nativeCurrency: {
15+
name: 'acala',
16+
symbol: 'ACA',
17+
decimals: 18,
18+
},
19+
rpcUrls: {
20+
default: { http: ['http://localhost:8545'] },
21+
public: { http: ['http://localhost:8545'] },
22+
},
23+
network: 'local',
24+
},
25+
transport: http('http://localhost:8545')
26+
}).extend(publicActions)
27+
28+
describe('Echo contract', function () {
29+
it("can deploy, read, and write contract", async () => {
30+
/* ----------------- deploy ----------------- */
31+
const deployHash = await client.deployContract({
32+
abi: EchoJson.abi,
33+
args: [],
34+
bytecode: EchoJson.bytecode as `0x${string}`,
35+
})
36+
37+
await client.waitForTransactionReceipt({ hash: deployHash })
38+
const tx = await client.getTransaction({ hash: deployHash })
39+
40+
const contractAddr = getContractAddress({
41+
from: tx.from,
42+
nonce: BigInt(tx.nonce),
43+
})
44+
45+
/* ----------------- read ----------------- */
46+
let echoValue = await client.readContract({
47+
address: contractAddr,
48+
abi: EchoJson.abi,
49+
functionName: 'echo',
50+
})
51+
expect(echoValue).to.equal('Deployed successfully!');
52+
53+
/* ----------------- write ----------------- */
54+
const { request } = await client.simulateContract({
55+
address: contractAddr,
56+
abi: EchoJson.abi,
57+
functionName: 'scream',
58+
args: ['Hello World!'],
59+
})
60+
const callHash = await client.writeContract(request)
61+
await client.waitForTransactionReceipt({ hash: callHash })
62+
63+
echoValue = await client.readContract({
64+
address: contractAddr,
65+
abi: EchoJson.abi,
66+
functionName: 'echo',
67+
})
68+
expect(echoValue).to.equal('Hello World!');
69+
})
70+
});

examples/viem/tsconfig.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es2020",
4+
"module": "commonjs",
5+
"esModuleInterop": true,
6+
"forceConsistentCasingInFileNames": true,
7+
"strict": true,
8+
"skipLibCheck": true,
9+
"resolveJsonModule": true
10+
},
11+
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
},
1111
"workspaces": [
1212
"packages/*",
13-
"examples/waffle/*"
13+
"examples/waffle/*",
14+
"examples/viem"
1415
],
1516
"scripts": {
1617
"clean": "yarn workspaces foreach -pvit --include \"@acala-network/*\" run clean",

packages/eth-rpc-adapter/src/utils/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const yargsOptions = yargs(hideBin(process.argv))
3131
endpoint: {
3232
alias: 'e',
3333
demandOption: false,
34-
default: ENDPOINT_URL ?? 'ws://localhost:9944',
34+
default: ENDPOINT_URL ?? 'ws://0.0.0.0:9944',
3535
describe: 'Node websocket endpoint(s): can provide one or more endpoints, seperated by comma',
3636
type: 'string',
3737
},

0 commit comments

Comments
 (0)