diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..f54b198 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,10 @@ +# This CODEOWNERS file sets the individuals responsible for code in the zksync2-go Golang SDK repository. + +# These users are the default owners for everything in the repo. +# They will be requested for review when someone opens a pull request. +* @zksync-sdk/txfusion + +# You can also specify code owners for specific directories or files. +# For example: +# /src/ @developer1 @developer2 +# /docs/ @documenter diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..593c6a0 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,71 @@ +# Contributing + +## Welcome! 👋 + +Hello there, contributor! We're delighted that you're considering contributing to the `zksync2-go` project. This document is here to guide you through the steps and best practices for contributing to this Golang-based repository. + +Please take a moment to review this document to ensure a smooth and efficient contribution process for everyone involved. + +## Getting Started + +- **Fork the repository.** Begin by forking the main `zksync2-go` repository to your personal GitHub account. + +- **Clone the repository.** After forking, clone the repository to your local machine: + +```bash +git clone https://github.com//zksync2-go.git +``` + +- **Create a new branch.** Use descriptive names for your branches to help identify the feature, bugfix, or enhancement you're addressing: + +```bash +git checkout -b feature/description-of-your-feature +``` + +## Making Changes + +- **Write your code.** Ensure your code is thoroughly tested and functions as expected. Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines. +- **Compile and test.** Before submitting a pull request, ensure your code compiles, passes lint checks, and all tests are successful. You should also write unit tests for your contributions. Use the following command for these checks: + +```bash +go fmt ./... +got test ./... +``` + +- **Commit your changes.** Adhere to the [Conventional Commits](https://www.conventionalcommits.org/) standard when writing commit messages. + +- **Push your changes.** Push the changes to your forked repository: + +```bash +git push origin feature/description-of-your-feature +``` + +## Submitting a Pull Request + +- **Initiate a pull request (PR).** Go to the main `zksync2-go` repository. Your recently pushed branch should be highlighted, showing a "Compare & pull request" button. Click on it and provide a clear, detailed description of your changes in the PR. + +- **Await a review.** Our maintainers will review your PR. They might request changes or clarifications, so be ready to address any feedback. + +## Code Style Guide + +We follow basic coding style guidelines. Before committing, ensure your code is formatted and lint checks pass: + +```bash +go fmt ./... +``` + +This ensures consistent code style throughout the project and helps identify potential issues early. + +## Need Assistance? + +If you're unsure about something or have questions, don't hesitate to open an issue or initiate a discussion in our [zkSync Community Hub](https://github.com/zkSync-Community-Hub/zkSync-developers/discussions). We're here to assist! + +## What's Next? + +Once your PR is approved and merged, your contribution will be integrated into the `zksync2-go` repository. Congratulations, and thank you! We value your contribution and look forward to future collaborations. + +Remember, the best contributions come from enjoying the process, being respectful, and continuously learning. Thanks for being a part of our community! + +--- + +*Last updated: Nov 10, 2023* \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..5e8f33e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,45 @@ +--- +name: Bug report +about: Use this template for reporting issues +title: "" +labels: bug +assignees: '' + +--- + +### 🐛 Bug Report for zksync2-js JavaScript SDK + +#### 📝 Description + +Provide a clear and concise description of the bug. + + +#### 🔄 Reproduction Steps + +1. Step 1 +2. Step 2 +3. ... + +#### 🤔 Expected Behavior + +Describe what you expected to happen. + +#### 😯 Current Behavior + +Describe what actually happened. + +#### 🖥️ Environment + +- **Node version**: [e.g., Node 18.16.1] +- **Operating System & Version**: [e.g., Ubuntu 20.04] +- **Other relevant environment details**: + +#### 📋 Additional Context + +Add any other context about the problem here. If applicable, add screenshots to help explain. + +#### 📎 Log Output + +``` +Paste any relevant log output here. +``` \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..7fa1610 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: true +contact_links: + - name: zksync-developers Discussion + url: https://github.com/zkSync-Community-Hub/zkync-developers/discussions + about: Please provide feedback, and ask questions here. + - name: zksync-web3 SDK documentation page + url: https://era.zksync.io/docs/api/js/ + about: Please refer to the documentation for immediate answers. + - name: zksync2-js SDK documentation page + url: https://era.zksync.io/docs/api/js/zksync2-js + about: Please refer to the documentation for immediate answers. diff --git a/.github/ISSUE_TEMPLATE/feature_report.md b/.github/ISSUE_TEMPLATE/feature_report.md new file mode 100644 index 0000000..4e30b23 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_report.md @@ -0,0 +1,26 @@ +--- +name: Feature request +about: Use this template for requesting features +title: "" +labels: feat +assignees: '' + +--- + +### 🌟 Feature Request + +#### 📝 Description + +Provide a clear and concise description of the feature you'd like to see. + +#### 🤔 Rationale + +Explain why this feature is important and how it benefits the project. + +#### 🖼️ Mockups/Examples + +If applicable, provide mockups or examples of how the feature would work. + +#### 📋 Additional Context + +Add any other context or information about the feature request here. \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..a45b9c3 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,17 @@ +# What :computer: +* First thing updated with this PR +* Second thing updated with this PR +* Third thing updated with this PR + +# Why :hand: +* Reason why first thing was added to PR +* Reason why second thing was added to PR +* Reason why third thing was added to PR + +# Evidence :camera: +Include screenshots, screen recordings, or `console` output here demonstrating that your changes work as intended + + + +# Notes :memo: +* Any notes/thoughts that the reviewers should know prior to reviewing the code? diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index df8c107..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,21 +0,0 @@ -# Contribution - -Thank you for considering helping out with the source code! We welcome contributions from anyone on the internet, and -are grateful for even the smallest of fixes! - -If you'd like to contribute to project, please fork, fix, commit and send a pull request for the maintainers to -review and merge into the main code base. If you wish to submit more complex changes though, please check up with the -core devs first on our [Discord Server](https://join.zksync.dev/) to ensure those changes are in line with the general -philosophy of the project and/or get some early feedback which can make both your efforts much lighter and our review and merge procedures quick -and simple. - -Please make sure your contributions adhere to our coding guidelines: - -- Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines -(i.e. uses [gofmt](https://golang.org/cmd/gofmt/)). -- Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) -guidelines. -- Pull requests need to be based on and opened against the `main` branch. -- Commit message should follow [defined format](commit-format.md). - - diff --git a/README.md b/README.md index cfdddd4..8204e99 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,56 @@ -zkSync 2 Golang SDK -=== +# 🚀 zksync2-go Golang SDK 🚀 +In order to provide easy access to all the features of zkSync Era, the `zksync2-go` Golang SDK was created, +which is made in a way that has an interface very similar to those of [geth](https://geth.ethereum.org/). In +fact, `geth` is a dependency of our library and most of the objects exported by `zksync2-go` ( +e.g. `Wallet`, `Client` etc.) inherit from the corresponding `geth` objects and override only the fields that need +to be changed. -## Requirements +While most of the existing SDKs should work out of the box, deploying smart contracts or using unique zkSync features, +like account abstraction, requires providing additional fields to those that Ethereum transactions have by default. -Go version >= 1.17 +The library is made in such a way that after replacing `geth` with `zksync2-go` most client apps will work out of +box. -Also, Go modules was used +🔗 For a detailed walkthrough, refer to the [official documentation](https://era.zksync.io/docs/api/go). -## Installation +## 📌 Overview -Add this package to your project: +To begin, it is useful to have a basic understanding of the types of objects available and what they are responsible for, at a high level: -```shell -$ go get github.com/zksync-sdk/zksync2-go +- `Client` provides connection to the zkSync Era blockchain, which allows querying the blockchain state, such as account, block or transaction details, + querying event logs or evaluating read-only code using call. Additionally, the client facilitates writing to the blockchain by sending + transactions. +- `Wallet` wraps all operations that interact with an account. An account generally has a private key, which can be used to sign a variety of + types of payloads. It provides easy usage of the most common features. + +## 🛠 Prerequisites + +- `go: >= 1.17` ([installation guide](https://go.dev/doc/install)) + +## 📥 Installation & Setup + +```bash +go get github.com/zksync-sdk/zksync2-go ``` -## Using examples +## 📝 Examples The complete examples with various use cases are available [here](https://github.com/zksync-sdk/zksync2-examples/tree/main/go). -### How to init main components +### Connect to the zkSync Era network: ```go import ( - "context" - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" - "github.com/zksync-sdk/zksync2-go/accounts" "github.com/zksync-sdk/zksync2-go/clients" - "github.com/zksync-sdk/zksync2-go/utils" "log" - "math/big" "os" ) var ( - PrivateKey = os.Getenv("PRIVATE_KEY") - ZkSyncProvider = "https://testnet.era.zksync.dev" - EthereumProvider = "https://rpc.ankr.com/eth_goerli" + ZkSyncProvider = "https://testnet.era.zksync.dev" // zkSync Era testnet + EthereumProvider = "https://rpc.ankr.com/eth_goerli" // goerli testnet ) // Connect to zkSync network client, err := clients.Dial(ZkSyncProvider) @@ -55,306 +65,115 @@ if err != nil { log.Panic(err) } defer ethClient.Close() - -// Create wallet -w, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient) -if err != nil { - log.Panic(err) -} -``` - -Now, using this three instances - zkSync client, ethereum client and wallet, -you can perform all basic actions with ZkSync network. - -### Get balance of ZkSync account -```go -balance, err := w.Balance(context.Background(), utils.EthAddress, nil) -if err != nil { - log.Panic(err) -} -fmt.Println("Balance: ", balance) ``` -### Deposit +### Get the latest block number -#### Deposit ETH token -```go -tx, err := w.Deposit(accounts.DepositTransaction{ - Token: utils.EthAddress, - Amount: big.NewInt(2_000_000_000_000_000_000), - To: w.Address(), - }) +```ts +blockNumber, err := client.BlockNumber(context.Background()) if err != nil { log.Panic(err) } -fmt.Println("L1 transaction: ", tx.Hash()) +fmt.Println("Block number: ", blockNumber) ``` -#### Deposit ERC20 token -```go -TokenL1Address := common.HexToAddress("0xf10A110E59a22b444c669C83b02f0E6d945b2b69") +### Get the latest block -tx, err := w.Deposit(accounts.DepositTransaction{ - Token: TokenL1Address, - Amount: big.NewInt(5), - To: w.Address(), - ApproveERC20: true, - RefundRecipient: w.Address(), -}) +```ts +block, err := client.BlockByNumber(context.Background(), nil) if err != nil { log.Panic(err) } -fmt.Println("L1 deposit transaction: ", tx.Hash()) +fmt.Printf("%+v\n", block) ``` -Also, you can get hash of corresponding L2 transaction: -```go -// Wait for deposit transaction to be finalized on L1 network -_, err = bind.WaitMined(context.Background(), ethClient, tx) -if err != nil { - log.Panic(err) -} - -// Get transaction receipt for deposit transaction on L1 network -l1Receipt, err := ethClient.TransactionReceipt(context.Background(), tx.Hash()) -if err != nil { - log.Panic(err) -} +### Create a wallet -l2Tx, err := client.L2TransactionFromPriorityOp(context.Background(), l1Receipt) +```ts +privateKey := os.Getenv("PRIVATE_KEY") +w, err := accounts.NewWallet(common.Hex2Bytes(privateKey), &client, ethClient) if err != nil { log.Panic(err) } -fmt.Println("L2 transaction", l2Tx.Hash) -``` -And claim back failed deposit: -```go -cfdTx, err := w.ClaimFailedDeposit(nil, l2Tx.Hash) -if err != nil { - fmt.Println(err) // this should trigger if deposit succeed -} -fmt.Println("ClaimFailedDeposit hash: ", cfdTx.Hash) ``` -### Transfer +### Check account balances -#### Transfer ETH token ```go -tx, err := w.Transfer(accounts.TransferTransaction{ - To: common.HexToAddress(PublicKey2), - Amount: big.NewInt(7_000_000_000_000_000_000), - Token: utils.EthAddress, -}) +balance, err := w.Balance(context.Background(), utils.EthAddress, nil) // balance on zkSync Era network if err != nil { log.Panic(err) } -fmt.Println("Transaction: ", tx.Hash()) -``` - -#### Transfer ERC20 token -```go -TokenL2Address := common.HexToAddress("0x16D1b10bC0BEa66B47bEe0f4c72543fE79192f0f") -Receiver := common.HexToAddress("0xa61464658AfeAf65CccaaFD3a512b69A83B77618") +fmt.Println("Balance: ", balance) -tx, err := w.Transfer(accounts.TransferTransaction{ - To: common.HexToAddress(Receiver), - Amount: big.NewInt(1), - Token: TokenL2Address, -}) +balanceL1, err := w.BalanceL1(nil, utils.EthAddress) // balance on goerli network if err != nil { log.Panic(err) } -fmt.Println("Transaction: ", tx.Hash()) +fmt.Println("Balance L1: ", balanceL1) ``` -### Withdraw +### Transfer funds -#### Withdraw ETH token -```go -tx, err := w.Withdraw(accounts.WithdrawalTransaction{ - To: w.Address(), - Amount: big.NewInt(1_000_000_000_000_000_000), - Token: utils.EthAddress, -}) -if err != nil { - log.Panic(err) -} -fmt.Println("Withdraw transaction: ", tx.Hash()) -``` +Transfer funds among accounts on L2 network. -#### Withdraw ERC20 token -```go -TokenL2Address = common.HexToAddress("0x16D1b10bC0BEa66B47bEe0f4c72543fE79192f0f") -tx, err := w.Withdraw(accounts.WithdrawalTransaction{ - To: w.Address(), - Amount: big.NewInt(1), - Token: TokenL2Address, -}) -if err != nil { - log.Panic(err) -} -fmt.Println("Withdraw transaction: ", tx.Hash()) -``` - -After the withdrawal is finished on L2 network, `FinalizeWithdraw` is required to -be executed on L1 network. ```go -// Wait until transaction is finalized -_, err = client.WaitFinalized(context.Background(), tx.Hash()) +chainID, err := client.ChainID(context.Background()) if err != nil { log.Panic(err) } - -// Perform finalize withdrawal -finalizeWithdrawTx, err := w.FinalizeWithdraw(nil, tx.Hash(), 0) +receiver, err := accounts.NewRandomWallet(chainID.Int64(), &client, ethClient) if err != nil { log.Panic(err) } -fmt.Println("Finalize withdraw transaction: ", finalizeWithdrawTx.Hash()) -``` -Also, you can check its status with: -```go -isFinalized, err := w.IsWithdrawFinalized(nil, tx.Hash(), 0) +tx, err := w.Transfer(accounts.TransferTransaction{ + To: receiver.Address(), + Amount: big.NewInt(7_000_000_000_000_000_000), + Token: utils.EthAddress, +}) if err != nil { log.Panic(err) } -fmt.Println("Is Withdraw finalized?", isFinalized) +fmt.Println("Transaction: ", tx.Hash()) ``` -### Deploy smart contract -```go -// Read smart contract bytecode -bytecode, err := os.ReadFile("Incrementer.zbin") -if err != nil { - log.Panic(err) -} - -// Get ABI -abi, err := incrementer.IncrementerMetaData.GetAbi() -if err != nil { - log.Panic(err) -} +### Deposit funds -// Encode constructor arguments -constructor, err := abi.Pack("", big.NewInt(2)) -if err != nil { - log.Panicf("error while encoding constructor arguments: %s", err) -} +Transfer funds from L1 to L2 network. -// Deploy paymaster contract -hash, err := w.DeployAccountWithCreate(accounts.CreateTransaction{ - Bytecode: bytecode, - Calldata: constructor, +```ts +tx, err := w.Deposit(accounts.DepositTransaction{ + Token: utils.EthAddress, + Amount: big.NewInt(2_000_000_000_000_000_000), + To: w.Address(), }) if err != nil { log.Panic(err) } -fmt.Println("Transaction: ", hash) - -// Wait unit transaction is finalized -_, err = client.WaitMined(context.Background(), hash) -if err != nil { - log.Panic(err) -} - -receipt, err := client.TransactionReceipt(context.Background(), hash) -if err != nil { - log.Panic(err) -} -contractAddress := receipt.ContractAddress -fmt.Println("Paymaster address", contractAddress.String()) +fmt.Println("L1 transaction: ", tx.Hash()) ``` -### Execute smart contract - -#### Static execution using bindings -```go -incrementerContract, err := incrementer.NewIncrementer(contractAddress, client) -if err != nil { - log.Panic(err) -} - -// Execute Get method -value, err := incrementerContract.Get(nil) -if err != nil { - log.Panic(err) -} -fmt.Println("Value before Increment method execution: ", value) - -// Start configuring transaction parameters -opts, err := bind.NewKeyedTransactorWithChainID(w.Signer().PrivateKey(), w.Signer().Domain().ChainId) -if err != nil { - log.Panic(err) -} +### Withdraw funds -// Execute Set method from storage smart contract with configured transaction parameters -tx, err := incrementerContract.Increment(opts) -if err != nil { - log.Panic(err) -} -// Wait for transaction to be finalized -_, err = client.WaitMined(context.Background(), tx.Hash()) -if err != nil { - log.Panic(err) -} -``` -#### Dynamic execution using EIP-712 transaction -```go -abiIncrementer, err := abi.JSON(strings.NewReader("")); -if err != nil { - log.Panic(err) -} -// Encode mint function from token contract -calldata, err := abiIncrementer.Pack("increment") -if err != nil { - log.Panic(err) -} +Transfer funds from L2 to L1 network. -hash, err := w.SendTransaction(context.Background(), &accounts.Transaction{ - To: &TokenAddress, - Data: calldata, +```ts +tx, err := w.Withdraw(accounts.WithdrawalTransaction{ + To: w.Address(), + Amount: big.NewInt(1_000_000_000_000_000_000), + Token: utils.EthAddress, }) -fmt.Println("Transaction: ", hash) -``` -**In order to utilize Account Abstraction and Paymaster features, EIP-712 transactions must be used!** - -### Deploy smart account -```go -// Read paymaster contract from standard json -_, paymasterAbi, bytecode, err := utils.ReadStandardJson("Paymaster.json") if err != nil { log.Panic(err) } +fmt.Println("Withdraw transaction: ", tx.Hash()) +``` -// Encode paymaster constructor -constructor, err := paymasterAbi.Pack("", common.HexToAddress(TokenAddress)) -if err != nil { - log.Panic(err) -} - -// Deploy paymaster contract -hash, err := w.DeployAccount(accounts.Create2Transaction{Bytecode: bytecode, Calldata: constructor}) -if err != nil { - log.Panic(err) -} -if err != nil { - log.Panic(err) -} -fmt.Println("Transaction: ", hash) - -// Wait unit transaction is finalized -_, err = client.WaitMined(context.Background(), hash) -if err != nil { - log.Panic(err) -} +## 🤝 Contributing -// Get address of deployed smart contract -contractAddress, err := utils.ComputeL2Create2Address(w.Address(), bytecode, constructor, nil) -if err != nil { - log.Panic(err) -} -fmt.Println("Paymaster address: ", contractAddress.String()) +We welcome contributions from the community! If you're interested in contributing to the zksync2-go Golang SDK, +please take a look at our [CONTRIBUTING.md](./.github/CONTRIBUTING.md) for guidelines and details on the process. -``` \ No newline at end of file +Thank you for making zksync2-go Golang SDK better! 🙌 \ No newline at end of file diff --git a/accounts/types.go b/accounts/types.go index 9f059b2..5a5b1d0 100644 --- a/accounts/types.go +++ b/accounts/types.go @@ -633,7 +633,7 @@ func (t *CreateTransaction) ToTransaction(deploymentType DeploymentType, opts *T } else { data, err = utils.EncodeCreateAccount(t.Bytecode, t.Calldata, zkTypes.Version1) if err != nil { - return nil, fmt.Errorf("failed to encode create2Account call: %w", err) + return nil, fmt.Errorf("failed to encode createAccount call: %w", err) } } diff --git a/accounts/wallet_l1.go b/accounts/wallet_l1.go index d7ec7d8..1473443 100644 --- a/accounts/wallet_l1.go +++ b/accounts/wallet_l1.go @@ -296,7 +296,7 @@ func (a *WalletL1) FullRequiredDepositFee(ctx context.Context, msg DepositCallMs l1GasLimit, err := a.EstimateGasDeposit(ensureContext(ctx), DepositCallMsg{ To: msg.To, Token: msg.Token, - Amount: msg.Amount, + Amount: amountForEstimation, OperatorTip: msg.OperatorTip, BridgeAddress: msg.BridgeAddress, L2GasLimit: msg.L2GasLimit, diff --git a/clients/base_client.go b/clients/base_client.go index c55e064..83ecf47 100644 --- a/clients/base_client.go +++ b/clients/base_client.go @@ -357,7 +357,7 @@ func (c *BaseClient) TestnetPaymaster(ctx context.Context) (common.Address, erro var res string err := c.rpcClient.CallContext(ctx, &res, "zks_getTestnetPaymaster") if err != nil { - return common.Address{}, fmt.Errorf("failed to query zks_estimateFee: %w", err) + return common.Address{}, fmt.Errorf("failed to query zks_getTestnetPaymaster: %w", err) } return common.HexToAddress(res), nil } diff --git a/commit-format.md b/commit-format.md deleted file mode 100644 index aa17fb8..0000000 --- a/commit-format.md +++ /dev/null @@ -1,116 +0,0 @@ -# Commit Message Format - -*This specification is inspired by and supersedes -the [AngularJS commit message format](https://gist.github.com/brianclements/841ea7bffdb01346392c).* - -We have very precise rules over how our Git commit messages must be formatted. -This format leads to **easier to read commit history**. - -Each commit message consists of a **header**, a **body**, and a **footer**. - -``` -
- - - -