Showing preview only (708K chars total). Download the full file or copy to clipboard to get everything.
Repository: umbracle/ethgo
Branch: main
Commit: 92266b0b0212
Files: 181
Total size: 661.5 KB
Directory structure:
gitextract_zpf77o7o/
├── .github/
│ └── workflows/
│ ├── pr.yaml
│ └── release.yaml
├── .gitignore
├── .goreleaser.yaml
├── 4byte/
│ ├── 4byte.go
│ └── 4byte_test.go
├── CHANGELOG.md
├── LICENSE
├── Makefile
├── README.md
├── abi/
│ ├── abi.go
│ ├── abi_test.go
│ ├── decode.go
│ ├── decode_test.go
│ ├── encode.go
│ ├── encoding_test.go
│ ├── revert.go
│ ├── revert_test.go
│ ├── testing.go
│ ├── topics.go
│ ├── topics_test.go
│ ├── type.go
│ └── type_test.go
├── blocktracker/
│ ├── blocktracker.go
│ └── blocktracker_test.go
├── builtin/
│ ├── ens/
│ │ ├── artifacts/
│ │ │ ├── ENS.abi
│ │ │ └── Resolver.abi
│ │ ├── ens.go
│ │ ├── ens_artifacts.go
│ │ ├── ens_resolver.go
│ │ ├── ens_resolver_test.go
│ │ ├── resolver.go
│ │ ├── resolver_artifacts.go
│ │ ├── utils.go
│ │ └── utils_test.go
│ └── erc20/
│ ├── artifacts/
│ │ └── ERC20.abi
│ ├── erc20.go
│ ├── erc20_artifacts.go
│ └── erc20_test.go
├── cmd/
│ ├── abigen/
│ │ ├── abigen.go
│ │ ├── gen.go
│ │ └── testdata/
│ │ ├── testdata.abi
│ │ ├── testdata.go
│ │ └── testdata_artifacts.go
│ ├── commands/
│ │ ├── 4byte.go
│ │ ├── abigen.go
│ │ ├── commands.go
│ │ ├── ens.go
│ │ ├── ens_resolve.go
│ │ └── version.go
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── version/
│ └── version.go
├── compiler/
│ ├── fixtures/
│ │ ├── ballot.sol
│ │ └── simple_auction.sol
│ ├── solidity.go
│ └── solidity_test.go
├── contract/
│ ├── contract.go
│ └── contract_test.go
├── e2e/
│ └── transaction_test.go
├── encoding.go
├── ens/
│ ├── address_mapping.go
│ ├── ens.go
│ └── ens_test.go
├── etherscan/
│ ├── etherscan.go
│ └── etherscan_test.go
├── examples/
│ ├── contract-call-basic.go
│ ├── contract-call-from.go
│ ├── contract-deploy.go
│ └── contract-transaction.go
├── go.mod
├── go.sum
├── jsonrpc/
│ ├── client.go
│ ├── codec/
│ │ └── codec.go
│ ├── debug.go
│ ├── debug_test.go
│ ├── eth.go
│ ├── eth_test.go
│ ├── net.go
│ ├── net_test.go
│ ├── subscribe.go
│ ├── subscribe_test.go
│ ├── transport/
│ │ ├── http.go
│ │ ├── ipc.go
│ │ ├── transport.go
│ │ └── websocket.go
│ ├── util.go
│ ├── web3.go
│ └── web3_test.go
├── keccak.go
├── keystore/
│ ├── utils.go
│ ├── v3.go
│ ├── v3_test.go
│ ├── v4.go
│ └── v4_test.go
├── networks.go
├── scripts/
│ ├── build-artifacts.sh
│ ├── setup-ci.sh
│ └── setup-geth.sh
├── signing/
│ ├── eip712.go
│ └── eip712_test.go
├── structs.go
├── structs_encoding_test.go
├── structs_marshal.go
├── structs_marshal_rlp.go
├── structs_marshal_rlp_test.go
├── structs_marshal_test.go
├── structs_test.go
├── structs_unmarshal.go
├── testcases/
│ ├── accounts_test.go
│ ├── contract_test.go
│ ├── eip712_test.go
│ ├── package.json
│ ├── transaction_test.go
│ └── util.go
├── testsuite/
│ ├── arbitrum-block-full.json
│ ├── block-full.json
│ ├── block-txn-hashes.json
│ ├── receipts.json
│ ├── transaction-call.json
│ ├── transaction-contract-creation.json
│ ├── transaction-eip1159.json
│ ├── transaction-eip1559-notype.json
│ ├── transaction-eip2930.json
│ └── transaction-pending.json
├── testutil/
│ ├── contract.go
│ ├── mock.go
│ ├── server.go
│ ├── server_test.go
│ └── util.go
├── tracker/
│ ├── README.md
│ ├── store/
│ │ ├── boltdb/
│ │ │ ├── bolt_store.go
│ │ │ └── bolt_store_test.go
│ │ ├── inmem/
│ │ │ ├── inmem_store.go
│ │ │ └── inmem_store_test.go
│ │ ├── postgresql/
│ │ │ ├── postgresql_store.go
│ │ │ └── postgresql_store_test.go
│ │ ├── store.go
│ │ └── testing.go
│ ├── tracker.go
│ └── tracker_test.go
├── units.go
├── wallet/
│ ├── fixtures/
│ │ └── wallet_json.json
│ ├── key.go
│ ├── key_test.go
│ ├── signer.go
│ ├── signer_test.go
│ ├── wallet_hd.go
│ ├── wallet_hd_test.go
│ ├── wallet_json.go
│ ├── wallet_json_test.go
│ ├── wallet_priv.go
│ └── wallet_priv_test.go
└── website/
├── README.md
├── components/
│ ├── eip.jsx
│ ├── godoc.jsx
│ └── primitives.jsx
├── next.config.js
├── package.json
├── pages/
│ ├── _app.js
│ ├── abi.mdx
│ ├── cli/
│ │ ├── 4byte.mdx
│ │ ├── abigen.mdx
│ │ ├── ens_resolve.mdx
│ │ ├── meta.json
│ │ └── version.mdx
│ ├── contract.mdx
│ ├── index.mdx
│ ├── integrations/
│ │ ├── 4byte.mdx
│ │ ├── ens.mdx
│ │ ├── etherscan.mdx
│ │ └── meta.json
│ ├── jsonrpc/
│ │ ├── eth.mdx
│ │ ├── index.mdx
│ │ ├── meta.json
│ │ └── net.mdx
│ ├── meta.json
│ └── signers/
│ ├── signer.mdx
│ └── wallet.mdx
└── theme.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/pr.yaml
================================================
name: Unit tests
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
name: Go test
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: "14"
- name: Install ethers testcases
run: cd ./testcases && npm install
- name: Setup go
uses: actions/setup-go@v1
with:
go-version: "1.18.1"
- name: "Setup"
run: ./scripts/setup-ci.sh
- name: "Setup geth"
run: ./scripts/setup-geth.sh
- name: Go test
run: go test -v ./...
================================================
FILE: .github/workflows/release.yaml
================================================
name: Release
on:
workflow_dispatch:
push:
branches-ignore:
- '**'
tags:
- 'v*.*.*'
# to be used by fork patch-releases ^^
- 'v*.*.*-*'
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Fetch all tags
run: git fetch --force --tags
- name: Setup go
uses: actions/setup-go@v1
with:
go-version: '1.18.1'
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
with:
distribution: goreleaser
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .gitignore
================================================
bin/
pkg/
.idea
# website
node_modules
.next
dist/
================================================
FILE: .goreleaser.yaml
================================================
before:
hooks:
- go mod tidy
builds:
- dir: cmd
env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
archives:
- replacements:
darwin: Darwin
linux: Linux
windows: Windows
386: i386
amd64: x86_64
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
================================================
FILE: 4byte/4byte.go
================================================
package fourbyte
import (
"encoding/hex"
"encoding/json"
"io/ioutil"
"net/http"
)
const (
fourByteURL = "https://www.4byte.directory"
)
// Resolve resolves a method/event signature
func Resolve(str string) (string, error) {
return get("/api/v1/signatures/?hex_signature=" + str)
}
// ResolveBytes resolves a method/event signature in bytes
func ResolveBytes(b []byte) (string, error) {
return Resolve(hex.EncodeToString(b))
}
func get(path string) (string, error) {
req, err := http.Get(fourByteURL + path)
if err != nil {
return "", err
}
defer req.Body.Close()
data, err := ioutil.ReadAll(req.Body)
if err != nil {
return "", err
}
var result struct {
Results []signatureResult
}
if err := json.Unmarshal(data, &result); err != nil {
return "", err
}
if len(result.Results) == 0 {
return "", nil
}
return result.Results[0].TextSignature, nil
}
type signatureResult struct {
TextSignature string `json:"text_signature"`
}
================================================
FILE: 4byte/4byte_test.go
================================================
package fourbyte
import (
"testing"
"github.com/stretchr/testify/assert"
)
func Test4Byte(t *testing.T) {
t.Skip("http api not stable, skip for now")
var cases = []struct {
in, out string
}{
{
"0xddf252ad",
"Transfer(address,address,uint256)",
},
{
"0x42842e0e",
"safeTransferFrom(address,address,uint256)",
},
}
for _, i := range cases {
found, err := Resolve(i.in)
assert.NoError(t, err)
assert.Equal(t, i.out, found)
}
}
================================================
FILE: CHANGELOG.md
================================================
# 0.1.4 (Unreleased)
- feat: Add override to `eth_call` request [[GH-240](https://github.com/umbracle/ethgo/issues/240)]
- fix: Recovery of typed transactions [[GH-238](https://github.com/umbracle/ethgo/issues/238)]
- fix: Parse `nonce` and `mixHash` on `Block` [[GH-228](https://github.com/umbracle/ethgo/issues/228)]
- feat: `abi` decodes function string in multilines [[GH-212](https://github.com/umbracle/ethgo/issues/212)]
- feat: `abi` DecodeStruct uses the `abi` tag instead of the default `mapstructure` [[GH-211](https://github.com/umbracle/ethgo/issues/211)]
- feat: Implement `ens` reverse resolver [[GH-210](https://github.com/umbracle/ethgo/issues/210)]
- fix: Jsonrpc eth_getLogs request cannot return string [[GH-209](https://github.com/umbracle/ethgo/issues/209)]
# 0.1.3 (13 June, 2022)
- Fix out-of-bounds reading of bytes during ABI decoding [[GH-205](https://github.com/umbracle/ethgo/issues/205)]
- Update `fastrlp` to `59d5dd3` commit to fix a bug on bytes length check [[GH-204](https://github.com/umbracle/ethgo/issues/204)]
- Fix out-of-bounds RLP unmarshal of transactions [[GH-203](https://github.com/umbracle/ethgo/issues/203)]
# 0.1.2 (5 May, 2022)
- Update `btcd` library to new `v0.22.1`
- Add option in `contract` to send transactions with EIP-1559 [[GH-198](https://github.com/umbracle/ethgo/issues/198)]
- Add custom `TxnOpts` to send a transaction in `contract` [[GH-195](https://github.com/umbracle/ethgo/issues/195)]
- Add `ens resolve` command to resolve an ENS name [[GH-196](https://github.com/umbracle/ethgo/issues/196)]
- Fix signing of typed transactions [[GH-197](https://github.com/umbracle/ethgo/issues/197)]
- Fix. Use `ethgo.BlockNumber` input to make `Call` in contract [[GH-194](https://github.com/umbracle/ethgo/issues/194)]
- Add `testcases` for contract signature and transaction signing [[GH-193](https://github.com/umbracle/ethgo/issues/193)]
- Add `eth_feeHistory` rpc endpoint [[GH-192](https://github.com/umbracle/ethgo/issues/192)]
- Update `testserver` to `go-ethereum:v1.10.15` [[GH-191](https://github.com/umbracle/ethgo/issues/191)]
- Do not decode `to` in `Transaction` if not exists [[GH-190](https://github.com/umbracle/ethgo/issues/190)]
# 0.1.1 (25 April, 2022)
- Retrieve latest nonce when sending a transaction on `contract` [[GH-185](https://github.com/umbracle/ethgo/issues/185)]
- Add `etherscan.GasPrice` function to return last block gas price [[GH-182](https://github.com/umbracle/ethgo/issues/182)]
- Add `4byte` package and cli [[GH-178](https://github.com/umbracle/ethgo/issues/178)]
- Install and use `ethers.js` spec tests for wallet private key decoding [[GH-177](https://github.com/umbracle/ethgo/issues/177)]
- Add `GetLogs` function Etherscan to return logs by filter [[GH-170](https://github.com/umbracle/ethgo/issues/170)]
- Add `Copy` function to major data types [[GH-169](https://github.com/umbracle/ethgo/issues/169)]
- Parse `fixed bytes` type in event topic [[GH-168](https://github.com/umbracle/ethgo/issues/168)]
- Introduce `NodeProvider` and update `Contract` and `abigen` format. [[GH-167](https://github.com/umbracle/ethgo/issues/167)]
# 0.1.0 (5 March, 2022)
- Initial public release.
================================================
FILE: LICENSE
================================================
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
================================================
FILE: Makefile
================================================
.PHONY: build-artifacts
build-artifacts:
@echo "--> Build Artifacts"
@sh -c ./scripts/build-artifacts.sh
================================================
FILE: README.md
================================================
# Eth-Go
[![Chat Badge]][chat link]
[chat badge]: https://img.shields.io/badge/chat-discord-%237289da
[chat link]: https://discord.gg/5A6Qm2u4yK
Ethgo is a lightweight SDK in Go to interact with Ethereum compatible blockchains.
- Website: https://www.ethgoproject.io
Ethgo provides the next key features:
- **Simple**: Light and with a small number of direct dependencies.
- **Ethereum ecosystem**: Native integration with other tools from the ecosystem like `ens` and `etherscan`.
- **Command-line-interface**: Ethgo is both a Golang SDK library and a CLI.
================================================
FILE: abi/abi.go
================================================
package abi
import (
"bytes"
"encoding/json"
"fmt"
"hash"
"io"
"regexp"
"strings"
"sync"
"github.com/umbracle/ethgo"
"golang.org/x/crypto/sha3"
)
// ABI represents the ethereum abi format
type ABI struct {
Constructor *Method
Methods map[string]*Method
MethodsBySignature map[string]*Method
Events map[string]*Event
Errors map[string]*Error
}
func (a *ABI) GetMethod(name string) *Method {
m := a.Methods[name]
return m
}
func (a *ABI) GetMethodBySignature(methodSignature string) *Method {
m := a.MethodsBySignature[methodSignature]
return m
}
func (a *ABI) addError(e *Error) {
if len(a.Errors) == 0 {
a.Errors = map[string]*Error{}
}
a.Errors[e.Name] = e
}
func (a *ABI) addEvent(e *Event) {
if len(a.Events) == 0 {
a.Events = map[string]*Event{}
}
name := overloadedName(e.Name, func(s string) bool {
_, ok := a.Events[s]
return ok
})
a.Events[name] = e
}
func (a *ABI) addMethod(m *Method) {
if len(a.Methods) == 0 {
a.Methods = map[string]*Method{}
}
if len(a.MethodsBySignature) == 0 {
a.MethodsBySignature = map[string]*Method{}
}
name := overloadedName(m.Name, func(s string) bool {
_, ok := a.Methods[s]
return ok
})
a.Methods[name] = m
a.MethodsBySignature[m.Sig()] = m
}
func overloadedName(rawName string, isAvail func(string) bool) string {
name := rawName
ok := isAvail(name)
for idx := 0; ok; idx++ {
name = fmt.Sprintf("%s%d", rawName, idx)
ok = isAvail(name)
}
return name
}
// NewABI returns a parsed ABI struct
func NewABI(s string) (*ABI, error) {
return NewABIFromReader(bytes.NewReader([]byte(s)))
}
// MustNewABI returns a parsed ABI contract or panics if fails
func MustNewABI(s string) *ABI {
a, err := NewABI(s)
if err != nil {
panic(err)
}
return a
}
// NewABIFromReader returns an ABI object from a reader
func NewABIFromReader(r io.Reader) (*ABI, error) {
var abi *ABI
dec := json.NewDecoder(r)
if err := dec.Decode(&abi); err != nil {
return nil, err
}
return abi, nil
}
// UnmarshalJSON implements json.Unmarshaler interface
func (a *ABI) UnmarshalJSON(data []byte) error {
var fields []struct {
Type string
Name string
Constant bool
Anonymous bool
StateMutability string
Inputs []*ArgumentStr
Outputs []*ArgumentStr
}
if err := json.Unmarshal(data, &fields); err != nil {
return err
}
for _, field := range fields {
switch field.Type {
case "constructor":
if a.Constructor != nil {
return fmt.Errorf("multiple constructor declaration")
}
input, err := NewTupleTypeFromArgs(field.Inputs)
if err != nil {
panic(err)
}
a.Constructor = &Method{
Inputs: input,
}
case "function", "":
c := field.Constant
if field.StateMutability == "view" || field.StateMutability == "pure" {
c = true
}
inputs, err := NewTupleTypeFromArgs(field.Inputs)
if err != nil {
panic(err)
}
outputs, err := NewTupleTypeFromArgs(field.Outputs)
if err != nil {
panic(err)
}
method := &Method{
Name: field.Name,
Const: c,
Inputs: inputs,
Outputs: outputs,
}
a.addMethod(method)
case "event":
input, err := NewTupleTypeFromArgs(field.Inputs)
if err != nil {
panic(err)
}
event := &Event{
Name: field.Name,
Anonymous: field.Anonymous,
Inputs: input,
}
a.addEvent(event)
case "error":
input, err := NewTupleTypeFromArgs(field.Inputs)
if err != nil {
panic(err)
}
errObj := &Error{
Name: field.Name,
Inputs: input,
}
a.addError(errObj)
case "fallback":
case "receive":
// do nothing
default:
return fmt.Errorf("unknown field type '%s'", field.Type)
}
}
return nil
}
// Method is a callable function in the contract
type Method struct {
Name string
Const bool
Inputs *Type
Outputs *Type
}
// Sig returns the signature of the method
func (m *Method) Sig() string {
return buildSignature(m.Name, m.Inputs)
}
// ID returns the id of the method
func (m *Method) ID() []byte {
k := acquireKeccak()
k.Write([]byte(m.Sig()))
dst := k.Sum(nil)[:4]
releaseKeccak(k)
return dst
}
// Encode encodes the inputs with this function
func (m *Method) Encode(args interface{}) ([]byte, error) {
data, err := Encode(args, m.Inputs)
if err != nil {
return nil, err
}
data = append(m.ID(), data...)
return data, nil
}
// Decode decodes the output with this function
func (m *Method) Decode(data []byte) (map[string]interface{}, error) {
if len(data) == 0 {
return nil, fmt.Errorf("empty response")
}
respInterface, err := Decode(m.Outputs, data)
if err != nil {
return nil, err
}
resp := respInterface.(map[string]interface{})
return resp, nil
}
// MustNewMethod creates a new solidity method object or fails
func MustNewMethod(name string) *Method {
method, err := NewMethod(name)
if err != nil {
panic(err)
}
return method
}
func NewMethod(name string) (*Method, error) {
name, inputs, outputs, err := parseMethodSignature(name)
if err != nil {
return nil, err
}
m := &Method{Name: name, Inputs: inputs, Outputs: outputs}
return m, nil
}
var (
funcRegexpWithReturn = regexp.MustCompile(`(\w*)\s*\((.*)\)(.*)\s*returns\s*\((.*)\)`)
funcRegexpWithoutReturn = regexp.MustCompile(`(\w*)\s*\((.*)\)(.*)`)
)
func parseMethodSignature(name string) (string, *Type, *Type, error) {
name = strings.Replace(name, "\n", " ", -1)
name = strings.Replace(name, "\t", " ", -1)
name = strings.TrimPrefix(name, "function ")
name = strings.TrimSpace(name)
var funcName, inputArgs, outputArgs string
if strings.Contains(name, "returns") {
matches := funcRegexpWithReturn.FindAllStringSubmatch(name, -1)
if len(matches) == 0 {
return "", nil, nil, fmt.Errorf("no matches found")
}
funcName = strings.TrimSpace(matches[0][1])
inputArgs = strings.TrimSpace(matches[0][2])
outputArgs = strings.TrimSpace(matches[0][4])
} else {
matches := funcRegexpWithoutReturn.FindAllStringSubmatch(name, -1)
if len(matches) == 0 {
return "", nil, nil, fmt.Errorf("no matches found")
}
funcName = strings.TrimSpace(matches[0][1])
inputArgs = strings.TrimSpace(matches[0][2])
}
input, err := NewType("tuple(" + inputArgs + ")")
if err != nil {
return "", nil, nil, err
}
output, err := NewType("tuple(" + outputArgs + ")")
if err != nil {
return "", nil, nil, err
}
return funcName, input, output, nil
}
// Event is a triggered log mechanism
type Event struct {
Name string
Anonymous bool
Inputs *Type
}
// Sig returns the signature of the event
func (e *Event) Sig() string {
return buildSignature(e.Name, e.Inputs)
}
// ID returns the id of the event used during logs
func (e *Event) ID() (res ethgo.Hash) {
k := acquireKeccak()
k.Write([]byte(e.Sig()))
dst := k.Sum(nil)
releaseKeccak(k)
copy(res[:], dst)
return
}
// MustNewEvent creates a new solidity event object or fails
func MustNewEvent(name string) *Event {
evnt, err := NewEvent(name)
if err != nil {
panic(err)
}
return evnt
}
// NewEvent creates a new solidity event object using the signature
func NewEvent(name string) (*Event, error) {
name, typ, err := parseEventOrErrorSignature("event ", name)
if err != nil {
return nil, err
}
return NewEventFromType(name, typ), nil
}
// Error is a solidity error object
type Error struct {
Name string
Inputs *Type
}
// NewError creates a new solidity error object
func NewError(name string) (*Error, error) {
name, typ, err := parseEventOrErrorSignature("error ", name)
if err != nil {
return nil, err
}
return &Error{Name: name, Inputs: typ}, nil
}
func parseEventOrErrorSignature(prefix string, name string) (string, *Type, error) {
if !strings.HasPrefix(name, prefix) {
return "", nil, fmt.Errorf("prefix '%s' not found", prefix)
}
name = strings.TrimPrefix(name, prefix)
if !strings.HasSuffix(name, ")") {
return "", nil, fmt.Errorf("failed to parse input, expected 'name(types)'")
}
indx := strings.Index(name, "(")
if indx == -1 {
return "", nil, fmt.Errorf("failed to parse input, expected 'name(types)'")
}
funcName, signature := name[:indx], name[indx:]
signature = "tuple" + signature
typ, err := NewType(signature)
if err != nil {
return "", nil, err
}
return funcName, typ, nil
}
// NewEventFromType creates a new solidity event object using the name and type
func NewEventFromType(name string, typ *Type) *Event {
return &Event{Name: name, Inputs: typ}
}
// Match checks wheter the log is from this event
func (e *Event) Match(log *ethgo.Log) bool {
if len(log.Topics) == 0 {
return false
}
if log.Topics[0] != e.ID() {
return false
}
return true
}
// ParseLog parses a log with this event
func (e *Event) ParseLog(log *ethgo.Log) (map[string]interface{}, error) {
if !e.Match(log) {
return nil, fmt.Errorf("log does not match this event")
}
return e.Inputs.ParseLog(log)
}
func buildSignature(name string, typ *Type) string {
types := make([]string, len(typ.tuple))
for i, input := range typ.tuple {
types[i] = strings.Replace(input.Elem.String(), "tuple", "", -1)
}
return fmt.Sprintf("%v(%v)", name, strings.Join(types, ","))
}
// ArgumentStr encodes a type object
type ArgumentStr struct {
Name string
Type string
Indexed bool
Components []*ArgumentStr
InternalType string
}
var keccakPool = sync.Pool{
New: func() interface{} {
return sha3.NewLegacyKeccak256()
},
}
func acquireKeccak() hash.Hash {
return keccakPool.Get().(hash.Hash)
}
func releaseKeccak(k hash.Hash) {
k.Reset()
keccakPool.Put(k)
}
func NewABIFromList(humanReadableAbi []string) (*ABI, error) {
res := &ABI{}
for _, c := range humanReadableAbi {
if strings.HasPrefix(c, "constructor") {
typ, err := NewType("tuple" + strings.TrimPrefix(c, "constructor"))
if err != nil {
return nil, err
}
res.Constructor = &Method{
Inputs: typ,
}
} else if strings.HasPrefix(c, "function ") {
method, err := NewMethod(c)
if err != nil {
return nil, err
}
res.addMethod(method)
} else if strings.HasPrefix(c, "event ") {
evnt, err := NewEvent(c)
if err != nil {
return nil, err
}
res.addEvent(evnt)
} else if strings.HasPrefix(c, "error ") {
errTyp, err := NewError(c)
if err != nil {
return nil, err
}
res.addError(errTyp)
} else {
return nil, fmt.Errorf("either event or function expected")
}
}
return res, nil
}
================================================
FILE: abi/abi_test.go
================================================
package abi
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAbi(t *testing.T) {
methodOutput := &Method{
Name: "abc",
Inputs: MustNewType("tuple()"),
Outputs: MustNewType("tuple()"),
}
balanceFunc := &Method{
Name: "balanceOf",
Const: true,
Inputs: MustNewType("tuple(address owner)"),
Outputs: MustNewType("tuple(uint256 balance)"),
}
cases := []struct {
Input string
Output *ABI
}{
{
Input: `[
{
"name": "abc",
"type": "function"
},
{
"name": "cde",
"type": "event",
"inputs": [
{
"indexed": true,
"name": "a",
"type": "address"
}
]
},
{
"name": "def",
"type": "error",
"inputs": [
{
"indexed": true,
"name": "a",
"type": "address"
}
]
},
{
"type": "function",
"name": "balanceOf",
"constant": true,
"stateMutability": "view",
"payable": false,
"inputs": [
{
"type": "address",
"name": "owner"
}
],
"outputs": [
{
"type": "uint256",
"name": "balance"
}
]
}
]`,
Output: &ABI{
Events: map[string]*Event{
"cde": {
Name: "cde",
Inputs: MustNewType("tuple(address indexed a)"),
},
},
Methods: map[string]*Method{
"abc": methodOutput,
"balanceOf": balanceFunc,
},
MethodsBySignature: map[string]*Method{
"abc()": methodOutput,
"balanceOf(address)": balanceFunc,
},
Errors: map[string]*Error{
"def": {
Name: "def",
Inputs: MustNewType("tuple(address indexed a)"),
},
},
},
},
}
for _, c := range cases {
t.Run("", func(t *testing.T) {
abi, err := NewABI(c.Input)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(abi, c.Output) {
t.Fatal("bad")
}
})
}
}
func TestAbi_InternalType(t *testing.T) {
const abiStr = `[
{
"inputs": [
{
"components": [
{
"internalType": "address",
"type": "address"
},
{
"internalType": "uint256[4]",
"type": "uint256[4]"
}
],
"internalType": "struct X",
"name": "newSet",
"type": "tuple[]"
},
{
"internalType": "custom_address",
"name": "_to",
"type": "address"
}
],
"outputs": [],
"name": "transfer",
"type": "function"
}
]`
abi, err := NewABI(abiStr)
require.NoError(t, err)
typ := abi.GetMethod("transfer").Inputs
require.Equal(t, typ.tuple[0].Elem.InternalType(), "struct X")
require.Equal(t, typ.tuple[0].Elem.elem.tuple[0].Elem.InternalType(), "address")
require.Equal(t, typ.tuple[0].Elem.elem.tuple[1].Elem.InternalType(), "uint256[4]")
require.Equal(t, typ.tuple[1].Elem.InternalType(), "custom_address")
}
func TestAbi_Polymorphism(t *testing.T) {
// This ABI contains 2 "transfer" functions (polymorphism)
const polymorphicABI = `[
{
"inputs": [
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "address",
"name": "_token",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]`
abi, err := NewABI(polymorphicABI)
if err != nil {
t.Fatal(err)
}
assert.Len(t, abi.Methods, 2)
assert.Equal(t, abi.GetMethod("transfer").Sig(), "transfer(address,address,uint256)")
assert.Equal(t, abi.GetMethod("transfer0").Sig(), "transfer(address,uint256)")
assert.NotEmpty(t, abi.GetMethodBySignature("transfer(address,address,uint256)"))
assert.NotEmpty(t, abi.GetMethodBySignature("transfer(address,uint256)"))
}
func TestAbi_HumanReadable(t *testing.T) {
cases := []string{
"constructor(string symbol, string name)",
"function transferFrom(address from, address to, uint256 value)",
"function balanceOf(address owner) view returns (uint256 balance)",
"function balanceOf() view returns ()",
"event Transfer(address indexed from, address indexed to, address value)",
"error InsufficientBalance(address owner, uint256 balance)",
"function addPerson(tuple(string name, uint16 age) person)",
"function addPeople(tuple(string name, uint16 age)[] person)",
"function getPerson(uint256 id) view returns (tuple(string name, uint16 age))",
"event PersonAdded(uint256 indexed id, tuple(string name, uint16 age) person)",
}
vv, err := NewABIFromList(cases)
assert.NoError(t, err)
// make it nil to not compare it and avoid writing each method twice for the test
vv.MethodsBySignature = nil
expect := &ABI{
Constructor: &Method{
Inputs: MustNewType("tuple(string symbol, string name)"),
},
Methods: map[string]*Method{
"transferFrom": {
Name: "transferFrom",
Inputs: MustNewType("tuple(address from, address to, uint256 value)"),
Outputs: MustNewType("tuple()"),
},
"balanceOf": {
Name: "balanceOf",
Inputs: MustNewType("tuple(address owner)"),
Outputs: MustNewType("tuple(uint256 balance)"),
},
"balanceOf0": {
Name: "balanceOf",
Inputs: MustNewType("tuple()"),
Outputs: MustNewType("tuple()"),
},
"addPerson": {
Name: "addPerson",
Inputs: MustNewType("tuple(tuple(string name, uint16 age) person)"),
Outputs: MustNewType("tuple()"),
},
"addPeople": {
Name: "addPeople",
Inputs: MustNewType("tuple(tuple(string name, uint16 age)[] person)"),
Outputs: MustNewType("tuple()"),
},
"getPerson": {
Name: "getPerson",
Inputs: MustNewType("tuple(uint256 id)"),
Outputs: MustNewType("tuple(tuple(string name, uint16 age))"),
},
},
Events: map[string]*Event{
"Transfer": {
Name: "Transfer",
Inputs: MustNewType("tuple(address indexed from, address indexed to, address value)"),
},
"PersonAdded": {
Name: "PersonAdded",
Inputs: MustNewType("tuple(uint256 indexed id, tuple(string name, uint16 age) person)"),
},
},
Errors: map[string]*Error{
"InsufficientBalance": {
Name: "InsufficientBalance",
Inputs: MustNewType("tuple(address owner, uint256 balance)"),
},
},
}
assert.Equal(t, expect, vv)
}
func TestAbi_ParseMethodSignature(t *testing.T) {
cases := []struct {
signature string
name string
input string
output string
}{
{
// both input and output
signature: "function approve(address to) returns (address)",
name: "approve",
input: "tuple(address)",
output: "tuple(address)",
},
{
// no input
signature: "function approve() returns (address)",
name: "approve",
input: "tuple()",
output: "tuple(address)",
},
{
// no output
signature: "function approve(address)",
name: "approve",
input: "tuple(address)",
output: "tuple()",
},
{
// multiline
signature: `function a(
uint256 b,
address[] c
)
returns
(
uint256[] d
)`,
name: "a",
input: "tuple(uint256,address[])",
output: "tuple(uint256[])",
},
}
for _, c := range cases {
name, input, output, err := parseMethodSignature(c.signature)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, name, c.name)
if input != nil {
assert.Equal(t, c.input, input.String())
} else {
assert.Equal(t, c.input, "")
}
if input != nil {
assert.Equal(t, c.output, output.String())
} else {
assert.Equal(t, c.output, "")
}
}
}
================================================
FILE: abi/decode.go
================================================
package abi
import (
"encoding/binary"
"fmt"
"math/big"
"reflect"
"strconv"
"github.com/mitchellh/mapstructure"
"github.com/umbracle/ethgo"
)
// Decode decodes the input with a given type
func Decode(t *Type, input []byte) (interface{}, error) {
if len(input) == 0 {
return nil, fmt.Errorf("empty input")
}
val, _, err := decode(t, input)
return val, err
}
// DecodeStruct decodes the input with a type to a struct
func DecodeStruct(t *Type, input []byte, out interface{}) error {
val, err := Decode(t, input)
if err != nil {
return err
}
dc := &mapstructure.DecoderConfig{
Result: out,
WeaklyTypedInput: true,
TagName: "abi",
}
ms, err := mapstructure.NewDecoder(dc)
if err != nil {
return err
}
if err = ms.Decode(val); err != nil {
return err
}
return nil
}
func decode(t *Type, input []byte) (interface{}, []byte, error) {
var data []byte
var length int
var err error
// safe check, input should be at least 32 bytes
if len(input) < 32 {
return nil, nil, fmt.Errorf("incorrect length")
}
if t.isVariableInput() {
length, err = readLength(input)
if err != nil {
return nil, nil, err
}
} else {
data = input[:32]
}
switch t.kind {
case KindTuple:
return decodeTuple(t, input)
case KindSlice:
return decodeArraySlice(t, input[32:], length)
case KindArray:
return decodeArraySlice(t, input, t.size)
}
var val interface{}
switch t.kind {
case KindBool:
val, err = decodeBool(data)
case KindInt, KindUInt:
val = readInteger(t, data)
case KindString:
val = string(input[32 : 32+length])
case KindBytes:
val = input[32 : 32+length]
case KindAddress:
val, err = readAddr(data)
case KindFixedBytes:
val, err = readFixedBytes(t, data)
case KindFunction:
val, err = readFunctionType(t, data)
default:
return nil, nil, fmt.Errorf("decoding not available for type '%s'", t.kind)
}
return val, input[32:], err
}
var (
maxUint256 = big.NewInt(0).Add(
big.NewInt(0).Exp(big.NewInt(2), big.NewInt(256), nil),
big.NewInt(-1))
maxInt256 = big.NewInt(0).Add(
big.NewInt(0).Exp(big.NewInt(2), big.NewInt(255), nil),
big.NewInt(-1))
)
func readAddr(b []byte) (ethgo.Address, error) {
res := ethgo.Address{}
if len(b) != 32 {
return res, fmt.Errorf("len is not correct")
}
copy(res[:], b[12:])
return res, nil
}
func readInteger(t *Type, b []byte) interface{} {
switch t.t.Kind() {
case reflect.Uint8:
return b[len(b)-1]
case reflect.Uint16:
return binary.BigEndian.Uint16(b[len(b)-2:])
case reflect.Uint32:
return binary.BigEndian.Uint32(b[len(b)-4:])
case reflect.Uint64:
return binary.BigEndian.Uint64(b[len(b)-8:])
case reflect.Int8:
return int8(b[len(b)-1])
case reflect.Int16:
return int16(binary.BigEndian.Uint16(b[len(b)-2:]))
case reflect.Int32:
return int32(binary.BigEndian.Uint32(b[len(b)-4:]))
case reflect.Int64:
return int64(binary.BigEndian.Uint64(b[len(b)-8:]))
default:
ret := new(big.Int).SetBytes(b)
if t.kind == KindUInt {
return ret
}
if ret.Cmp(maxInt256) > 0 {
ret.Add(maxUint256, big.NewInt(0).Neg(ret))
ret.Add(ret, big.NewInt(1))
ret.Neg(ret)
}
return ret
}
}
func readFunctionType(t *Type, word []byte) ([24]byte, error) {
res := [24]byte{}
if !allZeros(word[24:32]) {
return res, fmt.Errorf("function type expects the last 8 bytes to be empty but found: %b", word[24:32])
}
copy(res[:], word[0:24])
return res, nil
}
func readFixedBytes(t *Type, word []byte) (interface{}, error) {
array := reflect.New(t.t).Elem()
reflect.Copy(array, reflect.ValueOf(word[0:t.size]))
return array.Interface(), nil
}
func decodeTuple(t *Type, data []byte) (interface{}, []byte, error) {
res := make(map[string]interface{})
orig := data
origLen := len(orig)
for indx, arg := range t.tuple {
if len(data) < 32 {
return nil, nil, fmt.Errorf("incorrect length")
}
entry := data
if arg.Elem.isDynamicType() {
offset, err := readOffset(data, origLen)
if err != nil {
return nil, nil, err
}
entry = orig[offset:]
}
val, tail, err := decode(arg.Elem, entry)
if err != nil {
return nil, nil, err
}
if !arg.Elem.isDynamicType() {
data = tail
} else {
data = data[32:]
}
name := arg.Name
if name == "" {
name = strconv.Itoa(indx)
}
if _, ok := res[name]; !ok {
res[name] = val
} else {
return nil, nil, fmt.Errorf("tuple with repeated values")
}
}
return res, data, nil
}
func decodeArraySlice(t *Type, data []byte, size int) (interface{}, []byte, error) {
if size < 0 {
return nil, nil, fmt.Errorf("size is lower than zero")
}
if 32*size > len(data) {
return nil, nil, fmt.Errorf("size is too big")
}
var res reflect.Value
if t.kind == KindSlice {
res = reflect.MakeSlice(t.t, size, size)
} else if t.kind == KindArray {
res = reflect.New(t.t).Elem()
}
orig := data
origLen := len(orig)
for indx := 0; indx < size; indx++ {
isDynamic := t.elem.isDynamicType()
if len(data) < 32 {
return nil, nil, fmt.Errorf("incorrect length")
}
entry := data
if isDynamic {
offset, err := readOffset(data, origLen)
if err != nil {
return nil, nil, err
}
entry = orig[offset:]
}
val, tail, err := decode(t.elem, entry)
if err != nil {
return nil, nil, err
}
if !isDynamic {
data = tail
} else {
data = data[32:]
}
res.Index(indx).Set(reflect.ValueOf(val))
}
return res.Interface(), data, nil
}
func decodeBool(data []byte) (interface{}, error) {
switch data[31] {
case 0:
return false, nil
case 1:
return true, nil
default:
return false, fmt.Errorf("bad boolean")
}
}
func readOffset(data []byte, len int) (int, error) {
offsetBig := big.NewInt(0).SetBytes(data[0:32])
if offsetBig.BitLen() > 63 {
return 0, fmt.Errorf("offset larger than int64: %v", offsetBig.Int64())
}
offset := int(offsetBig.Int64())
if offset > len {
return 0, fmt.Errorf("offset insufficient %v require %v", len, offset)
}
return offset, nil
}
func readLength(data []byte) (int, error) {
lengthBig := big.NewInt(0).SetBytes(data[0:32])
if lengthBig.BitLen() > 63 {
return 0, fmt.Errorf("length larger than int64: %v", lengthBig.Int64())
}
length := int(lengthBig.Uint64())
// if we trim the length in the data there should be enough
// bytes to cover the length
if length > len(data)-32 {
return 0, fmt.Errorf("length insufficient %v require %v", len(data), length)
}
return length, nil
}
func allZeros(b []byte) bool {
for _, i := range b {
if i != 0 {
return false
}
}
return true
}
================================================
FILE: abi/decode_test.go
================================================
package abi
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestDecode_BytesBound(t *testing.T) {
typ := MustNewType("tuple(string)")
decodeTuple(typ, nil) // it should not panic
}
func TestDecode_DynamicLengthOutOfBounds(t *testing.T) {
input := []byte("00000000000000000000000000000000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00000000000000000000000000")
typ := MustNewType("tuple(bytes32, bytes, bytes)")
_, err := Decode(typ, input)
require.Error(t, err)
}
================================================
FILE: abi/encode.go
================================================
package abi
import (
"encoding/hex"
"fmt"
"math/big"
"reflect"
"strconv"
"strings"
"github.com/umbracle/ethgo"
)
var (
zero = big.NewInt(0)
one = big.NewInt(1)
)
// Encode encodes a value
func Encode(v interface{}, t *Type) ([]byte, error) {
return encode(reflect.ValueOf(v), t)
}
func encode(v reflect.Value, t *Type) ([]byte, error) {
if v.Kind() == reflect.Interface {
v = v.Elem()
}
switch t.kind {
case KindSlice, KindArray:
return encodeSliceAndArray(v, t)
case KindTuple:
return encodeTuple(v, t)
case KindString:
return encodeString(v)
case KindBool:
return encodeBool(v)
case KindAddress:
return encodeAddress(v)
case KindInt, KindUInt:
return encodeNum(v)
case KindBytes:
return encodeBytes(v)
case KindFixedBytes, KindFunction:
return encodeFixedBytes(v)
default:
return nil, fmt.Errorf("encoding not available for type '%s'", t.kind)
}
}
func encodeSliceAndArray(v reflect.Value, t *Type) ([]byte, error) {
if v.Kind() != reflect.Array && v.Kind() != reflect.Slice {
return nil, encodeErr(v, t.kind.String())
}
if v.Kind() == reflect.Array && t.kind != KindArray {
return nil, fmt.Errorf("expected array")
} else if v.Kind() == reflect.Slice && t.kind != KindSlice {
return nil, fmt.Errorf("expected slice")
}
if t.kind == KindArray && t.size != v.Len() {
return nil, fmt.Errorf("array len incompatible")
}
var ret, tail []byte
if t.isVariableInput() {
ret = append(ret, packNum(v.Len())...)
}
offset := 0
isDynamic := t.elem.isDynamicType()
if isDynamic {
offset = getTypeSize(t.elem) * v.Len()
}
for i := 0; i < v.Len(); i++ {
val, err := encode(v.Index(i), t.elem)
if err != nil {
return nil, err
}
if !isDynamic {
ret = append(ret, val...)
} else {
ret = append(ret, packNum(offset)...)
offset += len(val)
tail = append(tail, val...)
}
}
return append(ret, tail...), nil
}
func encodeTuple(v reflect.Value, t *Type) ([]byte, error) {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
var err error
isList := true
switch v.Kind() {
case reflect.Slice, reflect.Array:
case reflect.Map:
isList = false
case reflect.Struct:
isList = false
v, err = mapFromStruct(v)
if err != nil {
return nil, err
}
default:
return nil, encodeErr(v, "tuple")
}
if v.Len() < len(t.tuple) {
return nil, fmt.Errorf("expected at least the same length")
}
offset := 0
for _, elem := range t.tuple {
offset += getTypeSize(elem.Elem)
}
var ret, tail []byte
var aux reflect.Value
for i, elem := range t.tuple {
if isList {
aux = v.Index(i)
} else {
name := elem.Name
if name == "" {
name = strconv.Itoa(i)
}
aux = v.MapIndex(reflect.ValueOf(name))
}
if aux.Kind() == reflect.Invalid {
return nil, fmt.Errorf("cannot get key %s", elem.Name)
}
val, err := encode(aux, elem.Elem)
if err != nil {
return nil, err
}
if elem.Elem.isDynamicType() {
ret = append(ret, packNum(offset)...)
tail = append(tail, val...)
offset += len(val)
} else {
ret = append(ret, val...)
}
}
return append(ret, tail...), nil
}
func convertArrayToBytes(value reflect.Value) reflect.Value {
slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len())
reflect.Copy(slice, value)
return slice
}
func encodeFixedBytes(v reflect.Value) ([]byte, error) {
if v.Kind() == reflect.Array {
v = convertArrayToBytes(v)
}
if v.Kind() == reflect.String {
value, err := decodeHex(v.String())
if err != nil {
return nil, err
}
v = reflect.ValueOf(value)
}
return rightPad(v.Bytes(), 32), nil
}
func encodeAddress(v reflect.Value) ([]byte, error) {
if v.Kind() == reflect.Array {
v = convertArrayToBytes(v)
}
if v.Kind() == reflect.String {
var addr ethgo.Address
if err := addr.UnmarshalText([]byte(v.String())); err != nil {
return nil, err
}
v = reflect.ValueOf(addr.Bytes())
}
return leftPad(v.Bytes(), 32), nil
}
func encodeBytes(v reflect.Value) ([]byte, error) {
if v.Kind() == reflect.Array {
v = convertArrayToBytes(v)
}
if v.Kind() == reflect.String {
value, err := decodeHex(v.String())
if err != nil {
return nil, err
}
v = reflect.ValueOf(value)
}
return packBytesSlice(v.Bytes(), v.Len())
}
func encodeString(v reflect.Value) ([]byte, error) {
if v.Kind() != reflect.String {
return nil, encodeErr(v, "string")
}
return packBytesSlice([]byte(v.String()), v.Len())
}
func packBytesSlice(buf []byte, l int) ([]byte, error) {
len, err := encodeNum(reflect.ValueOf(l))
if err != nil {
return nil, err
}
return append(len, rightPad(buf, (l+31)/32*32)...), nil
}
func packNum(offset int) []byte {
n, _ := encodeNum(reflect.ValueOf(offset))
return n
}
func encodeNum(v reflect.Value) ([]byte, error) {
switch v.Kind() {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return toU256(new(big.Int).SetUint64(v.Uint())), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return toU256(big.NewInt(v.Int())), nil
case reflect.Ptr:
if v.Type() != bigIntT {
return nil, encodeErr(v.Elem(), "number")
}
return toU256(v.Interface().(*big.Int)), nil
case reflect.Float64:
return encodeNum(reflect.ValueOf(int64(v.Float())))
case reflect.String:
n, ok := new(big.Int).SetString(v.String(), 10)
if !ok {
n, ok = new(big.Int).SetString(v.String()[2:], 16)
if !ok {
return nil, encodeErr(v, "number")
}
}
return encodeNum(reflect.ValueOf(n))
default:
return nil, encodeErr(v, "number")
}
}
func encodeBool(v reflect.Value) ([]byte, error) {
if v.Kind() != reflect.Bool {
return nil, encodeErr(v, "bool")
}
if v.Bool() {
return leftPad(one.Bytes(), 32), nil
}
return leftPad(zero.Bytes(), 32), nil
}
func encodeErr(v reflect.Value, t string) error {
return fmt.Errorf("failed to encode %s as %s", v.Kind().String(), t)
}
func mapFromStruct(v reflect.Value) (reflect.Value, error) {
res := map[string]interface{}{}
typ := v.Type()
for i := 0; i < v.NumField(); i++ {
f := typ.Field(i)
if f.PkgPath != "" {
continue
}
tagValue := f.Tag.Get("abi")
if tagValue == "-" {
continue
}
name := strings.ToLower(f.Name)
if tagValue != "" {
name = tagValue
}
if _, ok := res[name]; !ok {
res[name] = v.Field(i).Interface()
}
}
return reflect.ValueOf(res), nil
}
var (
tt256 = new(big.Int).Lsh(big.NewInt(1), 256) // 2 ** 256
tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1)) // 2 ** 256 - 1
)
// U256 converts a big Int into a 256bit EVM number.
func toU256(n *big.Int) []byte {
b := new(big.Int)
b = b.Set(n)
if b.Sign() < 0 || b.BitLen() > 256 {
b.And(b, tt256m1)
}
return leftPad(b.Bytes(), 32)
}
func padBytes(b []byte, size int, left bool) []byte {
l := len(b)
if l == size {
return b
}
if l > size {
return b[l-size:]
}
tmp := make([]byte, size)
if left {
copy(tmp[size-l:], b)
} else {
copy(tmp, b)
}
return tmp
}
func leftPad(b []byte, size int) []byte {
return padBytes(b, size, true)
}
func rightPad(b []byte, size int) []byte {
return padBytes(b, size, false)
}
func encodeHex(b []byte) string {
return "0x" + hex.EncodeToString(b)
}
func decodeHex(str string) ([]byte, error) {
if strings.HasPrefix(str, "0x") {
str = str[2:]
}
buf, err := hex.DecodeString(str)
if err != nil {
return nil, fmt.Errorf("could not decode hex: %v", err)
}
return buf, nil
}
================================================
FILE: abi/encoding_test.go
================================================
package abi
import (
"encoding/hex"
"fmt"
"math/big"
"math/rand"
"os"
"reflect"
"strconv"
"testing"
"time"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/compiler"
"github.com/umbracle/ethgo/testutil"
)
func mustDecodeHex(str string) []byte {
buf, err := decodeHex(str)
if err != nil {
panic(fmt.Errorf("could not decode hex: %v", err))
}
return buf
}
func TestEncoding(t *testing.T) {
cases := []struct {
Type string
Input interface{}
}{
{
"uint40",
big.NewInt(50),
},
{
"int256",
big.NewInt(2),
},
{
"int256[]",
[]*big.Int{big.NewInt(1), big.NewInt(2)},
},
{
"int256",
big.NewInt(-10),
},
{
"bytes5",
[5]byte{0x1, 0x2, 0x3, 0x4, 0x5},
},
{
"bytes",
mustDecodeHex("0x12345678911121314151617181920211"),
},
{
"string",
"foobar",
},
{
"uint8[][2]",
[2][]uint8{{1}, {1}},
},
{
"address[]",
[]ethgo.Address{{1}, {2}},
},
{
"bytes10[]",
[][10]byte{
{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10},
{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x10},
},
},
{
"bytes[]",
[][]byte{
mustDecodeHex("0x11"),
mustDecodeHex("0x22"),
},
},
{
"uint32[2][3][4]",
[4][3][2]uint32{{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}, {{13, 14}, {15, 16}, {17, 18}}, {{19, 20}, {21, 22}, {23, 24}}},
},
{
"uint8[]",
[]uint8{1, 2},
},
{
"string[]",
[]string{"hello", "foobar"},
},
{
"string[2]",
[2]string{"hello", "foobar"},
},
{
"bytes32[][]",
[][][32]uint8{{{1}, {2}}, {{3}, {4}, {5}}},
},
{
"bytes32[][2]",
[2][][32]uint8{{{1}, {2}}, {{3}, {4}, {5}}},
},
{
"bytes32[3][2]",
[2][3][32]uint8{{{1}, {2}, {3}}, {{3}, {4}, {5}}},
},
{
"uint16[][2][]",
[][2][]uint16{
{{0, 1}, {2, 3}},
{{4, 5}, {6, 7}},
},
},
{
"tuple(bytes[] a)",
map[string]interface{}{
"a": [][]byte{{0xf0, 0xf0, 0xf0}, {0xf0, 0xf0, 0xf0}},
},
},
{
"tuple(uint32[2][][] a)",
// `[{"type": "uint32[2][][]"}]`,
map[string]interface{}{
"a": [][][2]uint32{{{uint32(1), uint32(200)}, {uint32(1), uint32(1000)}}, {{uint32(1), uint32(200)}, {uint32(1), uint32(1000)}}},
},
},
{
"tuple(uint64[2] a)",
map[string]interface{}{
"a": [2]uint64{1, 2},
},
},
{
"tuple(uint32[2][3][4] a)",
map[string]interface{}{
"a": [4][3][2]uint32{{{1, 2}, {3, 4}, {5, 6}}, {{7, 8}, {9, 10}, {11, 12}}, {{13, 14}, {15, 16}, {17, 18}}, {{19, 20}, {21, 22}, {23, 24}}},
},
},
{
"tuple(int32[] a)",
map[string]interface{}{
"a": []int32{1, 2},
},
},
{
"tuple(int32 a, int32 b)",
map[string]interface{}{
"a": int32(1),
"b": int32(2),
},
},
{
"tuple(string a, int32 b)",
map[string]interface{}{
"a": "Hello Worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"b": int32(2),
},
},
{
"tuple(int32[2] a, int32[] b)",
map[string]interface{}{
"a": [2]int32{1, 2},
"b": []int32{4, 5, 6},
},
},
{
// tuple with array slice
"tuple(address[] a)",
map[string]interface{}{
"a": []ethgo.Address{
{0x1},
},
},
},
{
// First dynamic second static
"tuple(int32[] a, int32[2] b)",
map[string]interface{}{
"a": []int32{1, 2, 3},
"b": [2]int32{4, 5},
},
},
{
// Both dynamic
"tuple(int32[] a, int32[] b)",
map[string]interface{}{
"a": []int32{1, 2, 3},
"b": []int32{4, 5, 6},
},
},
{
"tuple(string a, int64 b)",
map[string]interface{}{
"a": "hello World",
"b": int64(266),
},
},
{
// tuple array
"tuple(int32 a, int32 b)[2]",
[2]map[string]interface{}{
{
"a": int32(1),
"b": int32(2),
},
{
"a": int32(3),
"b": int32(4),
},
},
},
{
// tuple array with dynamic content
"tuple(int32[] a)[2]",
[2]map[string]interface{}{
{
"a": []int32{1, 2, 3},
},
{
"a": []int32{4, 5, 6},
},
},
},
{
// tuple slice
"tuple(int32 a, int32[] b)[]",
[]map[string]interface{}{
{
"a": int32(1),
"b": []int32{2, 3},
},
{
"a": int32(4),
"b": []int32{5, 6},
},
},
},
{
// nested tuple
"tuple(tuple(int32 c, int32[] d) a, int32[] b)",
map[string]interface{}{
"a": map[string]interface{}{
"c": int32(5),
"d": []int32{3, 4},
},
"b": []int32{1, 2},
},
},
{
"tuple(uint8[2] a, tuple(uint8 e, uint32 f)[2] b, uint16 c, uint64[2][1] d)",
map[string]interface{}{
"a": [2]uint8{uint8(1), uint8(2)},
"b": [2]map[string]interface{}{
{
"e": uint8(10),
"f": uint32(11),
},
{
"e": uint8(20),
"f": uint32(21),
},
},
"c": uint16(3),
"d": [1][2]uint64{{uint64(4), uint64(5)}},
},
},
{
"tuple(uint16 a, uint16 b)[1][]",
[][1]map[string]interface{}{
{
{
"a": uint16(1),
"b": uint16(2),
},
},
{
{
"a": uint16(3),
"b": uint16(4),
},
},
{
{
"a": uint16(5),
"b": uint16(6),
},
},
{
{
"a": uint16(7),
"b": uint16(8),
},
},
},
},
{
"tuple(uint64[][] a, tuple(uint8 a, uint32 b)[1] b, uint64 c)",
map[string]interface{}{
"a": [][]uint64{
{3, 4},
},
"b": [1]map[string]interface{}{
{
"a": uint8(1),
"b": uint32(2),
},
},
"c": uint64(10),
},
},
}
server := testutil.NewTestServer(t)
for _, c := range cases {
t.Run("", func(t *testing.T) {
t.Parallel()
tt, err := NewType(c.Type)
if err != nil {
t.Fatal(err)
}
if err := testEncodeDecode(t, server, tt, c.Input); err != nil {
t.Fatal(err)
}
})
}
}
func TestEncodingBestEffort(t *testing.T) {
strAddress := "0xdbb881a51CD4023E4400CEF3ef73046743f08da3"
ethAddress := ethgo.HexToAddress(strAddress)
overflowBigInt, _ := new(big.Int).SetString("50000000000000000000000000000000000000", 10)
cases := []struct {
Type string
Input interface{}
Expected interface{}
}{
{
"uint40",
float64(50),
big.NewInt(50),
},
{
"uint40",
"50",
big.NewInt(50),
},
{
"uint40",
"0x32",
big.NewInt(50),
},
{
"int256",
float64(2),
big.NewInt(2),
},
{
"int256",
"50000000000000000000000000000000000000",
overflowBigInt,
},
{
"int256",
"0x259DA6542D43623D04C5112000000000",
overflowBigInt,
},
{
"int256[]",
[]interface{}{float64(1), float64(2)},
[]*big.Int{big.NewInt(1), big.NewInt(2)},
},
{
"int256[]",
[]interface{}{"1", "2"},
[]*big.Int{big.NewInt(1), big.NewInt(2)},
},
{
"int256",
float64(-10),
big.NewInt(-10),
},
{
"int256",
"-10",
big.NewInt(-10),
},
{
"address[]",
[]interface{}{strAddress, strAddress},
[]ethgo.Address{ethAddress, ethAddress},
},
{
"uint8[]",
[]interface{}{float64(1), float64(2)},
[]uint8{1, 2},
},
{
"uint8[]",
[]interface{}{"1", "2"},
[]uint8{1, 2},
},
{
"bytes",
"0x11",
[]uint8{17},
},
{
"bytes32",
"0x11",
[32]uint8{17},
},
{
"tuple(address a)",
map[string]interface{}{
"a": strAddress,
},
map[string]interface{}{
"a": ethAddress,
},
},
{
"tuple(address[] a)",
map[string]interface{}{
"a": []interface{}{strAddress, strAddress},
},
map[string]interface{}{
"a": []ethgo.Address{ethAddress, ethAddress},
},
},
{
"tuple(address a, int64 b)",
map[string]interface{}{
"a": strAddress,
"b": float64(266),
},
map[string]interface{}{
"a": ethAddress,
"b": int64(266),
},
},
{
"tuple(address a, int256 b)",
map[string]interface{}{
"a": strAddress,
"b": "50000000000000000000000000000000000000",
},
map[string]interface{}{
"a": ethAddress,
"b": overflowBigInt,
},
},
{
"tuple(address a, int256 b)",
map[string]interface{}{
"a": strAddress,
"b": "0x259DA6542D43623D04C5112000000000",
},
map[string]interface{}{
"a": ethAddress,
"b": overflowBigInt,
},
},
}
server := testutil.NewTestServer(t)
for _, c := range cases {
t.Run("", func(t *testing.T) {
tt, err := NewType(c.Type)
if err != nil {
t.Fatal(err)
}
res1, err := Encode(c.Input, tt)
if err != nil {
t.Fatal(err)
}
res2, err := Decode(tt, res1)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(res2, c.Expected) {
t.Fatal("bad")
}
if tt.kind == KindTuple {
if err := testTypeWithContract(t, server, tt); err != nil {
t.Fatal(err)
}
}
})
}
}
func TestEncodingArguments(t *testing.T) {
cases := []struct {
Arg *ArgumentStr
Input interface{}
}{
{
&ArgumentStr{
Type: "tuple",
Components: []*ArgumentStr{
{
Name: "",
Type: "int32",
},
{
Name: "",
Type: "int32",
},
},
},
map[string]interface{}{
"0": int32(1),
"1": int32(2),
},
},
{
&ArgumentStr{
Type: "tuple",
Components: []*ArgumentStr{
{
Name: "a",
Type: "int32",
},
{
Name: "",
Type: "int32",
},
},
},
map[string]interface{}{
"a": int32(1),
"1": int32(2),
},
},
}
server := testutil.NewTestServer(t)
for _, c := range cases {
t.Run("", func(t *testing.T) {
tt, err := NewTypeFromArgument(c.Arg)
if err != nil {
t.Fatal(err)
}
if err := testEncodeDecode(t, server, tt, c.Input); err != nil {
t.Fatal(err)
}
})
}
}
func testEncodeDecode(t *testing.T, server *testutil.TestServer, tt *Type, input interface{}) error {
res1, err := Encode(input, tt)
if err != nil {
return err
}
res2, err := Decode(tt, res1)
if err != nil {
return err
}
if !reflect.DeepEqual(res2, input) {
return fmt.Errorf("bad")
}
if tt.kind == KindTuple {
if err := testTypeWithContract(t, server, tt); err != nil {
return err
}
}
return nil
}
func generateRandomArgs(n int) *Type {
inputs := []*TupleElem{}
for i := 0; i < randomInt(1, 10); i++ {
ttt, err := NewType(randomType())
if err != nil {
panic(err)
}
inputs = append(inputs, &TupleElem{
Name: fmt.Sprintf("arg%d", i),
Elem: ttt,
})
}
return &Type{
kind: KindTuple,
tuple: inputs,
}
}
func TestRandomEncoding(t *testing.T) {
rand.Seed(time.Now().UTC().UnixNano())
nStr := os.Getenv("RANDOM_TESTS")
n, err := strconv.Atoi(nStr)
if err != nil {
n = 100
}
server := testutil.NewTestServer(t)
for i := 0; i < int(n); i++ {
t.Run("", func(t *testing.T) {
t.Parallel()
tt := generateRandomArgs(randomInt(1, 4))
input := generateRandomType(tt)
if err := testEncodeDecode(t, server, tt, input); err != nil {
t.Fatal(err)
}
if err := testDecodePanic(tt, input); err != nil {
t.Fatal(err)
}
})
}
}
func testDecodePanic(tt *Type, input interface{}) error {
// test that the encoded input and random permutattions of the response do not cause
// panics on Decode function
res1, err := Encode(input, tt)
if err != nil {
return err
}
buf := make([]byte, len(res1))
// change each bit of the input with 1
for i := 0; i < len(res1); i++ {
copy(buf, res1)
buf[i] = 0xff
Decode(tt, buf)
}
return nil
}
func testTypeWithContract(t *testing.T, server *testutil.TestServer, typ *Type) error {
g := &generateContractImpl{}
source := g.run(typ)
output, err := compiler.NewSolidityCompiler("solc").CompileCode(source)
if err != nil {
return err
}
solcContract, ok := output.Contracts["<stdin>:Sample"]
if !ok {
return fmt.Errorf("Expected the contract to be called Sample")
}
abi, err := NewABI(string(solcContract.Abi))
if err != nil {
return err
}
binBuf, err := hex.DecodeString(solcContract.Bin)
if err != nil {
return err
}
txn := ðgo.Transaction{
Input: binBuf,
}
receipt, err := server.SendTxn(txn)
if err != nil {
return err
}
method, ok := abi.Methods["set"]
if !ok {
return fmt.Errorf("method set not found")
}
tt := method.Inputs
val := generateRandomType(tt)
data, err := method.Encode(val)
if err != nil {
return err
}
res, err := server.Call(ðgo.CallMsg{
To: &receipt.ContractAddress,
Data: data,
})
if err != nil {
return err
}
if res != encodeHex(data[4:]) { // remove funct signature in data
return fmt.Errorf("bad")
}
return nil
}
func TestEncodingStruct(t *testing.T) {
typ := MustNewType("tuple(address aa, uint256 b)")
type Obj struct {
A ethgo.Address `abi:"aa"`
B *big.Int
}
obj := Obj{
A: ethgo.Address{0x1},
B: big.NewInt(1),
}
encoded, err := typ.Encode(&obj)
if err != nil {
t.Fatal(err)
}
var obj2 Obj
if err := typ.DecodeStruct(encoded, &obj2); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(obj, obj2) {
t.Fatal("bad")
}
}
func TestEncodingStruct_camcelCase(t *testing.T) {
typ := MustNewType("tuple(address aA, uint256 b)")
type Obj struct {
A ethgo.Address `abi:"aA"`
B *big.Int
}
obj := Obj{
A: ethgo.Address{0x1},
B: big.NewInt(1),
}
encoded, err := typ.Encode(&obj)
if err != nil {
t.Fatal(err)
}
var obj2 Obj
if err := typ.DecodeStruct(encoded, &obj2); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(obj, obj2) {
t.Fatal("bad")
}
}
================================================
FILE: abi/revert.go
================================================
package abi
import (
"bytes"
"fmt"
)
var revertId = []byte{0x8, 0xC3, 0x79, 0xA0}
func UnpackRevertError(b []byte) (string, error) {
if !bytes.HasPrefix(b, revertId) {
return "", fmt.Errorf("revert error prefix not found")
}
b = b[4:]
tt := MustNewType("tuple(string)")
vals, err := tt.Decode(b)
if err != nil {
return "", err
}
revVal := vals.(map[string]interface{})["0"].(string)
return revVal, nil
}
================================================
FILE: abi/revert_test.go
================================================
package abi
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestUnpackRevertError(t *testing.T) {
data := "08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000"
raw, err := decodeHex(data)
assert.NoError(t, err)
reason, err := UnpackRevertError(raw)
assert.NoError(t, err)
assert.Equal(t, "revert reason", reason)
}
================================================
FILE: abi/testing.go
================================================
package abi
import (
"fmt"
"math/big"
"math/rand"
"reflect"
"strings"
"github.com/umbracle/ethgo"
)
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
var randomTypes = []string{
"bool",
"int",
"uint",
"array",
"slice",
"tuple",
"address",
"string",
"bytes",
"fixedBytes",
}
func randomNumberBits() int {
return randomInt(1, 31) * 8
}
func randomType() string {
return pickRandomType(1)
}
func pickRandomType(d int) string {
PICK:
t := randomTypes[rand.Intn(len(randomTypes))]
basicTypes := "bool,address,string,bytes,function"
if strings.Contains(basicTypes, t) {
return t
}
switch t {
case "int":
return fmt.Sprintf("int%d", randomNumberBits())
case "uint":
return fmt.Sprintf("uint%d", randomNumberBits())
case "fixedBytes":
return fmt.Sprintf("bytes%d", randomInt(1, 32))
}
if d > 3 {
// Allow only for 3 levels of depth
goto PICK
}
r := pickRandomType(d + 1)
switch t {
case "slice":
return fmt.Sprintf("%s[]", r)
case "array":
s := randomInt(1, 3)
return fmt.Sprintf("%s[%d]", r, s)
case "tuple":
size := randomInt(1, 5)
elems := []string{}
for i := 0; i < size; i++ {
elem := pickRandomType(d + 1)
elems = append(elems, fmt.Sprintf("%s arg%d", elem, i))
}
return fmt.Sprintf("tuple(%s)", strings.Join(elems, ","))
default:
panic(fmt.Errorf("type not implemented: %s", t))
}
}
func generateNumber(t *Type) interface{} {
b := make([]byte, t.size/8)
if t.kind == KindUInt {
rand.Read(b)
} else {
rand.Read(b[1:])
}
num := big.NewInt(1).SetBytes(b)
if t.size == 8 || t.size == 16 || t.size == 32 || t.size == 64 {
return reflect.ValueOf(num.Int64()).Convert(t.t).Interface()
}
return num
}
func generateRandomType(t *Type) interface{} {
switch t.kind {
case KindInt:
fallthrough
case KindUInt:
return generateNumber(t)
case KindBool:
if randomInt(0, 1) == 1 {
return true
}
return false
case KindAddress:
buf := ethgo.Address{}
rand.Read(buf[:])
return buf
case KindString:
return randString(randomInt(1, 100), letters)
case KindBytes:
buf := make([]byte, randomInt(1, 100))
rand.Read(buf)
return buf
case KindFixedBytes, KindFunction:
buf := make([]byte, t.size)
rand.Read(buf)
val := reflect.New(t.t).Elem()
for i := 0; i < len(buf); i++ {
val.Index(i).Set(reflect.ValueOf(buf[i]))
}
return val.Interface()
case KindSlice:
size := randomInt(0, 5)
val := reflect.MakeSlice(t.t, size, size)
for i := 0; i < size; i++ {
val.Index(i).Set(reflect.ValueOf(generateRandomType(t.elem)))
}
return val.Interface()
case KindArray:
val := reflect.New(t.t).Elem()
for i := 0; i < t.size; i++ {
val.Index(i).Set(reflect.ValueOf(generateRandomType(t.elem)))
}
return val.Interface()
case KindTuple:
vals := map[string]interface{}{}
for _, i := range t.tuple {
vals[i.Name] = generateRandomType(i.Elem)
}
return vals
default:
panic(fmt.Errorf("type not implemented: %s", t.kind.String()))
}
}
const hexLetters = "0123456789abcdef"
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func randString(n int, dict string) string {
b := make([]byte, n)
for i := range b {
b[i] = dict[rand.Intn(len(dict))]
}
return string(b)
}
type generateContractImpl struct {
structs []string
}
func (g *generateContractImpl) run(t *Type) string {
var input, output, body []string
for indx, i := range t.tuple {
val := g.getValue(i.Elem)
memory := ""
if val == "bytes" || strings.Contains(val, "[") || strings.Contains(val, "struct") || strings.Contains(val, "string") {
memory = " memory"
}
input = append(input, fmt.Sprintf("%s%s arg%d", val, memory, indx))
output = append(output, fmt.Sprintf("%s%s", val, memory))
body = append(body, fmt.Sprintf("arg%d", indx))
}
contractTemplate := `pragma solidity ^0.5.5;
pragma experimental ABIEncoderV2;
contract Sample {
// structs
%s
function set(%s) public view returns (%s) {
return (%s);
}
}`
contract := fmt.Sprintf(
contractTemplate,
strings.Join(g.structs, "\n"),
strings.Join(input, ","),
strings.Join(output, ","),
strings.Join(body, ","))
return contract
}
func (g *generateContractImpl) getValue(t *Type) string {
switch t.kind {
case KindTuple:
attrs := []string{}
for indx, i := range t.tuple {
attrs = append(attrs, fmt.Sprintf("%s attr%d;", g.getValue(i.Elem), indx))
}
id := len(g.structs)
str := fmt.Sprintf("struct struct%d {\n%s\n}\n", id, strings.Join(attrs, "\n"))
g.structs = append(g.structs, str)
return fmt.Sprintf("struct%d", id)
case KindSlice:
return fmt.Sprintf("%s[]", g.getValue(t.elem))
case KindArray:
return fmt.Sprintf("%s[%d]", g.getValue(t.elem), t.size)
default:
return t.String()
}
}
================================================
FILE: abi/topics.go
================================================
package abi
import (
"bytes"
"fmt"
"reflect"
"github.com/umbracle/ethgo"
)
// ParseLog parses an event log
func ParseLog(args *Type, log *ethgo.Log) (map[string]interface{}, error) {
var indexed, nonIndexed []*TupleElem
for _, arg := range args.TupleElems() {
if arg.Indexed {
indexed = append(indexed, arg)
} else {
nonIndexed = append(nonIndexed, arg)
}
}
// decode indexed fields
indexedObjs, err := ParseTopics(&Type{kind: KindTuple, tuple: indexed}, log.Topics[1:])
if err != nil {
return nil, err
}
var nonIndexedObjs map[string]interface{}
if len(nonIndexed) > 0 {
nonIndexedRaw, err := Decode(&Type{kind: KindTuple, tuple: nonIndexed}, log.Data)
if err != nil {
return nil, err
}
raw, ok := nonIndexedRaw.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("bad decoding")
}
nonIndexedObjs = raw
}
res := map[string]interface{}{}
for _, arg := range args.TupleElems() {
if arg.Indexed {
res[arg.Name] = indexedObjs[0]
indexedObjs = indexedObjs[1:]
} else {
res[arg.Name] = nonIndexedObjs[arg.Name]
}
}
return res, nil
}
// ParseTopics parses topics from a log event
func ParseTopics(args *Type, topics []ethgo.Hash) ([]interface{}, error) {
if args.kind != KindTuple {
return nil, fmt.Errorf("expected a tuple type")
}
if len(args.TupleElems()) != len(topics) {
return nil, fmt.Errorf("bad length")
}
elems := []interface{}{}
for indx, arg := range args.TupleElems() {
elem, err := ParseTopic(arg.Elem, topics[indx])
if err != nil {
return nil, err
}
elems = append(elems, elem)
}
return elems, nil
}
// ParseTopic parses an individual topic
func ParseTopic(t *Type, topic ethgo.Hash) (interface{}, error) {
switch t.kind {
case KindBool:
if bytes.Equal(topic[:], topicTrue[:]) {
return true, nil
} else if bytes.Equal(topic[:], topicFalse[:]) {
return false, nil
}
return true, fmt.Errorf("is not a boolean")
case KindInt, KindUInt:
return readInteger(t, topic[:]), nil
case KindAddress:
return readAddr(topic[:])
case KindFixedBytes:
return readFixedBytes(t, topic[:])
default:
return nil, fmt.Errorf("topic parsing for type %s not supported", t.String())
}
}
// EncodeTopic encodes a topic
func EncodeTopic(t *Type, val interface{}) (ethgo.Hash, error) {
return encodeTopic(t, reflect.ValueOf(val))
}
func encodeTopic(t *Type, val reflect.Value) (ethgo.Hash, error) {
switch t.kind {
case KindBool:
return encodeTopicBool(val)
case KindUInt, KindInt:
return encodeTopicNum(t, val)
case KindAddress:
return encodeTopicAddress(val)
}
return ethgo.Hash{}, fmt.Errorf("not found")
}
var topicTrue, topicFalse ethgo.Hash
func init() {
topicTrue[31] = 1
}
func encodeTopicAddress(val reflect.Value) (res ethgo.Hash, err error) {
var b []byte
b, err = encodeAddress(val)
if err != nil {
return
}
copy(res[:], b[:])
return
}
func encodeTopicNum(t *Type, val reflect.Value) (res ethgo.Hash, err error) {
var b []byte
b, err = encodeNum(val)
if err != nil {
return
}
copy(res[:], b[:])
return
}
func encodeTopicBool(v reflect.Value) (res ethgo.Hash, err error) {
if v.Kind() != reflect.Bool {
return ethgo.Hash{}, encodeErr(v, "bool")
}
if v.Bool() {
return topicTrue, nil
}
return topicFalse, nil
}
================================================
FILE: abi/topics_test.go
================================================
package abi
import (
"fmt"
"math/big"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/testutil"
)
func TestTopicEncoding(t *testing.T) {
cases := []struct {
Type string
Val interface{}
}{
{
Type: "bool",
Val: true,
},
{
Type: "bool",
Val: false,
},
{
Type: "uint64",
Val: uint64(20),
},
{
Type: "uint256",
Val: big.NewInt(1000000),
},
{
Type: "address",
Val: ethgo.Address{0x1},
},
}
for _, c := range cases {
tt, err := NewType(c.Type)
assert.NoError(t, err)
res, err := EncodeTopic(tt, c.Val)
assert.NoError(t, err)
val, err := ParseTopic(tt, res)
assert.NoError(t, err)
assert.Equal(t, val, c.Val)
}
}
func TestIntegrationTopics(t *testing.T) {
s := testutil.NewTestServer(t)
type field struct {
typ string
indx bool
val interface{}
valStr string
}
cases := []struct {
fields []field
}{
{
// uint
fields: []field{
{"uint32", false, uint32(1), "1"},
{"uint8", true, uint8(10), "10"},
},
},
{
// fixed bytes
fields: []field{
{"bytes1", false, [1]byte{0x1}, "0x01"},
{"bytes1", true, [1]byte{0x1}, "0x01"},
},
},
}
for _, c := range cases {
cc := &testutil.Contract{}
evnt := testutil.NewEvent("A")
input := []string{}
result := map[string]interface{}{}
for indx, field := range c.fields {
evnt.Add(field.typ, field.indx)
input = append(input, field.valStr)
result[fmt.Sprintf("val_%d", indx)] = field.val
}
cc.AddEvent(evnt)
cc.EmitEvent("setA", "A", input...)
// deploy the contract
artifact, addr, err := s.DeployContract(cc)
require.NoError(t, err)
receipt, err := s.TxnTo(addr, "setA")
require.NoError(t, err)
// read the abi
abi, err := NewABI(artifact.Abi)
assert.NoError(t, err)
// parse the logs
found, err := ParseLog(abi.Events["A"].Inputs, receipt.Logs[0])
assert.NoError(t, err)
if !reflect.DeepEqual(found, result) {
t.Fatal("not equal")
}
}
}
================================================
FILE: abi/type.go
================================================
package abi
import (
"fmt"
"math/big"
"reflect"
"regexp"
"strconv"
"strings"
"github.com/umbracle/ethgo"
)
// batch of predefined reflect types
var (
boolT = reflect.TypeOf(bool(false))
uint8T = reflect.TypeOf(uint8(0))
uint16T = reflect.TypeOf(uint16(0))
uint32T = reflect.TypeOf(uint32(0))
uint64T = reflect.TypeOf(uint64(0))
int8T = reflect.TypeOf(int8(0))
int16T = reflect.TypeOf(int16(0))
int32T = reflect.TypeOf(int32(0))
int64T = reflect.TypeOf(int64(0))
addressT = reflect.TypeOf(ethgo.Address{})
stringT = reflect.TypeOf("")
dynamicBytesT = reflect.SliceOf(reflect.TypeOf(byte(0)))
functionT = reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
tupleT = reflect.TypeOf(map[string]interface{}{})
bigIntT = reflect.TypeOf(new(big.Int))
)
// Kind represents the kind of abi type
type Kind int
const (
// KindBool is a boolean
KindBool Kind = iota
// KindUInt is an uint
KindUInt
// KindInt is an int
KindInt
// KindString is a string
KindString
// KindArray is an array
KindArray
// KindSlice is a slice
KindSlice
// KindAddress is an address
KindAddress
// KindBytes is a bytes array
KindBytes
// KindFixedBytes is a fixed bytes
KindFixedBytes
// KindFixedPoint is a fixed point
KindFixedPoint
// KindTuple is a tuple
KindTuple
// KindFunction is a function
KindFunction
)
func (k Kind) String() string {
names := [...]string{
"Bool",
"Uint",
"Int",
"String",
"Array",
"Slice",
"Address",
"Bytes",
"FixedBytes",
"FixedPoint",
"Tuple",
"Function",
}
return names[k]
}
// TupleElem is an element of a tuple
type TupleElem struct {
Name string
Elem *Type
Indexed bool
}
// Type is an ABI type
type Type struct {
kind Kind
size int
elem *Type
tuple []*TupleElem
t reflect.Type
itype string
}
func NewTupleType(inputs []*TupleElem) *Type {
return &Type{
kind: KindTuple,
tuple: inputs,
t: tupleT,
}
}
func NewTupleTypeFromArgs(inputs []*ArgumentStr) (*Type, error) {
elems := []*TupleElem{}
for _, i := range inputs {
typ, err := NewTypeFromArgument(i)
if err != nil {
return nil, err
}
elems = append(elems, &TupleElem{
Name: i.Name,
Elem: typ,
Indexed: i.Indexed,
})
}
return NewTupleType(elems), nil
}
// ParseLog parses a log using this type
func (t *Type) ParseLog(log *ethgo.Log) (map[string]interface{}, error) {
return ParseLog(t, log)
}
// Decode decodes an object using this type
func (t *Type) Decode(input []byte) (interface{}, error) {
return Decode(t, input)
}
// DecodeStruct decodes an object using this type to the out param
func (t *Type) DecodeStruct(input []byte, out interface{}) error {
return DecodeStruct(t, input, out)
}
// InternalType returns the internal type
func (t *Type) InternalType() string {
return t.itype
}
// Encode encodes an object using this type
func (t *Type) Encode(v interface{}) ([]byte, error) {
return Encode(v, t)
}
func (t *Type) String() string {
return t.Format(false)
}
// String returns the raw representation of the type
func (t *Type) Format(includeArgs bool) string {
switch t.kind {
case KindTuple:
rawAux := []string{}
for _, i := range t.TupleElems() {
name := i.Elem.Format(includeArgs)
if i.Indexed {
name += " indexed"
}
if includeArgs {
if i.Name != "" {
name += " " + i.Name
}
}
rawAux = append(rawAux, name)
}
return fmt.Sprintf("tuple(%s)", strings.Join(rawAux, ","))
case KindArray:
return fmt.Sprintf("%s[%d]", t.elem.Format(includeArgs), t.size)
case KindSlice:
return fmt.Sprintf("%s[]", t.elem.Format(includeArgs))
case KindBytes:
return "bytes"
case KindFixedBytes:
return fmt.Sprintf("bytes%d", t.size)
case KindString:
return "string"
case KindBool:
return "bool"
case KindAddress:
return "address"
case KindFunction:
return "function"
case KindUInt:
return fmt.Sprintf("uint%d", t.size)
case KindInt:
return fmt.Sprintf("int%d", t.size)
default:
panic(fmt.Errorf("BUG: abi type not found %s", t.kind.String()))
}
}
// Elem returns the elem value for slice and arrays
func (t *Type) Elem() *Type {
return t.elem
}
// Size returns the size of the type
func (t *Type) Size() int {
return t.size
}
// TupleElems returns the elems of the tuple
func (t *Type) TupleElems() []*TupleElem {
return t.tuple
}
// GoType returns the go type
func (t *Type) GoType() reflect.Type {
return t.t
}
// Kind returns the kind of the type
func (t *Type) Kind() Kind {
return t.kind
}
func (t *Type) isVariableInput() bool {
return t.kind == KindSlice || t.kind == KindBytes || t.kind == KindString
}
func (t *Type) isDynamicType() bool {
if t.kind == KindTuple {
for _, elem := range t.tuple {
if elem.Elem.isDynamicType() {
return true
}
}
return false
}
return t.kind == KindString || t.kind == KindBytes || t.kind == KindSlice || (t.kind == KindArray && t.elem.isDynamicType())
}
func parseType(arg *ArgumentStr) (string, error) {
if !strings.HasPrefix(arg.Type, "tuple") {
return arg.Type, nil
}
if len(arg.Components) == 0 {
return "tuple()", nil
}
// parse the arg components from the tuple
str := []string{}
for _, i := range arg.Components {
aux, err := parseType(i)
if err != nil {
return "", err
}
if i.Indexed {
str = append(str, aux+" indexed "+i.Name)
} else {
str = append(str, aux+" "+i.Name)
}
}
return fmt.Sprintf("tuple(%s)%s", strings.Join(str, ","), strings.TrimPrefix(arg.Type, "tuple")), nil
}
// NewTypeFromArgument parses an abi type from an argument
func NewTypeFromArgument(arg *ArgumentStr) (*Type, error) {
str, err := parseType(arg)
if err != nil {
return nil, err
}
typ, err := NewType(str)
if err != nil {
return nil, err
}
// fill-in the `internalType` field into the type elems
fillIn(typ, arg)
return typ, nil
}
func fillIn(typ *Type, arg *ArgumentStr) error {
typ.itype = arg.InternalType
if len(arg.Components) == 0 {
// no more items, nothing else to do
return nil
}
// tuple types in the ABI with slices are represented as
// tuple()[] or tuple()[2]. Thus, there might be element in the components
// section of the abi but the next item not be a tuple.
for {
kind := typ.kind
if kind == KindTuple {
break
}
if kind != KindArray && kind != KindSlice {
// error
return fmt.Errorf("array or slice not found")
}
typ = typ.Elem()
}
if len(arg.Components) != len(typ.tuple) {
// incorrect length
return fmt.Errorf("incorrect size")
}
for indx, i := range arg.Components {
fillIn(typ.tuple[indx].Elem, i)
}
return nil
}
// NewType parses a type in string format
func NewType(s string) (*Type, error) {
l := newLexer(s)
l.nextToken()
return readType(l)
}
// MustNewType parses a type in string format or panics if its invalid
func MustNewType(s string) *Type {
t, err := NewType(s)
if err != nil {
panic(err)
}
return t
}
func getTypeSize(t *Type) int {
if t.kind == KindArray && !t.elem.isDynamicType() {
if t.elem.kind == KindArray || t.elem.kind == KindTuple {
return t.size * getTypeSize(t.elem)
}
return t.size * 32
} else if t.kind == KindTuple && !t.isDynamicType() {
total := 0
for _, elem := range t.tuple {
total += getTypeSize(elem.Elem)
}
return total
}
return 32
}
var typeRegexp = regexp.MustCompile("^([[:alpha:]]+)([[:digit:]]*)$")
func expectedToken(t tokenType) error {
return fmt.Errorf("expected token %s", t.String())
}
func notExpectedToken(t tokenType) error {
return fmt.Errorf("token '%s' not expected", t.String())
}
func readType(l *lexer) (*Type, error) {
var tt *Type
tok := l.nextToken()
isTuple := false
if tok.typ == tupleToken {
if l.nextToken().typ != lparenToken {
return nil, expectedToken(lparenToken)
}
isTuple = true
} else if tok.typ == lparenToken {
isTuple = true
}
if isTuple {
var next token
elems := []*TupleElem{}
for {
name := ""
indexed := false
elem, err := readType(l)
if err != nil {
if l.current.typ == rparenToken && len(elems) == 0 {
// empty tuple 'tuple()'
break
}
return nil, fmt.Errorf("failed to decode type: %v", err)
}
switch l.peek.typ {
case strToken:
l.nextToken()
name = l.current.literal
case indexedToken:
l.nextToken()
indexed = true
if l.peek.typ == strToken {
l.nextToken()
name = l.current.literal
}
}
elems = append(elems, &TupleElem{
Name: name,
Elem: elem,
Indexed: indexed,
})
next = l.nextToken()
if next.typ == commaToken {
continue
} else if next.typ == rparenToken {
break
} else {
return nil, notExpectedToken(next.typ)
}
}
tt = &Type{kind: KindTuple, tuple: elems, t: tupleT}
} else if tok.typ != strToken {
return nil, expectedToken(strToken)
} else {
// Check normal types
elem, err := decodeSimpleType(tok.literal)
if err != nil {
return nil, err
}
tt = elem
}
// check for arrays at the end of the type
for {
if l.peek.typ != lbracketToken {
break
}
l.nextToken()
n := l.nextToken()
var tAux *Type
if n.typ == rbracketToken {
tAux = &Type{kind: KindSlice, elem: tt, t: reflect.SliceOf(tt.t)}
} else if n.typ == numberToken {
size, err := strconv.ParseUint(n.literal, 10, 32)
if err != nil {
return nil, fmt.Errorf("failed to read array size '%s': %v", n.literal, err)
}
tAux = &Type{kind: KindArray, elem: tt, size: int(size), t: reflect.ArrayOf(int(size), tt.t)}
if l.nextToken().typ != rbracketToken {
return nil, expectedToken(rbracketToken)
}
} else {
return nil, notExpectedToken(n.typ)
}
tt = tAux
}
return tt, nil
}
func decodeSimpleType(str string) (*Type, error) {
match := typeRegexp.FindStringSubmatch(str)
if len(match) == 0 {
return nil, fmt.Errorf("type format is incorrect. Expected 'type''bytes' but found '%s'", str)
}
match = match[1:]
var err error
t := match[0]
bytes := 0
ok := false
if bytesStr := match[1]; bytesStr != "" {
bytes, err = strconv.Atoi(bytesStr)
if err != nil {
return nil, fmt.Errorf("failed to parse bytes '%s': %v", bytesStr, err)
}
ok = true
}
// int and uint without bytes default to 256, 'bytes' may
// have or not, the rest dont have bytes
if t == "int" || t == "uint" {
if !ok {
bytes = 256
}
} else if t != "bytes" && ok {
return nil, fmt.Errorf("type %s does not expect bytes", t)
}
switch t {
case "uint":
var k reflect.Type
switch bytes {
case 8:
k = uint8T
case 16:
k = uint16T
case 32:
k = uint32T
case 64:
k = uint64T
default:
if bytes%8 != 0 {
panic(fmt.Errorf("number of bytes has to be M mod 8"))
}
k = bigIntT
}
return &Type{kind: KindUInt, size: int(bytes), t: k}, nil
case "int":
var k reflect.Type
switch bytes {
case 8:
k = int8T
case 16:
k = int16T
case 32:
k = int32T
case 64:
k = int64T
default:
if bytes%8 != 0 {
panic(fmt.Errorf("number of bytes has to be M mod 8"))
}
k = bigIntT
}
return &Type{kind: KindInt, size: int(bytes), t: k}, nil
case "byte":
bytes = 1
fallthrough
case "bytes":
if bytes == 0 {
return &Type{kind: KindBytes, t: dynamicBytesT}, nil
}
return &Type{kind: KindFixedBytes, size: int(bytes), t: reflect.ArrayOf(int(bytes), reflect.TypeOf(byte(0)))}, nil
case "string":
return &Type{kind: KindString, t: stringT}, nil
case "bool":
return &Type{kind: KindBool, t: boolT}, nil
case "address":
return &Type{kind: KindAddress, t: addressT, size: 20}, nil
case "function":
return &Type{kind: KindFunction, size: 24, t: functionT}, nil
default:
return nil, fmt.Errorf("unknown type '%s'", t)
}
}
type tokenType int
const (
eofToken tokenType = iota
strToken
numberToken
tupleToken
lparenToken
rparenToken
lbracketToken
rbracketToken
commaToken
indexedToken
invalidToken
)
func (t tokenType) String() string {
names := [...]string{
"eof",
"string",
"number",
"tuple",
"(",
")",
"[",
"]",
",",
"indexed",
"<invalid>",
}
return names[t]
}
type token struct {
typ tokenType
literal string
}
type lexer struct {
input string
current token
peek token
position int
readPosition int
ch byte
}
func newLexer(input string) *lexer {
l := &lexer{input: input}
l.readChar()
return l
}
func (l *lexer) readChar() {
if l.readPosition >= len(l.input) {
l.ch = 0
} else {
l.ch = l.input[l.readPosition]
}
l.position = l.readPosition
l.readPosition++
}
func (l *lexer) nextToken() token {
l.current = l.peek
l.peek = l.nextTokenImpl()
return l.current
}
func (l *lexer) nextTokenImpl() token {
var tok token
// skip whitespace
for l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' {
l.readChar()
}
switch l.ch {
case ',':
tok.typ = commaToken
case '(':
tok.typ = lparenToken
case ')':
tok.typ = rparenToken
case '[':
tok.typ = lbracketToken
case ']':
tok.typ = rbracketToken
case 0:
tok.typ = eofToken
default:
if isLetter(l.ch) {
tok.literal = l.readIdentifier()
if tok.literal == "tuple" {
tok.typ = tupleToken
} else if tok.literal == "indexed" {
tok.typ = indexedToken
} else {
tok.typ = strToken
}
return tok
} else if isDigit(l.ch) {
return token{numberToken, l.readNumber()}
} else {
tok.typ = invalidToken
}
}
l.readChar()
return tok
}
func (l *lexer) readIdentifier() string {
pos := l.position
for isLetter(l.ch) || isDigit(l.ch) {
l.readChar()
}
return l.input[pos:l.position]
}
func (l *lexer) readNumber() string {
position := l.position
for isDigit(l.ch) {
l.readChar()
}
return l.input[position:l.position]
}
func isDigit(ch byte) bool {
return '0' <= ch && ch <= '9'
}
func isLetter(ch byte) bool {
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'
}
================================================
FILE: abi/type_test.go
================================================
package abi
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestType(t *testing.T) {
cases := []struct {
s string
a *ArgumentStr
t *Type
r string
err bool
}{
{
s: "bool",
a: simpleType("bool"),
t: &Type{kind: KindBool, t: boolT},
},
{
s: "uint32",
a: simpleType("uint32"),
t: &Type{kind: KindUInt, size: 32, t: uint32T},
},
{
s: "int32",
a: simpleType("int32"),
t: &Type{kind: KindInt, size: 32, t: int32T},
},
{
s: "int32[]",
a: simpleType("int32[]"),
t: &Type{kind: KindSlice, t: reflect.SliceOf(int32T), elem: &Type{kind: KindInt, size: 32, t: int32T}},
},
{
s: "int",
a: simpleType("int"),
t: &Type{kind: KindInt, size: 256, t: bigIntT},
r: "int256",
},
{
s: "int[]",
a: simpleType("int[]"),
t: &Type{kind: KindSlice, t: reflect.SliceOf(bigIntT), elem: &Type{kind: KindInt, size: 256, t: bigIntT}},
r: "int256[]",
},
{
s: "bytes[2]",
a: simpleType("bytes[2]"),
t: &Type{
kind: KindArray,
t: reflect.ArrayOf(2, dynamicBytesT),
size: 2,
elem: &Type{
kind: KindBytes,
t: dynamicBytesT,
},
},
},
{
s: "address[]",
a: simpleType("address[]"),
t: &Type{kind: KindSlice, t: reflect.SliceOf(addressT), elem: &Type{kind: KindAddress, size: 20, t: addressT}},
},
{
s: "string[]",
a: simpleType("string[]"),
t: &Type{
kind: KindSlice,
t: reflect.SliceOf(stringT),
elem: &Type{
kind: KindString,
t: stringT,
},
},
},
{
s: "string[2]",
a: simpleType("string[2]"),
t: &Type{
kind: KindArray,
size: 2,
t: reflect.ArrayOf(2, stringT),
elem: &Type{
kind: KindString,
t: stringT,
},
},
},
{
s: "string[2][]",
a: simpleType("string[2][]"),
t: &Type{
kind: KindSlice,
t: reflect.SliceOf(reflect.ArrayOf(2, stringT)),
elem: &Type{
kind: KindArray,
size: 2,
t: reflect.ArrayOf(2, stringT),
elem: &Type{
kind: KindString,
t: stringT,
},
},
},
},
{
s: "tuple(int64 indexed arg0)",
a: &ArgumentStr{
Type: "tuple",
Components: []*ArgumentStr{
{
Name: "arg0",
Type: "int64",
Indexed: true,
},
},
},
t: &Type{
kind: KindTuple,
t: tupleT,
tuple: []*TupleElem{
{
Name: "arg0",
Elem: &Type{
kind: KindInt,
size: 64,
t: int64T,
},
Indexed: true,
},
},
},
},
{
s: "tuple(int64 arg_0)[2]",
a: &ArgumentStr{
Type: "tuple[2]",
Components: []*ArgumentStr{
{
Name: "arg_0",
Type: "int64",
},
},
},
t: &Type{
kind: KindArray,
size: 2,
t: reflect.ArrayOf(2, tupleT),
elem: &Type{
kind: KindTuple,
t: tupleT,
tuple: []*TupleElem{
{
Name: "arg_0",
Elem: &Type{
kind: KindInt,
size: 64,
t: int64T,
},
},
},
},
},
},
{
s: "tuple(int64 a)[]",
a: &ArgumentStr{
Type: "tuple[]",
Components: []*ArgumentStr{
{
Name: "a",
Type: "int64",
},
},
},
t: &Type{
kind: KindSlice,
t: reflect.SliceOf(tupleT),
elem: &Type{
kind: KindTuple,
t: tupleT,
tuple: []*TupleElem{
{
Name: "a",
Elem: &Type{
kind: KindInt,
size: 64,
t: int64T,
},
},
},
},
},
},
{
s: "tuple(int32 indexed arg0,tuple(int32 c) b_2)",
a: &ArgumentStr{
Type: "tuple",
Components: []*ArgumentStr{
{
Name: "arg0",
Type: "int32",
Indexed: true,
},
{
Name: "b_2",
Type: "tuple",
Components: []*ArgumentStr{
{
Name: "c",
Type: "int32",
},
},
},
},
},
t: &Type{
kind: KindTuple,
t: tupleT,
tuple: []*TupleElem{
{
Name: "arg0",
Elem: &Type{
kind: KindInt,
size: 32,
t: int32T,
},
Indexed: true,
},
{
Name: "b_2",
Elem: &Type{
kind: KindTuple,
t: tupleT,
tuple: []*TupleElem{
{
Name: "c",
Elem: &Type{
kind: KindInt,
size: 32,
t: int32T,
},
},
},
},
},
},
},
},
{
s: "tuple()",
a: &ArgumentStr{
Type: "tuple",
Components: []*ArgumentStr{},
},
t: &Type{
kind: KindTuple,
t: tupleT,
tuple: []*TupleElem{},
},
},
{
// hidden tuple token
s: "tuple((int32))",
a: &ArgumentStr{
Type: "tuple",
Components: []*ArgumentStr{
{
Type: "tuple",
Components: []*ArgumentStr{
{
Type: "int32",
},
},
},
},
},
t: &Type{
kind: KindTuple,
t: tupleT,
tuple: []*TupleElem{
{
Elem: &Type{
kind: KindTuple,
t: tupleT,
tuple: []*TupleElem{
{
Elem: &Type{
kind: KindInt,
size: 32,
t: int32T,
},
},
},
},
},
},
},
r: "tuple(tuple(int32))",
},
{
s: "int[[",
err: true,
},
{
s: "tuple[](a int32)",
err: true,
},
{
s: "int32[a]",
err: true,
},
{
s: "tuple(a int32",
err: true,
},
{
s: "tuple(a int32,",
err: true,
},
}
for _, c := range cases {
t.Run("", func(t *testing.T) {
e0, err := NewType(c.s)
if err != nil && !c.err {
t.Fatal(err)
}
if err == nil && c.err {
t.Fatal("it should have failed")
}
if !c.err {
// compare the string
expected := c.s
if c.r != "" {
expected = c.r
}
assert.Equal(t, expected, e0.Format(true))
e1, err := NewTypeFromArgument(c.a)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(c.t, e0) {
// fmt.Println(c.t.t)
// fmt.Println(e0.t)
t.Fatal("bad new type")
}
if !reflect.DeepEqual(c.t, e1) {
t.Fatal("bad")
}
}
})
}
}
func TestTypeArgument_InternalFields(t *testing.T) {
arg := &ArgumentStr{
Type: "tuple",
Components: []*ArgumentStr{
{
Type: "tuple[]",
Components: []*ArgumentStr{
{
Type: "int32",
InternalType: "c",
},
},
InternalType: "b",
},
},
}
res, err := NewTypeFromArgument(arg)
require.NoError(t, err)
require.Equal(t, res.tuple[0].Elem.itype, "b")
require.Equal(t, res.tuple[0].Elem.elem.tuple[0].Elem.itype, "c")
}
func TestSize(t *testing.T) {
cases := []struct {
Input string
Size int
}{
{
"int32", 32,
},
{
"int32[]", 32,
},
{
"int32[2]", 32 * 2,
},
{
"int32[2][2]", 32 * 2 * 2,
},
{
"string", 32,
},
{
"string[]", 32,
},
{
"tuple(uint8 a, uint32 b)[1]",
64,
},
}
for _, c := range cases {
t.Run("", func(t *testing.T) {
tt, err := NewType(c.Input)
if err != nil {
t.Fatal(err)
}
size := getTypeSize(tt)
if size != c.Size {
t.Fatalf("expected size %d but found %d", c.Size, size)
}
})
}
}
func simpleType(s string) *ArgumentStr {
return &ArgumentStr{
Type: s,
}
}
================================================
FILE: blocktracker/blocktracker.go
================================================
package blocktracker
import (
"context"
"fmt"
"sync"
"time"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/jsonrpc"
)
// BlockProvider are the eth1x methods required by the block tracker
type BlockProvider interface {
GetBlockByHash(hash ethgo.Hash, full bool) (*ethgo.Block, error)
GetBlockByNumber(i ethgo.BlockNumber, full bool) (*ethgo.Block, error)
}
const (
defaultMaxBlockBacklog = 10
)
// BlockTracker is an interface to track new blocks on the chain
type BlockTracker struct {
config *Config
blocks []*ethgo.Block
blocksLock sync.Mutex
subscriber BlockTrackerInterface
blockChs []chan *BlockEvent
blockChsLock sync.Mutex
provider BlockProvider
once sync.Once
closeCh chan struct{}
}
type Config struct {
Tracker BlockTrackerInterface
MaxBlockBacklog uint64
}
func DefaultConfig() *Config {
return &Config{
MaxBlockBacklog: defaultMaxBlockBacklog,
}
}
type ConfigOption func(*Config)
func WithBlockMaxBacklog(b uint64) ConfigOption {
return func(c *Config) {
c.MaxBlockBacklog = b
}
}
func WithTracker(b BlockTrackerInterface) ConfigOption {
return func(c *Config) {
c.Tracker = b
}
}
func NewBlockTracker(provider BlockProvider, opts ...ConfigOption) *BlockTracker {
config := DefaultConfig()
for _, opt := range opts {
opt(config)
}
tracker := config.Tracker
if tracker == nil {
tracker = NewJSONBlockTracker(provider)
}
return &BlockTracker{
blocks: []*ethgo.Block{},
blockChs: []chan *BlockEvent{},
config: config,
subscriber: tracker,
provider: provider,
closeCh: make(chan struct{}),
}
}
func (b *BlockTracker) Subscribe() chan *BlockEvent {
b.blockChsLock.Lock()
defer b.blockChsLock.Unlock()
ch := make(chan *BlockEvent, 1)
b.blockChs = append(b.blockChs, ch)
return ch
}
func (b *BlockTracker) AcquireLock() Lock {
return NewLock(&b.blocksLock)
}
func (t *BlockTracker) Init() (err error) {
var block *ethgo.Block
t.once.Do(func() {
block, err = t.provider.GetBlockByNumber(ethgo.Latest, false)
if err != nil {
return
}
if block.Number == 0 {
return
}
blocks := make([]*ethgo.Block, t.config.MaxBlockBacklog)
var i uint64
for i = 0; i < t.config.MaxBlockBacklog; i++ {
blocks[t.config.MaxBlockBacklog-i-1] = block
if block.Number == 0 {
break
}
block, err = t.provider.GetBlockByHash(block.ParentHash, false)
if err != nil {
return
} else if block == nil {
// if block does not exist (for example reorg happened) GetBlockByHash will return nil, nil
err = fmt.Errorf("block with hash %s not found", block.ParentHash)
return
}
}
if i != t.config.MaxBlockBacklog {
// less than maxBacklog elements
blocks = blocks[t.config.MaxBlockBacklog-i-1:]
}
t.blocks = blocks
})
return err
}
func (b *BlockTracker) MaxBlockBacklog() uint64 {
return b.config.MaxBlockBacklog
}
func (b *BlockTracker) LastBlocked() *ethgo.Block {
target := b.blocks[len(b.blocks)-1]
if target == nil {
return nil
}
return target.Copy()
}
func (b *BlockTracker) BlocksBlocked() []*ethgo.Block {
res := []*ethgo.Block{}
for _, i := range b.blocks {
res = append(res, i.Copy())
}
return res
}
func (b *BlockTracker) Len() int {
return len(b.blocks)
}
func (b *BlockTracker) Close() error {
close(b.closeCh)
return nil
}
func (b *BlockTracker) Start() error {
ctx, cancelFn := context.WithCancel(context.Background())
go func() {
<-b.closeCh
cancelFn()
}()
// start the polling
err := b.subscriber.Track(ctx, func(block *ethgo.Block) error {
return b.HandleReconcile(block)
})
if err != nil {
return err
}
return err
}
func (t *BlockTracker) AddBlockLocked(block *ethgo.Block) error {
if uint64(len(t.blocks)) == t.config.MaxBlockBacklog {
// remove past blocks if there are more than maxReconcileBlocks
t.blocks = t.blocks[1:]
}
if len(t.blocks) != 0 {
lastNum := t.blocks[len(t.blocks)-1].Number
if lastNum+1 != block.Number {
return fmt.Errorf("bad number sequence. %d and %d", lastNum, block.Number)
}
}
t.blocks = append(t.blocks, block)
return nil
}
func (t *BlockTracker) blockAtIndex(hash ethgo.Hash) int {
for indx, b := range t.blocks {
if b.Hash == hash {
return indx
}
}
return -1
}
func (t *BlockTracker) handleReconcileImpl(block *ethgo.Block) ([]*ethgo.Block, int, error) {
// The block already exists
if t.blockAtIndex(block.Hash) != -1 {
return nil, -1, nil
}
// The state is empty
if len(t.blocks) == 0 {
return []*ethgo.Block{block}, -1, nil
}
// Append to the head of the chain
if t.blocks[len(t.blocks)-1].Hash == block.ParentHash {
return []*ethgo.Block{block}, -1, nil
}
// Fork in the middle of the chain
if indx := t.blockAtIndex(block.ParentHash); indx != -1 {
return []*ethgo.Block{block}, indx, nil
}
// Backfill. We dont know the parent of the block.
// Need to query the chain untill we find a known block
added := []*ethgo.Block{block}
var indx int
count := uint64(0)
for {
if count > t.config.MaxBlockBacklog {
return nil, -1, fmt.Errorf("cannot reconcile more than max backlog values")
}
count++
parent, err := t.provider.GetBlockByHash(block.ParentHash, false)
if err != nil {
return nil, -1, fmt.Errorf("parent with hash retrieving error: %w", err)
} else if parent == nil {
// if block does not exist (for example reorg happened) GetBlockByHash will return nil, nil
return nil, -1, fmt.Errorf("parent with hash %s not found", block.ParentHash)
}
added = append(added, parent)
if indx = t.blockAtIndex(parent.ParentHash); indx != -1 {
break
}
block = parent
}
// need the blocks in reverse order
blocks := []*ethgo.Block{}
for i := len(added) - 1; i >= 0; i-- {
blocks = append(blocks, added[i])
}
return blocks, indx, nil
}
func (t *BlockTracker) HandleBlockEvent(block *ethgo.Block) (*BlockEvent, error) {
t.blocksLock.Lock()
defer t.blocksLock.Unlock()
blocks, indx, err := t.handleReconcileImpl(block)
if err != nil {
return nil, err
}
if len(blocks) == 0 {
return nil, nil
}
blockEvnt := &BlockEvent{}
// there are some blocks to remove
if indx != -1 {
for i := indx + 1; i < len(t.blocks); i++ {
blockEvnt.Removed = append(blockEvnt.Removed, t.blocks[i])
}
t.blocks = t.blocks[:indx+1]
}
// include the new blocks
for _, block := range blocks {
blockEvnt.Added = append(blockEvnt.Added, block)
if err := t.AddBlockLocked(block); err != nil {
return nil, err
}
}
return blockEvnt, nil
}
func (t *BlockTracker) HandleReconcile(block *ethgo.Block) error {
blockEvnt, err := t.HandleBlockEvent(block)
if err != nil {
return err
}
if blockEvnt == nil {
return nil
}
t.blockChsLock.Lock()
for _, ch := range t.blockChs {
select {
case ch <- blockEvnt:
default:
}
}
t.blockChsLock.Unlock()
return nil
}
type BlockTrackerInterface interface {
Track(context.Context, func(block *ethgo.Block) error) error
}
const (
defaultPollInterval = 1 * time.Second
)
// JSONBlockTracker implements the BlockTracker interface using
// the http jsonrpc endpoint
type JSONBlockTracker struct {
PollInterval time.Duration
provider BlockProvider
}
// NewJSONBlockTracker creates a new json block tracker
func NewJSONBlockTracker(provider BlockProvider) *JSONBlockTracker {
return &JSONBlockTracker{
provider: provider,
PollInterval: defaultPollInterval,
}
}
// Track implements the BlockTracker interface.
// This can take a long time so should be run concurrently.
func (k *JSONBlockTracker) Track(ctx context.Context, handle func(block *ethgo.Block) error) error {
var lastBlock *ethgo.Block
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(k.PollInterval):
block, err := k.provider.GetBlockByNumber(ethgo.Latest, false)
if err != nil {
return err
}
if lastBlock != nil && lastBlock.Hash == block.Hash {
continue
}
if err := handle(block); err != nil {
return err
}
lastBlock = block
}
}
}
// SubscriptionBlockTracker is an interface to track new blocks using
// the newHeads subscription endpoint
type SubscriptionBlockTracker struct {
client *jsonrpc.Client
}
// NewSubscriptionBlockTracker creates a new block tracker using the subscription endpoint
func NewSubscriptionBlockTracker(client *jsonrpc.Client) (*SubscriptionBlockTracker, error) {
if !client.SubscriptionEnabled() {
return nil, fmt.Errorf("subscription is not enabled")
}
s := &SubscriptionBlockTracker{
client: client,
}
return s, nil
}
// Track implements the BlockTracker interface
// This can take a long time so should be run concurrently.
// Note that the error return variable must be named so that subscription cancellation errors can be returned in defer.
func (s *SubscriptionBlockTracker) Track(ctx context.Context, handle func(block *ethgo.Block) error) (err error) {
data := make(chan []byte)
defer close(data)
// Subscribe with a callback. This callback must be unsubscribed
// before the data channel is closed, otherwise panic (write to closed channel)
callback := func(b []byte) {
data <- b
}
unsubscribe, err := s.client.Subscribe("newHeads", callback)
if err != nil {
return err
}
defer func() {
if cerr := unsubscribe(); cerr != nil {
// Ensure subscription cancellation errors are returned via named return var
if err == nil {
err = cerr
return
}
err = fmt.Errorf("failed to cancel: %s, after error %w", cerr.Error(), err)
}
}()
for {
select {
case buf := <-data:
var block ethgo.Block
if err := block.UnmarshalJSON(buf); err != nil {
return err
}
if err := handle(&block); err != nil {
return err
}
case <-ctx.Done():
return ctx.Err()
}
}
}
type Lock struct {
Locked bool
lock *sync.Mutex
}
func NewLock(lock *sync.Mutex) Lock {
return Lock{lock: lock}
}
func (l *Lock) Lock() {
l.Locked = true
l.lock.Lock()
}
func (l *Lock) Unlock() {
l.Locked = false
l.lock.Unlock()
}
// EventType is the type of the event
type EventType int
const (
// EventAdd happens when a new event is included in the chain
EventAdd EventType = iota
// EventDel may happen when there is a reorg and a past event is deleted
EventDel
)
// Event is an event emitted when a new log is included
type Event struct {
Type EventType
Added []*ethgo.Log
Removed []*ethgo.Log
}
// BlockEvent is an event emitted when a new block is included
type BlockEvent struct {
Type EventType
Added []*ethgo.Block
Removed []*ethgo.Block
}
================================================
FILE: blocktracker/blocktracker_test.go
================================================
package blocktracker
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/jsonrpc"
"github.com/umbracle/ethgo/testutil"
)
func testListener(t *testing.T, server *testutil.TestServer, tracker BlockTrackerInterface) {
ctx, cancelFn := context.WithCancel(context.Background())
defer cancelFn()
blocks := make(chan *ethgo.Block)
err := tracker.Track(ctx, func(block *ethgo.Block) error {
blocks <- block
return nil
})
if err != nil {
t.Fatal(err)
}
var lastBlock *ethgo.Block
count := uint64(0)
recv := func() {
count++
select {
case block := <-blocks:
if lastBlock != nil {
if lastBlock.Number+1 != block.Number {
t.Fatalf("bad sequence %d %d", lastBlock.Number, block.Number)
}
}
lastBlock = block
case <-time.After(4 * time.Second):
t.Fatal("timeout to receive block tracker block")
}
}
server.ProcessBlock()
recv()
server.ProcessBlock()
recv()
}
func TestBlockTracker_Listener_JsonRPC(t *testing.T) {
t.Skip("Too brittle on CI, FIX")
s := testutil.NewTestServer(t)
c, _ := jsonrpc.NewClient(s.HTTPAddr())
defer c.Close()
tracker := NewJSONBlockTracker(c.Eth())
tracker.PollInterval = 1 * time.Second
testListener(t, s, tracker)
}
func TestBlockTracker_Listener_Websocket(t *testing.T) {
t.Skip("Too brittle on CI, FIX")
s := testutil.NewTestServer(t)
c, _ := jsonrpc.NewClient(s.WSAddr())
defer c.Close()
tracker, err := NewSubscriptionBlockTracker(c)
if err != nil {
t.Fatal(err)
}
testListener(t, s, tracker)
}
func TestBlockTracker_Lifecycle(t *testing.T) {
t.Skip()
s := testutil.NewTestServer(t)
c, _ := jsonrpc.NewClient(s.HTTPAddr())
tr := NewBlockTracker(c.Eth())
assert.NoError(t, tr.Init())
go tr.Start()
// try to mine a block at least every 1 second
go func() {
for i := 0; i < 10; i++ {
s.ProcessBlock()
time.After(1 * time.Second)
}
}()
sub := tr.Subscribe()
for i := 0; i < 10; i++ {
select {
case <-sub:
case <-time.After(2 * time.Second):
t.Fatal("bad")
}
}
}
func TestBlockTracker_PopulateBlocks(t *testing.T) {
// more than maxBackLog blocks
{
l := testutil.MockList{}
l.Create(0, 15, func(b *testutil.MockBlock) {})
m := &testutil.MockClient{}
m.AddScenario(l)
tt0 := NewBlockTracker(m)
err := tt0.Init()
if err != nil {
t.Fatal(err)
}
if !testutil.CompareBlocks(l.ToBlocks()[5:], tt0.blocks) {
t.Fatal("bad")
}
}
// less than maxBackLog
{
l0 := testutil.MockList{}
l0.Create(0, 5, func(b *testutil.MockBlock) {})
m1 := &testutil.MockClient{}
m1.AddScenario(l0)
tt1 := NewBlockTracker(m1)
tt1.provider = m1
err := tt1.Init()
if err != nil {
panic(err)
}
if !testutil.CompareBlocks(l0.ToBlocks(), tt1.blocks) {
t.Fatal("bad")
}
}
}
func TestBlockTracker_Events(t *testing.T) {
type TestEvent struct {
Added testutil.MockList
Removed testutil.MockList
}
type Reconcile struct {
block *testutil.MockBlock
event *TestEvent
}
cases := []struct {
Name string
Scenario testutil.MockList
History testutil.MockList
Reconcile []Reconcile
Expected testutil.MockList
}{
{
Name: "Empty history",
Reconcile: []Reconcile{
{
block: testutil.Mock(0x1),
event: &TestEvent{
Added: testutil.MockList{
testutil.Mock(0x1),
},
},
},
},
Expected: []*testutil.MockBlock{
testutil.Mock(1),
},
},
{
Name: "Repeated header",
History: []*testutil.MockBlock{
testutil.Mock(0x1),
},
Reconcile: []Reconcile{
{
block: testutil.Mock(0x1),
},
},
Expected: []*testutil.MockBlock{
testutil.Mock(0x1),
},
},
{
Name: "New head",
History: testutil.MockList{
testutil.Mock(0x1),
},
Reconcile: []Reconcile{
{
block: testutil.Mock(0x2),
event: &TestEvent{
Added: testutil.MockList{
testutil.Mock(0x2),
},
},
},
},
Expected: testutil.MockList{
testutil.Mock(0x1),
testutil.Mock(0x2),
},
},
{
Name: "Ignore block already on history",
History: testutil.MockList{
testutil.Mock(0x1),
testutil.Mock(0x2),
testutil.Mock(0x3),
},
Reconcile: []Reconcile{
{
block: testutil.Mock(0x2),
},
},
Expected: testutil.MockList{
testutil.Mock(0x1),
testutil.Mock(0x2),
testutil.Mock(0x3),
},
},
{
Name: "Multi Roll back",
History: testutil.MockList{
testutil.Mock(0x1),
testutil.Mock(0x2),
testutil.Mock(0x3),
testutil.Mock(0x4),
},
Reconcile: []Reconcile{
{
block: testutil.Mock(0x30).Parent(0x2),
event: &TestEvent{
Added: testutil.MockList{
testutil.Mock(0x30).Parent(0x2),
},
Removed: testutil.MockList{
testutil.Mock(0x3),
testutil.Mock(0x4),
},
},
},
},
Expected: testutil.MockList{
testutil.Mock(0x1),
testutil.Mock(0x2),
testutil.Mock(0x30).Parent(0x2),
},
},
{
Name: "Backfills missing blocks",
Scenario: testutil.MockList{
testutil.Mock(0x3),
testutil.Mock(0x4),
},
History: testutil.MockList{
testutil.Mock(0x1),
testutil.Mock(0x2),
},
Reconcile: []Reconcile{
{
block: testutil.Mock(0x5),
event: &TestEvent{
Added: testutil.MockList{
testutil.Mock(0x3),
testutil.Mock(0x4),
testutil.Mock(0x5),
},
},
},
},
Expected: testutil.MockList{
testutil.Mock(0x1),
testutil.Mock(0x2),
testutil.Mock(0x3),
testutil.Mock(0x4),
testutil.Mock(0x5),
},
},
{
Name: "Rolls back and backfills",
Scenario: testutil.MockList{
testutil.Mock(0x30).Parent(0x2).Num(3),
testutil.Mock(0x40).Parent(0x30).Num(4),
},
History: testutil.MockList{
testutil.Mock(0x1),
testutil.Mock(0x2),
testutil.Mock(0x3),
testutil.Mock(0x4),
},
Reconcile: []Reconcile{
{
block: testutil.Mock(0x50).Parent(0x40).Num(5),
event: &TestEvent{
Added: testutil.MockList{
testutil.Mock(0x30).Parent(0x2).Num(3),
testutil.Mock(0x40).Parent(0x30).Num(4),
testutil.Mock(0x50).Parent(0x40).Num(5),
},
Removed: testutil.MockList{
testutil.Mock(0x3),
testutil.Mock(0x4),
},
},
},
},
Expected: testutil.MockList{
testutil.Mock(0x1),
testutil.Mock(0x2),
testutil.Mock(0x30).Parent(0x2).Num(3),
testutil.Mock(0x40).Parent(0x30).Num(4),
testutil.Mock(0x50).Parent(0x40).Num(5),
},
},
}
for _, c := range cases {
t.Run(c.Name, func(t *testing.T) {
// safe check for now, we ma need to restart the tracker and mock client for every reconcile scenario?
if len(c.Reconcile) != 1 {
t.Fatal("only one reconcile supported so far")
}
m := &testutil.MockClient{}
// add the full scenario with the logs
m.AddScenario(c.Scenario)
tt := NewBlockTracker(m)
// build past block history
for _, b := range c.History.ToBlocks() {
tt.AddBlockLocked(b)
}
sub := tt.Subscribe()
for _, b := range c.Reconcile {
if err := tt.HandleReconcile(b.block.Block()); err != nil {
t.Fatal(err)
}
if b.event == nil {
continue
}
var blockEvnt *BlockEvent
select {
case blockEvnt = <-sub:
case <-time.After(1 * time.Second):
t.Fatal("block event timeout")
}
// check blocks
if !testutil.CompareBlocks(b.event.Added.ToBlocks(), blockEvnt.Added) {
t.Fatal("err")
}
if !testutil.CompareBlocks(b.event.Removed.ToBlocks(), blockEvnt.Removed) {
t.Fatal("err")
}
}
if !testutil.CompareBlocks(tt.blocks, c.Expected.ToBlocks()) {
t.Fatal("bad")
}
})
}
}
================================================
FILE: builtin/ens/artifacts/ENS.abi
================================================
[{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"label","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setSubnodeOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"ttl","type":"uint64"}],"name":"setTTL","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"ttl","outputs":[{"name":"","type":"uint64"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"label","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"resolver","type":"address"}],"name":"NewResolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"ttl","type":"uint64"}],"name":"NewTTL","type":"event"}]
================================================
FILE: builtin/ens/artifacts/Resolver.abi
================================================
[{"constant":true,"inputs":[{"name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"},{"name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"name":"contentType","type":"uint256"},{"name":"data","type":"bytes"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"x","type":"bytes32"},{"name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"content","outputs":[{"name":"ret","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"addr","outputs":[{"name":"ret","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"contentType","type":"uint256"},{"name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"name","outputs":[{"name":"ret","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"hash","type":"bytes32"}],"name":"setContent","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"name":"x","type":"bytes32"},{"name":"y","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"addr","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"ensAddr","type":"address"}],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"hash","type":"bytes32"}],"name":"ContentChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"x","type":"bytes32"},{"indexed":false,"name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"}]
================================================
FILE: builtin/ens/ens.go
================================================
// Code generated by ethgo/abigen. DO NOT EDIT.
// Hash: bfee2618a5908e1a24f19dcce873d3b8e797374138dd7604f7b593db3cca5c17
// Version: 0.1.1
package ens
import (
"fmt"
"math/big"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/contract"
"github.com/umbracle/ethgo/jsonrpc"
)
var (
_ = big.NewInt
_ = jsonrpc.NewClient
)
// ENS is a solidity contract
type ENS struct {
c *contract.Contract
}
// DeployENS deploys a new ENS contract
func DeployENS(provider *jsonrpc.Client, from ethgo.Address, args []interface{}, opts ...contract.ContractOption) (contract.Txn, error) {
return contract.DeployContract(abiENS, binENS, args, opts...)
}
// NewENS creates a new instance of the contract at a specific address
func NewENS(addr ethgo.Address, opts ...contract.ContractOption) *ENS {
return &ENS{c: contract.NewContract(addr, abiENS, opts...)}
}
// calls
// Owner calls the owner method in the solidity contract
func (e *ENS) Owner(node [32]byte, block ...ethgo.BlockNumber) (retval0 ethgo.Address, err error) {
var out map[string]interface{}
var ok bool
out, err = e.c.Call("owner", ethgo.EncodeBlock(block...), node)
if err != nil {
return
}
// decode outputs
retval0, ok = out["0"].(ethgo.Address)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// Resolver calls the resolver method in the solidity contract
func (e *ENS) Resolver(node [32]byte, block ...ethgo.BlockNumber) (retval0 ethgo.Address, err error) {
var out map[string]interface{}
var ok bool
out, err = e.c.Call("resolver", ethgo.EncodeBlock(block...), node)
if err != nil {
return
}
// decode outputs
retval0, ok = out["0"].(ethgo.Address)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// Ttl calls the ttl method in the solidity contract
func (e *ENS) Ttl(node [32]byte, block ...ethgo.BlockNumber) (retval0 uint64, err error) {
var out map[string]interface{}
var ok bool
out, err = e.c.Call("ttl", ethgo.EncodeBlock(block...), node)
if err != nil {
return
}
// decode outputs
retval0, ok = out["0"].(uint64)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// txns
// SetOwner sends a setOwner transaction in the solidity contract
func (e *ENS) SetOwner(node [32]byte, owner ethgo.Address) (contract.Txn, error) {
return e.c.Txn("setOwner", node, owner)
}
// SetResolver sends a setResolver transaction in the solidity contract
func (e *ENS) SetResolver(node [32]byte, resolver ethgo.Address) (contract.Txn, error) {
return e.c.Txn("setResolver", node, resolver)
}
// SetSubnodeOwner sends a setSubnodeOwner transaction in the solidity contract
func (e *ENS) SetSubnodeOwner(node [32]byte, label [32]byte, owner ethgo.Address) (contract.Txn, error) {
return e.c.Txn("setSubnodeOwner", node, label, owner)
}
// SetTTL sends a setTTL transaction in the solidity contract
func (e *ENS) SetTTL(node [32]byte, ttl uint64) (contract.Txn, error) {
return e.c.Txn("setTTL", node, ttl)
}
// events
func (e *ENS) NewOwnerEventSig() ethgo.Hash {
return e.c.GetABI().Events["NewOwner"].ID()
}
func (e *ENS) NewResolverEventSig() ethgo.Hash {
return e.c.GetABI().Events["NewResolver"].ID()
}
func (e *ENS) NewTTLEventSig() ethgo.Hash {
return e.c.GetABI().Events["NewTTL"].ID()
}
func (e *ENS) TransferEventSig() ethgo.Hash {
return e.c.GetABI().Events["Transfer"].ID()
}
================================================
FILE: builtin/ens/ens_artifacts.go
================================================
package ens
import (
"encoding/hex"
"fmt"
"github.com/umbracle/ethgo/abi"
)
var abiENS *abi.ABI
// ENSAbi returns the abi of the ENS contract
func ENSAbi() *abi.ABI {
return abiENS
}
var binENS []byte
// ENSBin returns the bin of the ENS contract
func ENSBin() []byte {
return binENS
}
func init() {
var err error
abiENS, err = abi.NewABI(abiENSStr)
if err != nil {
panic(fmt.Errorf("cannot parse ENS abi: %v", err))
}
if len(binENSStr) != 0 {
binENS, err = hex.DecodeString(binENSStr[2:])
if err != nil {
panic(fmt.Errorf("cannot parse ENS bin: %v", err))
}
}
}
var binENSStr = "0x6060604052341561000f57600080fd5b60008080526020527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb58054600160a060020a033316600160a060020a0319909116179055610503806100626000396000f3006060604052600436106100825763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630178b8bf811461008757806302571be3146100b957806306ab5923146100cf57806314ab9038146100f657806316a25cbd146101195780631896f70a1461014c5780635b0fc9c31461016e575b600080fd5b341561009257600080fd5b61009d600435610190565b604051600160a060020a03909116815260200160405180910390f35b34156100c457600080fd5b61009d6004356101ae565b34156100da57600080fd5b6100f4600435602435600160a060020a03604435166101c9565b005b341561010157600080fd5b6100f460043567ffffffffffffffff6024351661028b565b341561012457600080fd5b61012f600435610357565b60405167ffffffffffffffff909116815260200160405180910390f35b341561015757600080fd5b6100f4600435600160a060020a036024351661038e565b341561017957600080fd5b6100f4600435600160a060020a0360243516610434565b600090815260208190526040902060010154600160a060020a031690565b600090815260208190526040902054600160a060020a031690565b600083815260208190526040812054849033600160a060020a039081169116146101f257600080fd5b8484604051918252602082015260409081019051908190039020915083857fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8285604051600160a060020a03909116815260200160405180910390a3506000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790555050565b600082815260208190526040902054829033600160a060020a039081169116146102b457600080fd5b827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa688360405167ffffffffffffffff909116815260200160405180910390a250600091825260208290526040909120600101805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60009081526020819052604090206001015474010000000000000000000000000000000000000000900467ffffffffffffffff1690565b600082815260208190526040902054829033600160a060020a039081169116146103b757600080fd5b827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120600101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b600082815260208190526040902054829033600160a060020a0390811691161461045d57600080fd5b827fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26683604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555600a165627a7a72305820f4c798d4c84c9912f389f64631e85e8d16c3e6644f8c2e1579936015c7d5f6660029"
var abiENSStr = `[{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"label","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setSubnodeOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"ttl","type":"uint64"}],"name":"setTTL","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"ttl","outputs":[{"name":"","type":"uint64"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"label","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"resolver","type":"address"}],"name":"NewResolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"ttl","type":"uint64"}],"name":"NewTTL","type":"event"}]`
================================================
FILE: builtin/ens/ens_resolver.go
================================================
package ens
import (
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/contract"
"github.com/umbracle/ethgo/jsonrpc"
"strings"
)
type ENSResolver struct {
e *ENS
provider *jsonrpc.Eth
}
func NewENSResolver(addr ethgo.Address, provider *jsonrpc.Client) *ENSResolver {
return &ENSResolver{NewENS(addr, contract.WithJsonRPC(provider.Eth())), provider.Eth()}
}
func (e *ENSResolver) Resolve(addr string, block ...ethgo.BlockNumber) (res ethgo.Address, err error) {
addrHash := NameHash(addr)
resolver, err := e.prepareResolver(addrHash, block...)
if err != nil {
return
}
res, err = resolver.Addr(addrHash, block...)
return
}
func addressToReverseDomain(addr ethgo.Address) string {
return strings.ToLower(strings.TrimPrefix(addr.String(), "0x")) + ".addr.reverse"
}
func (e *ENSResolver) ReverseResolve(addr ethgo.Address, block ...ethgo.BlockNumber) (res string, err error) {
addrHash := NameHash(addressToReverseDomain(addr))
resolver, err := e.prepareResolver(addrHash, block...)
if err != nil {
return
}
res, err = resolver.Name(addrHash, block...)
return
}
func (e *ENSResolver) prepareResolver(inputHash ethgo.Hash, block ...ethgo.BlockNumber) (*Resolver, error) {
resolverAddr, err := e.e.Resolver(inputHash, block...)
if err != nil {
return nil, err
}
resolver := NewResolver(resolverAddr, contract.WithJsonRPC(e.provider))
return resolver, nil
}
================================================
FILE: builtin/ens/ens_resolver_test.go
================================================
package ens
import (
"encoding/hex"
"testing"
"github.com/stretchr/testify/assert"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/jsonrpc"
"github.com/umbracle/ethgo/testutil"
)
var (
mainnetAddr = ethgo.HexToAddress("0x314159265dD8dbb310642f98f50C066173C1259b")
)
func TestResolveAddr(t *testing.T) {
c, _ := jsonrpc.NewClient(testutil.TestInfuraEndpoint(t))
r := NewENSResolver(mainnetAddr, c)
cases := []struct {
Addr string
Expected string
}{
{
Addr: "arachnid.eth",
Expected: "0xfdb33f8ac7ce72d7d4795dd8610e323b4c122fbb",
},
}
for _, c := range cases {
t.Run("", func(t *testing.T) {
found, err := r.Resolve(c.Addr)
assert.NoError(t, err)
assert.Equal(t, "0x"+hex.EncodeToString(found[:]), c.Expected)
})
}
}
================================================
FILE: builtin/ens/resolver.go
================================================
// Code generated by ethgo/abigen. DO NOT EDIT.
// Hash: 3d1ecdf4aa6a2c578e0c3bbb14cc28ae2c8ebc4495f7d6128959f961afd0f635
// Version: 0.1.1
package ens
import (
"fmt"
"math/big"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/contract"
"github.com/umbracle/ethgo/jsonrpc"
)
var (
_ = big.NewInt
_ = jsonrpc.NewClient
)
// Resolver is a solidity contract
type Resolver struct {
c *contract.Contract
}
// DeployResolver deploys a new Resolver contract
func DeployResolver(provider *jsonrpc.Client, from ethgo.Address, args []interface{}, opts ...contract.ContractOption) (contract.Txn, error) {
return contract.DeployContract(abiResolver, binResolver, args, opts...)
}
// NewResolver creates a new instance of the contract at a specific address
func NewResolver(addr ethgo.Address, opts ...contract.ContractOption) *Resolver {
return &Resolver{c: contract.NewContract(addr, abiResolver, opts...)}
}
// calls
// ABI calls the ABI method in the solidity contract
func (r *Resolver) ABI(node [32]byte, contentTypes *big.Int, block ...ethgo.BlockNumber) (retval0 *big.Int, retval1 []byte, err error) {
var out map[string]interface{}
var ok bool
out, err = r.c.Call("ABI", ethgo.EncodeBlock(block...), node, contentTypes)
if err != nil {
return
}
// decode outputs
retval0, ok = out["contentType"].(*big.Int)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
retval1, ok = out["data"].([]byte)
if !ok {
err = fmt.Errorf("failed to encode output at index 1")
return
}
return
}
// Addr calls the addr method in the solidity contract
func (r *Resolver) Addr(node [32]byte, block ...ethgo.BlockNumber) (retval0 ethgo.Address, err error) {
var out map[string]interface{}
var ok bool
out, err = r.c.Call("addr", ethgo.EncodeBlock(block...), node)
if err != nil {
return
}
// decode outputs
retval0, ok = out["ret"].(ethgo.Address)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// Content calls the content method in the solidity contract
func (r *Resolver) Content(node [32]byte, block ...ethgo.BlockNumber) (retval0 [32]byte, err error) {
var out map[string]interface{}
var ok bool
out, err = r.c.Call("content", ethgo.EncodeBlock(block...), node)
if err != nil {
return
}
// decode outputs
retval0, ok = out["ret"].([32]byte)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// Name calls the name method in the solidity contract
func (r *Resolver) Name(node [32]byte, block ...ethgo.BlockNumber) (retval0 string, err error) {
var out map[string]interface{}
var ok bool
out, err = r.c.Call("name", ethgo.EncodeBlock(block...), node)
if err != nil {
return
}
// decode outputs
retval0, ok = out["ret"].(string)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// Pubkey calls the pubkey method in the solidity contract
func (r *Resolver) Pubkey(node [32]byte, block ...ethgo.BlockNumber) (retval0 [32]byte, retval1 [32]byte, err error) {
var out map[string]interface{}
var ok bool
out, err = r.c.Call("pubkey", ethgo.EncodeBlock(block...), node)
if err != nil {
return
}
// decode outputs
retval0, ok = out["x"].([32]byte)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
retval1, ok = out["y"].([32]byte)
if !ok {
err = fmt.Errorf("failed to encode output at index 1")
return
}
return
}
// SupportsInterface calls the supportsInterface method in the solidity contract
func (r *Resolver) SupportsInterface(interfaceID [4]byte, block ...ethgo.BlockNumber) (retval0 bool, err error) {
var out map[string]interface{}
var ok bool
out, err = r.c.Call("supportsInterface", ethgo.EncodeBlock(block...), interfaceID)
if err != nil {
return
}
// decode outputs
retval0, ok = out["0"].(bool)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// txns
// SetABI sends a setABI transaction in the solidity contract
func (r *Resolver) SetABI(node [32]byte, contentType *big.Int, data []byte) (contract.Txn, error) {
return r.c.Txn("setABI", node, contentType, data)
}
// SetAddr sends a setAddr transaction in the solidity contract
func (r *Resolver) SetAddr(node [32]byte, addr ethgo.Address) (contract.Txn, error) {
return r.c.Txn("setAddr", node, addr)
}
// SetContent sends a setContent transaction in the solidity contract
func (r *Resolver) SetContent(node [32]byte, hash [32]byte) (contract.Txn, error) {
return r.c.Txn("setContent", node, hash)
}
// SetName sends a setName transaction in the solidity contract
func (r *Resolver) SetName(node [32]byte, name string) (contract.Txn, error) {
return r.c.Txn("setName", node, name)
}
// SetPubkey sends a setPubkey transaction in the solidity contract
func (r *Resolver) SetPubkey(node [32]byte, x [32]byte, y [32]byte) (contract.Txn, error) {
return r.c.Txn("setPubkey", node, x, y)
}
// events
func (r *Resolver) ABIChangedEventSig() ethgo.Hash {
return r.c.GetABI().Events["ABIChanged"].ID()
}
func (r *Resolver) AddrChangedEventSig() ethgo.Hash {
return r.c.GetABI().Events["AddrChanged"].ID()
}
func (r *Resolver) ContentChangedEventSig() ethgo.Hash {
return r.c.GetABI().Events["ContentChanged"].ID()
}
func (r *Resolver) NameChangedEventSig() ethgo.Hash {
return r.c.GetABI().Events["NameChanged"].ID()
}
func (r *Resolver) PubkeyChangedEventSig() ethgo.Hash {
return r.c.GetABI().Events["PubkeyChanged"].ID()
}
================================================
FILE: builtin/ens/resolver_artifacts.go
================================================
package ens
import (
"encoding/hex"
"fmt"
"github.com/umbracle/ethgo/abi"
)
var abiResolver *abi.ABI
// ResolverAbi returns the abi of the Resolver contract
func ResolverAbi() *abi.ABI {
return abiResolver
}
var binResolver []byte
// ResolverBin returns the bin of the Resolver contract
func ResolverBin() []byte {
return binResolver
}
func init() {
var err error
abiResolver, err = abi.NewABI(abiResolverStr)
if err != nil {
panic(fmt.Errorf("cannot parse Resolver abi: %v", err))
}
if len(binResolverStr) != 0 {
binResolver, err = hex.DecodeString(binResolverStr[2:])
if err != nil {
panic(fmt.Errorf("cannot parse Resolver bin: %v", err))
}
}
}
var binResolverStr = "0x6060604052341561000f57600080fd5b6040516020806111b28339810160405280805160008054600160a060020a03909216600160a060020a0319909216919091179055505061115e806100546000396000f3006060604052600436106100ab5763ffffffff60e060020a60003504166301ffc9a781146100b057806310f13a8c146100e45780632203ab561461017e57806329cd62ea146102155780632dff6941146102315780633b3b57de1461025957806359d1d43c1461028b578063623195b014610358578063691f3431146103b457806377372213146103ca578063c3d014d614610420578063c869023314610439578063d5fa2b0014610467575b600080fd5b34156100bb57600080fd5b6100d0600160e060020a031960043516610489565b604051901515815260200160405180910390f35b34156100ef57600080fd5b61017c600480359060446024803590810190830135806020601f8201819004810201604051908101604052818152929190602084018383808284378201915050505050509190803590602001908201803590602001908080601f0160208091040260200160405190810160405281815292919060208401838380828437509496506105f695505050505050565b005b341561018957600080fd5b610197600435602435610807565b60405182815260406020820181815290820183818151815260200191508051906020019080838360005b838110156101d95780820151838201526020016101c1565b50505050905090810190601f1680156102065780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b341561022057600080fd5b61017c600435602435604435610931565b341561023c57600080fd5b610247600435610a30565b60405190815260200160405180910390f35b341561026457600080fd5b61026f600435610a46565b604051600160a060020a03909116815260200160405180910390f35b341561029657600080fd5b6102e1600480359060446024803590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610a6195505050505050565b60405160208082528190810183818151815260200191508051906020019080838360005b8381101561031d578082015183820152602001610305565b50505050905090810190601f16801561034a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561036357600080fd5b61017c600480359060248035919060649060443590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610b8095505050505050565b34156103bf57600080fd5b6102e1600435610c7c565b34156103d557600080fd5b61017c600480359060446024803590810190830135806020601f82018190048102016040519081016040528181529291906020840183838082843750949650610d4295505050505050565b341561042b57600080fd5b61017c600435602435610e8c565b341561044457600080fd5b61044f600435610f65565b60405191825260208201526040908101905180910390f35b341561047257600080fd5b61017c600435600160a060020a0360243516610f82565b6000600160e060020a031982167f3b3b57de0000000000000000000000000000000000000000000000000000000014806104ec5750600160e060020a031982167fd8389dc500000000000000000000000000000000000000000000000000000000145b806105205750600160e060020a031982167f691f343100000000000000000000000000000000000000000000000000000000145b806105545750600160e060020a031982167f2203ab5600000000000000000000000000000000000000000000000000000000145b806105885750600160e060020a031982167fc869023300000000000000000000000000000000000000000000000000000000145b806105bc5750600160e060020a031982167f59d1d43c00000000000000000000000000000000000000000000000000000000145b806105f05750600160e060020a031982167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b600080548491600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561064f57600080fd5b6102c65a03f1151561066057600080fd5b50505060405180519050600160a060020a031614151561067f57600080fd5b6000848152600160205260409081902083916005909101908590518082805190602001908083835b602083106106c65780518252601f1990920191602091820191016106a7565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902090805161070a929160200190611085565b50826040518082805190602001908083835b6020831061073b5780518252601f19909201916020918201910161071c565b6001836020036101000a0380198251168184511617909252505050919091019250604091505051908190039020847fd8c9334b1a9c2f9da342a0a2b32629c1a229b6445dad78947f674b44444a75508560405160208082528190810183818151815260200191508051906020019080838360005b838110156107c75780820151838201526020016107af565b50505050905090810190601f1680156107f45780820380516001836020036101000a031916815260200191505b509250505060405180910390a350505050565b6000610811611103565b60008481526001602081905260409091209092505b838311610924578284161580159061085f5750600083815260068201602052604081205460026000196101006001841615020190911604115b15610919578060060160008481526020019081526020016000208054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561090d5780601f106108e25761010080835404028352916020019161090d565b820191906000526020600020905b8154815290600101906020018083116108f057829003601f168201915b50505050509150610929565b600290920291610826565b600092505b509250929050565b600080548491600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b151561098a57600080fd5b6102c65a03f1151561099b57600080fd5b50505060405180519050600160a060020a03161415156109ba57600080fd5b6040805190810160409081528482526020808301859052600087815260019091522060030181518155602082015160019091015550837f1d6f5e03d3f63eb58751986629a5439baee5079ff04f345becb66e23eb154e46848460405191825260208201526040908101905180910390a250505050565b6000908152600160208190526040909120015490565b600090815260016020526040902054600160a060020a031690565b610a69611103565b60008381526001602052604090819020600501908390518082805190602001908083835b60208310610aac5780518252601f199092019160209182019101610a8d565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610b735780601f10610b4857610100808354040283529160200191610b73565b820191906000526020600020905b815481529060010190602001808311610b5657829003601f168201915b5050505050905092915050565b600080548491600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610bd957600080fd5b6102c65a03f11515610bea57600080fd5b50505060405180519050600160a060020a0316141515610c0957600080fd5b6000198301831615610c1a57600080fd5b60008481526001602090815260408083208684526006019091529020828051610c47929160200190611085565b5082847faa121bbeef5f32f5961a2a28966e769023910fc9479059ee3495d4c1a696efe360405160405180910390a350505050565b610c84611103565b6001600083600019166000191681526020019081526020016000206002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610d365780601f10610d0b57610100808354040283529160200191610d36565b820191906000526020600020905b815481529060010190602001808311610d1957829003601f168201915b50505050509050919050565b600080548391600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610d9b57600080fd5b6102c65a03f11515610dac57600080fd5b50505060405180519050600160a060020a0316141515610dcb57600080fd5b6000838152600160205260409020600201828051610ded929160200190611085565b50827fb7d29e911041e8d9b843369e890bcb72c9388692ba48b65ac54e7214c4c348f78360405160208082528190810183818151815260200191508051906020019080838360005b83811015610e4d578082015183820152602001610e35565b50505050905090810190601f168015610e7a5780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505050565b600080548391600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610ee557600080fd5b6102c65a03f11515610ef657600080fd5b50505060405180519050600160a060020a0316141515610f1557600080fd5b6000838152600160208190526040918290200183905583907f0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc9084905190815260200160405180910390a2505050565b600090815260016020526040902060038101546004909101549091565b600080548391600160a060020a033381169216906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b1515610fdb57600080fd5b6102c65a03f11515610fec57600080fd5b50505060405180519050600160a060020a031614151561100b57600080fd5b60008381526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03851617905583907f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd290849051600160a060020a03909116815260200160405180910390a2505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106110c657805160ff19168380011785556110f3565b828001600101855582156110f3579182015b828111156110f35782518255916020019190600101906110d8565b506110ff929150611115565b5090565b60206040519081016040526000815290565b61112f91905b808211156110ff576000815560010161111b565b905600a165627a7a723058201ecacbc445b9fbcd91b0ab164389f69d7283b856883bc7437eeed1008345a4920029"
var abiResolverStr = `[{"constant":true,"inputs":[{"name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"},{"name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"name":"contentType","type":"uint256"},{"name":"data","type":"bytes"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"x","type":"bytes32"},{"name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"content","outputs":[{"name":"ret","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"addr","outputs":[{"name":"ret","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"contentType","type":"uint256"},{"name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"name","outputs":[{"name":"ret","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"hash","type":"bytes32"}],"name":"setContent","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"name":"x","type":"bytes32"},{"name":"y","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"addr","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"ensAddr","type":"address"}],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"hash","type":"bytes32"}],"name":"ContentChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"x","type":"bytes32"},{"indexed":false,"name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"}]`
================================================
FILE: builtin/ens/utils.go
================================================
package ens
import (
"strings"
"github.com/umbracle/ethgo"
"golang.org/x/crypto/sha3"
)
// NameHash returns the hash of an ENS name
func NameHash(str string) (node ethgo.Hash) {
if str == "" {
return
}
aux := make([]byte, 32)
hash := sha3.NewLegacyKeccak256()
labels := strings.Split(str, ".")
for i := len(labels) - 1; i >= 0; i-- {
label := labels[i]
hash.Write([]byte(label))
aux = hash.Sum(aux) // append the hash of the label to node
hash.Reset()
hash.Write(aux)
aux = hash.Sum(aux[:0])
hash.Reset()
}
copy(node[:], aux)
return
}
================================================
FILE: builtin/ens/utils_test.go
================================================
package ens
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNameHash(t *testing.T) {
cases := []struct {
Name string
Expected string
}{
{
Name: "eth",
Expected: "0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae",
},
{
Name: "foo.eth",
Expected: "0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f",
},
}
for _, c := range cases {
t.Run("", func(t *testing.T) {
found := NameHash(c.Name)
assert.Equal(t, c.Expected, found.String())
})
}
}
================================================
FILE: builtin/erc20/artifacts/ERC20.abi
================================================
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]
================================================
FILE: builtin/erc20/erc20.go
================================================
// Code generated by ethgo/abigen. DO NOT EDIT.
// Hash: a1a873d70d345feef023ee086fd6135b24d775444b950ee9d5ea411e72b0f373
// Version: 0.1.1
package erc20
import (
"fmt"
"math/big"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/contract"
"github.com/umbracle/ethgo/jsonrpc"
)
var (
_ = big.NewInt
_ = jsonrpc.NewClient
)
// ERC20 is a solidity contract
type ERC20 struct {
c *contract.Contract
}
// NewERC20 creates a new instance of the contract at a specific address
func NewERC20(addr ethgo.Address, opts ...contract.ContractOption) *ERC20 {
return &ERC20{c: contract.NewContract(addr, abiERC20, opts...)}
}
// calls
// Allowance calls the allowance method in the solidity contract
func (e *ERC20) Allowance(owner ethgo.Address, spender ethgo.Address, block ...ethgo.BlockNumber) (retval0 *big.Int, err error) {
var out map[string]interface{}
var ok bool
out, err = e.c.Call("allowance", ethgo.EncodeBlock(block...), owner, spender)
if err != nil {
return
}
// decode outputs
retval0, ok = out["0"].(*big.Int)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// BalanceOf calls the balanceOf method in the solidity contract
func (e *ERC20) BalanceOf(owner ethgo.Address, block ...ethgo.BlockNumber) (retval0 *big.Int, err error) {
var out map[string]interface{}
var ok bool
out, err = e.c.Call("balanceOf", ethgo.EncodeBlock(block...), owner)
if err != nil {
return
}
// decode outputs
retval0, ok = out["balance"].(*big.Int)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// Decimals calls the decimals method in the solidity contract
func (e *ERC20) Decimals(block ...ethgo.BlockNumber) (retval0 uint8, err error) {
var out map[string]interface{}
var ok bool
out, err = e.c.Call("decimals", ethgo.EncodeBlock(block...))
if err != nil {
return
}
// decode outputs
retval0, ok = out["0"].(uint8)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// Name calls the name method in the solidity contract
func (e *ERC20) Name(block ...ethgo.BlockNumber) (retval0 string, err error) {
var out map[string]interface{}
var ok bool
out, err = e.c.Call("name", ethgo.EncodeBlock(block...))
if err != nil {
return
}
// decode outputs
retval0, ok = out["0"].(string)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// Symbol calls the symbol method in the solidity contract
func (e *ERC20) Symbol(block ...ethgo.BlockNumber) (retval0 string, err error) {
var out map[string]interface{}
var ok bool
out, err = e.c.Call("symbol", ethgo.EncodeBlock(block...))
if err != nil {
return
}
// decode outputs
retval0, ok = out["0"].(string)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// TotalSupply calls the totalSupply method in the solidity contract
func (e *ERC20) TotalSupply(block ...ethgo.BlockNumber) (retval0 *big.Int, err error) {
var out map[string]interface{}
var ok bool
out, err = e.c.Call("totalSupply", ethgo.EncodeBlock(block...))
if err != nil {
return
}
// decode outputs
retval0, ok = out["0"].(*big.Int)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
return
}
// txns
// Approve sends a approve transaction in the solidity contract
func (e *ERC20) Approve(spender ethgo.Address, value *big.Int) (contract.Txn, error) {
return e.c.Txn("approve", spender, value)
}
// Transfer sends a transfer transaction in the solidity contract
func (e *ERC20) Transfer(to ethgo.Address, value *big.Int) (contract.Txn, error) {
return e.c.Txn("transfer", to, value)
}
// TransferFrom sends a transferFrom transaction in the solidity contract
func (e *ERC20) TransferFrom(from ethgo.Address, to ethgo.Address, value *big.Int) (contract.Txn, error) {
return e.c.Txn("transferFrom", from, to, value)
}
// events
func (e *ERC20) ApprovalEventSig() ethgo.Hash {
return e.c.GetABI().Events["Approval"].ID()
}
func (e *ERC20) TransferEventSig() ethgo.Hash {
return e.c.GetABI().Events["Transfer"].ID()
}
================================================
FILE: builtin/erc20/erc20_artifacts.go
================================================
package erc20
import (
"encoding/hex"
"fmt"
"github.com/umbracle/ethgo/abi"
)
var abiERC20 *abi.ABI
// ERC20Abi returns the abi of the ERC20 contract
func ERC20Abi() *abi.ABI {
return abiERC20
}
var binERC20 []byte
func init() {
var err error
abiERC20, err = abi.NewABI(abiERC20Str)
if err != nil {
panic(fmt.Errorf("cannot parse ERC20 abi: %v", err))
}
if len(binERC20Str) != 0 {
binERC20, err = hex.DecodeString(binERC20Str[2:])
if err != nil {
panic(fmt.Errorf("cannot parse ERC20 bin: %v", err))
}
}
}
var binERC20Str = ""
var abiERC20Str = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]`
================================================
FILE: builtin/erc20/erc20_test.go
================================================
package erc20
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/contract"
"github.com/umbracle/ethgo/jsonrpc"
"github.com/umbracle/ethgo/testutil"
)
var (
zeroX = ethgo.HexToAddress("0xe41d2489571d322189246dafa5ebde1f4699f498")
)
func TestERC20Decimals(t *testing.T) {
c, _ := jsonrpc.NewClient(testutil.TestInfuraEndpoint(t))
erc20 := NewERC20(zeroX, contract.WithJsonRPC(c.Eth()))
decimals, err := erc20.Decimals()
assert.NoError(t, err)
if decimals != 18 {
t.Fatal("bad")
}
}
func TestERC20Name(t *testing.T) {
c, _ := jsonrpc.NewClient(testutil.TestInfuraEndpoint(t))
erc20 := NewERC20(zeroX, contract.WithJsonRPC(c.Eth()))
name, err := erc20.Name()
assert.NoError(t, err)
assert.Equal(t, name, "0x Protocol Token")
}
func TestERC20Symbol(t *testing.T) {
c, _ := jsonrpc.NewClient(testutil.TestInfuraEndpoint(t))
erc20 := NewERC20(zeroX, contract.WithJsonRPC(c.Eth()))
symbol, err := erc20.Symbol()
assert.NoError(t, err)
assert.Equal(t, symbol, "ZRX")
}
func TestTotalSupply(t *testing.T) {
c, _ := jsonrpc.NewClient(testutil.TestInfuraEndpoint(t))
erc20 := NewERC20(zeroX, contract.WithJsonRPC(c.Eth()))
supply, err := erc20.TotalSupply()
assert.NoError(t, err)
assert.Equal(t, supply.String(), "1000000000000000000000000000")
}
================================================
FILE: cmd/abigen/abigen.go
================================================
package abigen
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strings"
"path/filepath"
"github.com/umbracle/ethgo/compiler"
)
func Parse(sources string, pckg string, output string) error {
config := &config{
Package: pckg,
Output: output,
}
if sources == "" {
return fmt.Errorf("no source")
}
for _, source := range strings.Split(sources, ",") {
matches, err := filepath.Glob(source)
if err != nil {
fmt.Printf("Failed to read files: %v", err)
os.Exit(1)
}
if len(matches) == 0 {
fmt.Printf("No match for source: %s\n", source)
continue
}
for _, source := range matches {
artifacts, err := process(source, config)
if err != nil {
fmt.Printf("Failed to parse sources: %v", err)
os.Exit(1)
}
// hash the source file
raw := sha256.Sum256([]byte(source))
hash := hex.EncodeToString(raw[:])
if err := gen(artifacts, config, hash); err != nil {
fmt.Printf("Failed to generate sources: %v", err)
os.Exit(1)
}
}
}
return nil
}
const (
solExt = 1
abiExt = 2
jsonExt = 3
)
func process(sources string, config *config) (map[string]*compiler.Artifact, error) {
files := strings.Split(sources, ",")
if len(files) == 0 {
return nil, fmt.Errorf("input not found")
}
prev := -1
for _, f := range files {
var ext int
switch extt := filepath.Ext(f); extt {
case ".abi":
ext = abiExt
case ".sol":
ext = solExt
case ".json":
ext = jsonExt
default:
return nil, fmt.Errorf("file extension '%s' not found", extt)
}
if prev == -1 {
prev = ext
} else if ext != prev {
return nil, fmt.Errorf("two file formats found")
}
}
switch prev {
case abiExt:
return processAbi(files, config)
case solExt:
return processSolc(files)
case jsonExt:
return processJson(files)
}
return nil, nil
}
func processSolc(sources []string) (map[string]*compiler.Artifact, error) {
c := compiler.NewSolidityCompiler("solc")
raw, err := c.Compile(sources...)
if err != nil {
return nil, err
}
res := map[string]*compiler.Artifact{}
for rawName, entry := range raw.Contracts {
name := strings.Split(rawName, ":")[1]
res[strings.Title(name)] = entry
}
return res, nil
}
func processAbi(sources []string, config *config) (map[string]*compiler.Artifact, error) {
artifacts := map[string]*compiler.Artifact{}
for _, abiPath := range sources {
content, err := ioutil.ReadFile(abiPath)
if err != nil {
return nil, fmt.Errorf("failed to read abi file (%s): %v", abiPath, err)
}
// Use the name of the file to name the contract
path, name := filepath.Split(abiPath)
name = strings.TrimSuffix(name, filepath.Ext(name))
binPath := filepath.Join(path, name+".bin")
bin, err := ioutil.ReadFile(binPath)
if err != nil {
// bin not found
bin = []byte{}
}
artifacts[strings.Title(name)] = &compiler.Artifact{
Abi: string(content),
Bin: string(bin),
}
}
return artifacts, nil
}
type JSONArtifact struct {
Bytecode string `json:"bytecode"`
Abi json.RawMessage `json:"abi"`
}
func processJson(sources []string) (map[string]*compiler.Artifact, error) {
artifacts := map[string]*compiler.Artifact{}
for _, jsonPath := range sources {
content, err := ioutil.ReadFile(jsonPath)
if err != nil {
return nil, fmt.Errorf("failed to read abi file (%s): %v", jsonPath, err)
}
// Use the name of the file to name the contract
_, name := filepath.Split(jsonPath)
name = strings.TrimSuffix(name, ".json")
var art *JSONArtifact
if err := json.Unmarshal(content, &art); err != nil {
return nil, err
}
artifacts[strings.Title(name)] = &compiler.Artifact{
Abi: string(art.Abi),
Bin: "0x" + art.Bytecode,
}
}
return artifacts, nil
}
================================================
FILE: cmd/abigen/gen.go
================================================
package abigen
import (
"bytes"
"fmt"
"io/ioutil"
"path/filepath"
"reflect"
"strings"
"text/template"
"github.com/umbracle/ethgo/abi"
"github.com/umbracle/ethgo/cmd/version"
"github.com/umbracle/ethgo/compiler"
)
type config struct {
Package string
Output string
}
func cleanName(str string) string {
return handleSnakeCase(strings.Trim(str, "_"))
}
func outputArg(str string) string {
return str
}
func handleSnakeCase(str string) string {
if !strings.Contains(str, "_") {
return str
}
spl := strings.Split(str, "_")
res := ""
for indx, elem := range spl {
if indx != 0 {
elem = strings.Title(elem)
}
res += elem
}
return res
}
func funcName(str string) string {
return strings.Title(handleSnakeCase(str))
}
func encodeSimpleArg(typ *abi.Type) string {
switch typ.Kind() {
case abi.KindAddress:
return "ethgo.Address"
case abi.KindString:
return "string"
case abi.KindBool:
return "bool"
case abi.KindInt:
return typ.GoType().String()
case abi.KindUInt:
return typ.GoType().String()
case abi.KindFixedBytes:
return fmt.Sprintf("[%d]byte", typ.Size())
case abi.KindBytes:
return "[]byte"
case abi.KindSlice:
return "[]" + encodeSimpleArg(typ.Elem())
default:
return fmt.Sprintf("input not done for type: %s", typ.String())
}
}
func encodeArg(str interface{}) string {
arg, ok := str.(*abi.TupleElem)
if !ok {
panic("bad 1")
}
return encodeSimpleArg(arg.Elem)
}
func tupleLen(tuple interface{}) interface{} {
if isNil(tuple) {
return 0
}
arg, ok := tuple.(*abi.Type)
if !ok {
panic("bad tuple")
}
return len(arg.TupleElems())
}
func tupleElems(tuple interface{}) []interface{} {
res := []interface{}{}
if isNil(tuple) {
return res
}
arg, ok := tuple.(*abi.Type)
if !ok {
panic("bad tuple")
}
for _, i := range arg.TupleElems() {
res = append(res, i)
}
return res
}
func isNil(c interface{}) bool {
return c == nil || (reflect.ValueOf(c).Kind() == reflect.Ptr && reflect.ValueOf(c).IsNil())
}
func gen(artifacts map[string]*compiler.Artifact, config *config, hash string) error {
funcMap := template.FuncMap{
"title": strings.Title,
"clean": cleanName,
"arg": encodeArg,
"outputArg": outputArg,
"funcName": funcName,
"tupleElems": tupleElems,
"tupleLen": tupleLen,
}
tmplAbi, err := template.New("eth-abi").Funcs(funcMap).Parse(templateAbiStr)
if err != nil {
return err
}
tmplBin, err := template.New("eth-abi").Funcs(funcMap).Parse(templateBinStr)
if err != nil {
return err
}
for name, artifact := range artifacts {
// parse abi
abi, err := abi.NewABI(artifact.Abi)
if err != nil {
return err
}
input := map[string]interface{}{
"Hash": hash,
"Version": version.Version,
"Ptr": strings.ToLower(string(name[0])),
"Config": config,
"Contract": artifact,
"Abi": abi,
"Name": name,
}
filename := strings.ToLower(name)
var b bytes.Buffer
if err := tmplAbi.Execute(&b, input); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(config.Output, filename+".go"), []byte(b.Bytes()), 0644); err != nil {
return err
}
b.Reset()
if err := tmplBin.Execute(&b, input); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(config.Output, filename+"_artifacts.go"), []byte(b.Bytes()), 0644); err != nil {
return err
}
}
return nil
}
var templateAbiStr = `// Code generated by ethgo/abigen. DO NOT EDIT.
// Hash: {{.Hash}}
// Version: {{.Version}}
package {{.Config.Package}}
import (
"fmt"
"math/big"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/contract"
"github.com/umbracle/ethgo/jsonrpc"
)
var (
_ = big.NewInt
_ = jsonrpc.NewClient
)
// {{.Name}} is a solidity contract
type {{.Name}} struct {
c *contract.Contract
}
{{if .Contract.Bin}}
// Deploy{{.Name}} deploys a new {{.Name}} contract
func Deploy{{.Name}}(provider *jsonrpc.Client, from ethgo.Address, args []interface{}, opts ...contract.ContractOption) (contract.Txn, error) {
return contract.DeployContract(abi{{.Name}}, bin{{.Name}}, args, opts...)
}
{{end}}
// New{{.Name}} creates a new instance of the contract at a specific address
func New{{.Name}}(addr ethgo.Address, opts ...contract.ContractOption) *{{.Name}} {
return &{{.Name}}{c: contract.NewContract(addr, abi{{.Name}}, opts...)}
}
// calls
{{range $key, $value := .Abi.Methods}}{{if .Const}}
// {{funcName $key}} calls the {{$key}} method in the solidity contract
func ({{$.Ptr}} *{{$.Name}}) {{funcName $key}}({{range $index, $val := tupleElems .Inputs}}{{if .Name}}{{clean .Name}}{{else}}val{{$index}}{{end}} {{arg .}}, {{end}}block ...ethgo.BlockNumber) ({{range $index, $val := tupleElems .Outputs}}retval{{$index}} {{arg .}}, {{end}}err error) {
var out map[string]interface{}
{{ $length := tupleLen .Outputs }}{{ if ne $length 0 }}var ok bool{{ end }}
out, err = {{$.Ptr}}.c.Call("{{$key}}", ethgo.EncodeBlock(block...){{range $index, $val := tupleElems .Inputs}}, {{if .Name}}{{clean .Name}}{{else}}val{{$index}}{{end}}{{end}})
if err != nil {
return
}
// decode outputs
{{range $index, $val := tupleElems .Outputs}}retval{{$index}}, ok = out["{{if .Name}}{{.Name}}{{else}}{{$index}}{{end}}"].({{arg .}})
if !ok {
err = fmt.Errorf("failed to encode output at index {{$index}}")
return
}
{{end}}
return
}
{{end}}{{end}}
// txns
{{range $key, $value := .Abi.Methods}}{{if not .Const}}
// {{funcName $key}} sends a {{$key}} transaction in the solidity contract
func ({{$.Ptr}} *{{$.Name}}) {{funcName $key}}({{range $index, $input := tupleElems .Inputs}}{{if $index}}, {{end}}{{clean .Name}} {{arg .}}{{end}}) (contract.Txn, error) {
return {{$.Ptr}}.c.Txn("{{$key}}"{{range $index, $elem := tupleElems .Inputs}}, {{clean $elem.Name}}{{end}})
}
{{end}}{{end}}
// events
{{range $key, $value := .Abi.Events}}
func ({{$.Ptr}} *{{$.Name}}) {{funcName $key}}EventSig() ethgo.Hash {
return {{$.Ptr}}.c.GetABI().Events["{{funcName $key}}"].ID()
}
{{end}}`
var templateBinStr = `package {{.Config.Package}}
import (
"encoding/hex"
"fmt"
"github.com/umbracle/ethgo/abi"
)
var abi{{.Name}} *abi.ABI
// {{.Name}}Abi returns the abi of the {{.Name}} contract
func {{.Name}}Abi() *abi.ABI {
return abi{{.Name}}
}
var bin{{.Name}} []byte
{{if .Contract.Bin}}
// {{.Name}}Bin returns the bin of the {{.Name}} contract
func {{.Name}}Bin() []byte {
return bin{{.Name}}
}
{{end}}
func init() {
var err error
abi{{.Name}}, err = abi.NewABI(abi{{.Name}}Str)
if err != nil {
panic(fmt.Errorf("cannot parse {{.Name}} abi: %v", err))
}
if len(bin{{.Name}}Str) != 0 {
bin{{.Name}}, err = hex.DecodeString(bin{{.Name}}Str[2:])
if err != nil {
panic(fmt.Errorf("cannot parse {{.Name}} bin: %v", err))
}
}
}
var bin{{.Name}}Str = "{{.Contract.Bin}}"
var abi{{.Name}}Str = ` + "`" + `{{.Contract.Abi}}` + "`\n"
================================================
FILE: cmd/abigen/testdata/testdata.abi
================================================
[
{
"constant": false,
"inputs": [
{
"name": "_val1",
"type": "address"
},
{
"name": "_val2",
"type": "uint256"
}
],
"name": "txnBasicInput",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "callBasicInput",
"outputs": [
{
"name": "",
"type": "uint256"
},
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "owner",
"type": "address"
},
{
"indexed": true,
"name": "spender",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256"
}
],
"name": "eventBasic",
"type": "event"
}
]
================================================
FILE: cmd/abigen/testdata/testdata.go
================================================
// Code generated by ethgo/abigen. DO NOT EDIT.
// Hash: 3f1af52b391dcf1991b5cee7468a69f382cfa0f819eaff85474464c969fe7ea9
// Version: 0.1.1
package testdata
import (
"fmt"
"math/big"
"github.com/umbracle/ethgo"
"github.com/umbracle/ethgo/contract"
"github.com/umbracle/ethgo/jsonrpc"
)
var (
_ = big.NewInt
_ = jsonrpc.NewClient
)
// Testdata is a solidity contract
type Testdata struct {
c *contract.Contract
}
// NewTestdata creates a new instance of the contract at a specific address
func NewTestdata(addr ethgo.Address, opts ...contract.ContractOption) *Testdata {
return &Testdata{c: contract.NewContract(addr, abiTestdata, opts...)}
}
// calls
// CallBasicInput calls the callBasicInput method in the solidity contract
func (t *Testdata) CallBasicInput(block ...ethgo.BlockNumber) (retval0 *big.Int, retval1 ethgo.Address, err error) {
var out map[string]interface{}
var ok bool
out, err = t.c.Call("callBasicInput", ethgo.EncodeBlock(block...))
if err != nil {
return
}
// decode outputs
retval0, ok = out["0"].(*big.Int)
if !ok {
err = fmt.Errorf("failed to encode output at index 0")
return
}
retval1, ok = out["1"].(ethgo.Address)
if !ok {
err = fmt.Errorf("failed to encode output at index 1")
return
}
return
}
// txns
// TxnBasicInput sends a txnBasicInput transaction in the solidity contract
func (t *Testdata) TxnBasicInput(val1 ethgo.Address, val2 *big.Int) (contract.Txn, error) {
return t.c.Txn("txnBasicInput", val1, val2)
}
// events
func (t *Testdata) EventBasicEventSig() ethgo.Hash {
return t.c.GetABI().Events["EventBasic"].ID()
}
================================================
FILE: cmd/abigen/testdata/testdata_artifacts.go
================================================
package testdata
import (
"encoding/hex"
"fmt"
"github.com/umbracle/ethgo/abi"
)
var abiTestdata *abi.ABI
// TestdataAbi returns the abi of the Testdata contract
func TestdataAbi() *abi.ABI {
return abiTestdata
}
var binTestdata []byte
func init() {
var err error
abiTestdata, err = abi.NewABI(abiTestdataStr)
if err != nil {
panic(fmt.Errorf("cannot parse Testdata abi: %v", err))
}
if len(binTestdataStr) != 0 {
binTestdata, err = hex.DecodeString(binTestdataStr[2:])
if err != nil {
panic(fmt.Errorf("cannot parse Testdata bin: %v", err))
}
}
}
var binTestdataStr = ""
var abiTestdataStr = `[
{
"constant": false,
"inputs": [
{
"name": "_val1",
"type": "address"
},
{
"name": "_val2",
"type": "uint256"
}
],
"name": "txnBasicInput",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "callBasicInput",
"outputs": [
{
"name": "",
"type": "uint256"
},
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "owner",
"type": "address"
},
{
"indexed": true,
"name": "spender",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256"
}
],
"name": "eventBasic",
"type": "event"
}
]`
================================================
FILE: cmd/commands/4byte.go
================================================
package commands
import (
"github.com/mitchellh/cli"
fourbyte "github.com/umbracle/ethgo/4byte"
)
// FourByteCommand is the command to resolve 4byte actions
type FourByteCommand struct {
UI cli.Ui
}
// Help implements the cli.Command interface
func (c *FourByteCommand) Help() string {
return `Usage: ethgo 4byte [signature]
Resolve a 4byte signature`
}
// Synopsis implements the cli.Command interface
func (c *FourByteCommand) Synopsis() string {
return "Resolve a 4byte signature"
}
// Run implements the cli.Command interface
func (c *FourByteCommand) Run(args []string) int {
if len(args) == 0 {
c.UI.Output("No arguments provided")
return 1
}
found, err := fourbyte.Resolve(args[0])
if err != nil {
c.UI.Output(err.Error())
return 1
}
if found == "" {
c.UI.Output("Resolve not found")
return 1
}
c.UI.Output(found)
return 0
}
================================================
FILE: cmd/commands/abigen.go
================================================
package commands
import (
flag "github.com/spf13/pflag"
"github.com/umbracle/ethgo/cmd/abigen"
)
// VersionCommand is the command to show the version of the agent
type AbigenCommand struct {
*baseCommand
source string
pckg string
output string
}
// Help implements the cli.Command interface
func (c *AbigenCommand) Help() string {
return `Usage: ethgo abigen
Compute the abigen.
` + c.Flags().FlagUsages()
}
// Synopsis implements the cli.Command interface
func (c *AbigenCommand) Synopsis() string {
return "Compute the abigen"
}
func (c *AbigenCommand) Flags() *flag.FlagSet {
flags := c.baseCommand.Flags("abigen")
flags.StringVar(&c.source, "source", "", "Source data")
flags.StringVar(&c.pckg, "package", "main", "Name of the package")
flags.StringVar(&c.output, "output", ".", "Output directory")
return flags
}
// Run implements the cli.Command interface
func (c *AbigenCommand) Run(args []string) int {
flags := c.Flags()
if err := flags.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
if err := abigen.Parse(c.source, c.pckg, c.output); err != nil {
c.UI.Error(err.Error())
return 1
}
return 0
}
================================================
FILE: cmd/commands/commands.go
================================================
package commands
import (
"os"
"github.com/mitchellh/cli"
flag "github.com/spf13/pflag"
)
func Commands() map[string]cli.CommandFactory {
ui := &cli.BasicUi{
Reader: os.Stdin,
Writer: os.Stdout,
ErrorWriter: os.Stderr,
}
baseCommand := &baseCommand{
UI: ui,
}
return map[string]cli.CommandFactory{
"abigen": func() (cli.Command, error) {
return &AbigenCommand{
baseCommand: baseCommand,
}, nil
},
"4byte": func() (cli.Command, error) {
return &FourByteCommand{
UI: ui,
}, nil
},
"ens": func() (cli.Command, error) {
return &EnsCommand{
UI: ui,
}, nil
},
"ens resolve": func() (cli.Command, error) {
return &EnsResolveCommand{
UI: ui,
}, nil
},
"version": func() (cli.Command, error) {
return &VersionCommand{
UI: ui,
}, nil
},
}
}
type baseCommand struct {
UI cli.Ui
}
func (b *baseCommand) Flags(name string) *flag.FlagSet {
flags := flag.NewFlagSet(name, 0)
return flags
}
================================================
FILE: cmd/commands/ens.go
================================================
package commands
import (
"github.com/mitchellh/cli"
)
// EnsCommand is the group command for ens
type EnsCommand struct {
UI cli.Ui
}
// Help implements the cli.Command interface
func (c *EnsCommand) Help() string {
return `Usage: ethgo ens
Interact with ens`
}
// Synopsis implements the cli.Command interface
func (c *EnsCommand) Synopsis() string {
return "Interact with ens"
}
// Run implements the cli.Command interface
func (c *EnsCommand) Run(args []string) int {
return 0
}
================================================
FILE: cmd/commands/ens_resolve.go
================================================
package commands
import (
"os"
"github.com/mitchellh/cli"
flag "github.com/spf13/pflag"
"github.com/umbracle/ethgo/ens"
)
func defaultJsonRPCProvider() string {
if provider := os.Getenv("JSONRPC_PROVIDER"); provider != "" {
return provider
}
return "http://localhost:8545"
}
// EnsResolveCommand is the command to resolve an ens name
type EnsResolveCommand struct {
UI cli.Ui
provider string
}
// Help implements the cli.Command interface
func (c *EnsResolveCommand) Help() string {
return `Usage: ethgo ens resolve <name>
Resolve an ens name
` + c.Flags().FlagUsages()
}
// Synopsis implements the cli.Command interface
func (c *EnsResolveCommand) Synopsis() string {
return "Resolve an ens name"
}
func (c *EnsResolveCommand) Flags() *flag.FlagSet {
flags := flag.NewFlagSet("ens resolve", flag.PanicOnError)
flags.StringVar(&c.provider, "provider", defaultJsonRPCProvider(), "")
return flags
}
// Run implements the cli.Command interface
func (c *EnsResolveCommand) Run(args []string) int {
flags := c.Flags()
if err := flags.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
args = flags.Args()
if len(args) != 1 {
c.UI.Error("one argument <name> expected")
return 1
}
e, err := ens.NewENS(ens.WithAddress(c.provider))
if err != nil {
c.UI.Error(err.Error())
return 1
}
addr, err := e.Resolve(args[0])
if err != nil {
c.UI.Error(err.Error())
return 1
}
c.UI.Output(addr.String())
return 0
}
================================================
FILE: cmd/commands/version.go
================================================
package commands
import (
"github.com/mitchellh/cli"
"github.com/umbracle/ethgo/cmd/version"
)
// VersionCommand is the command to show the version of the agent
type VersionCommand struct {
UI cli.Ui
}
// Help implements the cli.Command interface
func (c *VersionCommand) Help() string {
return `Usage: ethgo version
Display the Ethgo version`
}
// Synopsis implements the cli.Command interface
func (c *VersionCommand) Synopsis() string {
return "Display the Ethgo version"
}
// Run implements the cli.Command interface
func (c *VersionCommand) Run(args []string) int {
c.UI.Output(version.GetVersion())
return 0
}
================================================
FILE: cmd/go.mod
================================================
module github.com/umbracle/ethgo/cmd
go 1.17
require (
github.com/mitchellh/cli v1.1.2
github.com/umbracle/ethgo v0.0.0-20220303093617-1621d9ff042b
)
require github.com/spf13/pflag v1.0.5
require (
github.com/Masterminds/goutils v1.1.0 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect
github.com/bgentry/speakeasy v0.1.0 // indirect
github.com/btcsuite/btcd v0.22.1 // indirect
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect
github.com/fatih/color v1.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/gorilla/websocket v1.4.1 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.0.0 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.11 // indirect
github.com/klauspost/compress v1.4.1 // indirect
github.com/klauspost/cpuid v1.2.0 // indirect
github.com/mattn/go-colorable v0.0.9 // indirect
github.com/mattn/go-isatty v0.0.3 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/posener/complete v1.1.1 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.4.0 // indirect
github.com/valyala/fastjson v1.4.1 // indirect
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect
golang.org/x/text v0.3.2 // indirect
)
replace github.com/umbracle/ethgo => ../
================================================
FILE: cmd/go.sum
================================================
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Microsoft/go-winio v0.4.13 h1:Hmi80lzZuI/CaYmlJp/b+FjZdRZhKu9c2mDVqKlLWVs=
github.com/Microsoft/go-winio v0.4.13/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c=
github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ=
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6Ti
gitextract_zpf77o7o/
├── .github/
│ └── workflows/
│ ├── pr.yaml
│ └── release.yaml
├── .gitignore
├── .goreleaser.yaml
├── 4byte/
│ ├── 4byte.go
│ └── 4byte_test.go
├── CHANGELOG.md
├── LICENSE
├── Makefile
├── README.md
├── abi/
│ ├── abi.go
│ ├── abi_test.go
│ ├── decode.go
│ ├── decode_test.go
│ ├── encode.go
│ ├── encoding_test.go
│ ├── revert.go
│ ├── revert_test.go
│ ├── testing.go
│ ├── topics.go
│ ├── topics_test.go
│ ├── type.go
│ └── type_test.go
├── blocktracker/
│ ├── blocktracker.go
│ └── blocktracker_test.go
├── builtin/
│ ├── ens/
│ │ ├── artifacts/
│ │ │ ├── ENS.abi
│ │ │ └── Resolver.abi
│ │ ├── ens.go
│ │ ├── ens_artifacts.go
│ │ ├── ens_resolver.go
│ │ ├── ens_resolver_test.go
│ │ ├── resolver.go
│ │ ├── resolver_artifacts.go
│ │ ├── utils.go
│ │ └── utils_test.go
│ └── erc20/
│ ├── artifacts/
│ │ └── ERC20.abi
│ ├── erc20.go
│ ├── erc20_artifacts.go
│ └── erc20_test.go
├── cmd/
│ ├── abigen/
│ │ ├── abigen.go
│ │ ├── gen.go
│ │ └── testdata/
│ │ ├── testdata.abi
│ │ ├── testdata.go
│ │ └── testdata_artifacts.go
│ ├── commands/
│ │ ├── 4byte.go
│ │ ├── abigen.go
│ │ ├── commands.go
│ │ ├── ens.go
│ │ ├── ens_resolve.go
│ │ └── version.go
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── version/
│ └── version.go
├── compiler/
│ ├── fixtures/
│ │ ├── ballot.sol
│ │ └── simple_auction.sol
│ ├── solidity.go
│ └── solidity_test.go
├── contract/
│ ├── contract.go
│ └── contract_test.go
├── e2e/
│ └── transaction_test.go
├── encoding.go
├── ens/
│ ├── address_mapping.go
│ ├── ens.go
│ └── ens_test.go
├── etherscan/
│ ├── etherscan.go
│ └── etherscan_test.go
├── examples/
│ ├── contract-call-basic.go
│ ├── contract-call-from.go
│ ├── contract-deploy.go
│ └── contract-transaction.go
├── go.mod
├── go.sum
├── jsonrpc/
│ ├── client.go
│ ├── codec/
│ │ └── codec.go
│ ├── debug.go
│ ├── debug_test.go
│ ├── eth.go
│ ├── eth_test.go
│ ├── net.go
│ ├── net_test.go
│ ├── subscribe.go
│ ├── subscribe_test.go
│ ├── transport/
│ │ ├── http.go
│ │ ├── ipc.go
│ │ ├── transport.go
│ │ └── websocket.go
│ ├── util.go
│ ├── web3.go
│ └── web3_test.go
├── keccak.go
├── keystore/
│ ├── utils.go
│ ├── v3.go
│ ├── v3_test.go
│ ├── v4.go
│ └── v4_test.go
├── networks.go
├── scripts/
│ ├── build-artifacts.sh
│ ├── setup-ci.sh
│ └── setup-geth.sh
├── signing/
│ ├── eip712.go
│ └── eip712_test.go
├── structs.go
├── structs_encoding_test.go
├── structs_marshal.go
├── structs_marshal_rlp.go
├── structs_marshal_rlp_test.go
├── structs_marshal_test.go
├── structs_test.go
├── structs_unmarshal.go
├── testcases/
│ ├── accounts_test.go
│ ├── contract_test.go
│ ├── eip712_test.go
│ ├── package.json
│ ├── transaction_test.go
│ └── util.go
├── testsuite/
│ ├── arbitrum-block-full.json
│ ├── block-full.json
│ ├── block-txn-hashes.json
│ ├── receipts.json
│ ├── transaction-call.json
│ ├── transaction-contract-creation.json
│ ├── transaction-eip1159.json
│ ├── transaction-eip1559-notype.json
│ ├── transaction-eip2930.json
│ └── transaction-pending.json
├── testutil/
│ ├── contract.go
│ ├── mock.go
│ ├── server.go
│ ├── server_test.go
│ └── util.go
├── tracker/
│ ├── README.md
│ ├── store/
│ │ ├── boltdb/
│ │ │ ├── bolt_store.go
│ │ │ └── bolt_store_test.go
│ │ ├── inmem/
│ │ │ ├── inmem_store.go
│ │ │ └── inmem_store_test.go
│ │ ├── postgresql/
│ │ │ ├── postgresql_store.go
│ │ │ └── postgresql_store_test.go
│ │ ├── store.go
│ │ └── testing.go
│ ├── tracker.go
│ └── tracker_test.go
├── units.go
├── wallet/
│ ├── fixtures/
│ │ └── wallet_json.json
│ ├── key.go
│ ├── key_test.go
│ ├── signer.go
│ ├── signer_test.go
│ ├── wallet_hd.go
│ ├── wallet_hd_test.go
│ ├── wallet_json.go
│ ├── wallet_json_test.go
│ ├── wallet_priv.go
│ └── wallet_priv_test.go
└── website/
├── README.md
├── components/
│ ├── eip.jsx
│ ├── godoc.jsx
│ └── primitives.jsx
├── next.config.js
├── package.json
├── pages/
│ ├── _app.js
│ ├── abi.mdx
│ ├── cli/
│ │ ├── 4byte.mdx
│ │ ├── abigen.mdx
│ │ ├── ens_resolve.mdx
│ │ ├── meta.json
│ │ └── version.mdx
│ ├── contract.mdx
│ ├── index.mdx
│ ├── integrations/
│ │ ├── 4byte.mdx
│ │ ├── ens.mdx
│ │ ├── etherscan.mdx
│ │ └── meta.json
│ ├── jsonrpc/
│ │ ├── eth.mdx
│ │ ├── index.mdx
│ │ ├── meta.json
│ │ └── net.mdx
│ ├── meta.json
│ └── signers/
│ ├── signer.mdx
│ └── wallet.mdx
└── theme.config.js
SYMBOL INDEX (1011 symbols across 123 files)
FILE: 4byte/4byte.go
constant fourByteURL (line 11) | fourByteURL = "https://www.4byte.directory"
function Resolve (line 15) | func Resolve(str string) (string, error) {
function ResolveBytes (line 20) | func ResolveBytes(b []byte) (string, error) {
function get (line 24) | func get(path string) (string, error) {
type signatureResult (line 49) | type signatureResult struct
FILE: 4byte/4byte_test.go
function Test4Byte (line 9) | func Test4Byte(t *testing.T) {
FILE: abi/abi.go
type ABI (line 18) | type ABI struct
method GetMethod (line 26) | func (a *ABI) GetMethod(name string) *Method {
method GetMethodBySignature (line 31) | func (a *ABI) GetMethodBySignature(methodSignature string) *Method {
method addError (line 36) | func (a *ABI) addError(e *Error) {
method addEvent (line 43) | func (a *ABI) addEvent(e *Event) {
method addMethod (line 54) | func (a *ABI) addMethod(m *Method) {
method UnmarshalJSON (line 104) | func (a *ABI) UnmarshalJSON(data []byte) error {
function overloadedName (line 69) | func overloadedName(rawName string, isAvail func(string) bool) string {
function NewABI (line 80) | func NewABI(s string) (*ABI, error) {
function MustNewABI (line 85) | func MustNewABI(s string) *ABI {
function NewABIFromReader (line 94) | func NewABIFromReader(r io.Reader) (*ABI, error) {
type Method (line 190) | type Method struct
method Sig (line 198) | func (m *Method) Sig() string {
method ID (line 203) | func (m *Method) ID() []byte {
method Encode (line 212) | func (m *Method) Encode(args interface{}) ([]byte, error) {
method Decode (line 222) | func (m *Method) Decode(data []byte) (map[string]interface{}, error) {
function MustNewMethod (line 235) | func MustNewMethod(name string) *Method {
function NewMethod (line 243) | func NewMethod(name string) (*Method, error) {
function parseMethodSignature (line 257) | func parseMethodSignature(name string) (string, *Type, *Type, error) {
type Event (line 295) | type Event struct
method Sig (line 302) | func (e *Event) Sig() string {
method ID (line 307) | func (e *Event) ID() (res ethgo.Hash) {
method Match (line 379) | func (e *Event) Match(log *ethgo.Log) bool {
method ParseLog (line 390) | func (e *Event) ParseLog(log *ethgo.Log) (map[string]interface{}, erro...
function MustNewEvent (line 317) | func MustNewEvent(name string) *Event {
function NewEvent (line 326) | func NewEvent(name string) (*Event, error) {
type Error (line 335) | type Error struct
function NewError (line 341) | func NewError(name string) (*Error, error) {
function parseEventOrErrorSignature (line 349) | func parseEventOrErrorSignature(prefix string, name string) (string, *Ty...
function NewEventFromType (line 374) | func NewEventFromType(name string, typ *Type) *Event {
function buildSignature (line 397) | func buildSignature(name string, typ *Type) string {
type ArgumentStr (line 406) | type ArgumentStr struct
function acquireKeccak (line 420) | func acquireKeccak() hash.Hash {
function releaseKeccak (line 424) | func releaseKeccak(k hash.Hash) {
function NewABIFromList (line 429) | func NewABIFromList(humanReadableAbi []string) (*ABI, error) {
FILE: abi/abi_test.go
function TestAbi (line 11) | func TestAbi(t *testing.T) {
function TestAbi_InternalType (line 115) | func TestAbi_InternalType(t *testing.T) {
function TestAbi_Polymorphism (line 156) | func TestAbi_Polymorphism(t *testing.T) {
function TestAbi_HumanReadable (line 226) | func TestAbi_HumanReadable(t *testing.T) {
function TestAbi_ParseMethodSignature (line 301) | func TestAbi_ParseMethodSignature(t *testing.T) {
FILE: abi/decode.go
function Decode (line 15) | func Decode(t *Type, input []byte) (interface{}, error) {
function DecodeStruct (line 24) | func DecodeStruct(t *Type, input []byte, out interface{}) error {
function decode (line 45) | func decode(t *Type, input []byte) (interface{}, []byte, error) {
function readAddr (line 114) | func readAddr(b []byte) (ethgo.Address, error) {
function readInteger (line 123) | func readInteger(t *Type, b []byte) interface{} {
function readFunctionType (line 164) | func readFunctionType(t *Type, word []byte) ([24]byte, error) {
function readFixedBytes (line 173) | func readFixedBytes(t *Type, word []byte) (interface{}, error) {
function decodeTuple (line 179) | func decodeTuple(t *Type, data []byte) (interface{}, []byte, error) {
function decodeArraySlice (line 222) | func decodeArraySlice(t *Type, data []byte, size int) (interface{}, []by...
function decodeBool (line 270) | func decodeBool(data []byte) (interface{}, error) {
function readOffset (line 281) | func readOffset(data []byte, len int) (int, error) {
function readLength (line 293) | func readLength(data []byte) (int, error) {
function allZeros (line 308) | func allZeros(b []byte) bool {
FILE: abi/decode_test.go
function TestDecode_BytesBound (line 9) | func TestDecode_BytesBound(t *testing.T) {
function TestDecode_DynamicLengthOutOfBounds (line 14) | func TestDecode_DynamicLengthOutOfBounds(t *testing.T) {
FILE: abi/encode.go
function Encode (line 20) | func Encode(v interface{}, t *Type) ([]byte, error) {
function encode (line 24) | func encode(v reflect.Value, t *Type) ([]byte, error) {
function encodeSliceAndArray (line 59) | func encodeSliceAndArray(v reflect.Value, t *Type) ([]byte, error) {
function encodeTuple (line 101) | func encodeTuple(v reflect.Value, t *Type) ([]byte, error) {
function convertArrayToBytes (line 167) | func convertArrayToBytes(value reflect.Value) reflect.Value {
function encodeFixedBytes (line 173) | func encodeFixedBytes(v reflect.Value) ([]byte, error) {
function encodeAddress (line 188) | func encodeAddress(v reflect.Value) ([]byte, error) {
function encodeBytes (line 202) | func encodeBytes(v reflect.Value) ([]byte, error) {
function encodeString (line 217) | func encodeString(v reflect.Value) ([]byte, error) {
function packBytesSlice (line 224) | func packBytesSlice(buf []byte, l int) ([]byte, error) {
function packNum (line 232) | func packNum(offset int) []byte {
function encodeNum (line 237) | func encodeNum(v reflect.Value) ([]byte, error) {
function encodeBool (line 269) | func encodeBool(v reflect.Value) ([]byte, error) {
function encodeErr (line 279) | func encodeErr(v reflect.Value, t string) error {
function mapFromStruct (line 283) | func mapFromStruct(v reflect.Value) (reflect.Value, error) {
function toU256 (line 314) | func toU256(n *big.Int) []byte {
function padBytes (line 325) | func padBytes(b []byte, size int, left bool) []byte {
function leftPad (line 342) | func leftPad(b []byte, size int) []byte {
function rightPad (line 346) | func rightPad(b []byte, size int) []byte {
function encodeHex (line 350) | func encodeHex(b []byte) string {
function decodeHex (line 354) | func decodeHex(str string) ([]byte, error) {
FILE: abi/encoding_test.go
function mustDecodeHex (line 19) | func mustDecodeHex(str string) []byte {
function TestEncoding (line 27) | func TestEncoding(t *testing.T) {
function TestEncodingBestEffort (line 335) | func TestEncodingBestEffort(t *testing.T) {
function TestEncodingArguments (line 503) | func TestEncodingArguments(t *testing.T) {
function testEncodeDecode (line 564) | func testEncodeDecode(t *testing.T, server *testutil.TestServer, tt *Typ...
function generateRandomArgs (line 585) | func generateRandomArgs(n int) *Type {
function TestRandomEncoding (line 603) | func TestRandomEncoding(t *testing.T) {
function testDecodePanic (line 632) | func testDecodePanic(tt *Type, input interface{}) error {
function testTypeWithContract (line 653) | func testTypeWithContract(t *testing.T, server *testutil.TestServer, typ...
function TestEncodingStruct (line 709) | func TestEncodingStruct(t *testing.T) {
function TestEncodingStruct_camcelCase (line 735) | func TestEncodingStruct_camcelCase(t *testing.T) {
FILE: abi/revert.go
function UnpackRevertError (line 10) | func UnpackRevertError(b []byte) (string, error) {
FILE: abi/revert_test.go
function TestUnpackRevertError (line 9) | func TestUnpackRevertError(t *testing.T) {
FILE: abi/testing.go
function randomInt (line 13) | func randomInt(min, max int) int {
function randomNumberBits (line 30) | func randomNumberBits() int {
function randomType (line 34) | func randomType() string {
function pickRandomType (line 38) | func pickRandomType(d int) string {
function generateNumber (line 86) | func generateNumber(t *Type) interface{} {
function generateRandomType (line 101) | func generateRandomType(t *Type) interface{} {
constant hexLetters (line 165) | hexLetters = "0123456789abcdef"
constant letters (line 167) | letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
function randString (line 169) | func randString(n int, dict string) string {
type generateContractImpl (line 177) | type generateContractImpl struct
method run (line 181) | func (g *generateContractImpl) run(t *Type) string {
method getValue (line 217) | func (g *generateContractImpl) getValue(t *Type) string {
FILE: abi/topics.go
function ParseLog (line 12) | func ParseLog(args *Type, log *ethgo.Log) (map[string]interface{}, error) {
function ParseTopics (line 56) | func ParseTopics(args *Type, topics []ethgo.Hash) ([]interface{}, error) {
function ParseTopic (line 77) | func ParseTopic(t *Type, topic ethgo.Hash) (interface{}, error) {
function EncodeTopic (line 102) | func EncodeTopic(t *Type, val interface{}) (ethgo.Hash, error) {
function encodeTopic (line 106) | func encodeTopic(t *Type, val reflect.Value) (ethgo.Hash, error) {
function init (line 123) | func init() {
function encodeTopicAddress (line 127) | func encodeTopicAddress(val reflect.Value) (res ethgo.Hash, err error) {
function encodeTopicNum (line 137) | func encodeTopicNum(t *Type, val reflect.Value) (res ethgo.Hash, err err...
function encodeTopicBool (line 147) | func encodeTopicBool(v reflect.Value) (res ethgo.Hash, err error) {
FILE: abi/topics_test.go
function TestTopicEncoding (line 15) | func TestTopicEncoding(t *testing.T) {
function TestIntegrationTopics (line 56) | func TestIntegrationTopics(t *testing.T) {
FILE: abi/type.go
type Kind (line 34) | type Kind
method String (line 74) | func (k Kind) String() string {
constant KindBool (line 38) | KindBool Kind = iota
constant KindUInt (line 41) | KindUInt
constant KindInt (line 44) | KindInt
constant KindString (line 47) | KindString
constant KindArray (line 50) | KindArray
constant KindSlice (line 53) | KindSlice
constant KindAddress (line 56) | KindAddress
constant KindBytes (line 59) | KindBytes
constant KindFixedBytes (line 62) | KindFixedBytes
constant KindFixedPoint (line 65) | KindFixedPoint
constant KindTuple (line 68) | KindTuple
constant KindFunction (line 71) | KindFunction
type TupleElem (line 94) | type TupleElem struct
type Type (line 101) | type Type struct
method ParseLog (line 135) | func (t *Type) ParseLog(log *ethgo.Log) (map[string]interface{}, error) {
method Decode (line 140) | func (t *Type) Decode(input []byte) (interface{}, error) {
method DecodeStruct (line 145) | func (t *Type) DecodeStruct(input []byte, out interface{}) error {
method InternalType (line 150) | func (t *Type) InternalType() string {
method Encode (line 155) | func (t *Type) Encode(v interface{}) ([]byte, error) {
method String (line 159) | func (t *Type) String() string {
method Format (line 164) | func (t *Type) Format(includeArgs bool) string {
method Elem (line 218) | func (t *Type) Elem() *Type {
method Size (line 223) | func (t *Type) Size() int {
method TupleElems (line 228) | func (t *Type) TupleElems() []*TupleElem {
method GoType (line 233) | func (t *Type) GoType() reflect.Type {
method Kind (line 238) | func (t *Type) Kind() Kind {
method isVariableInput (line 242) | func (t *Type) isVariableInput() bool {
method isDynamicType (line 246) | func (t *Type) isDynamicType() bool {
function NewTupleType (line 110) | func NewTupleType(inputs []*TupleElem) *Type {
function NewTupleTypeFromArgs (line 118) | func NewTupleTypeFromArgs(inputs []*ArgumentStr) (*Type, error) {
function parseType (line 258) | func parseType(arg *ArgumentStr) (string, error) {
function NewTypeFromArgument (line 284) | func NewTypeFromArgument(arg *ArgumentStr) (*Type, error) {
function fillIn (line 300) | func fillIn(typ *Type, arg *ArgumentStr) error {
function NewType (line 336) | func NewType(s string) (*Type, error) {
function MustNewType (line 344) | func MustNewType(s string) *Type {
function getTypeSize (line 352) | func getTypeSize(t *Type) int {
function expectedToken (line 370) | func expectedToken(t tokenType) error {
function notExpectedToken (line 374) | func notExpectedToken(t tokenType) error {
function readType (line 378) | func readType(l *lexer) (*Type, error) {
function decodeSimpleType (line 484) | func decodeSimpleType(str string) (*Type, error) {
type tokenType (line 581) | type tokenType
method String (line 597) | func (t tokenType) String() string {
constant eofToken (line 584) | eofToken tokenType = iota
constant strToken (line 585) | strToken
constant numberToken (line 586) | numberToken
constant tupleToken (line 587) | tupleToken
constant lparenToken (line 588) | lparenToken
constant rparenToken (line 589) | rparenToken
constant lbracketToken (line 590) | lbracketToken
constant rbracketToken (line 591) | rbracketToken
constant commaToken (line 592) | commaToken
constant indexedToken (line 593) | indexedToken
constant invalidToken (line 594) | invalidToken
type token (line 614) | type token struct
type lexer (line 619) | type lexer struct
method readChar (line 634) | func (l *lexer) readChar() {
method nextToken (line 645) | func (l *lexer) nextToken() token {
method nextTokenImpl (line 651) | func (l *lexer) nextTokenImpl() token {
method readIdentifier (line 695) | func (l *lexer) readIdentifier() string {
method readNumber (line 704) | func (l *lexer) readNumber() string {
function newLexer (line 628) | func newLexer(input string) *lexer {
function isDigit (line 712) | func isDigit(ch byte) bool {
function isLetter (line 716) | func isLetter(ch byte) bool {
FILE: abi/type_test.go
function TestType (line 11) | func TestType(t *testing.T) {
function TestTypeArgument_InternalFields (line 367) | func TestTypeArgument_InternalFields(t *testing.T) {
function TestSize (line 391) | func TestSize(t *testing.T) {
function simpleType (line 435) | func simpleType(s string) *ArgumentStr {
FILE: blocktracker/blocktracker.go
type BlockProvider (line 14) | type BlockProvider interface
constant defaultMaxBlockBacklog (line 20) | defaultMaxBlockBacklog = 10
type BlockTracker (line 24) | type BlockTracker struct
method Subscribe (line 80) | func (b *BlockTracker) Subscribe() chan *BlockEvent {
method AcquireLock (line 89) | func (b *BlockTracker) AcquireLock() Lock {
method Init (line 93) | func (t *BlockTracker) Init() (err error) {
method MaxBlockBacklog (line 132) | func (b *BlockTracker) MaxBlockBacklog() uint64 {
method LastBlocked (line 136) | func (b *BlockTracker) LastBlocked() *ethgo.Block {
method BlocksBlocked (line 144) | func (b *BlockTracker) BlocksBlocked() []*ethgo.Block {
method Len (line 152) | func (b *BlockTracker) Len() int {
method Close (line 156) | func (b *BlockTracker) Close() error {
method Start (line 161) | func (b *BlockTracker) Start() error {
method AddBlockLocked (line 177) | func (t *BlockTracker) AddBlockLocked(block *ethgo.Block) error {
method blockAtIndex (line 192) | func (t *BlockTracker) blockAtIndex(hash ethgo.Hash) int {
method handleReconcileImpl (line 201) | func (t *BlockTracker) handleReconcileImpl(block *ethgo.Block) ([]*eth...
method HandleBlockEvent (line 258) | func (t *BlockTracker) HandleBlockEvent(block *ethgo.Block) (*BlockEve...
method HandleReconcile (line 290) | func (t *BlockTracker) HandleReconcile(block *ethgo.Block) error {
type Config (line 36) | type Config struct
function DefaultConfig (line 41) | func DefaultConfig() *Config {
type ConfigOption (line 47) | type ConfigOption
function WithBlockMaxBacklog (line 49) | func WithBlockMaxBacklog(b uint64) ConfigOption {
function WithTracker (line 55) | func WithTracker(b BlockTrackerInterface) ConfigOption {
function NewBlockTracker (line 61) | func NewBlockTracker(provider BlockProvider, opts ...ConfigOption) *Bloc...
type BlockTrackerInterface (line 311) | type BlockTrackerInterface interface
constant defaultPollInterval (line 316) | defaultPollInterval = 1 * time.Second
type JSONBlockTracker (line 321) | type JSONBlockTracker struct
method Track (line 336) | func (k *JSONBlockTracker) Track(ctx context.Context, handle func(bloc...
function NewJSONBlockTracker (line 327) | func NewJSONBlockTracker(provider BlockProvider) *JSONBlockTracker {
type SubscriptionBlockTracker (line 364) | type SubscriptionBlockTracker struct
method Track (line 382) | func (s *SubscriptionBlockTracker) Track(ctx context.Context, handle f...
function NewSubscriptionBlockTracker (line 369) | func NewSubscriptionBlockTracker(client *jsonrpc.Client) (*SubscriptionB...
type Lock (line 423) | type Lock struct
method Lock (line 432) | func (l *Lock) Lock() {
method Unlock (line 437) | func (l *Lock) Unlock() {
function NewLock (line 428) | func NewLock(lock *sync.Mutex) Lock {
type EventType (line 443) | type EventType
constant EventAdd (line 447) | EventAdd EventType = iota
constant EventDel (line 449) | EventDel
type Event (line 453) | type Event struct
type BlockEvent (line 460) | type BlockEvent struct
FILE: blocktracker/blocktracker_test.go
function testListener (line 14) | func testListener(t *testing.T, server *testutil.TestServer, tracker Blo...
function TestBlockTracker_Listener_JsonRPC (line 53) | func TestBlockTracker_Listener_JsonRPC(t *testing.T) {
function TestBlockTracker_Listener_Websocket (line 66) | func TestBlockTracker_Listener_Websocket(t *testing.T) {
function TestBlockTracker_Lifecycle (line 81) | func TestBlockTracker_Lifecycle(t *testing.T) {
function TestBlockTracker_PopulateBlocks (line 109) | func TestBlockTracker_PopulateBlocks(t *testing.T) {
function TestBlockTracker_Events (line 149) | func TestBlockTracker_Events(t *testing.T) {
FILE: builtin/ens/ens.go
type ENS (line 21) | type ENS struct
method Owner (line 38) | func (e *ENS) Owner(node [32]byte, block ...ethgo.BlockNumber) (retval...
method Resolver (line 58) | func (e *ENS) Resolver(node [32]byte, block ...ethgo.BlockNumber) (ret...
method Ttl (line 78) | func (e *ENS) Ttl(node [32]byte, block ...ethgo.BlockNumber) (retval0 ...
method SetOwner (line 100) | func (e *ENS) SetOwner(node [32]byte, owner ethgo.Address) (contract.T...
method SetResolver (line 105) | func (e *ENS) SetResolver(node [32]byte, resolver ethgo.Address) (cont...
method SetSubnodeOwner (line 110) | func (e *ENS) SetSubnodeOwner(node [32]byte, label [32]byte, owner eth...
method SetTTL (line 115) | func (e *ENS) SetTTL(node [32]byte, ttl uint64) (contract.Txn, error) {
method NewOwnerEventSig (line 121) | func (e *ENS) NewOwnerEventSig() ethgo.Hash {
method NewResolverEventSig (line 125) | func (e *ENS) NewResolverEventSig() ethgo.Hash {
method NewTTLEventSig (line 129) | func (e *ENS) NewTTLEventSig() ethgo.Hash {
method TransferEventSig (line 133) | func (e *ENS) TransferEventSig() ethgo.Hash {
function DeployENS (line 26) | func DeployENS(provider *jsonrpc.Client, from ethgo.Address, args []inte...
function NewENS (line 31) | func NewENS(addr ethgo.Address, opts ...contract.ContractOption) *ENS {
FILE: builtin/ens/ens_artifacts.go
function ENSAbi (line 13) | func ENSAbi() *abi.ABI {
function ENSBin (line 20) | func ENSBin() []byte {
function init (line 24) | func init() {
FILE: builtin/ens/ens_resolver.go
type ENSResolver (line 10) | type ENSResolver struct
method Resolve (line 19) | func (e *ENSResolver) Resolve(addr string, block ...ethgo.BlockNumber)...
method ReverseResolve (line 33) | func (e *ENSResolver) ReverseResolve(addr ethgo.Address, block ...ethg...
method prepareResolver (line 44) | func (e *ENSResolver) prepareResolver(inputHash ethgo.Hash, block ...e...
function NewENSResolver (line 15) | func NewENSResolver(addr ethgo.Address, provider *jsonrpc.Client) *ENSRe...
function addressToReverseDomain (line 29) | func addressToReverseDomain(addr ethgo.Address) string {
FILE: builtin/ens/ens_resolver_test.go
function TestResolveAddr (line 17) | func TestResolveAddr(t *testing.T) {
FILE: builtin/ens/resolver.go
type Resolver (line 21) | type Resolver struct
method ABI (line 38) | func (r *Resolver) ABI(node [32]byte, contentTypes *big.Int, block ......
method Addr (line 63) | func (r *Resolver) Addr(node [32]byte, block ...ethgo.BlockNumber) (re...
method Content (line 83) | func (r *Resolver) Content(node [32]byte, block ...ethgo.BlockNumber) ...
method Name (line 103) | func (r *Resolver) Name(node [32]byte, block ...ethgo.BlockNumber) (re...
method Pubkey (line 123) | func (r *Resolver) Pubkey(node [32]byte, block ...ethgo.BlockNumber) (...
method SupportsInterface (line 148) | func (r *Resolver) SupportsInterface(interfaceID [4]byte, block ...eth...
method SetABI (line 170) | func (r *Resolver) SetABI(node [32]byte, contentType *big.Int, data []...
method SetAddr (line 175) | func (r *Resolver) SetAddr(node [32]byte, addr ethgo.Address) (contrac...
method SetContent (line 180) | func (r *Resolver) SetContent(node [32]byte, hash [32]byte) (contract....
method SetName (line 185) | func (r *Resolver) SetName(node [32]byte, name string) (contract.Txn, ...
method SetPubkey (line 190) | func (r *Resolver) SetPubkey(node [32]byte, x [32]byte, y [32]byte) (c...
method ABIChangedEventSig (line 196) | func (r *Resolver) ABIChangedEventSig() ethgo.Hash {
method AddrChangedEventSig (line 200) | func (r *Resolver) AddrChangedEventSig() ethgo.Hash {
method ContentChangedEventSig (line 204) | func (r *Resolver) ContentChangedEventSig() ethgo.Hash {
method NameChangedEventSig (line 208) | func (r *Resolver) NameChangedEventSig() ethgo.Hash {
method PubkeyChangedEventSig (line 212) | func (r *Resolver) PubkeyChangedEventSig() ethgo.Hash {
function DeployResolver (line 26) | func DeployResolver(provider *jsonrpc.Client, from ethgo.Address, args [...
function NewResolver (line 31) | func NewResolver(addr ethgo.Address, opts ...contract.ContractOption) *R...
FILE: builtin/ens/resolver_artifacts.go
function ResolverAbi (line 13) | func ResolverAbi() *abi.ABI {
function ResolverBin (line 20) | func ResolverBin() []byte {
function init (line 24) | func init() {
FILE: builtin/ens/utils.go
function NameHash (line 11) | func NameHash(str string) (node ethgo.Hash) {
FILE: builtin/ens/utils_test.go
function TestNameHash (line 9) | func TestNameHash(t *testing.T) {
FILE: builtin/erc20/erc20.go
type ERC20 (line 21) | type ERC20 struct
method Allowance (line 33) | func (e *ERC20) Allowance(owner ethgo.Address, spender ethgo.Address, ...
method BalanceOf (line 53) | func (e *ERC20) BalanceOf(owner ethgo.Address, block ...ethgo.BlockNum...
method Decimals (line 73) | func (e *ERC20) Decimals(block ...ethgo.BlockNumber) (retval0 uint8, e...
method Name (line 93) | func (e *ERC20) Name(block ...ethgo.BlockNumber) (retval0 string, err ...
method Symbol (line 113) | func (e *ERC20) Symbol(block ...ethgo.BlockNumber) (retval0 string, er...
method TotalSupply (line 133) | func (e *ERC20) TotalSupply(block ...ethgo.BlockNumber) (retval0 *big....
method Approve (line 155) | func (e *ERC20) Approve(spender ethgo.Address, value *big.Int) (contra...
method Transfer (line 160) | func (e *ERC20) Transfer(to ethgo.Address, value *big.Int) (contract.T...
method TransferFrom (line 165) | func (e *ERC20) TransferFrom(from ethgo.Address, to ethgo.Address, val...
method ApprovalEventSig (line 171) | func (e *ERC20) ApprovalEventSig() ethgo.Hash {
method TransferEventSig (line 175) | func (e *ERC20) TransferEventSig() ethgo.Hash {
function NewERC20 (line 26) | func NewERC20(addr ethgo.Address, opts ...contract.ContractOption) *ERC20 {
FILE: builtin/erc20/erc20_artifacts.go
function ERC20Abi (line 13) | func ERC20Abi() *abi.ABI {
function init (line 19) | func init() {
FILE: builtin/erc20/erc20_test.go
function TestERC20Decimals (line 17) | func TestERC20Decimals(t *testing.T) {
function TestERC20Name (line 28) | func TestERC20Name(t *testing.T) {
function TestERC20Symbol (line 37) | func TestERC20Symbol(t *testing.T) {
function TestTotalSupply (line 46) | func TestTotalSupply(t *testing.T) {
FILE: cmd/abigen/abigen.go
function Parse (line 17) | func Parse(sources string, pckg string, output string) error {
constant solExt (line 58) | solExt = 1
constant abiExt (line 59) | abiExt = 2
constant jsonExt (line 60) | jsonExt = 3
function process (line 63) | func process(sources string, config *config) (map[string]*compiler.Artif...
function processSolc (line 102) | func processSolc(sources []string) (map[string]*compiler.Artifact, error) {
function processAbi (line 116) | func processAbi(sources []string, config *config) (map[string]*compiler....
type JSONArtifact (line 144) | type JSONArtifact struct
function processJson (line 149) | func processJson(sources []string) (map[string]*compiler.Artifact, error) {
FILE: cmd/abigen/gen.go
type config (line 17) | type config struct
function cleanName (line 22) | func cleanName(str string) string {
function outputArg (line 26) | func outputArg(str string) string {
function handleSnakeCase (line 30) | func handleSnakeCase(str string) string {
function funcName (line 46) | func funcName(str string) string {
function encodeSimpleArg (line 50) | func encodeSimpleArg(typ *abi.Type) string {
function encodeArg (line 81) | func encodeArg(str interface{}) string {
function tupleLen (line 89) | func tupleLen(tuple interface{}) interface{} {
function tupleElems (line 100) | func tupleElems(tuple interface{}) []interface{} {
function isNil (line 116) | func isNil(c interface{}) bool {
function gen (line 120) | func gen(artifacts map[string]*compiler.Artifact, config *config, hash s...
FILE: cmd/abigen/testdata/testdata.go
type Testdata (line 21) | type Testdata struct
method CallBasicInput (line 33) | func (t *Testdata) CallBasicInput(block ...ethgo.BlockNumber) (retval0...
method TxnBasicInput (line 60) | func (t *Testdata) TxnBasicInput(val1 ethgo.Address, val2 *big.Int) (c...
method EventBasicEventSig (line 66) | func (t *Testdata) EventBasicEventSig() ethgo.Hash {
function NewTestdata (line 26) | func NewTestdata(addr ethgo.Address, opts ...contract.ContractOption) *T...
FILE: cmd/abigen/testdata/testdata_artifacts.go
function TestdataAbi (line 13) | func TestdataAbi() *abi.ABI {
function init (line 19) | func init() {
FILE: cmd/commands/4byte.go
type FourByteCommand (line 9) | type FourByteCommand struct
method Help (line 14) | func (c *FourByteCommand) Help() string {
method Synopsis (line 21) | func (c *FourByteCommand) Synopsis() string {
method Run (line 26) | func (c *FourByteCommand) Run(args []string) int {
FILE: cmd/commands/abigen.go
type AbigenCommand (line 9) | type AbigenCommand struct
method Help (line 18) | func (c *AbigenCommand) Help() string {
method Synopsis (line 26) | func (c *AbigenCommand) Synopsis() string {
method Flags (line 30) | func (c *AbigenCommand) Flags() *flag.FlagSet {
method Run (line 41) | func (c *AbigenCommand) Run(args []string) int {
FILE: cmd/commands/commands.go
function Commands (line 10) | func Commands() map[string]cli.CommandFactory {
type baseCommand (line 50) | type baseCommand struct
method Flags (line 54) | func (b *baseCommand) Flags(name string) *flag.FlagSet {
FILE: cmd/commands/ens.go
type EnsCommand (line 8) | type EnsCommand struct
method Help (line 13) | func (c *EnsCommand) Help() string {
method Synopsis (line 20) | func (c *EnsCommand) Synopsis() string {
method Run (line 25) | func (c *EnsCommand) Run(args []string) int {
FILE: cmd/commands/ens_resolve.go
function defaultJsonRPCProvider (line 11) | func defaultJsonRPCProvider() string {
type EnsResolveCommand (line 19) | type EnsResolveCommand struct
method Help (line 26) | func (c *EnsResolveCommand) Help() string {
method Synopsis (line 34) | func (c *EnsResolveCommand) Synopsis() string {
method Flags (line 38) | func (c *EnsResolveCommand) Flags() *flag.FlagSet {
method Run (line 46) | func (c *EnsResolveCommand) Run(args []string) int {
FILE: cmd/commands/version.go
type VersionCommand (line 9) | type VersionCommand struct
method Help (line 14) | func (c *VersionCommand) Help() string {
method Synopsis (line 21) | func (c *VersionCommand) Synopsis() string {
method Run (line 26) | func (c *VersionCommand) Run(args []string) int {
FILE: cmd/main.go
function main (line 11) | func main() {
function Run (line 16) | func Run(args []string) int {
FILE: cmd/version/version.go
function GetVersion (line 17) | func GetVersion() string {
FILE: compiler/solidity.go
type Output (line 16) | type Output struct
type Source (line 22) | type Source struct
type Artifact (line 26) | type Artifact struct
type Solidity (line 35) | type Solidity struct
method CompileCode (line 45) | func (s *Solidity) CompileCode(code string) (*Output, error) {
method Compile (line 57) | func (s *Solidity) Compile(files ...string) (*Output, error) {
method compileImpl (line 64) | func (s *Solidity) compileImpl(code string, files ...string) (*Output,...
function NewSolidityCompiler (line 40) | func NewSolidityCompiler(path string) *Solidity {
function DownloadSolidity (line 97) | func DownloadSolidity(version string, dst string, renameDst bool) error {
FILE: compiler/solidity_test.go
function init (line 21) | func init() {
function TestSolidityInline (line 36) | func TestSolidityInline(t *testing.T) {
function TestSolidity (line 92) | func TestSolidity(t *testing.T) {
function existsSolidity (line 108) | func existsSolidity(t *testing.T, path string) bool {
function TestDownloadSolidityCompiler (line 130) | func TestDownloadSolidityCompiler(t *testing.T) {
FILE: contract/contract.go
type Provider (line 15) | type Provider interface
type jsonRPCNodeProvider (line 20) | type jsonRPCNodeProvider struct
method Call (line 25) | func (j *jsonRPCNodeProvider) Call(addr ethgo.Address, input []byte, o...
method Txn (line 44) | func (j *jsonRPCNodeProvider) Txn(addr ethgo.Address, key ethgo.Key, i...
type jsonrpcTransaction (line 56) | type jsonrpcTransaction struct
method Hash (line 68) | func (j *jsonrpcTransaction) Hash() ethgo.Hash {
method WithOpts (line 72) | func (j *jsonrpcTransaction) WithOpts(opts *TxnOpts) {
method Build (line 76) | func (j *jsonrpcTransaction) Build() error {
method Do (line 147) | func (j *jsonrpcTransaction) Do() error {
method Wait (line 173) | func (j *jsonrpcTransaction) Wait() (*ethgo.Receipt, error) {
type Txn (line 192) | type Txn interface
type Opts (line 199) | type Opts struct
type ContractOption (line 207) | type ContractOption
function WithJsonRPCEndpoint (line 209) | func WithJsonRPCEndpoint(endpoint string) ContractOption {
function WithJsonRPC (line 215) | func WithJsonRPC(client *jsonrpc.Eth) ContractOption {
function WithProvider (line 221) | func WithProvider(provider Provider) ContractOption {
function WithSender (line 227) | func WithSender(sender ethgo.Key) ContractOption {
function WithEIP1559 (line 233) | func WithEIP1559() ContractOption {
function DeployContract (line 239) | func DeployContract(abi *abi.ABI, bin []byte, args []interface{}, opts ....
function NewContract (line 245) | func NewContract(addr ethgo.Address, abi *abi.ABI, opts ...ContractOptio...
type Contract (line 274) | type Contract struct
method GetABI (line 282) | func (a *Contract) GetABI() *abi.ABI {
method Txn (line 293) | func (a *Contract) Txn(method string, args ...interface{}) (Txn, error) {
method Call (line 339) | func (a *Contract) Call(method string, block ethgo.BlockNumber, args ....
type TxnOpts (line 286) | type TxnOpts struct
type CallOpts (line 334) | type CallOpts struct
FILE: contract/contract_test.go
function TestContract_NoInput (line 22) | func TestContract_NoInput(t *testing.T) {
function TestContract_IO (line 52) | func TestContract_IO(t *testing.T) {
function TestContract_From (line 73) | func TestContract_From(t *testing.T) {
function TestContract_Deploy (line 97) | func TestContract_Deploy(t *testing.T) {
function TestContract_Transaction (line 135) | func TestContract_Transaction(t *testing.T) {
function TestContract_CallAtBlock (line 168) | func TestContract_CallAtBlock(t *testing.T) {
function TestContract_SendValueContractCall (line 227) | func TestContract_SendValueContractCall(t *testing.T) {
function TestContract_EIP1559 (line 266) | func TestContract_EIP1559(t *testing.T) {
FILE: e2e/transaction_test.go
function TestSendSignedTransaction (line 14) | func TestSendSignedTransaction(t *testing.T) {
FILE: encoding.go
type ArgBig (line 10) | type ArgBig
method UnmarshalText (line 12) | func (a *ArgBig) UnmarshalText(input []byte) error {
method MarshalText (line 23) | func (a ArgBig) MarshalText() ([]byte, error) {
type ArgUint64 (line 28) | type ArgUint64
method MarshalText (line 30) | func (b ArgUint64) MarshalText() ([]byte, error) {
method UnmarshalText (line 37) | func (u *ArgUint64) UnmarshalText(input []byte) error {
method Uint64 (line 50) | func (u *ArgUint64) Uint64() uint64 {
type ArgBytes (line 54) | type ArgBytes
method MarshalText (line 56) | func (b ArgBytes) MarshalText() ([]byte, error) {
method UnmarshalText (line 60) | func (b *ArgBytes) UnmarshalText(input []byte) error {
method Bytes (line 71) | func (b *ArgBytes) Bytes() []byte {
function decodeToHex (line 75) | func decodeToHex(b []byte) ([]byte, error) {
function encodeToHex (line 84) | func encodeToHex(b []byte) []byte {
FILE: ens/ens.go
type EnsConfig (line 12) | type EnsConfig struct
type EnsOption (line 19) | type EnsOption
function WithResolver (line 21) | func WithResolver(resolver ethgo.Address) EnsOption {
function WithLogger (line 27) | func WithLogger(logger *log.Logger) EnsOption {
function WithAddress (line 33) | func WithAddress(addr string) EnsOption {
function WithClient (line 39) | func WithClient(client *jsonrpc.Client) EnsOption {
type ENS (line 45) | type ENS struct
method Resolve (line 85) | func (e *ENS) Resolve(name string) (ethgo.Address, error) {
method ReverseResolve (line 90) | func (e *ENS) ReverseResolve(addr ethgo.Address) (string, error) {
function NewENS (line 49) | func NewENS(opts ...EnsOption) (*ENS, error) {
FILE: ens/ens_test.go
function TestENS_Resolve (line 11) | func TestENS_Resolve(t *testing.T) {
FILE: etherscan/etherscan.go
type Etherscan (line 15) | type Etherscan struct
method Query (line 55) | func (e *Etherscan) Query(module, action string, out interface{}, para...
method BlockNumber (line 108) | func (e *Etherscan) BlockNumber() (uint64, error) {
method GetBlockByNumber (line 117) | func (e *Etherscan) GetBlockByNumber(i ethgo.BlockNumber, full bool) (...
method GetContractCode (line 137) | func (e *Etherscan) GetContractCode(addr ethgo.Address) (*ContractCode...
method GasPrice (line 151) | func (e *Etherscan) GasPrice() (uint64, error) {
method GetLogs (line 165) | func (e *Etherscan) GetLogs(filter *ethgo.LogFilter) ([]*ethgo.Log, er...
function NewEtherscanFromNetwork (line 22) | func NewEtherscanFromNetwork(n ethgo.Network, apiKey string) (*Etherscan...
function NewEtherscan (line 44) | func NewEtherscan(url, apiKey string) *Etherscan {
type proxyResponse (line 48) | type proxyResponse struct
type ContractCode (line 129) | type ContractCode struct
function parseUint64orHex (line 200) | func parseUint64orHex(str string) (uint64, error) {
FILE: etherscan/etherscan_test.go
function testEtherscanMainnet (line 11) | func testEtherscanMainnet(t *testing.T) *Etherscan {
function TestNewEtherscan (line 19) | func TestNewEtherscan(t *testing.T) {
function TestBlockByNumber (line 27) | func TestBlockByNumber(t *testing.T) {
function TestGetBlockByNumber (line 34) | func TestGetBlockByNumber(t *testing.T) {
function TestContract (line 41) | func TestContract(t *testing.T) {
function TestGetLogs (line 50) | func TestGetLogs(t *testing.T) {
function TestGasPrice (line 68) | func TestGasPrice(t *testing.T) {
FILE: examples/contract-call-basic.go
function handleErr (line 13) | func handleErr(err error) {
function contractCall (line 20) | func contractCall() {
FILE: examples/contract-call-from.go
function contractCallFrom (line 14) | func contractCallFrom() {
FILE: examples/contract-deploy.go
function contractDeploy (line 10) | func contractDeploy() {
FILE: examples/contract-transaction.go
function contractTransaction (line 13) | func contractTransaction() {
FILE: jsonrpc/client.go
type Client (line 8) | type Client struct
method Close (line 55) | func (c *Client) Close() error {
method Call (line 60) | func (c *Client) Call(method string, out interface{}, params ...interf...
method SetMaxConnsLimit (line 65) | func (c *Client) SetMaxConnsLimit(count int) {
type endpoints (line 13) | type endpoints struct
type Config (line 20) | type Config struct
type ConfigOption (line 24) | type ConfigOption
function WithHeaders (line 26) | func WithHeaders(headers map[string]string) ConfigOption {
function NewClient (line 34) | func NewClient(addr string, opts ...ConfigOption) (*Client, error) {
FILE: jsonrpc/codec/codec.go
type Request (line 9) | type Request struct
type Response (line 17) | type Response struct
type ErrorObject (line 24) | type ErrorObject struct
method Error (line 37) | func (e *ErrorObject) Error() string {
type Subscription (line 31) | type Subscription struct
FILE: jsonrpc/debug.go
type Debug (line 5) | type Debug struct
method TraceTransaction (line 41) | func (d *Debug) TraceTransaction(hash ethgo.Hash, opts TraceTransactio...
method Debug (line 10) | func (c *Client) Debug() *Debug {
type TraceTransactionOptions (line 14) | type TraceTransactionOptions struct
type TransactionTrace (line 24) | type TransactionTrace struct
type StructLogs (line 30) | type StructLogs struct
FILE: jsonrpc/debug_test.go
function TestDebug_TraceTransaction (line 11) | func TestDebug_TraceTransaction(t *testing.T) {
FILE: jsonrpc/eth.go
type Eth (line 13) | type Eth struct
method GetCode (line 23) | func (e *Eth) GetCode(addr ethgo.Address, block ethgo.BlockNumberOrHas...
method Accounts (line 32) | func (e *Eth) Accounts() ([]ethgo.Address, error) {
method GetStorageAt (line 41) | func (e *Eth) GetStorageAt(addr ethgo.Address, slot ethgo.Hash, block ...
method BlockNumber (line 48) | func (e *Eth) BlockNumber() (uint64, error) {
method GetBlockByNumber (line 57) | func (e *Eth) GetBlockByNumber(i ethgo.BlockNumber, full bool) (*ethgo...
method GetBlockByHash (line 66) | func (e *Eth) GetBlockByHash(hash ethgo.Hash, full bool) (*ethgo.Block...
method GetFilterChanges (line 75) | func (e *Eth) GetFilterChanges(id string) ([]*ethgo.Log, error) {
method GetTransactionByHash (line 84) | func (e *Eth) GetTransactionByHash(hash ethgo.Hash) (*ethgo.Transactio...
method GetFilterChangesBlock (line 91) | func (e *Eth) GetFilterChangesBlock(id string) ([]ethgo.Hash, error) {
method NewFilter (line 100) | func (e *Eth) NewFilter(filter *ethgo.LogFilter) (string, error) {
method NewBlockFilter (line 107) | func (e *Eth) NewBlockFilter() (string, error) {
method UninstallFilter (line 114) | func (e *Eth) UninstallFilter(id string) (bool, error) {
method SendRawTransaction (line 121) | func (e *Eth) SendRawTransaction(data []byte) (ethgo.Hash, error) {
method SendTransaction (line 129) | func (e *Eth) SendTransaction(txn *ethgo.Transaction) (ethgo.Hash, err...
method GetTransactionReceipt (line 136) | func (e *Eth) GetTransactionReceipt(hash ethgo.Hash) (*ethgo.Receipt, ...
method GetNonce (line 143) | func (e *Eth) GetNonce(addr ethgo.Address, blockNumber ethgo.BlockNumb...
method GetBalance (line 152) | func (e *Eth) GetBalance(addr ethgo.Address, blockNumber ethgo.BlockNu...
method GasPrice (line 165) | func (e *Eth) GasPrice() (uint64, error) {
method Call (line 174) | func (e *Eth) Call(msg *ethgo.CallMsg, block ethgo.BlockNumber, overri...
method EstimateGasContract (line 189) | func (e *Eth) EstimateGasContract(bin []byte) (uint64, error) {
method EstimateGas (line 201) | func (e *Eth) EstimateGas(msg *ethgo.CallMsg) (uint64, error) {
method GetLogs (line 210) | func (e *Eth) GetLogs(filter *ethgo.LogFilter) ([]*ethgo.Log, error) {
method ChainID (line 219) | func (e *Eth) ChainID() (*big.Int, error) {
method FeeHistory (line 269) | func (e *Eth) FeeHistory(blockCount uint64, newestBlock ethgo.BlockNum...
method MaxPriorityFeePerGas (line 279) | func (e *Eth) MaxPriorityFeePerGas() (*big.Int, error) {
method Eth (line 18) | func (c *Client) Eth() *Eth {
type FeeHistory (line 228) | type FeeHistory struct
method UnmarshalJSON (line 235) | func (f *FeeHistory) UnmarshalJSON(data []byte) error {
FILE: jsonrpc/eth_test.go
function TestEthAccounts (line 22) | func TestEthAccounts(t *testing.T) {
function TestEthBlockNumber (line 32) | func TestEthBlockNumber(t *testing.T) {
function TestEthGetCode (line 53) | func TestEthGetCode(t *testing.T) {
function TestEthGetBalance (line 78) | func TestEthGetBalance(t *testing.T) {
function TestEthGetBlockByNumber (line 92) | func TestEthGetBlockByNumber(t *testing.T) {
function TestEthGetBlockByHash (line 111) | func TestEthGetBlockByHash(t *testing.T) {
function TestEthGasPrice (line 128) | func TestEthGasPrice(t *testing.T) {
function TestEthSendTransaction (line 138) | func TestEthSendTransaction(t *testing.T) {
function TestEthEstimateGas (line 165) | func TestEthEstimateGas(t *testing.T) {
function TestEthGetLogs (line 199) | func TestEthGetLogs(t *testing.T) {
function TestEthChainID (line 238) | func TestEthChainID(t *testing.T) {
function TestEthCall (line 249) | func TestEthCall(t *testing.T) {
function TestEthGetNonce (line 297) | func TestEthGetNonce(t *testing.T) {
function TestEthTransactionsInBlock (line 318) | func TestEthTransactionsInBlock(t *testing.T) {
function TestEthGetStorageAt (line 354) | func TestEthGetStorageAt(t *testing.T) {
function TestEthFeeHistory (line 391) | func TestEthFeeHistory(t *testing.T) {
function TestEthMaxPriorityFeePerGas (line 402) | func TestEthMaxPriorityFeePerGas(t *testing.T) {
FILE: jsonrpc/net.go
type Net (line 4) | type Net struct
method Version (line 14) | func (n *Net) Version() (uint64, error) {
method Listening (line 23) | func (n *Net) Listening() (bool, error) {
method PeerCount (line 30) | func (n *Net) PeerCount() (uint64, error) {
method Net (line 9) | func (c *Client) Net() *Net {
FILE: jsonrpc/net_test.go
function TestNetVersion (line 10) | func TestNetVersion(t *testing.T) {
function TestNetListening (line 20) | func TestNetListening(t *testing.T) {
function TestNetPeerCount (line 31) | func TestNetPeerCount(t *testing.T) {
FILE: jsonrpc/subscribe.go
method SubscriptionEnabled (line 10) | func (c *Client) SubscriptionEnabled() bool {
method Subscribe (line 16) | func (c *Client) Subscribe(method string, callback func(b []byte)) (func...
FILE: jsonrpc/subscribe_test.go
function TestSubscribeNewHead (line 13) | func TestSubscribeNewHead(t *testing.T) {
FILE: jsonrpc/transport/http.go
type HTTP (line 12) | type HTTP struct
method Close (line 29) | func (h *HTTP) Close() error {
method Call (line 34) | func (h *HTTP) Call(method string, out interface{}, params ...interfac...
method SetMaxConnsPerHost (line 92) | func (h *HTTP) SetMaxConnsPerHost(count int) {
function newHTTP (line 18) | func newHTTP(addr string, headers map[string]string) *HTTP {
FILE: jsonrpc/transport/ipc.go
function newIPC (line 8) | func newIPC(addr string) (Transport, error) {
type ipcCodec (line 23) | type ipcCodec struct
method Close (line 29) | func (i *ipcCodec) Close() error {
method Read (line 33) | func (i *ipcCodec) Read(b []byte) ([]byte, error) {
method Write (line 42) | func (i *ipcCodec) Write(b []byte) error {
FILE: jsonrpc/transport/transport.go
type Transport (line 9) | type Transport interface
type PubSubTransport (line 21) | type PubSubTransport interface
constant wsPrefix (line 27) | wsPrefix = "ws://"
constant wssPrefix (line 28) | wssPrefix = "wss://"
function NewTransport (line 32) | func NewTransport(url string, headers map[string]string) (Transport, err...
FILE: jsonrpc/transport/websocket.go
function newWebsocket (line 15) | func newWebsocket(url string, headers map[string]string) (Transport, err...
type ackMessage (line 33) | type ackMessage struct
type callback (line 38) | type callback
type stream (line 40) | type stream struct
method Close (line 69) | func (s *stream) Close() error {
method incSeq (line 74) | func (s *stream) incSeq() uint64 {
method isClosed (line 78) | func (s *stream) isClosed() bool {
method listen (line 87) | func (s *stream) listen() {
method handleSubscription (line 121) | func (s *stream) handleSubscription(response codec.Request) {
method handleMsg (line 139) | func (s *stream) handleMsg(response codec.Response) {
method setHandler (line 158) | func (s *stream) setHandler(id uint64, ack chan *ackMessage) {
method Call (line 183) | func (s *stream) Call(method string, out interface{}, params ...interf...
method unsubscribe (line 219) | func (s *stream) unsubscribe(id string) error {
method setSubscription (line 238) | func (s *stream) setSubscription(id string, callback func(b []byte)) {
method Subscribe (line 246) | func (s *stream) Subscribe(method string, callback func(b []byte)) (fu...
method SetMaxConnsPerHost (line 260) | func (s *stream) SetMaxConnsPerHost(count int) {
function newStream (line 56) | func newStream(codec Codec) (*stream, error) {
type websocketCodec (line 263) | type websocketCodec struct
method Close (line 267) | func (w *websocketCodec) Close() error {
method Write (line 271) | func (w *websocketCodec) Write(b []byte) error {
method Read (line 275) | func (w *websocketCodec) Read(b []byte) ([]byte, error) {
type Codec (line 285) | type Codec interface
FILE: jsonrpc/util.go
type ArgBig (line 11) | type ArgBig
method UnmarshalText (line 13) | func (a *ArgBig) UnmarshalText(input []byte) error {
method Big (line 24) | func (a *ArgBig) Big() *big.Int {
function encodeUintToHex (line 29) | func encodeUintToHex(i uint64) string {
function parseBigInt (line 33) | func parseBigInt(str string) *big.Int {
function parseUint64orHex (line 40) | func parseUint64orHex(str string) (uint64, error) {
function encodeToHex (line 49) | func encodeToHex(b []byte) string {
function parseHexBytes (line 53) | func parseHexBytes(str string) ([]byte, error) {
FILE: jsonrpc/web3.go
type Web3 (line 4) | type Web3 struct
method ClientVersion (line 14) | func (w *Web3) ClientVersion() (string, error) {
method Sha3 (line 21) | func (w *Web3) Sha3(val []byte) ([]byte, error) {
method Web3 (line 9) | func (c *Client) Web3() *Web3 {
FILE: jsonrpc/web3_test.go
function TestWeb3ClientVersion (line 11) | func TestWeb3ClientVersion(t *testing.T) {
function TestWeb3Sha3 (line 21) | func TestWeb3Sha3(t *testing.T) {
FILE: keccak.go
function Keccak256 (line 6) | func Keccak256(v ...[]byte) []byte {
FILE: keystore/utils.go
function getRand (line 17) | func getRand(size int) []byte {
type hexString (line 23) | type hexString
method MarshalJSON (line 25) | func (h hexString) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 30) | func (h *hexString) UnmarshalJSON(data []byte) error {
function aesCTR (line 42) | func aesCTR(key, cipherText, iv []byte) ([]byte, error) {
type pbkdf2Params (line 55) | type pbkdf2Params struct
method Key (line 62) | func (p *pbkdf2Params) Key(password []byte) []byte {
type scryptParams (line 66) | type scryptParams struct
method Key (line 74) | func (s *scryptParams) Key(password []byte) ([]byte, error) {
function applyKdf (line 78) | func applyKdf(fn string, password, paramsRaw []byte) ([]byte, error) {
FILE: keystore/v3.go
function EncryptV3 (line 13) | func EncryptV3(content []byte, password string, customScrypt ...int) ([]...
function DecryptV3 (line 69) | func DecryptV3(content []byte, password string) ([]byte, error) {
type v3Encoding (line 100) | type v3Encoding struct
method Marshal (line 106) | func (j *v3Encoding) Marshal() ([]byte, error) {
method Unmarshal (line 115) | func (j *v3Encoding) Unmarshal(data []byte) error {
type cryptoEncoding (line 119) | type cryptoEncoding struct
FILE: keystore/v3_test.go
function TestV3_EncodeDecode (line 9) | func TestV3_EncodeDecode(t *testing.T) {
FILE: keystore/v4.go
function EncryptV4 (line 13) | func EncryptV4(content []byte, password string) ([]byte, error) {
type cipherParams (line 73) | type cipherParams struct
function DecryptV4 (line 77) | func DecryptV4(content []byte, password string) ([]byte, error) {
type v4Encoding (line 122) | type v4Encoding struct
method Marshal (line 131) | func (j *v4Encoding) Marshal() ([]byte, error) {
method Unmarshal (line 135) | func (j *v4Encoding) Unmarshal(data []byte) error {
type v4crypto (line 139) | type v4crypto struct
type v4Module (line 145) | type v4Module struct
function normalizePassword (line 153) | func normalizePassword(password string) string {
FILE: keystore/v4_test.go
function TestV4_EncodeDecode (line 9) | func TestV4_EncodeDecode(t *testing.T) {
function TestV4_NormalizePassword (line 22) | func TestV4_NormalizePassword(t *testing.T) {
FILE: networks.go
type Network (line 4) | type Network
constant Mainnet (line 8) | Mainnet Network = 1
constant Ropsten (line 11) | Ropsten Network = 3
constant Rinkeby (line 14) | Rinkeby Network = 4
constant Goerli (line 17) | Goerli Network = 5
FILE: signing/eip712.go
type EIP712MessageBuilder (line 15) | type EIP712MessageBuilder struct
method GetEncodedType (line 21) | func (e *EIP712MessageBuilder[T]) GetEncodedType() string {
function NewEIP712MessageBuilder (line 25) | func NewEIP712MessageBuilder[T any](domain *EIP712Domain) *EIP712Message...
function decodeStructType (line 38) | func decodeStructType(typ reflect.Type, result *map[string][]*EIP712Type...
function isByteSlice (line 67) | func isByteSlice(t reflect.Type) bool {
function isByteArray (line 71) | func isByteArray(t reflect.Type) bool {
function decodeTypes (line 80) | func decodeTypes(val reflect.Type, result *map[string][]*EIP712Type) str...
method Build (line 130) | func (e *EIP712MessageBuilder[T]) Build(obj *T) *EIP712TypedData {
function structToMap (line 142) | func structToMap(v reflect.Value) map[string]interface{} {
function sliceToArray (line 202) | func sliceToArray(slice interface{}) interface{} {
type EIP712Type (line 222) | type EIP712Type struct
type EIP712TypedData (line 227) | type EIP712TypedData struct
method Hash (line 234) | func (t *EIP712TypedData) Hash() ([]byte, error) {
type EIP712Domain (line 253) | type EIP712Domain struct
method hashStruct (line 279) | func (e *EIP712Domain) hashStruct() ([]byte, error) {
method getObjs (line 285) | func (e *EIP712Domain) getObjs() ([]*EIP712Type, map[string]interface{...
function hashStruct (line 261) | func hashStruct(primary string, types map[string][]*EIP712Type, data map...
function encodeData (line 317) | func encodeData(primary string, types map[string][]*EIP712Type, data map...
function encodeItem (line 337) | func encodeItem(typ string, types map[string][]*EIP712Type, val interfac...
function getDependencies (line 397) | func getDependencies(primary string, types map[string][]*EIP712Type) []s...
function encodeType (line 440) | func encodeType(primary string, types map[string][]*EIP712Type) string {
function decodeHexString (line 455) | func decodeHexString(str string) ([]byte, error) {
FILE: signing/eip712_test.go
type Message (line 11) | type Message struct
type Message2 (line 19) | type Message2 struct
function TestBuildMessage_Encode (line 24) | func TestBuildMessage_Encode(t *testing.T) {
function TestBuildMessage_BasicTypes (line 54) | func TestBuildMessage_BasicTypes(t *testing.T) {
FILE: structs.go
type Address (line 20) | type Address
method Address (line 41) | func (a Address) Address() Address {
method Sign (line 46) | func (a Address) Sign(hash []byte) ([]byte, error) {
method UnmarshalText (line 51) | func (a *Address) UnmarshalText(b []byte) error {
method MarshalText (line 56) | func (a Address) MarshalText() ([]byte, error) {
method Bytes (line 61) | func (a Address) Bytes() []byte {
method String (line 65) | func (a Address) String() string {
method checksumEncode (line 69) | func (a Address) checksumEncode() string {
function HexToAddress (line 23) | func HexToAddress(str string) Address {
function BytesToAddress (line 30) | func BytesToAddress(b []byte) Address {
type Hash (line 89) | type Hash
method UnmarshalText (line 110) | func (h *Hash) UnmarshalText(b []byte) error {
method MarshalText (line 115) | func (h Hash) MarshalText() ([]byte, error) {
method Bytes (line 120) | func (h Hash) Bytes() []byte {
method String (line 124) | func (h Hash) String() string {
method Location (line 128) | func (h Hash) Location() string {
function HexToHash (line 92) | func HexToHash(str string) Hash {
function BytesToHash (line 99) | func BytesToHash(b []byte) Hash {
type Block (line 132) | type Block struct
method Copy (line 154) | func (b *Block) Copy() *Block {
type TransactionType (line 168) | type TransactionType
constant TransactionLegacy (line 171) | TransactionLegacy TransactionType = 0
constant TransactionAccessList (line 173) | TransactionAccessList TransactionType = 1
constant TransactionDynamicFee (line 175) | TransactionDynamicFee TransactionType = 2
type Transaction (line 178) | type Transaction struct
method Copy (line 208) | func (t *Transaction) Copy() *Transaction {
type AccessEntry (line 235) | type AccessEntry struct
type AccessList (line 240) | type AccessList
method Copy (line 242) | func (a *AccessList) Copy() AccessList {
type CallMsg (line 255) | type CallMsg struct
type LogFilter (line 264) | type LogFilter struct
method SetFromUint64 (line 272) | func (l *LogFilter) SetFromUint64(num uint64) {
method SetToUint64 (line 277) | func (l *LogFilter) SetToUint64(num uint64) {
method SetTo (line 282) | func (l *LogFilter) SetTo(b BlockNumber) {
type Receipt (line 286) | type Receipt struct
method Copy (line 301) | func (r *Receipt) Copy() *Receipt {
type Log (line 312) | type Log struct
method Copy (line 324) | func (l *Log) Copy() *Log {
type BlockNumber (line 331) | type BlockNumber
method Location (line 339) | func (b BlockNumber) Location() string {
method String (line 343) | func (b BlockNumber) String() string {
constant Latest (line 334) | Latest BlockNumber = -1
constant Earliest (line 335) | Earliest BlockNumber = -2
constant Pending (line 336) | Pending BlockNumber = -3
function EncodeBlock (line 358) | func EncodeBlock(block ...BlockNumber) BlockNumber {
type BlockNumberOrHash (line 365) | type BlockNumberOrHash interface
function min (line 369) | func min(i, j int) int {
type Key (line 376) | type Key interface
function completeHex (line 381) | func completeHex(str string, num int) []byte {
type OverrideAccount (line 397) | type OverrideAccount struct
type StateOverride (line 405) | type StateOverride
FILE: structs_encoding_test.go
function compactJSON (line 14) | func compactJSON(s string) string {
function TestDecodeL2Block (line 22) | func TestDecodeL2Block(t *testing.T) {
function TestEncodingJSON_Block (line 33) | func TestEncodingJSON_Block(t *testing.T) {
function TestEncodingJSON_Transaction (line 50) | func TestEncodingJSON_Transaction(t *testing.T) {
type testFile (line 71) | type testFile struct
function readTestsuite (line 76) | func readTestsuite(t *testing.T, pattern string) (res []*testFile) {
FILE: structs_marshal.go
method MarshalJSON (line 14) | func (l *Log) MarshalJSON() ([]byte, error) {
method MarshalJSON (line 44) | func (t *Block) MarshalJSON() ([]byte, error) {
method MarshalJSON (line 104) | func (t *Transaction) MarshalJSON() ([]byte, error) {
method marshalJSON (line 114) | func (t *Transaction) marshalJSON(a *fastjson.Arena) *fastjson.Value {
method marshalJSON (line 174) | func (t *AccessList) marshalJSON(a *fastjson.Arena) *fastjson.Value {
method MarshalJSON (line 191) | func (c *CallMsg) MarshalJSON() ([]byte, error) {
method MarshalJSON (line 219) | func (l *LogFilter) MarshalJSON() ([]byte, error) {
method MarshalJSON (line 271) | func (s StateOverride) MarshalJSON() ([]byte, error) {
FILE: structs_marshal_rlp.go
method GetHash (line 11) | func (t *Transaction) GetHash() (hash Hash, err error) {
method MarshalRLPTo (line 20) | func (t *Transaction) MarshalRLPTo(dst []byte) ([]byte, error) {
method MarshalRLPWith (line 33) | func (t *Transaction) MarshalRLPWith(arena *fastrlp.Arena) (*fastrlp.Val...
method UnmarshalRLP (line 84) | func (t *Transaction) UnmarshalRLP(buf []byte) error {
method UnmarshalRLPWith (line 108) | func (t *Transaction) UnmarshalRLPWith(v *fastrlp.Value) error {
method MarshalRLPTo (line 212) | func (a *AccessList) MarshalRLPTo(dst []byte) ([]byte, error) {
method MarshalRLPWith (line 216) | func (a *AccessList) MarshalRLPWith(arena *fastrlp.Arena) (*fastrlp.Valu...
method UnmarshalRLP (line 238) | func (a *AccessList) UnmarshalRLP(buf []byte) error {
method UnmarshalRLPWith (line 242) | func (a *AccessList) UnmarshalRLPWith(v *fastrlp.Value) error {
FILE: structs_marshal_rlp_test.go
function TestEncodingRLP_Transaction_Fuzz (line 11) | func TestEncodingRLP_Transaction_Fuzz(t *testing.T) {
function TestEncodingRLP_AccessList_Fuzz (line 45) | func TestEncodingRLP_AccessList_Fuzz(t *testing.T) {
FILE: structs_marshal_test.go
function generateHashPtr (line 12) | func generateHashPtr(input string) *Hash {
function TestLogFilter_MarshalJSON (line 17) | func TestLogFilter_MarshalJSON(t *testing.T) {
function TestMarshal_StateOverride (line 100) | func TestMarshal_StateOverride(t *testing.T) {
FILE: structs_test.go
function TestAddress_Checksum (line 13) | func TestAddress_Checksum(t *testing.T) {
function TestAddress_HexToString (line 40) | func TestAddress_HexToString(t *testing.T) {
function TestHash_HexToString (line 46) | func TestHash_HexToString(t *testing.T) {
function TestBlock_Copy (line 50) | func TestBlock_Copy(t *testing.T) {
function TestTransaction_Copy (line 62) | func TestTransaction_Copy(t *testing.T) {
function TestReceipt_Copy (line 84) | func TestReceipt_Copy(t *testing.T) {
function TestLog_Copy (line 98) | func TestLog_Copy(t *testing.T) {
function TestReceipt_Unmarshal (line 112) | func TestReceipt_Unmarshal(t *testing.T) {
FILE: structs_unmarshal.go
method UnmarshalJSON (line 16) | func (b *Block) UnmarshalJSON(buf []byte) error {
method UnmarshalJSON (line 116) | func (t *Transaction) UnmarshalJSON(buf []byte) error {
function isKeySet (line 129) | func isKeySet(v *fastjson.Value, key string) bool {
method unmarshalJSON (line 134) | func (t *Transaction) unmarshalJSON(v *fastjson.Value) error {
method unmarshalJSON (line 254) | func (t *AccessList) unmarshalJSON(v *fastjson.Value) error {
method UnmarshalJSON (line 285) | func (r *Receipt) UnmarshalJSON(buf []byte) error {
method UnmarshalJSON (line 354) | func (lf *LogFilter) UnmarshalJSON(buf []byte) error {
method UnmarshalJSON (line 471) | func (r *Log) UnmarshalJSON(buf []byte) error {
method unmarshalJSON (line 482) | func (r *Log) unmarshalJSON(v *fastjson.Value) error {
function fieldNotFull (line 530) | func fieldNotFull(v *fastjson.Value, key string) bool {
function decodeBigInt (line 541) | func decodeBigInt(b *big.Int, v *fastjson.Value, key string) (*big.Int, ...
function decodeBytes (line 564) | func decodeBytes(dst []byte, v *fastjson.Value, key string, bits ...int)...
function decodeUint (line 590) | func decodeUint(v *fastjson.Value, key string) (uint64, error) {
function decodeInt64 (line 613) | func decodeInt64(v *fastjson.Value, key string) (int64, error) {
function decodeNonce (line 636) | func decodeNonce(n *[8]byte, v *fastjson.Value, key string) error {
function decodeHash (line 648) | func decodeHash(h *Hash, v *fastjson.Value, key string) error {
function decodeAddr (line 663) | func decodeAddr(a *Address, v *fastjson.Value, key string) error {
function decodeBool (line 672) | func decodeBool(v *fastjson.Value, key string) (bool, error) {
function unmarshalTextByte (line 686) | func unmarshalTextByte(dst, src []byte, size int) error {
FILE: testcases/accounts_test.go
function TestAccounts (line 14) | func TestAccounts(t *testing.T) {
FILE: testcases/contract_test.go
function TestContract_Signatures (line 13) | func TestContract_Signatures(t *testing.T) {
function TestContract_Interface (line 31) | func TestContract_Interface(t *testing.T) {
FILE: testcases/eip712_test.go
type eip712Testcase (line 12) | type eip712Testcase struct
method getDomain (line 30) | func (e *eip712Testcase) getDomain() *signing.EIP712Domain {
function TestEIP712 (line 53) | func TestEIP712(t *testing.T) {
FILE: testcases/transaction_test.go
function getUint64FromBigInt (line 13) | func getUint64FromBigInt(b *ethgo.ArgBig) (uint64, bool) {
function TestTransactions (line 21) | func TestTransactions(t *testing.T) {
function TestTypedTransactions (line 86) | func TestTypedTransactions(t *testing.T) {
FILE: testcases/util.go
function ReadTestCase (line 15) | func ReadTestCase(t *testing.T, name string, target interface{}) {
FILE: testutil/contract.go
type Contract (line 14) | type Contract struct
method AddEvent (line 20) | func (c *Contract) AddEvent(e *Event) {
method GetEvent (line 30) | func (c *Contract) GetEvent(name string) *Event {
method Print (line 40) | func (c *Contract) Print() string {
method AddCallback (line 54) | func (c *Contract) AddCallback(f func() string) {
method Compile (line 62) | func (c *Contract) Compile() (*compiler.Artifact, error) {
method AddConstructor (line 75) | func (c *Contract) AddConstructor(args ...string) {
method AddDualCaller (line 97) | func (c *Contract) AddDualCaller(funcName string, args ...string) {
method AddOutputCaller (line 118) | func (c *Contract) AddOutputCaller(funcName string) {
method EmitEvent (line 127) | func (c *Contract) EmitEvent(funcName string, name string, args ...str...
type eventField (line 145) | type eventField struct
type Event (line 151) | type Event struct
method printDecl (line 156) | func (e *Event) printDecl() string {
method printSetter (line 169) | func (e *Event) printSetter() string {
method Add (line 192) | func (e *Event) Add(typStr string, indexed bool) *Event {
method Sig (line 201) | func (e *Event) Sig() string {
function NewEvent (line 216) | func NewEvent(name string, args ...interface{}) *Event {
FILE: testutil/mock.go
type mockCall (line 14) | type mockCall
constant blockByNumberCall (line 17) | blockByNumberCall mockCall = iota
constant blockByHashCall (line 18) | blockByHashCall
constant blockNumberCall (line 19) | blockNumberCall
constant getLogsCall (line 20) | getLogsCall
type MockClient (line 23) | type MockClient struct
method SetChainID (line 32) | func (m *MockClient) SetChainID(id *big.Int) {
method ChainID (line 36) | func (d *MockClient) ChainID() (*big.Int, error) {
method GetLastBlocks (line 43) | func (d *MockClient) GetLastBlocks(n uint64) (res []*ethgo.Block) {
method GetAllLogs (line 58) | func (d *MockClient) GetAllLogs() (res []*ethgo.Log) {
method AddScenario (line 68) | func (d *MockClient) AddScenario(m MockList) {
method AddLogs (line 102) | func (d *MockClient) AddLogs(logs []*ethgo.Log) {
method addBlocks (line 117) | func (d *MockClient) addBlocks(bb ...*ethgo.Block) {
method BlockNumber (line 133) | func (d *MockClient) BlockNumber() (uint64, error) {
method GetBlockByHash (line 140) | func (d *MockClient) GetBlockByHash(hash ethgo.Hash, full bool) (*ethg...
method blockByNumberLock (line 151) | func (d *MockClient) blockByNumberLock(i uint64) (*ethgo.Block, error) {
method GetBlockByNumber (line 159) | func (d *MockClient) GetBlockByNumber(i ethgo.BlockNumber, full bool) ...
method GetLogs (line 177) | func (d *MockClient) GetLogs(filter *ethgo.LogFilter) ([]*ethgo.Log, e...
type MockLog (line 207) | type MockLog struct
type MockBlock (line 211) | type MockBlock struct
method Extra (line 233) | func (m *MockBlock) Extra(data string) *MockBlock {
method GetLogs (line 238) | func (m *MockBlock) GetLogs() (logs []*ethgo.Log) {
method Log (line 245) | func (m *MockBlock) Log(data string) *MockBlock {
method GetNum (line 250) | func (m *MockBlock) GetNum() int {
method Num (line 254) | func (m *MockBlock) Num(i int) *MockBlock {
method Parent (line 259) | func (m *MockBlock) Parent(i int) *MockBlock {
method Hash (line 277) | func (m *MockBlock) Hash() ethgo.Hash {
method Block (line 281) | func (m *MockBlock) Block() *ethgo.Block {
function mustDecodeHash (line 219) | func mustDecodeHash(str string) []byte {
function encodeHash (line 265) | func encodeHash(str string) (h ethgo.Hash) {
function Mock (line 292) | func Mock(number int) *MockBlock {
type MockList (line 296) | type MockList
method Create (line 298) | func (m *MockList) Create(from, to int, callback func(b *MockBlock)) {
method GetLogs (line 306) | func (m *MockList) GetLogs() (res []*ethgo.Log) {
method ToBlocks (line 313) | func (m *MockList) ToBlocks() []*ethgo.Block {
FILE: testutil/server.go
function getOpenPort (line 33) | func getOpenPort() string {
function MultiAddr (line 47) | func MultiAddr(t *testing.T, c func(s *TestServer, addr string)) {
type TestServerConfig (line 63) | type TestServerConfig struct
type ServerConfigCallback (line 68) | type ServerConfigCallback
type TestServer (line 71) | type TestServer struct
method Account (line 172) | func (t *TestServer) Account(i int) ethgo.Address {
method IPCPath (line 177) | func (t *TestServer) IPCPath() string {
method WSAddr (line 183) | func (t *TestServer) WSAddr() string {
method HTTPAddr (line 188) | func (t *TestServer) HTTPAddr() string {
method ProcessBlockWithReceipt (line 193) | func (t *TestServer) ProcessBlockWithReceipt() (*ethgo.Receipt, error) {
method ProcessBlock (line 202) | func (t *TestServer) ProcessBlock() error {
method Call (line 214) | func (t *TestServer) Call(msg *ethgo.CallMsg) (string, error) {
method Fund (line 225) | func (t *TestServer) Fund(address ethgo.Address) (*ethgo.Receipt, erro...
method Transfer (line 229) | func (t *TestServer) Transfer(address ethgo.Address, value *big.Int) (...
method TxnTo (line 238) | func (t *TestServer) TxnTo(address ethgo.Address, method string) (*eth...
method SendTxn (line 246) | func (t *TestServer) SendTxn(txn *ethgo.Transaction) (*ethgo.Receipt, ...
method WaitForReceipt (line 273) | func (t *TestServer) WaitForReceipt(hash ethgo.Hash) (*ethgo.Receipt, ...
method DeployContract (line 296) | func (t *TestServer) DeployContract(c *Contract) (*compiler.Artifact, ...
function DeployTestServer (line 78) | func DeployTestServer(t *testing.T, cb ServerConfigCallback) *TestServer {
function NewTestServer (line 151) | func NewTestServer(t *testing.T, addrs ...string) *TestServer {
function isEmptyAddr (line 209) | func isEmptyAddr(w ethgo.Address) bool {
type jsonRPCRequest (line 318) | type jsonRPCRequest struct
type jsonRPCResponse (line 324) | type jsonRPCResponse struct
type jsonRPCErrorObject (line 330) | type jsonRPCErrorObject struct
type ethClient (line 336) | type ethClient struct
method call (line 342) | func (e *ethClient) call(method string, out interface{}, params ...int...
function MethodSig (line 387) | func MethodSig(name string) []byte {
function TestInfuraEndpoint (line 395) | func TestInfuraEndpoint(t *testing.T) string {
function testHTTPEndpoint (line 403) | func testHTTPEndpoint(endpoint string) error {
FILE: testutil/server_test.go
function TestDeployServer (line 10) | func TestDeployServer(t *testing.T) {
FILE: testutil/util.go
function CompareLogs (line 10) | func CompareLogs(one, two []*ethgo.Log) bool {
function CompareBlocks (line 20) | func CompareBlocks(one, two []*ethgo.Block) bool {
FILE: tracker/store/boltdb/bolt_store.go
type BoltStore (line 20) | type BoltStore struct
method setupDB (line 40) | func (b *BoltStore) setupDB() error {
method Close (line 54) | func (b *BoltStore) Close() error {
method Get (line 59) | func (b *BoltStore) Get(k string) (string, error) {
method ListPrefix (line 73) | func (b *BoltStore) ListPrefix(prefix string) ([]string, error) {
method Set (line 89) | func (b *BoltStore) Set(k, v string) error {
method GetEntry (line 104) | func (b *BoltStore) GetEntry(hash string) (store.Entry, error) {
function New (line 25) | func New(path string) (*BoltStore, error) {
type Entry (line 126) | type Entry struct
method LastIndex (line 132) | func (e *Entry) LastIndex() (uint64, error) {
method StoreLog (line 147) | func (e *Entry) StoreLog(log *ethgo.Log) error {
method StoreLogs (line 152) | func (e *Entry) StoreLogs(logs []*ethgo.Log) error {
method RemoveLogs (line 180) | func (e *Entry) RemoveLogs(indx uint64) error {
method GetLog (line 200) | func (e *Entry) GetLog(indx uint64, log *ethgo.Log) error {
function bytesToUint64 (line 216) | func bytesToUint64(b []byte) uint64 {
function uint64ToBytes (line 220) | func uint64ToBytes(u uint64) []byte {
FILE: tracker/store/boltdb/bolt_store_test.go
function setupDB (line 12) | func setupDB(t *testing.T) (store.Store, func()) {
function TestBoltDBStore (line 32) | func TestBoltDBStore(t *testing.T) {
FILE: tracker/store/inmem/inmem_store.go
type InmemStore (line 14) | type InmemStore struct
method Close (line 29) | func (i *InmemStore) Close() error {
method Get (line 34) | func (i *InmemStore) Get(k string) (string, error) {
method ListPrefix (line 41) | func (i *InmemStore) ListPrefix(prefix string) ([]string, error) {
method Set (line 55) | func (i *InmemStore) Set(k, v string) error {
method GetEntry (line 63) | func (i *InmemStore) GetEntry(hash string) (store.Entry, error) {
function NewInmemStore (line 21) | func NewInmemStore() *InmemStore {
type Entry (line 78) | type Entry struct
method LastIndex (line 84) | func (e *Entry) LastIndex() (uint64, error) {
method Logs (line 91) | func (e *Entry) Logs() []*ethgo.Log {
method StoreLogs (line 96) | func (e *Entry) StoreLogs(logs []*ethgo.Log) error {
method RemoveLogs (line 106) | func (e *Entry) RemoveLogs(indx uint64) error {
method GetLog (line 114) | func (e *Entry) GetLog(indx uint64, log *ethgo.Log) error {
FILE: tracker/store/inmem/inmem_store_test.go
function TestInMemoryStore (line 9) | func TestInMemoryStore(t *testing.T) {
FILE: tracker/store/postgresql/postgresql_store.go
type PostgreSQLStore (line 20) | type PostgreSQLStore struct
method Close (line 45) | func (p *PostgreSQLStore) Close() error {
method Get (line 50) | func (p *PostgreSQLStore) Get(k string) (string, error) {
method ListPrefix (line 62) | func (p *PostgreSQLStore) ListPrefix(prefix string) ([]string, error) {
method Set (line 71) | func (p *PostgreSQLStore) Set(k, v string) error {
method GetEntry (line 79) | func (p *PostgreSQLStore) GetEntry(hash string) (store.Entry, error) {
function NewPostgreSQLStore (line 25) | func NewPostgreSQLStore(endpoint string) (*PostgreSQLStore, error) {
function NewSQLStore (line 34) | func NewSQLStore(db *sql.DB, driver string) (*PostgreSQLStore, error) {
type Entry (line 92) | type Entry struct
method LastIndex (line 98) | func (e *Entry) LastIndex() (uint64, error) {
method StoreLogs (line 110) | func (e *Entry) StoreLogs(logs []*ethgo.Log) error {
method RemoveLogs (line 153) | func (e *Entry) RemoveLogs(indx uint64) error {
method GetLog (line 161) | func (e *Entry) GetLog(indx uint64, log *ethgo.Log) error {
type logObj (line 208) | type logObj struct
function logSQLSchema (line 226) | func logSQLSchema(name string) string {
FILE: tracker/store/postgresql/postgresql_store_test.go
function setupDB (line 12) | func setupDB(t *testing.T) (store.Store, func()) {
function TestPostgreSQLStore (line 49) | func TestPostgreSQLStore(t *testing.T) {
FILE: tracker/store/store.go
type Store (line 6) | type Store interface
type Entry (line 24) | type Entry interface
FILE: tracker/store/testing.go
type SetupDB (line 11) | type SetupDB
function TestStore (line 14) | func TestStore(t *testing.T, setup SetupDB) {
function testMultipleStores (line 22) | func testMultipleStores(t *testing.T, setup SetupDB) {
function testPrefix (line 65) | func testPrefix(t *testing.T, setup SetupDB) {
function testGetSet (line 104) | func testGetSet(t *testing.T, setup SetupDB) {
function testStoreLogs (line 145) | func testStoreLogs(t *testing.T, setup SetupDB) {
function testRemoveLogs (line 199) | func testRemoveLogs(t *testing.T, setup SetupDB) {
FILE: tracker/tracker.go
constant defaultBatchSize (line 34) | defaultBatchSize = 100
type BlockTracking (line 38) | type BlockTracking interface
type FilterConfig (line 53) | type FilterConfig struct
method buildHash (line 61) | func (f *FilterConfig) buildHash() {
method getFilterSearch (line 86) | func (f *FilterConfig) getFilterSearch() *ethgo.LogFilter {
type Config (line 98) | type Config struct
type ConfigOption (line 106) | type ConfigOption
function WithBatchSize (line 108) | func WithBatchSize(b uint64) ConfigOption {
function WithBlockTracker (line 114) | func WithBlockTracker(b BlockTracking) ConfigOption {
function WithStore (line 120) | func WithStore(s store.Store) ConfigOption {
function WithFilter (line 126) | func WithFilter(f *FilterConfig) ConfigOption {
function WithEtherscan (line 132) | func WithEtherscan(k string) ConfigOption {
function DefaultConfig (line 139) | func DefaultConfig() *Config {
type Provider (line 149) | type Provider interface
type Tracker (line 158) | type Tracker struct
method setupFilter (line 201) | func (t *Tracker) setupFilter() error {
method Entry (line 237) | func (t *Tracker) Entry() store.Entry {
method GetLastBlock (line 242) | func (t *Tracker) GetLastBlock() (*ethgo.Block, error) {
method storeLastBlock (line 261) | func (t *Tracker) storeLastBlock(b *ethgo.Block) error {
method emitEvent (line 273) | func (t *Tracker) emitEvent(evnt *Event) {
method IsSynced (line 288) | func (t *Tracker) IsSynced() bool {
method Wait (line 293) | func (t *Tracker) Wait() {
method WaitDuration (line 298) | func (t *Tracker) WaitDuration(dur time.Duration) error {
method findAncestor (line 315) | func (t *Tracker) findAncestor(block, pivot *ethgo.Block) (uint64, err...
method emitLogs (line 346) | func (t *Tracker) emitLogs(typ EventType, logs []*ethgo.Log) {
method syncBatch (line 368) | func (t *Tracker) syncBatch(ctx context.Context, from, to uint64) error {
method preSyncCheck (line 432) | func (t *Tracker) preSyncCheck() error {
method preSyncCheckImpl (line 440) | func (t *Tracker) preSyncCheckImpl() error {
method fastTrack (line 476) | func (t *Tracker) fastTrack(filterConfig *FilterConfig) (*ethgo.Block,...
method BatchSync (line 551) | func (t *Tracker) BatchSync(ctx context.Context) error {
method Sync (line 592) | func (t *Tracker) Sync(ctx context.Context) error {
method syncImpl (line 611) | func (t *Tracker) syncImpl(ctx context.Context) error {
method removeLogs (line 751) | func (t *Tracker) removeLogs(number uint64, hash *ethgo.Hash) ([]*ethg...
method handleBlockEvnt (line 797) | func (t *Tracker) handleBlockEvnt(blockEvnt *blocktracker.BlockEvent) ...
method doFilter (line 820) | func (t *Tracker) doFilter(added []*ethgo.Block, removed []*ethgo.Bloc...
method getBlockByNumber (line 865) | func (t *Tracker) getBlockByNumber(blockNumber uint64) (*ethgo.Block, ...
function NewTracker (line 175) | func NewTracker(provider Provider, opts ...ConfigOption) (*Tracker, erro...
function tooMuchDataRequestedError (line 357) | func tooMuchDataRequestedError(err error) bool {
function revertLogs (line 790) | func revertLogs(in []*ethgo.Log) (out []*ethgo.Log) {
type EventType (line 878) | type EventType
constant EventAdd (line 882) | EventAdd EventType = iota
constant EventDel (line 884) | EventDel
type Event (line 888) | type Event struct
type BlockEvent (line 895) | type BlockEvent struct
function min (line 901) | func min(i, j uint64) uint64 {
function parseUint64orHex (line 908) | func parseUint64orHex(str string) (uint64, error) {
FILE: tracker/tracker_test.go
function testConfig (line 24) | func testConfig() ConfigOption {
function testFilter (line 30) | func testFilter(t *testing.T, provider Provider, filterConfig *FilterCon...
function TestPolling (line 43) | func TestPolling(t *testing.T) {
function TestFilterIntegration (line 102) | func TestFilterIntegration(t *testing.T) {
function TestPreflight (line 139) | func TestPreflight(t *testing.T) {
function TestTrackerSyncerRestarts (line 178) | func TestTrackerSyncerRestarts(t *testing.T) {
function testSyncerReconcile (line 234) | func testSyncerReconcile(t *testing.T, iniLen, forkNum, endLen int) {
function TestTrackerSyncerReconcile (line 317) | func TestTrackerSyncerReconcile(t *testing.T) {
function randomInt (line 326) | func randomInt(min, max int) int {
function testTrackerSyncerRandom (line 330) | func testTrackerSyncerRandom(t *testing.T, n int, backlog uint64) {
function TestTrackerSyncerRandom (line 431) | func TestTrackerSyncerRandom(t *testing.T) {
function TestTrackerReconcile (line 441) | func TestTrackerReconcile(t *testing.T) {
type mockClientWithLimit (line 717) | type mockClientWithLimit struct
method GetLogs (line 722) | func (m *mockClientWithLimit) GetLogs(filter *ethgo.LogFilter) ([]*eth...
function TestTooMuchDataRequested (line 737) | func TestTooMuchDataRequested(t *testing.T) {
FILE: units.go
function convert (line 5) | func convert(val uint64, decimals int64) *big.Int {
function Ether (line 12) | func Ether(i uint64) *big.Int {
function Gwei (line 17) | func Gwei(i uint64) *big.Int {
FILE: wallet/key.go
type Key (line 20) | type Key struct
method Address (line 26) | func (k *Key) Address() ethgo.Address {
method MarshallPrivateKey (line 30) | func (k *Key) MarshallPrivateKey() ([]byte, error) {
method SignMsg (line 34) | func (k *Key) SignMsg(msg []byte) ([]byte, error) {
method Sign (line 38) | func (k *Key) Sign(hash []byte) ([]byte, error) {
function NewKey (line 51) | func NewKey(prv *ecdsa.PrivateKey) (*Key, error) {
function pubKeyToAddress (line 65) | func pubKeyToAddress(pub *ecdsa.PublicKey) (addr ethgo.Address) {
function GenerateKey (line 72) | func GenerateKey() (*Key, error) {
function EcrecoverMsg (line 80) | func EcrecoverMsg(msg, signature []byte) (ethgo.Address, error) {
function Ecrecover (line 84) | func Ecrecover(hash, signature []byte) (ethgo.Address, error) {
function RecoverPubkey (line 92) | func RecoverPubkey(signature, hash []byte) (*ecdsa.PublicKey, error) {
FILE: wallet/key_test.go
function TestKeySign (line 9) | func TestKeySign(t *testing.T) {
FILE: wallet/signer.go
type Signer (line 10) | type Signer interface
type EIP1155Signer (line 18) | type EIP1155Signer struct
method RecoverSender (line 26) | func (e *EIP1155Signer) RecoverSender(tx *ethgo.Transaction) (ethgo.Ad...
method SignTx (line 57) | func (e *EIP1155Signer) SignTx(tx *ethgo.Transaction, key ethgo.Key) (...
function NewEIP155Signer (line 22) | func NewEIP155Signer(chainID uint64) *EIP1155Signer {
function trimBytesZeros (line 47) | func trimBytesZeros(b []byte) []byte {
function signHash (line 76) | func signHash(tx *ethgo.Transaction, chainID uint64) []byte {
function encodeSignature (line 132) | func encodeSignature(R, S []byte, V byte) ([]byte, error) {
FILE: wallet/signer_test.go
function TestSigner_SignAndRecover (line 13) | func TestSigner_SignAndRecover(t *testing.T) {
function TestSigner_EIP1155 (line 56) | func TestSigner_EIP1155(t *testing.T) {
function TestTrimBytesZeros (line 76) | func TestTrimBytesZeros(t *testing.T) {
FILE: wallet/wallet_hd.go
type DerivationPath (line 14) | type DerivationPath
method Derive (line 22) | func (d *DerivationPath) Derive(master *hdkeychain.ExtendedKey) (*ecds...
function parseDerivationPath (line 38) | func parseDerivationPath(path string) (*DerivationPath, error) {
function NewWalletFromMnemonic (line 78) | func NewWalletFromMnemonic(mnemonic string) (*Key, error) {
FILE: wallet/wallet_hd_test.go
function TestWallet_Mnemonic (line 9) | func TestWallet_Mnemonic(t *testing.T) {
function TestWallet_MnemonicDerivationPath (line 14) | func TestWallet_MnemonicDerivationPath(t *testing.T) {
FILE: wallet/wallet_json.go
function NewJSONWalletFromFile (line 9) | func NewJSONWalletFromFile(path string, password string) (*Key, error) {
function NewJSONWalletFromContent (line 17) | func NewJSONWalletFromContent(content []byte, password string) (*Key, er...
FILE: wallet/wallet_json_test.go
function TestWallet_JSON (line 11) | func TestWallet_JSON(t *testing.T) {
FILE: wallet/wallet_priv.go
function ParsePrivateKey (line 9) | func ParsePrivateKey(buf []byte) (*ecdsa.PrivateKey, error) {
function NewWalletFromPrivKey (line 14) | func NewWalletFromPrivKey(p []byte) (*Key, error) {
FILE: wallet/wallet_priv_test.go
function TestWallet_Priv (line 9) | func TestWallet_Priv(t *testing.T) {
FILE: website/components/eip.jsx
function EIPLink (line 4) | function EIPLink({children, num}) {
FILE: website/components/godoc.jsx
function GodocLink (line 6) | function GodocLink({children, href}) {
FILE: website/components/primitives.jsx
function Address (line 5) | function Address({text='Address'}) {
function Hash (line 9) | function Hash({text='Hash'}) {
function Block (line 13) | function Block() {
function Blocktag (line 17) | function Blocktag() {
function ABI (line 21) | function ABI() {
function Transaction (line 25) | function Transaction() {
function Receipt (line 29) | function Receipt() {
function LogFilter (line 33) | function LogFilter() {
function Log (line 37) | function Log({text='Log'}) {
FILE: website/pages/_app.js
function Nextra (line 11) | function Nextra({ Component, pageProps }) {
Condensed preview — 181 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (741K chars).
[
{
"path": ".github/workflows/pr.yaml",
"chars": 577,
"preview": "name: Unit tests\non: [pull_request]\njobs:\n build:\n runs-on: ubuntu-latest\n name: Go test\n steps:\n - uses:"
},
{
"path": ".github/workflows/release.yaml",
"chars": 683,
"preview": "name: Release\n\non:\n workflow_dispatch:\n push:\n branches-ignore:\n - '**'\n tags:\n - 'v*.*.*'\n # to "
},
{
"path": ".gitignore",
"chars": 54,
"preview": "bin/\npkg/\n\n.idea\n\n# website\nnode_modules\n.next\n\ndist/\n"
},
{
"path": ".goreleaser.yaml",
"chars": 451,
"preview": "before:\n hooks:\n - go mod tidy\nbuilds:\n - dir: cmd\n env:\n - CGO_ENABLED=0\n goos:\n - linux\n - w"
},
{
"path": "4byte/4byte.go",
"chars": 964,
"preview": "package fourbyte\n\nimport (\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"net/http\"\n)\n\nconst (\n\tfourByteURL = \"https://"
},
{
"path": "4byte/4byte_test.go",
"chars": 465,
"preview": "package fourbyte\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc Test4Byte(t *testing.T) {\n\tt.Skip(\""
},
{
"path": "CHANGELOG.md",
"chars": 3194,
"preview": "# 0.1.4 (Unreleased)\n\n- feat: Add override to `eth_call` request [[GH-240](https://github.com/umbracle/ethgo/issues/240)"
},
{
"path": "LICENSE",
"chars": 16725,
"preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
},
{
"path": "Makefile",
"chars": 109,
"preview": "\n.PHONY: build-artifacts\nbuild-artifacts: \n\t@echo \"--> Build Artifacts\"\n\t@sh -c ./scripts/build-artifacts.sh\n"
},
{
"path": "README.md",
"chars": 567,
"preview": "\n# Eth-Go\n\n[![Chat Badge]][chat link]\n\n[chat badge]: https://img.shields.io/badge/chat-discord-%237289da\n[chat link]: ht"
},
{
"path": "abi/abi.go",
"chars": 10487,
"preview": "package abi\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"hash\"\n\t\"io\"\n\t\"regexp\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/umbracle"
},
{
"path": "abi/abi_test.go",
"chars": 8829,
"preview": "package abi\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require"
},
{
"path": "abi/decode.go",
"chars": 6567,
"preview": "package abi\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"strconv\"\n\n\t\"github.com/mitchellh/mapstructure\"\n"
},
{
"path": "abi/decode_test.go",
"chars": 574,
"preview": "package abi\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestDecode_BytesBound(t *testing.T) {\n\t"
},
{
"path": "abi/encode.go",
"chars": 7434,
"preview": "package abi\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n"
},
{
"path": "abi/encoding_test.go",
"chars": 13342,
"preview": "package abi\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"math/rand\"\n\t\"os\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"testing\"\n\t\"time\"\n\n\t\""
},
{
"path": "abi/revert.go",
"chars": 423,
"preview": "package abi\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\nvar revertId = []byte{0x8, 0xC3, 0x79, 0xA0}\n\nfunc UnpackRevertError(b []byte) "
},
{
"path": "abi/revert_test.go",
"chars": 492,
"preview": "package abi\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestUnpackRevertError(t *testing.T) {\n\td"
},
{
"path": "abi/testing.go",
"chars": 4774,
"preview": "package abi\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\t\"math/rand\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\nfunc random"
},
{
"path": "abi/topics.go",
"chars": 3290,
"preview": "package abi\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"reflect\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\n// ParseLog parses an event log\nfunc P"
},
{
"path": "abi/topics_test.go",
"chars": 2088,
"preview": "package abi\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stret"
},
{
"path": "abi/type.go",
"chars": 13986,
"preview": "package abi\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\n// "
},
{
"path": "abi/type_test.go",
"chars": 7330,
"preview": "package abi\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require"
},
{
"path": "blocktracker/blocktracker.go",
"chars": 10549,
"preview": "package blocktracker\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/eth"
},
{
"path": "blocktracker/blocktracker_test.go",
"chars": 7742,
"preview": "package blocktracker\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracl"
},
{
"path": "builtin/ens/artifacts/ENS.abi",
"chars": 1845,
"preview": "[{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"resolver\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}]"
},
{
"path": "builtin/ens/artifacts/Resolver.abi",
"chars": 2872,
"preview": "[{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"ty"
},
{
"path": "builtin/ens/ens.go",
"chars": 3427,
"preview": "// Code generated by ethgo/abigen. DO NOT EDIT.\n// Hash: bfee2618a5908e1a24f19dcce873d3b8e797374138dd7604f7b593db3cca5c1"
},
{
"path": "builtin/ens/ens_artifacts.go",
"chars": 5241,
"preview": "package ens\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n)\n\nvar abiENS *abi.ABI\n\n// ENSAbi returns"
},
{
"path": "builtin/ens/ens_resolver.go",
"chars": 1404,
"preview": "package ens\n\nimport (\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/contract\"\n\t\"github.com/umbracle/ethgo/jso"
},
{
"path": "builtin/ens/ens_resolver_test.go",
"chars": 777,
"preview": "package ens\n\nimport (\n\t\"encoding/hex\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"g"
},
{
"path": "builtin/ens/resolver.go",
"chars": 5514,
"preview": "// Code generated by ethgo/abigen. DO NOT EDIT.\n// Hash: 3d1ecdf4aa6a2c578e0c3bbb14cc28ae2c8ebc4495f7d6128959f961afd0f63"
},
{
"path": "builtin/ens/resolver_artifacts.go",
"chars": 12661,
"preview": "package ens\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n)\n\nvar abiResolver *abi.ABI\n\n// ResolverA"
},
{
"path": "builtin/ens/utils.go",
"chars": 571,
"preview": "package ens\n\nimport (\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"golang.org/x/crypto/sha3\"\n)\n\n// NameHash returns the ha"
},
{
"path": "builtin/ens/utils_test.go",
"chars": 548,
"preview": "package ens\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestNameHash(t *testing.T) {\n\tcases := ["
},
{
"path": "builtin/erc20/artifacts/ERC20.abi",
"chars": 2114,
"preview": "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"v"
},
{
"path": "builtin/erc20/erc20.go",
"chars": 4143,
"preview": "// Code generated by ethgo/abigen. DO NOT EDIT.\n// Hash: a1a873d70d345feef023ee086fd6135b24d775444b950ee9d5ea411e72b0f37"
},
{
"path": "builtin/erc20/erc20_artifacts.go",
"chars": 2691,
"preview": "package erc20\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n)\n\nvar abiERC20 *abi.ABI\n\n// ERC20Abi r"
},
{
"path": "builtin/erc20/erc20_test.go",
"chars": 1337,
"preview": "package erc20\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbr"
},
{
"path": "cmd/abigen/abigen.go",
"chars": 3766,
"preview": "package abigen\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"strings\"\n\n\t\"path/"
},
{
"path": "cmd/abigen/gen.go",
"chars": 6869,
"preview": "package abigen\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"text/template\"\n\n\t\"github."
},
{
"path": "cmd/abigen/testdata/testdata.abi",
"chars": 1421,
"preview": "[\n {\n \"constant\": false,\n \"inputs\": [\n {\n \"name\": \"_val1\",\n \"t"
},
{
"path": "cmd/abigen/testdata/testdata.go",
"chars": 1606,
"preview": "// Code generated by ethgo/abigen. DO NOT EDIT.\n// Hash: 3f1af52b391dcf1991b5cee7468a69f382cfa0f819eaff85474464c969fe7ea"
},
{
"path": "cmd/abigen/testdata/testdata_artifacts.go",
"chars": 2046,
"preview": "package testdata\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n)\n\nvar abiTestdata *abi.ABI\n\n// Test"
},
{
"path": "cmd/commands/4byte.go",
"chars": 868,
"preview": "package commands\n\nimport (\n\t\"github.com/mitchellh/cli\"\n\tfourbyte \"github.com/umbracle/ethgo/4byte\"\n)\n\n// FourByteCommand"
},
{
"path": "cmd/commands/abigen.go",
"chars": 1161,
"preview": "package commands\n\nimport (\n\tflag \"github.com/spf13/pflag\"\n\t\"github.com/umbracle/ethgo/cmd/abigen\"\n)\n\n// VersionCommand i"
},
{
"path": "cmd/commands/commands.go",
"chars": 982,
"preview": "package commands\n\nimport (\n\t\"os\"\n\n\t\"github.com/mitchellh/cli\"\n\tflag \"github.com/spf13/pflag\"\n)\n\nfunc Commands() map[stri"
},
{
"path": "cmd/commands/ens.go",
"chars": 496,
"preview": "package commands\n\nimport (\n\t\"github.com/mitchellh/cli\"\n)\n\n// EnsCommand is the group command for ens\ntype EnsCommand str"
},
{
"path": "cmd/commands/ens_resolve.go",
"chars": 1469,
"preview": "package commands\n\nimport (\n\t\"os\"\n\n\t\"github.com/mitchellh/cli\"\n\tflag \"github.com/spf13/pflag\"\n\t\"github.com/umbracle/ethgo"
},
{
"path": "cmd/commands/version.go",
"chars": 631,
"preview": "package commands\n\nimport (\n\t\"github.com/mitchellh/cli\"\n\t\"github.com/umbracle/ethgo/cmd/version\"\n)\n\n// VersionCommand is "
},
{
"path": "cmd/go.mod",
"chars": 1953,
"preview": "module github.com/umbracle/ethgo/cmd\n\ngo 1.17\n\nrequire (\n\tgithub.com/mitchellh/cli v1.1.2\n\tgithub.com/umbracle/ethgo v0."
},
{
"path": "cmd/go.sum",
"chars": 18669,
"preview": "bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=\ngithub.com/Azur"
},
{
"path": "cmd/main.go",
"chars": 469,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/mitchellh/cli\"\n\t\"github.com/umbracle/ethgo/cmd/commands\"\n)\n\nfunc main("
},
{
"path": "cmd/version/version.go",
"chars": 548,
"preview": "package version\n\nimport \"fmt\"\n\nvar (\n\t// GitCommit is the git commit that was compiled.\n\tGitCommit string\n\n\t// Version i"
},
{
"path": "compiler/fixtures/ballot.sol",
"chars": 5387,
"preview": "pragma solidity >=0.4.22 <0.6.0;\n\n/// @title Voting with delegation.\ncontract Ballot {\n // This declares a new comple"
},
{
"path": "compiler/fixtures/simple_auction.sol",
"chars": 4320,
"preview": "pragma solidity >=0.4.22 <0.6.0;\n\ncontract SimpleAuction {\n // Parameters of the auction. Times are either\n // abs"
},
{
"path": "compiler/solidity.go",
"chars": 3389,
"preview": "package compiler\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filep"
},
{
"path": "compiler/solidity_test.go",
"chars": 2946,
"preview": "package compiler\n\nimport (\n\t\"bytes\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"g"
},
{
"path": "contract/contract.go",
"chars": 7381,
"preview": "package contract\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/"
},
{
"path": "contract/contract_test.go",
"chars": 7126,
"preview": "package contract\n\nimport (\n\t\"encoding/hex\"\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/st"
},
{
"path": "e2e/transaction_test.go",
"chars": 1672,
"preview": "package e2e\n\nimport (\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"githu"
},
{
"path": "encoding.go",
"chars": 1550,
"preview": "package ethgo\n\nimport (\n\t\"encoding/hex\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype ArgBig big.Int\n\nfunc (a *ArgBig) Unmar"
},
{
"path": "ens/address_mapping.go",
"chars": 265,
"preview": "package ens\n\nimport \"github.com/umbracle/ethgo\"\n\nvar defaultEnsAddr = ethgo.HexToAddress(\"0x00000000000C2E074eC69A0dFb29"
},
{
"path": "ens/ens.go",
"chars": 1870,
"preview": "package ens\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/builtin/ens\"\n\t\"github.com/"
},
{
"path": "ens/ens_test.go",
"chars": 581,
"preview": "package ens\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbrac"
},
{
"path": "etherscan/etherscan.go",
"chars": 4761,
"preview": "package etherscan\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umb"
},
{
"path": "etherscan/etherscan_test.go",
"chars": 1639,
"preview": "package etherscan\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo\"\n)\n\nfunc"
},
{
"path": "examples/contract-call-basic.go",
"chars": 825,
"preview": "package examples\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.co"
},
{
"path": "examples/contract-call-from.go",
"chars": 895,
"preview": "package examples\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.co"
},
{
"path": "examples/contract-deploy.go",
"chars": 471,
"preview": "package examples\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/ethgo/contract\"\n)\n\nfunc contra"
},
{
"path": "examples/contract-transaction.go",
"chars": 1018,
"preview": "package examples\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/abi\"\n\t\"github.com/umbracle/e"
},
{
"path": "go.mod",
"chars": 2224,
"preview": "module github.com/umbracle/ethgo\n\ngo 1.18\n\nrequire (\n\tgithub.com/btcsuite/btcd v0.23.3\n\tgithub.com/btcsuite/btcd/btcec/v"
},
{
"path": "go.sum",
"chars": 22056,
"preview": "github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=\ngithub.c"
},
{
"path": "jsonrpc/client.go",
"chars": 1331,
"preview": "package jsonrpc\n\nimport (\n\t\"github.com/umbracle/ethgo/jsonrpc/transport\"\n)\n\n// Client is the jsonrpc client\ntype Client "
},
{
"path": "jsonrpc/codec/codec.go",
"chars": 1005,
"preview": "package codec\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// Request is a jsonrpc request\ntype Request struct {\n\tJsonRPC string"
},
{
"path": "jsonrpc/debug.go",
"chars": 1183,
"preview": "package jsonrpc\n\nimport \"github.com/umbracle/ethgo\"\n\ntype Debug struct {\n\tc *Client\n}\n\n// Debug returns the reference to"
},
{
"path": "jsonrpc/debug_test.go",
"chars": 721,
"preview": "package jsonrpc\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\t\"git"
},
{
"path": "jsonrpc/eth.go",
"chars": 8514,
"preview": "package jsonrpc\n\nimport (\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\n// Eth is"
},
{
"path": "jsonrpc/eth_test.go",
"chars": 10736,
"preview": "package jsonrpc\n\nimport (\n\t\"bytes\"\n\t\"encoding/hex\"\n\t\"math/big\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/asse"
},
{
"path": "jsonrpc/net.go",
"chars": 826,
"preview": "package jsonrpc\n\n// Net is the net namespace\ntype Net struct {\n\tc *Client\n}\n\n// Net returns the reference to the net nam"
},
{
"path": "jsonrpc/net_test.go",
"chars": 816,
"preview": "package jsonrpc\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo/testutil\"\n)\n\nfun"
},
{
"path": "jsonrpc/subscribe.go",
"chars": 611,
"preview": "package jsonrpc\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/jsonrpc/transport\"\n)\n\n// SubscriptionEnabled returns true "
},
{
"path": "jsonrpc/subscribe_test.go",
"chars": 1241,
"preview": "package jsonrpc\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/eth"
},
{
"path": "jsonrpc/transport/http.go",
"chars": 1962,
"preview": "package transport\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo/jsonrpc/codec\"\n\t\"github.com/valyala/fas"
},
{
"path": "jsonrpc/transport/ipc.go",
"chars": 711,
"preview": "package transport\n\nimport (\n\t\"encoding/json\"\n\t\"net\"\n)\n\nfunc newIPC(addr string) (Transport, error) {\n\tconn, err := net.D"
},
{
"path": "jsonrpc/transport/transport.go",
"chars": 1232,
"preview": "package transport\n\nimport (\n\t\"os\"\n\t\"strings\"\n)\n\n// Transport is an inteface for transport methods to send jsonrpc reques"
},
{
"path": "jsonrpc/transport/websocket.go",
"chars": 5365,
"preview": "package transport\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/gorilla/web"
},
{
"path": "jsonrpc/util.go",
"chars": 1145,
"preview": "package jsonrpc\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype ArgBig big.Int\n\nfunc (a *ArgB"
},
{
"path": "jsonrpc/web3.go",
"chars": 635,
"preview": "package jsonrpc\n\n// Web3 is the web3 namespace\ntype Web3 struct {\n\tc *Client\n}\n\n// Web3 returns the reference to the web"
},
{
"path": "jsonrpc/web3_test.go",
"chars": 723,
"preview": "package jsonrpc\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethgo/testutil\"\n\t\"gola"
},
{
"path": "keccak.go",
"chars": 217,
"preview": "package ethgo\n\nimport \"golang.org/x/crypto/sha3\"\n\n// Keccak256 calculates the Keccak256\nfunc Keccak256(v ...[]byte) []by"
},
{
"path": "keystore/utils.go",
"chars": 2108,
"preview": "package keystore\n\nimport (\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n\t\"crypto/rand\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"encoding/jso"
},
{
"path": "keystore/v3.go",
"chars": 2858,
"preview": "package keystore\n\nimport (\n\t\"bytes\"\n\t\"crypto/aes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\n// EncryptV3 "
},
{
"path": "keystore/v3_test.go",
"chars": 341,
"preview": "package keystore\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestV3_EncodeDecode(t *testing.T) {"
},
{
"path": "keystore/v4.go",
"chars": 3837,
"preview": "package keystore\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha256\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"golang.org/x/text/unicode/nor"
},
{
"path": "keystore/v4_test.go",
"chars": 720,
"preview": "package keystore\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestV4_EncodeDecode(t *testing.T) {"
},
{
"path": "networks.go",
"chars": 285,
"preview": "package ethgo\n\n// Network is a chain id\ntype Network uint64\n\nconst (\n\t// Mainnet is the mainnet network\n\tMainnet Network"
},
{
"path": "scripts/build-artifacts.sh",
"chars": 534,
"preview": "#!/usr/bin/env bash\n\nset -o errexit\ncd cmd\n\necho \"--> Build ENS\"\n\nENS_ARTIFACTS=../builtin/ens/artifacts\ngo run main.go "
},
{
"path": "scripts/setup-ci.sh",
"chars": 293,
"preview": "#!/usr/bin/env bash\n\n# set -o errexit\n\ninstall_solidity() {\n VERSION=\"0.5.5\"\n DOWNLOAD=https://github.com/ethereum"
},
{
"path": "scripts/setup-geth.sh",
"chars": 458,
"preview": "#!/bin/bash\n\n# Start geth test server\ndocker run --name geth-test -d -p 8545:8545 -p 8546:8546 ethereum/client-go:v1.10."
},
{
"path": "signing/eip712.go",
"chars": 10608,
"preview": "package signing\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo\""
},
{
"path": "signing/eip712_test.go",
"chars": 1435,
"preview": "package signing\n\nimport (\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n)\n"
},
{
"path": "structs.go",
"chars": 7852,
"preview": "package ethgo\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nvar (\n\t// ZeroAddress is an address "
},
{
"path": "structs_encoding_test.go",
"chars": 1887,
"preview": "package ethgo\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testif"
},
{
"path": "structs_marshal.go",
"chars": 8237,
"preview": "package ethgo\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/valyala/fastjson\"\n)\n\nvar defaultArena fastjson."
},
{
"path": "structs_marshal_rlp.go",
"chars": 6069,
"preview": "package ethgo\n\nimport (\n\t\"fmt\"\n\t\"math/big\"\n\n\t\"github.com/umbracle/fastrlp\"\n)\n\n// GetHash returns the Hash of the transac"
},
{
"path": "structs_marshal_rlp_test.go",
"chars": 1158,
"preview": "package ethgo\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/fastrlp\"\n)\n\nfunc "
},
{
"path": "structs_marshal_test.go",
"chars": 2606,
"preview": "package ethgo\n\nimport (\n\t\"encoding/json\"\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stre"
},
{
"path": "structs_test.go",
"chars": 2705,
"preview": "package ethgo\n\nimport (\n\t_ \"embed\"\n\t\"encoding/json\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/ass"
},
{
"path": "structs_unmarshal.go",
"chars": 16053,
"preview": "package ethgo\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/valyala/fastjson\"\n)\n\nvar "
},
{
"path": "testcases/accounts_test.go",
"chars": 1245,
"preview": "package testcases\n\nimport (\n\t\"encoding/hex\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/st"
},
{
"path": "testcases/contract_test.go",
"chars": 1548,
"preview": "package testcases\n\nimport (\n\t\"encoding/hex\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/umbracle/ethg"
},
{
"path": "testcases/eip712_test.go",
"chars": 1515,
"preview": "package testcases\n\nimport (\n\t\"encoding/hex\"\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/"
},
{
"path": "testcases/package.json",
"chars": 289,
"preview": "{\n \"name\": \"testsuite\",\n \"version\": \"1.0.0\",\n \"description\": \"\",\n \"main\": \"index.js\",\n \"scripts\": {\n \"test\": \"ec"
},
{
"path": "testcases/transaction_test.go",
"chars": 4499,
"preview": "package testcases\n\nimport (\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/"
},
{
"path": "testcases/util.go",
"chars": 738,
"preview": "package testcases\n\nimport (\n\t\"compress/gzip\"\n\t\"encoding/json\"\n\t\"os\"\n\t\"path\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"testing\"\n\n\t\"gi"
},
{
"path": "testsuite/arbitrum-block-full.json",
"chars": 152073,
"preview": "{\n \"baseFeePerGas\": \"0x5f5e100\",\n \"difficulty\": \"0x1\",\n \"extraData\": \"0x000000000000000000000000000000000000000"
},
{
"path": "testsuite/block-full.json",
"chars": 1834,
"preview": "{\n \"number\": \"0x1\",\n \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n \"parentHash"
},
{
"path": "testsuite/block-txn-hashes.json",
"chars": 1134,
"preview": "{\n \"number\": \"0x1\",\n \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n \"parentHash"
},
{
"path": "testsuite/receipts.json",
"chars": 2357,
"preview": "[\n {\n \"blockHash\": \"0x1ee40a01cdb865600eef166d175eade70ab51f215c5663a7fcc5ec1f960f4e40\",\n \"blockNumber\""
},
{
"path": "testsuite/transaction-call.json",
"chars": 640,
"preview": "{\n \"type\": \"0x0\",\n \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n \"from\": \"0x00"
},
{
"path": "testsuite/transaction-contract-creation.json",
"chars": 600,
"preview": "{\n \"type\": \"0x0\",\n \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n \"from\": \"0x00"
},
{
"path": "testsuite/transaction-eip1159.json",
"chars": 907,
"preview": "{\n \"type\": \"0x2\",\n \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n \"from\": \"0x00"
},
{
"path": "testsuite/transaction-eip1559-notype.json",
"chars": 888,
"preview": "{\n \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n \"from\": \"0x000000000000000000000"
},
{
"path": "testsuite/transaction-eip2930.json",
"chars": 866,
"preview": "{\n \"type\": \"0x1\",\n \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n \"from\": \"0x00"
},
{
"path": "testsuite/transaction-pending.json",
"chars": 574,
"preview": "{\n \"type\": \"0x0\",\n \"hash\": \"0x0000000000000000000000000000000000000000000000000000000000000001\",\n \"from\": \"0x00"
},
{
"path": "testutil/contract.go",
"chars": 5254,
"preview": "package testutil\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/umbracle/ethgo/compiler\"\n\t\"golang."
},
{
"path": "testutil/mock.go",
"chars": 6030,
"preview": "package testutil\n\nimport (\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/umbracle/ethgo"
},
{
"path": "testutil/server.go",
"chars": 9001,
"preview": "package testutil\n\nimport (\n\t\"bytes\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"math/big\"\n\t\"math/rand\"\n\t\"net\""
},
{
"path": "testutil/server_test.go",
"chars": 353,
"preview": "package testutil\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/umbracle/ethgo\"\n)\n\nfunc TestD"
},
{
"path": "testutil/util.go",
"chars": 748,
"preview": "package testutil\n\nimport (\n\t\"math/big\"\n\t\"reflect\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\nfunc CompareLogs(one, two []*ethgo.Lo"
},
{
"path": "tracker/README.md",
"chars": 2753,
"preview": "\n# Tracker\n\n```\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/binary\"\n\t\"flag\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"git"
},
{
"path": "tracker/store/boltdb/bolt_store.go",
"chars": 4425,
"preview": "package trackerboltdb\n\nimport (\n\t\"bytes\"\n\t\"encoding/binary\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/tr"
},
{
"path": "tracker/store/boltdb/bolt_store_test.go",
"chars": 542,
"preview": "package trackerboltdb\n\nimport (\n\t\"io/ioutil\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/umbracle/ethgo/tracker/stor"
},
{
"path": "tracker/store/inmem/inmem_store.go",
"chars": 2303,
"preview": "package inmem\n\nimport (\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/ethgo/tracker/store\"\n)\n\nv"
},
{
"path": "tracker/store/inmem/inmem_store_test.go",
"chars": 226,
"preview": "package inmem\n\nimport (\n\t\"testing\"\n\n\t\"github.com/umbracle/ethgo/tracker/store\"\n)\n\nfunc TestInMemoryStore(t *testing.T) {"
},
{
"path": "tracker/store/postgresql/postgresql_store.go",
"chars": 5655,
"preview": "package trackerpostgresql\n\nimport (\n\t\"database/sql\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/jmoiron/sqlx\"\n\t\"gith"
},
{
"path": "tracker/store/postgresql/postgresql_store_test.go",
"chars": 1095,
"preview": "package trackerpostgresql\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/ory/dockertest\"\n\t\"github.com/umbracl"
},
{
"path": "tracker/store/store.go",
"chars": 815,
"preview": "package store\n\nimport \"github.com/umbracle/ethgo\"\n\n// Store is a datastore for the tracker\ntype Store interface {\n\t// Ge"
},
{
"path": "tracker/store/testing.go",
"chars": 4052,
"preview": "package store\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/umbracle/ethgo\"\n)\n\n// SetupDB is a function that creates a b"
},
{
"path": "tracker/tracker.go",
"chars": 19600,
"preview": "package tracker\n\nimport (\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"math"
},
{
"path": "tracker/tracker_test.go",
"chars": 17359,
"preview": "package tracker\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"math/rand\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github."
},
{
"path": "units.go",
"chars": 440,
"preview": "package ethgo\n\nimport \"math/big\"\n\nfunc convert(val uint64, decimals int64) *big.Int {\n\tv := big.NewInt(int64(val))\n\texp "
},
{
"path": "wallet/fixtures/wallet_json.json",
"chars": 1821,
"preview": "[\n {\n \"wallet\": {\n \"crypto\": {\n \"cipher\": \"aes-128-ctr\",\n \"cipherpara"
},
{
"path": "wallet/key.go",
"chars": 2356,
"preview": "package wallet\n\nimport (\n\t\"crypto/ecdsa\"\n\t\"crypto/elliptic\"\n\t\"crypto/rand\"\n\t\"fmt\"\n\n\t\"github.com/btcsuite/btcd/btcec/v2\"\n"
},
{
"path": "wallet/key_test.go",
"chars": 356,
"preview": "package wallet\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestKeySign(t *testing.T) {\n\tkey, err"
},
{
"path": "wallet/signer.go",
"chars": 2887,
"preview": "package wallet\n\nimport (\n\t\"math/big\"\n\n\t\"github.com/umbracle/ethgo\"\n\t\"github.com/umbracle/fastrlp\"\n)\n\ntype Signer interfa"
},
{
"path": "wallet/signer_test.go",
"chars": 2120,
"preview": "package wallet\n\nimport (\n\t\"math/big\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/req"
},
{
"path": "wallet/wallet_hd.go",
"chars": 2014,
"preview": "package wallet\n\nimport (\n\t\"crypto/ecdsa\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"strings\"\n\n\t\"github.com/btcsuite/btcd/btcutil/hdkeychain\"\n\t"
},
{
"path": "wallet/wallet_hd_test.go",
"chars": 798,
"preview": "package wallet\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestWallet_Mnemonic(t *testing.T) {\n\t"
},
{
"path": "wallet/wallet_json.go",
"chars": 543,
"preview": "package wallet\n\nimport (\n\t\"io/ioutil\"\n\n\t\"github.com/umbracle/ethgo/keystore\"\n)\n\nfunc NewJSONWalletFromFile(path string, "
},
{
"path": "wallet/wallet_json_test.go",
"chars": 538,
"preview": "package wallet\n\nimport (\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestWal"
},
{
"path": "wallet/wallet_priv.go",
"chars": 359,
"preview": "package wallet\n\nimport (\n\t\"crypto/ecdsa\"\n\n\t\"github.com/btcsuite/btcd/btcec/v2\"\n)\n\nfunc ParsePrivateKey(buf []byte) (*ecd"
},
{
"path": "wallet/wallet_priv_test.go",
"chars": 335,
"preview": "package wallet\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc TestWallet_Priv(t *testing.T) {\n\tkey,"
},
{
"path": "website/README.md",
"chars": 58,
"preview": "\n# Website\n\n## Usage\n\n```\n$ npm install\n$ npm run dev\n```\n"
},
{
"path": "website/components/eip.jsx",
"chars": 192,
"preview": "\nimport Link from 'next/link'\n\nexport default function EIPLink({children, num}) {\n return <Link href={`https://github"
},
{
"path": "website/components/godoc.jsx",
"chars": 216,
"preview": "\nimport Link from 'next/link'\n\nconst goDocRef = \"https://pkg.go.dev/github.com/umbracle/ethgo/\"\n\nexport default function"
},
{
"path": "website/components/primitives.jsx",
"chars": 1000,
"preview": "\nimport Link from 'next/link'\nimport GodocLink from \"./godoc\"\n\nfunction Address({text='Address'}) {\n return <GodocLin"
},
{
"path": "website/next.config.js",
"chars": 159,
"preview": "// next.config.js\nconst withNextra = require('nextra')({\n theme: 'nextra-theme-docs',\n themeConfig: './theme.confi"
},
{
"path": "website/package.json",
"chars": 339,
"preview": "{\n \"dependencies\": {\n \"next\": \"^12.0.9\",\n \"nextra\": \"^2.0.0-alpha.23\",\n \"nextra-theme-docs\": \"^2.0.0-alpha.23\""
},
{
"path": "website/pages/_app.js",
"chars": 556,
"preview": "import 'nextra-theme-docs/style.css'\n\nimport Prism from 'prism-react-renderer/prism'\n(typeof global !== \"undefined\" ? gl"
},
{
"path": "website/pages/abi.mdx",
"chars": 1408,
"preview": "\n# Application Binary interface\n\nTo use the library import:\n\n```go\n\"github.com/umbracle/ethgo/abi\"\n```\n\nDeclare basic ob"
},
{
"path": "website/pages/cli/4byte.mdx",
"chars": 192,
"preview": "\n# 4byte\n\nThe `4byte` command resolve a function or event bytes signature to its full name using the [4byte](https://www"
},
{
"path": "website/pages/cli/abigen.mdx",
"chars": 607,
"preview": "\n# Abigen\n\nThe `abigen` command generates bindings to interact with smart contracts using Go. It requires as input the A"
},
{
"path": "website/pages/cli/ens_resolve.mdx",
"chars": 373,
"preview": "\n# Ens resolve\n\nThe `ens resolve <name>` command resolves an ENS name to its Ethereum address.\n\n## Usage\n\n```shell\n$ eth"
},
{
"path": "website/pages/cli/meta.json",
"chars": 86,
"preview": "{\n \"abigen\": \"Abigen\",\n \"version\": \"Version\",\n \"ens_resolve\": \"Ens Resolve\"\n}"
},
{
"path": "website/pages/cli/version.mdx",
"chars": 115,
"preview": "\n# Version\n\nThe `version` command outputs the version of the Ethgo binary.\n\n## Usage\n\n```shell\n$ ethgo version\n```\n"
},
{
"path": "website/pages/contract.mdx",
"chars": 2813,
"preview": "\nimport GoDocLink from '../components/godoc'\nimport EIPLink from '../components/eip'\nimport {Address, ABI} from '../comp"
},
{
"path": "website/pages/index.mdx",
"chars": 102,
"preview": "\n# Introduction\n\n`Ethgo` is a lightweight SDK in Go to interact with Ethereum compatible blockchains.\n"
},
{
"path": "website/pages/integrations/4byte.mdx",
"chars": 522,
"preview": "\nimport GoDocLink from '../../components/godoc'\n\n# 4Byte\n\n[4Byte](https://www.4byte.directory/) is a public directory th"
},
{
"path": "website/pages/integrations/ens.mdx",
"chars": 1659,
"preview": "\nimport GoDocLink from '../../components/godoc'\nimport {Address, Hash, Blocktag, Block, Transaction, Receipt} from '../."
},
{
"path": "website/pages/integrations/etherscan.mdx",
"chars": 2526,
"preview": "\nimport GoDocLink from '../../components/godoc'\nimport {Log, Address, Hash, Blocktag, Block, Transaction, Receipt, LogFi"
},
{
"path": "website/pages/integrations/meta.json",
"chars": 68,
"preview": "{\n \"ens\": \"Ethereum Name Service\",\n \"etherscan\": \"Etherscan\"\n}"
},
{
"path": "website/pages/jsonrpc/eth.mdx",
"chars": 4409,
"preview": "\nimport GoDocLink from '../../components/godoc'\nimport {Address, Hash, Blocktag, Block, Transaction, Receipt} from '../."
},
{
"path": "website/pages/jsonrpc/index.mdx",
"chars": 1508,
"preview": "\nimport GoDocLink from '../../components/godoc'\nimport {Address, Hash, Blocktag, Block, Transaction, Receipt} from '../."
},
{
"path": "website/pages/jsonrpc/meta.json",
"chars": 63,
"preview": "{\n \"index\": \"Overview\",\n \"eth\": \"Eth\",\n \"net\": \"Net\"\n}"
},
{
"path": "website/pages/jsonrpc/net.mdx",
"chars": 404,
"preview": "\nimport GoDocLink from '../../components/godoc'\nimport {Address, Hash, Blocktag, Block, Transaction, Receipt} from '../."
},
{
"path": "website/pages/meta.json",
"chars": 227,
"preview": "{\n \"index\": \"Introduction\",\n \"jsonrpc\": \"JsonRPC\",\n \"abi\": \"Application Binary Interface\",\n \"signers\": \"Sign"
},
{
"path": "website/pages/signers/signer.mdx",
"chars": 177,
"preview": "\n# Signers\n\nThe `Signer` represents an abstract entity that can sign arbitrary messages.\n\n```go\ntype Key interface {\n\tAd"
},
{
"path": "website/pages/signers/wallet.mdx",
"chars": 825,
"preview": "\nimport GoDocLink from '../../components/godoc'\n\n# Wallet\n\nThe `wallet` package is an implementation of the [Signer](./s"
},
{
"path": "website/theme.config.js",
"chars": 1131,
"preview": "export default {\n projectLink: 'https://github.com/umbracle/ethgo', // GitHub link in the navbar\n docsRepositoryBa"
}
]
About this extraction
This page contains the full source code of the umbracle/ethgo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 181 files (661.5 KB), approximately 234.9k tokens, and a symbol index with 1011 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.