Skip to content

Commit

Permalink
viem examples (#910)
Browse files Browse the repository at this point in the history
* wip

* basic example works

* add doc and polish
  • Loading branch information
shunjizhan authored Dec 28, 2023
1 parent 08c1a2f commit 3700887
Show file tree
Hide file tree
Showing 11 changed files with 1,461 additions and 34 deletions.
44 changes: 44 additions & 0 deletions examples/viem/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
node_modules
.env

# Hardhat files
/cache
/artifacts

# TypeChain files
/typechain
/typechain-types

# solidity-coverage files
/coverage
/coverage.json

node_modules
.env

# Hardhat files
/cache
/artifacts

# TypeChain files
/typechain
/typechain-types

# solidity-coverage files
/coverage
/coverage.json

node_modules
.env

# Hardhat files
/cache
/artifacts

# TypeChain files
/typechain
/typechain-types

# solidity-coverage files
/coverage
/coverage.json
53 changes: 53 additions & 0 deletions examples/viem/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Acala EVM+ Examples - Viem
This example demonstrate how to use viem to interact with Acala EVM+. It deploys and interacts with the Echo contracts.

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.

## Start a Local Development Stack
clean up docker containers
```
docker compose down -v
```

start the local development stack
```
docker compose up
```

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.
```
--------------------------------------------
🚀 SERVER STARTED 🚀
--------------------------------------------
version : bodhi.js/eth-rpc-adapter/2.7.16
endpoint url : ws://mandala-node:9944
subquery url : http://graphql-engine:3001
listening to : 8545
max blockCache : 200
max batchSize : 50
max storageSize : 5000
safe mode : false
local mode : true
rich mode : false
http only : false
verbose : true
--------------------------------------------
```

For more information about the local development stack, please refer to the [doc](https://evmdocs.acala.network/network/network-setup/local-development-network).

## Run the Example
- install deps
```
yarn install
```

- compile the contract
```
yarn build
```

- run tests on local mandala
```
yarn test
```
19 changes: 19 additions & 0 deletions examples/viem/contracts/Echo.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pragma solidity =0.8.9;

contract Echo{
string public echo;
uint echoCount;

event NewEcho(string message, uint count);

constructor() {
echo = "Deployed successfully!";
}

function scream(string memory message) public returns(string memory){
echo = message;
echoCount += 1;
emit NewEcho(message, echoCount);
return message;
}
}
86 changes: 86 additions & 0 deletions examples/viem/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
services:
mandala-node:
image: ghcr.io/acalanetwork/mandala-node:sha-7ae4bf4
container_name: mandala-node
ports:
- 9944:9944
command:
- --dev
- -levm=debug
- --rpc-external
- --rpc-cors=all
- --rpc-methods=unsafe
- --pruning=archive
- --instant-sealing

postgres:
image: postgres:12-alpine
container_name: postgres
ports:
- 5432:5432
environment:
POSTGRES_PASSWORD: postgres

subquery-node:
image: acala/evm-subql:2.7.16
container_name: subquery-node
ports:
- 3000:3000
depends_on:
- mandala-node
- postgres
restart: always
extra_hosts:
- host.docker.internal:host-gateway
environment:
DB_USER: postgres
DB_PASS: postgres
DB_DATABASE: postgres
DB_HOST: host.docker.internal
DB_PORT: 5432
command:
- -f=project.yaml # local mandala
- --network-endpoint=ws://mandala-node:9944
- --db-schema=acala_evm
- --log-level=debug
- --unsafe
- --disable-historical

graphql-engine:
image: onfinality/subql-query:v1.4.0
container_name: graphql-engine
ports:
- 3001:3001
depends_on:
- subquery-node
restart: always
extra_hosts:
- host.docker.internal:host-gateway
environment:
DB_USER: postgres
DB_PASS: postgres
DB_DATABASE: postgres
DB_HOST: host.docker.internal
DB_PORT: 5432
PORT: 3001
command:
- --name=acala_evm
- --playground
- --indexer=http://subquery-node:3000

eth-rpc-adapter-server:
image: acala/eth-rpc-adapter:2.7.16
container_name: eth-rpc-adapter-server
restart: always
depends_on:
- mandala-node
- graphql-engine
ports:
- 8545:8545
extra_hosts:
- host.docker.internal:host-gateway
environment:
- SUBQL_URL=http://graphql-engine:3001
- ENDPOINT_URL=ws://mandala-node:9944
- LOCAL_MODE=1
command: yarn start
7 changes: 7 additions & 0 deletions examples/viem/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { HardhatUserConfig } from 'hardhat/config';

const config: HardhatUserConfig = {
solidity: '0.8.9',
};

export default config;
15 changes: 15 additions & 0 deletions examples/viem/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "evm-examples-viem",
"version": "1.0.0",
"main": "src/index.ts",
"scripts": {
"build": "hardhat compile",
"test": "hardhat test"
},
"devDependencies": {
"@types/node": "^20.10.5",
"hardhat": "^2.19.4",
"typescript": "^5.3.3",
"viem": "^1.21.0"
}
}
70 changes: 70 additions & 0 deletions examples/viem/test/echo.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { expect } from 'chai';
import { createWalletClient, http, getContractAddress, publicActions } from 'viem'
import { mnemonicToAccount } from 'viem/accounts'

import EchoJson from '../artifacts/contracts/Echo.sol/Echo.json';

const TEST_MNEMONIC = 'fox sight canyon orphan hotel grow hedgehog build bless august weather swarm';
const account = mnemonicToAccount(TEST_MNEMONIC)
const client = createWalletClient({
account,
chain: { // TODO: support public mandala after PR is merged
name: 'local',
id: 595,
nativeCurrency: {
name: 'acala',
symbol: 'ACA',
decimals: 18,
},
rpcUrls: {
default: { http: ['http://localhost:8545'] },
public: { http: ['http://localhost:8545'] },
},
network: 'local',
},
transport: http('http://localhost:8545')
}).extend(publicActions)

describe('Echo contract', function () {
it("can deploy, read, and write contract", async () => {
/* ----------------- deploy ----------------- */
const deployHash = await client.deployContract({
abi: EchoJson.abi,
args: [],
bytecode: EchoJson.bytecode as `0x${string}`,
})

await client.waitForTransactionReceipt({ hash: deployHash })
const tx = await client.getTransaction({ hash: deployHash })

const contractAddr = getContractAddress({
from: tx.from,
nonce: BigInt(tx.nonce),
})

/* ----------------- read ----------------- */
let echoValue = await client.readContract({
address: contractAddr,
abi: EchoJson.abi,
functionName: 'echo',
})
expect(echoValue).to.equal('Deployed successfully!');

/* ----------------- write ----------------- */
const { request } = await client.simulateContract({
address: contractAddr,
abi: EchoJson.abi,
functionName: 'scream',
args: ['Hello World!'],
})
const callHash = await client.writeContract(request)
await client.waitForTransactionReceipt({ hash: callHash })

echoValue = await client.readContract({
address: contractAddr,
abi: EchoJson.abi,
functionName: 'echo',
})
expect(echoValue).to.equal('Hello World!');
})
});
11 changes: 11 additions & 0 deletions examples/viem/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"resolveJsonModule": true
},
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
},
"workspaces": [
"packages/*",
"examples/waffle/*"
"examples/waffle/*",
"examples/viem"
],
"scripts": {
"clean": "yarn workspaces foreach -pvit --include \"@acala-network/*\" run clean",
Expand Down
2 changes: 1 addition & 1 deletion packages/eth-rpc-adapter/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const yargsOptions = yargs(hideBin(process.argv))
endpoint: {
alias: 'e',
demandOption: false,
default: ENDPOINT_URL ?? 'ws://localhost:9944',
default: ENDPOINT_URL ?? 'ws://0.0.0.0:9944',
describe: 'Node websocket endpoint(s): can provide one or more endpoints, seperated by comma',
type: 'string',
},
Expand Down
Loading

0 comments on commit 3700887

Please sign in to comment.