{"id":21280820,"url":"https://github.com/consensysmesh/py-eip712-structs","last_synced_at":"2025-07-11T10:32:50.603Z","repository":{"id":43284535,"uuid":"174646351","full_name":"ConsenSysMesh/py-eip712-structs","owner":"ConsenSysMesh","description":"EIP712 data structure management for python","archived":false,"fork":false,"pushed_at":"2024-06-16T19:33:56.000Z","size":83,"stargazers_count":34,"open_issues_count":7,"forks_count":25,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-11-14T14:33:57.440Z","etag":null,"topics":["eip712","ethereum","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ConsenSysMesh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-09T04:05:48.000Z","updated_at":"2024-08-12T19:46:31.000Z","dependencies_parsed_at":"2024-06-18T19:45:31.913Z","dependency_job_id":"68e66426-748d-4f06-a7a1-cfd319afb9c3","html_url":"https://github.com/ConsenSysMesh/py-eip712-structs","commit_stats":{"total_commits":55,"total_committers":1,"mean_commits":55.0,"dds":0.0,"last_synced_commit":"b05c1dfe073644ceef1b339a28cd201cb6d2ea88"},"previous_names":["ajrgrubbs/py-eip712-structs"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ConsenSysMesh%2Fpy-eip712-structs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ConsenSysMesh%2Fpy-eip712-structs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ConsenSysMesh%2Fpy-eip712-structs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ConsenSysMesh%2Fpy-eip712-structs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ConsenSysMesh","download_url":"https://codeload.github.com/ConsenSysMesh/py-eip712-structs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225715945,"owners_count":17512908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["eip712","ethereum","python"],"created_at":"2024-11-21T10:41:04.666Z","updated_at":"2024-11-21T10:41:08.047Z","avatar_url":"https://github.com/ConsenSysMesh.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EIP-712 Structs  [![Build Status](https://travis-ci.org/ConsenSys/py-eip712-structs.svg?branch=master)](https://travis-ci.org/ConsenSys/py-eip712-structs) [![Coverage Status](https://coveralls.io/repos/github/ConsenSys/py-eip712-structs/badge.svg?branch=master)](https://coveralls.io/github/ConsenSys/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:\u003cbr/\u003e\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# Values can be get/set dictionary-style:\nmine['some_number'] = 4567\nassert mine['some_string'] == 'hello world'\nassert mine['some_number'] == 4567\n\n# Into a message dict - domain required\nmy_msg = mine.to_message(domain)\n\n# Into message JSON - domain required.\n# This method converts bytes types for you, which the default JSON encoder won't handle.\nmy_msg_json = mine.to_message_json(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# At this point, Message is equivalent to `struct Message { address to; address from; }`\n\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: \u003cbr/\u003e\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(\u003citem_type\u003e[, \u003coptional_length\u003e])\n```\n\n- `\u003citem_type\u003e` - The basic type or struct that will live in the array\n- `\u003coptional_length\u003e` - 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 the world! :heart:\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconsensysmesh%2Fpy-eip712-structs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconsensysmesh%2Fpy-eip712-structs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconsensysmesh%2Fpy-eip712-structs/lists"}