Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/hairyf/harsta
harsta is a contract development tool based on Hardhat, designed to streamline the development, testing, and referencing of contracts, addresses, ABIs, and contract instances.
https://github.com/hairyf/harsta
builder contract exporter hardhat hardhat-deploy viem wagmi
Last synced: 2 months ago
JSON representation
harsta is a contract development tool based on Hardhat, designed to streamline the development, testing, and referencing of contracts, addresses, ABIs, and contract instances.
- Host: GitHub
- URL: https://github.com/hairyf/harsta
- Owner: hairyf
- License: mit
- Created: 2024-07-28T10:22:36.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2024-08-13T09:58:12.000Z (5 months ago)
- Last Synced: 2024-09-14T12:46:19.323Z (3 months ago)
- Topics: builder, contract, exporter, hardhat, hardhat-deploy, viem, wagmi
- Language: TypeScript
- Homepage: https://github.com/hairyf/harsta
- Size: 581 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
## harsta
I have been searching for a way to integrate Hardhat with other frameworks (such as nextjs/vue), but unfortunately, I have not found one. Therefore, I plan to implement it myself.
**harsta** is a contract development tool based on Hardhat, designed to streamline the development, testing, and referencing of contracts, addresses, ABIs, and contract instances.
**harsta** simplifies the configuration files for end-to-end development and contract writing. You only need to write one configuration that can be referenced anywhere.
![image](./public/flow.png)
- [Address visualization and third-party ABI](#directory)
- [Common Harsta Config for Browser and Node.js](#config)
- [Automatic deployment based on config](#deployments)
- [Seamless Wagmi support](#wagmi)
- [Rapid deploy tests based on hardhat-deploy](#tests)## Installation
You can quickly create a project like Hardhat using the command `pnpm harsta create`, or you can install it separately in any project:
```sh
$ pnpm harsta create# OR
$ pnpm install hardhat harsta @harsta/client
# OR
$ pnpm install hardhat harsta
```> Note: `@harsta/client` is optional. If installed, `harsta compile` will automatically be bundled into `@harsta/client`.
## Directory
- `contracts/`, `test/`
The location of contract source files and tests, similar to Hardhat.
- `config/addresses.ts`
This file contains all contract addresses used in the project. You can customize this file, and it will be automatically updated after contract updates/deployments.
```ts
export default {
[chainIdNumber]: { [contractName]: '0x...' },
// or the contract address currently used in your project
0: { USDT: '0x...' }
}
```- `config/fragments/*.json`
Additional third-party contracts used, which will be compiled into contract instances.
## Quick Start
**harsta** has three key commands:
```sh
harsta compile Compile and output the directory
harsta test Run integration tests
harsta deploy Deploy and save deployments
```To compile your contracts in `contracts/`:
```
$ pnpm harsta compile
```If `@harsta/client` is not installed, **harsta** will default output to `dist`. You can change the output directory with the `--output` option.
After compilation, if you install `@harsta/client`, you can directly reference `@harsta/client` as follows:
```ts
import {
addresses,
chains,
contracts,
defaultChain,
interfaces,
} from '@harsta/client'// Automatically import contract addresses from the default chain
const lock = contracts.Lock.resolve()
const time = await lock.unlockTime()// Use other addresses through attach
const lock2 = contracts.Lock.attach(addresses[chains.ethereum.id].Lock)// Connect to a contract by passing a chain
const lock3 = contracts.Lock.resolve(chains.ethereum, '0x...')
```Send and write contract:
```ts
import { contracts, updateRunner } from '@harsta/client'
// Update the default runner (singer) to support transactions
import { Wallet } from 'ethers'const wallet = new Wallet('...')
updateRunner(wallet)const lock = contracts.Lock.resolve()
const transaction = await lock.withdraw()
```## Config
**harsta**'s config is similar to Hardhat but more streamlined and simple, with comprehensive chain config.
```ts
import { defineConfig } from 'harsta'
import 'dotenv/config'const config = defineConfig({
solidity: '0.8.20',
defaultNetwork: 'geneva',
namedAccounts: {/* ... */},
networks: {
ethereum: {
name: 'Ethereum',
rpc: '...',
id: 0,
icon: '',
currency: {
decimals: 18,
name: 'ETH',
symbol: 'ETH'
},
explorer: {/* ... */},
// Optional, if not written, it will not be accepted by Hardhat
deploy: {
accounts: [/* account #0 | account #1 */],
saveDeployments: true,
allowUnlimitedContractSize: true,
gas: 'auto',
gasPrice: 'auto',
},
verify: {
uri: '...',
key: '...'
}
}
},
// ...
})
```## Deployments
After writing your contracts, you need to define the `deployments` in the configuration file:
```ts
const config = defileConfig({
deployments: {
Constant1: { args: [/* args... */] },
Constant2: { update: 'proxy', args: async env => [/* args... */] },
Constant3: { update: 'uups', args: () => [/* ...args */] }
}
})
```Next, deploy to the desired chain:
```sh
$ pnpm harsta deploy --network [your network]
```After deployment, the `config/addresses.ts` file will be automatically updated and recompiled.
### Update
If your contract files are updated, rerun the script:
- `contracts/Constant1.sol` has been modified
- `contracts/Constant2.sol` has been modifiedRerunning the `deploy` script will redeploy the `Constant1|Constant2` contracts.
If your contract is an upgradable contract, create a new file:
- `contracts/Constant1.sol` original contract
- `contracts/Constant1V1.sol` upgraded contractRerunning `deploy` will upgrade the contract.
## Wagmi
**harsta** naturally supports wagmi. By adding a few lines of code, you can use the compiled information and contracts of all chains:
config.ts:
```ts
import { createConfig, http } from '@wagmi/core'
import { createClient } from 'viem'
import { chains } from '@harsta/client'export const config = createConfig({
chains: [chains.ethereum, chains.sepolia],
client({ chain }) {
return createClient({ chain, transport: http() })
},
})
```App.tsx:
```tsx
import { WagmiProvider, useClient, useConnectorClient } from 'wagmi'
import { SubscribeWagmiConfig } from '@harsta/client/wagmi'
import { config } from './config'function App() {
return (
{/* your page content */}
)
}
```Any page:
```tsx
import { addresses, contracts } from '@harsta/client'
import { useAccount } from 'wagmi'function Page() {
const { isConnected } = useAccount()
async function withdraw() {
const lock = contracts.Lock.resolve('singer')
const transaction = await lock.withdraw()
}
return (
<>
{isConnected && (
Withdraw
)}
>
)
}
export default Page
```By modifying `.env` to change the default chain and configuration used by the contract:
```
NEXT_PUBLIC_DEFAULT_CHAIN = 'sepolia'
# OR
DEFAULT_CHAIN = 'sepolia'
```## Tests
You can ensure that deployment scripts are executed in tests by calling `await deployments.fixture(['MyContract'])`. This is optimized so that if multiple tests use the same contract, the deployment will be done once, and each test will start in exactly the same state.
```ts
import { deployments, ethers } from 'hardhat'
import { expect } from 'chai'describe('storage contract', () => {
beforeEach(async () => {
await deployments.fixture(['Storage'])
})
it('test', async () => {
const Storage = await deployments.get('Storage')
const storage = await ethers.getContractAt('Storage', Storage.address)
// ...
})
})
```