eip712-structs


Nameeip712-structs JSON
Version 1.1.0 PyPI version JSON
download
home_pagehttps://github.com/ajrgrubbs/py-eip712-structs
SummaryA python library for EIP712 objects
upload_time2019-06-15 04:54:49
maintainer
docs_urlNone
authorAJ Grubbs
requires_python
licenseMIT
keywords ethereum eip712 solidity
VCS
bugtrack_url
requirements atomicwrites attrdict attrs certifi chardet coverage coveralls cytoolz docopt eth-abi eth-account eth-hash eth-keyfile eth-keys eth-rlp eth-typing eth-utils hexbytes idna importlib-metadata lru-dict more-itertools packaging parsimonious pluggy py pycryptodome pyparsing pysha3 pytest pytest-cov requests rlp six toolz urllib3 wcwidth web3 websockets zipp
Travis-CI
coveralls test coverage No coveralls.
            # EIP-712 Structs  [![Build Status](https://travis-ci.org/ajrgrubbs/py-eip712-structs.svg?branch=master)](https://travis-ci.org/ajrgrubbs/py-eip712-structs) [![Coverage Status](https://coveralls.io/repos/github/ajrgrubbs/py-eip712-structs/badge.svg?branch=master)](https://coveralls.io/github/ajrgrubbs/py-eip712-structs?branch=master)

A python interface for simple EIP-712 struct construction.

In this module, a "struct" is structured data as defined in the standard.
It is not the same as the Python Standard Library's struct (e.g., `import struct`).

Read the proposal:<br/>
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md

#### Supported Python Versions
- `3.6`
- `3.7`

## Install
```bash
pip install eip712-structs
```

## Usage
See [API.md](API.md) for a succinct summary of available methods.

Examples/Details below.

#### Quickstart
Say we want to represent the following struct, convert it to a message and sign it:
```text
struct MyStruct {
    string some_string;
    uint256 some_number;
}
```

With this module, that would look like:
```python
# Make a unique domain
from eip712_structs import make_domain
domain = make_domain(name='Some name', version='1.0.0')  # Make a Domain Separator

# Define your struct type
from eip712_structs import EIP712Struct, String, Uint
class MyStruct(EIP712Struct):
    some_string = String()
    some_number = Uint(256)

# Create an instance with some data
mine = MyStruct(some_string='hello world', some_number=1234)

# Into a message dict (serializable to JSON) - domain required
my_msg = mine.to_message(domain)

# Into signable bytes - domain required
my_bytes = mine.signable_bytes(domain)
```

See [Member Types](#member-types) for more information on supported types.

#### Dynamic construction
Attributes may be added dynamically as well. This may be necessary if you
want to use a reserved keyword like `from`.

```python
from eip712_structs import EIP712Struct, Address
class Message(EIP712Struct):
    pass

Message.to = Address()
setattr(Message, 'from', Address())
```

#### The domain separator
EIP-712 specifies a domain struct, to differentiate between identical structs that may be unrelated.
A helper method exists for this purpose.
All values to the `make_domain()`
function are optional - but at least one must be defined. If omitted, the resulting
domain struct's definition leaves out the parameter entirely.

The full signature: <br/>
`make_domain(name: string, version: string, chainId: uint256, verifyingContract: address, salt: bytes32)`

##### Setting a default domain
Constantly providing the same domain can be cumbersome. You can optionally set a default, and then forget it.
It is automatically used by `.to_message()` and `.signable_bytes()`

```python
import eip712_structs

foo = SomeStruct()

my_domain = eip712_structs.make_domain(name='hello world')
eip712_structs.default_domain = my_domain

assert foo.to_message() == foo.to_message(my_domain)
assert foo.signable_bytes() == foo.signable_bytes(my_domain)
```

## Member Types

### Basic types
EIP712's basic types map directly to solidity types.

```python
from eip712_structs import Address, Boolean, Bytes, Int, String, Uint

Address()  # Solidity's 'address'
Boolean()  # 'bool'
Bytes()    # 'bytes'
Bytes(N)   # 'bytesN' - N must be an int from 1 through 32
Int(N)     # 'intN' - N must be a multiple of 8, from 8 to 256
String()   # 'string'
Uint(N)    # 'uintN' - N must be a multiple of 8, from 8 to 256
```

Use like:
```python
from eip712_structs import EIP712Struct, Address, Bytes

class Foo(EIP712Struct):
    member_name_0 = Address()
    member_name_1 = Bytes(5)
    # ...etc
```

### Struct references
In addition to holding basic types, EIP712 structs may also hold other structs!
Usage is almost the same - the difference is you don't "instantiate" the class.

Example:
```python
from eip712_structs import EIP712Struct, String

class Dog(EIP712Struct):
    name = String()
    breed = String()

class Person(EIP712Struct):
    name = String()
    dog = Dog  # Take note - no parentheses!

# Dog "stands alone"
Dog.encode_type()     # Dog(string name,string breed)

# But Person knows how to include Dog
Person.encode_type()  # Person(string name,Dog dog)Dog(string name,string breed)
```

Instantiating the structs with nested values may be done a couple different ways:

```python
# Method one: set it to a struct
dog = Dog(name='Mochi', breed='Corgi')
person = Person(name='E.M.', dog=dog)

# Method two: set it to a dict - the underlying struct is built for you
person = Person(
    name='E.M.',
    dog={
        'name': 'Mochi',
        'breed': 'Corgi',
    }
)
```

### Arrays
Arrays are also supported for the standard.

```python
array_member = Array(<item_type>[, <optional_length>])
```

- `<item_type>` - The basic type or struct that will live in the array
- `<optional_length>` - If given, the array is set to that length.

For example:
```python
dynamic_array = Array(String())      # String[] dynamic_array
static_array  = Array(String(), 10)  # String[10] static_array
struct_array = Array(MyStruct, 10)   # MyStruct[10] - again, don't instantiate structs like the basic types
```

## Development
Contributions always welcome.

Install dependencies:
- `pip install -r requirements.txt`

Run tests:
- `python setup.py test`
- Some tests expect an active local ganache chain on http://localhost:8545. Docker will compile the contracts and start the chain for you.
- Docker is optional, but useful to test the whole suite. If no chain is detected, chain tests are skipped.
- Usage:
    - `docker-compose up -d` (Starts containers in the background)
    - Note: Contracts are compiled when you run `up`, but won't be deployed until the test is run.
    - Cleanup containers when you're done: `docker-compose down`

Deploying a new version:
- Bump the version number in `setup.py`, commit it into master.
- Make a release tag on the master branch in Github. Travis should handle the rest.


## Shameless Plug
Written by [ConsenSys](https://consensys.net) for ourselves and the community! :heart:
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/ajrgrubbs/py-eip712-structs",
    "name": "eip712-structs",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "ethereum eip712 solidity",
    "author": "AJ Grubbs",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/36/e0/0c79d27da8918f7642cba8ad4b0e6176ff7a8b4774f363c6ceb2513474be/eip712-structs-1.1.0.tar.gz",
    "platform": "",
    "description": "# EIP-712 Structs  [![Build Status](https://travis-ci.org/ajrgrubbs/py-eip712-structs.svg?branch=master)](https://travis-ci.org/ajrgrubbs/py-eip712-structs) [![Coverage Status](https://coveralls.io/repos/github/ajrgrubbs/py-eip712-structs/badge.svg?branch=master)](https://coveralls.io/github/ajrgrubbs/py-eip712-structs?branch=master)\n\nA python interface for simple EIP-712 struct construction.\n\nIn this module, a \"struct\" is structured data as defined in the standard.\nIt is not the same as the Python Standard Library's struct (e.g., `import struct`).\n\nRead the proposal:<br/>\nhttps://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md\n\n#### Supported Python Versions\n- `3.6`\n- `3.7`\n\n## Install\n```bash\npip install eip712-structs\n```\n\n## Usage\nSee [API.md](API.md) for a succinct summary of available methods.\n\nExamples/Details below.\n\n#### Quickstart\nSay we want to represent the following struct, convert it to a message and sign it:\n```text\nstruct MyStruct {\n    string some_string;\n    uint256 some_number;\n}\n```\n\nWith this module, that would look like:\n```python\n# Make a unique domain\nfrom eip712_structs import make_domain\ndomain = make_domain(name='Some name', version='1.0.0')  # Make a Domain Separator\n\n# Define your struct type\nfrom eip712_structs import EIP712Struct, String, Uint\nclass MyStruct(EIP712Struct):\n    some_string = String()\n    some_number = Uint(256)\n\n# Create an instance with some data\nmine = MyStruct(some_string='hello world', some_number=1234)\n\n# Into a message dict (serializable to JSON) - domain required\nmy_msg = mine.to_message(domain)\n\n# Into signable bytes - domain required\nmy_bytes = mine.signable_bytes(domain)\n```\n\nSee [Member Types](#member-types) for more information on supported types.\n\n#### Dynamic construction\nAttributes may be added dynamically as well. This may be necessary if you\nwant to use a reserved keyword like `from`.\n\n```python\nfrom eip712_structs import EIP712Struct, Address\nclass Message(EIP712Struct):\n    pass\n\nMessage.to = Address()\nsetattr(Message, 'from', Address())\n```\n\n#### The domain separator\nEIP-712 specifies a domain struct, to differentiate between identical structs that may be unrelated.\nA helper method exists for this purpose.\nAll values to the `make_domain()`\nfunction are optional - but at least one must be defined. If omitted, the resulting\ndomain struct's definition leaves out the parameter entirely.\n\nThe full signature: <br/>\n`make_domain(name: string, version: string, chainId: uint256, verifyingContract: address, salt: bytes32)`\n\n##### Setting a default domain\nConstantly providing the same domain can be cumbersome. You can optionally set a default, and then forget it.\nIt is automatically used by `.to_message()` and `.signable_bytes()`\n\n```python\nimport eip712_structs\n\nfoo = SomeStruct()\n\nmy_domain = eip712_structs.make_domain(name='hello world')\neip712_structs.default_domain = my_domain\n\nassert foo.to_message() == foo.to_message(my_domain)\nassert foo.signable_bytes() == foo.signable_bytes(my_domain)\n```\n\n## Member Types\n\n### Basic types\nEIP712's basic types map directly to solidity types.\n\n```python\nfrom eip712_structs import Address, Boolean, Bytes, Int, String, Uint\n\nAddress()  # Solidity's 'address'\nBoolean()  # 'bool'\nBytes()    # 'bytes'\nBytes(N)   # 'bytesN' - N must be an int from 1 through 32\nInt(N)     # 'intN' - N must be a multiple of 8, from 8 to 256\nString()   # 'string'\nUint(N)    # 'uintN' - N must be a multiple of 8, from 8 to 256\n```\n\nUse like:\n```python\nfrom eip712_structs import EIP712Struct, Address, Bytes\n\nclass Foo(EIP712Struct):\n    member_name_0 = Address()\n    member_name_1 = Bytes(5)\n    # ...etc\n```\n\n### Struct references\nIn addition to holding basic types, EIP712 structs may also hold other structs!\nUsage is almost the same - the difference is you don't \"instantiate\" the class.\n\nExample:\n```python\nfrom eip712_structs import EIP712Struct, String\n\nclass Dog(EIP712Struct):\n    name = String()\n    breed = String()\n\nclass Person(EIP712Struct):\n    name = String()\n    dog = Dog  # Take note - no parentheses!\n\n# Dog \"stands alone\"\nDog.encode_type()     # Dog(string name,string breed)\n\n# But Person knows how to include Dog\nPerson.encode_type()  # Person(string name,Dog dog)Dog(string name,string breed)\n```\n\nInstantiating the structs with nested values may be done a couple different ways:\n\n```python\n# Method one: set it to a struct\ndog = Dog(name='Mochi', breed='Corgi')\nperson = Person(name='E.M.', dog=dog)\n\n# Method two: set it to a dict - the underlying struct is built for you\nperson = Person(\n    name='E.M.',\n    dog={\n        'name': 'Mochi',\n        'breed': 'Corgi',\n    }\n)\n```\n\n### Arrays\nArrays are also supported for the standard.\n\n```python\narray_member = Array(<item_type>[, <optional_length>])\n```\n\n- `<item_type>` - The basic type or struct that will live in the array\n- `<optional_length>` - If given, the array is set to that length.\n\nFor example:\n```python\ndynamic_array = Array(String())      # String[] dynamic_array\nstatic_array  = Array(String(), 10)  # String[10] static_array\nstruct_array = Array(MyStruct, 10)   # MyStruct[10] - again, don't instantiate structs like the basic types\n```\n\n## Development\nContributions always welcome.\n\nInstall dependencies:\n- `pip install -r requirements.txt`\n\nRun tests:\n- `python setup.py test`\n- Some tests expect an active local ganache chain on http://localhost:8545. Docker will compile the contracts and start the chain for you.\n- Docker is optional, but useful to test the whole suite. If no chain is detected, chain tests are skipped.\n- Usage:\n    - `docker-compose up -d` (Starts containers in the background)\n    - Note: Contracts are compiled when you run `up`, but won't be deployed until the test is run.\n    - Cleanup containers when you're done: `docker-compose down`\n\nDeploying a new version:\n- Bump the version number in `setup.py`, commit it into master.\n- Make a release tag on the master branch in Github. Travis should handle the rest.\n\n\n## Shameless Plug\nWritten by [ConsenSys](https://consensys.net) for ourselves and the community! :heart:",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A python library for EIP712 objects",
    "version": "1.1.0",
    "project_urls": {
        "Homepage": "https://github.com/ajrgrubbs/py-eip712-structs"
    },
    "split_keywords": [
        "ethereum",
        "eip712",
        "solidity"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "36e00c79d27da8918f7642cba8ad4b0e6176ff7a8b4774f363c6ceb2513474be",
                "md5": "91b66a28a1e8343dd6fe94312d12aa5d",
                "sha256": "b24400aef07b4d0287fb9bf8ce02b0abbe80c476d1b67222a7c5158df3a3e38d"
            },
            "downloads": -1,
            "filename": "eip712-structs-1.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "91b66a28a1e8343dd6fe94312d12aa5d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 12853,
            "upload_time": "2019-06-15T04:54:49",
            "upload_time_iso_8601": "2019-06-15T04:54:49.299015Z",
            "url": "https://files.pythonhosted.org/packages/36/e0/0c79d27da8918f7642cba8ad4b0e6176ff7a8b4774f363c6ceb2513474be/eip712-structs-1.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2019-06-15 04:54:49",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ajrgrubbs",
    "github_project": "py-eip712-structs",
    "travis_ci": true,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "atomicwrites",
            "specs": [
                [
                    "==",
                    "1.3.0"
                ]
            ]
        },
        {
            "name": "attrdict",
            "specs": [
                [
                    "==",
                    "2.0.1"
                ]
            ]
        },
        {
            "name": "attrs",
            "specs": [
                [
                    "==",
                    "19.1.0"
                ]
            ]
        },
        {
            "name": "certifi",
            "specs": [
                [
                    "==",
                    "2019.3.9"
                ]
            ]
        },
        {
            "name": "chardet",
            "specs": [
                [
                    "==",
                    "3.0.4"
                ]
            ]
        },
        {
            "name": "coverage",
            "specs": [
                [
                    "==",
                    "4.5.3"
                ]
            ]
        },
        {
            "name": "coveralls",
            "specs": [
                [
                    "==",
                    "1.8.0"
                ]
            ]
        },
        {
            "name": "cytoolz",
            "specs": [
                [
                    "==",
                    "0.9.0.1"
                ]
            ]
        },
        {
            "name": "docopt",
            "specs": [
                [
                    "==",
                    "0.6.2"
                ]
            ]
        },
        {
            "name": "eth-abi",
            "specs": [
                [
                    "==",
                    "1.3.0"
                ]
            ]
        },
        {
            "name": "eth-account",
            "specs": [
                [
                    "==",
                    "0.3.0"
                ]
            ]
        },
        {
            "name": "eth-hash",
            "specs": [
                [
                    "==",
                    "0.2.0"
                ]
            ]
        },
        {
            "name": "eth-keyfile",
            "specs": [
                [
                    "==",
                    "0.5.1"
                ]
            ]
        },
        {
            "name": "eth-keys",
            "specs": [
                [
                    "==",
                    "0.2.3"
                ]
            ]
        },
        {
            "name": "eth-rlp",
            "specs": [
                [
                    "==",
                    "0.1.2"
                ]
            ]
        },
        {
            "name": "eth-typing",
            "specs": [
                [
                    "==",
                    "2.1.0"
                ]
            ]
        },
        {
            "name": "eth-utils",
            "specs": [
                [
                    "==",
                    "1.6.0"
                ]
            ]
        },
        {
            "name": "hexbytes",
            "specs": [
                [
                    "==",
                    "0.2.0"
                ]
            ]
        },
        {
            "name": "idna",
            "specs": [
                [
                    "==",
                    "2.8"
                ]
            ]
        },
        {
            "name": "importlib-metadata",
            "specs": [
                [
                    "==",
                    "0.17"
                ]
            ]
        },
        {
            "name": "lru-dict",
            "specs": [
                [
                    "==",
                    "1.1.6"
                ]
            ]
        },
        {
            "name": "more-itertools",
            "specs": [
                [
                    "==",
                    "7.0.0"
                ]
            ]
        },
        {
            "name": "packaging",
            "specs": [
                [
                    "==",
                    "19.0"
                ]
            ]
        },
        {
            "name": "parsimonious",
            "specs": [
                [
                    "==",
                    "0.8.1"
                ]
            ]
        },
        {
            "name": "pluggy",
            "specs": [
                [
                    "==",
                    "0.12.0"
                ]
            ]
        },
        {
            "name": "py",
            "specs": [
                [
                    "==",
                    "1.8.0"
                ]
            ]
        },
        {
            "name": "pycryptodome",
            "specs": [
                [
                    "==",
                    "3.8.2"
                ]
            ]
        },
        {
            "name": "pyparsing",
            "specs": [
                [
                    "==",
                    "2.4.0"
                ]
            ]
        },
        {
            "name": "pysha3",
            "specs": [
                [
                    "==",
                    "1.0.2"
                ]
            ]
        },
        {
            "name": "pytest",
            "specs": [
                [
                    "==",
                    "4.6.2"
                ]
            ]
        },
        {
            "name": "pytest-cov",
            "specs": [
                [
                    "==",
                    "2.7.1"
                ]
            ]
        },
        {
            "name": "requests",
            "specs": [
                [
                    "==",
                    "2.22.0"
                ]
            ]
        },
        {
            "name": "rlp",
            "specs": [
                [
                    "==",
                    "1.1.0"
                ]
            ]
        },
        {
            "name": "six",
            "specs": [
                [
                    "==",
                    "1.12.0"
                ]
            ]
        },
        {
            "name": "toolz",
            "specs": [
                [
                    "==",
                    "0.9.0"
                ]
            ]
        },
        {
            "name": "urllib3",
            "specs": [
                [
                    "==",
                    "1.25.3"
                ]
            ]
        },
        {
            "name": "wcwidth",
            "specs": [
                [
                    "==",
                    "0.1.7"
                ]
            ]
        },
        {
            "name": "web3",
            "specs": [
                [
                    "==",
                    "4.9.2"
                ]
            ]
        },
        {
            "name": "websockets",
            "specs": [
                [
                    "==",
                    "6.0"
                ]
            ]
        },
        {
            "name": "zipp",
            "specs": [
                [
                    "==",
                    "0.5.1"
                ]
            ]
        }
    ],
    "lcname": "eip712-structs"
}
        
Elapsed time: 0.07659s