def validate_rpc_transaction_vs_fixture(transaction, fixture): expected = fixture_transaction_in_rpc_format(fixture) actual_transaction = dissoc( transaction, 'hash', ) assert actual_transaction == expected
def pack_transaction(trx): global g_chain_id trx = dissoc(trx, 'from') trx = serializable_unsigned_transaction_from_dict(trx) trx = encode_transaction(trx, vrs=(g_chain_id, 0, 0)) trx = trx.hex() return trx
def sign_transaction(self, transaction_dict): if not isinstance(transaction_dict, Mapping): raise TypeError("transaction_dict must be dict-like, got %r" % transaction_dict) # allow from field, *only* if it matches the private key if 'from' in transaction_dict: if transaction_dict['from'] == self.KeyPair.address: sanitized_transaction = dissoc(transaction_dict, 'from') else: raise TypeError("from field must match key's %s, but it was %s" % ( self.KeyPair.address, transaction_dict['from'], )) else: sanitized_transaction = transaction_dict # sign transaction ( v, r, s, rlp_encoded, ) = self.sign_transaction_dict(sanitized_transaction) transaction_hash = keccak(rlp_encoded) return AttributeDict({ 'rawTransaction': HexBytes(rlp_encoded), 'hash': HexBytes(transaction_hash), 'r': r, 's': s, 'v': v, })
def _add_transaction_to_pending_block(self, transaction, txn_type='send'): self.validator.validate_inbound_transaction(transaction, txn_type=txn_type) raw_transaction = self.normalizer.normalize_inbound_transaction(transaction) if raw_transaction['from'] in self._account_passwords: unlocked_until = self._account_unlock[raw_transaction['from']] account_password = self._account_passwords[raw_transaction['from']] is_locked = account_password is not None and unlocked_until is not None and ( unlocked_until is False or time.time() > unlocked_until ) if is_locked: raise AccountLocked("The account is currently locked") if {'r', 's', 'v'}.issubset(transaction.keys()): try: raw_transaction_hash = self.backend.send_signed_transaction(raw_transaction) except NotImplementedError: unsigned_transaction = dissoc(raw_transaction, 'r', 's', 'v') raw_transaction_hash = self.backend.send_transaction(unsigned_transaction) else: raw_transaction_hash = self.backend.send_transaction(raw_transaction) self.validator.validate_outbound_transaction_hash(raw_transaction_hash) transaction_hash = self.normalizer.normalize_outbound_transaction_hash( raw_transaction_hash, ) self._handle_filtering_for_transaction(transaction_hash) return transaction_hash
def request_status(scan_id): request = scan_db.get(scan_id) def _dirty(system_name): return market_db.get(("dirty", system_name), default=None) dirty = groupby(_dirty, request["system_names"]) system_completion = { ("Partial" if k is True else "Complete" if k is False else "Pending"): len(v) for (k, v) in dirty.items() } num_systems = len(request["system_names"]) partial_or_pending = (system_completion.get("Partial", 0) + system_completion.get("Pending", 0)) system_completion_percent = 100 * ( (num_systems - partial_or_pending) / num_systems) def _shell_status(item): return AsyncResult(item["task_id"]).state shell_completion = groupby(_shell_status, request["tasks"].values()) return { "scan_id": request["scan_id"], "location": request["location"], "radius": request["radius"], "system_completion_percent": system_completion_percent, "system_completion": system_completion, "system_names": request["system_names"], "tasks": shell_completion, "unfinished_shells": dissoc(shell_completion, "SUCCESS"), }
def validate_rpc_transaction_vs_fixture(transaction, fixture): expected = fixture_transaction_in_rpc_format(fixture) actual_transaction = dissoc( transaction, 'hash', ) assert actual_transaction == expected
def get_timed_out(self) -> List[Hash32]: timed_out = cytoolz.valfilter( lambda v: time.time() - v[0] > self.reply_timeout, self.active_requests) for peer, (_, node_keys) in timed_out.items(): self.logger.debug( "Timed out waiting for %d nodes from %s", len(node_keys), peer) self.active_requests = cytoolz.dissoc(self.active_requests, *timed_out.keys()) return list(cytoolz.concat(node_keys for _, node_keys in timed_out.values()))
def test_build_transaction_with_contract_fallback_function(web3, fallback_function_contract): txn = fallback_function_contract.fallback.buildTransaction() assert dissoc(txn, 'gas') == { 'to': fallback_function_contract.address, 'data': '0x', 'value': 0, 'gasPrice': 1, 'chainId': 1 }
def test_build_transaction_with_contract_no_arguments(web3, math_contract, buildTransaction): txn = buildTransaction(contract=math_contract, contract_function='increment') assert dissoc(txn, 'gas') == { 'to': math_contract.address, 'data': '0xd09de08a', 'value': 0, 'gasPrice': 1, 'chainId': 1 }
def encode_transaction(unsigned_transaction, vrs): (v, r, s) = vrs chain_naive_transaction = dissoc(unsigned_transaction.as_dict(), 'v', 'r', 's') signed_transaction = BcosTransaction(v=v, r=r, s=s, **chain_naive_transaction) return rlp.encode(signed_transaction)
def load_and_clean(name): with open("building_permit_data/{0}.json".format(name)) as f: data = ujson.load(f) lines = data[name] new_lines = [dissoc(l, exclude) for l in lines] df = pd.DataFrame.from_records(new_lines) for k in df.columns: if k in fields: df[k] = df[k].astype(fields[k]) return df
def load_and_clean(name): with open('building_permit_data/{0}.json'.format(name)) as f: data = ujson.load(f) lines = data[name] new_lines = [dissoc(l, exclude) for l in lines] df = pd.DataFrame.from_records(new_lines) for k in df.columns: if k in fields: df[k] = df[k].astype(fields[k]) return df
def validate_rpc_block_vs_fixture_header(block, header_fixture): expected = fixture_block_in_rpc_format(header_fixture) actual_block = dissoc( block, 'size', 'totalDifficulty', 'transactions', 'uncles', ) assert actual_block == expected
def validate_rpc_block_vs_fixture_header(block, header_fixture): expected = fixture_block_in_rpc_format(header_fixture) actual_block = dissoc( block, 'size', 'totalDifficulty', 'transactions', 'uncles', ) assert actual_block == expected
def test_build_transaction_with_contract_fallback_function( web3, fallback_function_contract): txn = fallback_function_contract.fallback.buildTransaction() assert dissoc(txn, 'gas') == { 'to': fallback_function_contract.address, 'data': '0x', 'value': 0, 'gasPrice': 1, 'chainId': 1 }
def test_build_transaction_with_contract_default_account_is_set( web3, math_contract, buildTransaction): txn = buildTransaction(contract=math_contract, contract_function='increment') assert dissoc(txn, 'gas') == { 'to': math_contract.address, 'data': '0xd09de08a', 'value': 0, 'gasPrice': 1, 'chainId': 1 }
def inner(*args: Any, **kwargs: Any) -> Any: try: log_queue = kwargs['log_queue'] except KeyError: raise KeyError(f"The `log_queue` argument is required when calling `{fn.__name__}`") else: level = kwargs.get('log_level', logging.INFO) setup_queue_logging(log_queue, level) inner_kwargs = dissoc(kwargs, 'log_queue', 'log_level') return fn(*args, **inner_kwargs)
def difference(self, other: Type['GeneSignature']) -> Type['GeneSignature']: """ Creates a new :class:`GeneSignature` instance which is the difference of this signature and the supplied other signature. The weight associated with the genes in the difference are taken from this gene signature. :param other: The other :class:`GeneSignature`. :return: the new :class:`GeneSignature` instance. """ return self.copy(name="({} - {})".format(self.name, other.name) if self.name != other.name else self.name, gene2weight=frozendict(dissoc(dict(self.gene2weight), *other.genes)))
def test_build_transaction_with_gas_price_strategy_set(web3, math_contract, buildTransaction): def my_gas_price_strategy(web3, transaction_params): return 5 web3.eth.setGasPriceStrategy(my_gas_price_strategy) txn = buildTransaction(contract=math_contract, contract_function='increment') assert dissoc(txn, 'gas') == { 'to': math_contract.address, 'data': '0xd09de08a', 'value': 0, 'gasPrice': 5, 'chainId': 1 }
def encode_transaction( unsigned_transaction, vrs ): # https://github.com/ethereum/eth-account/blob/00e7b10005c5fa7090086fcef37a76296c524e17/eth_account/_utils/transactions.py#L55 '''serialize and encode an unsigned transaction with v,r,s''' (v, r, s) = vrs chain_naive_transaction = dissoc(unsigned_transaction.as_dict(), 'v', 'r', 's') if isinstance(unsigned_transaction, (UnsignedHarmonyTxData, SignedHarmonyTxData)): serializer = SignedHarmonyTxData else: serializer = SignedEthereumTxData signed_transaction = serializer(v=v, r=r, s=s, **chain_naive_transaction) return rlp.encode(signed_transaction)
def encode_transaction(unsigned_transaction, vrs): (v, r, s) = vrs chain_naive_transaction = dissoc(unsigned_transaction.as_dict(), 'v', 'r', 's') if isinstance(unsigned_transaction, TypedTransaction): # Typed transaction have their own encoding format, so we must delegate the encoding. chain_naive_transaction['v'] = v chain_naive_transaction['r'] = r chain_naive_transaction['s'] = s signed_typed_transaction = TypedTransaction.from_dict( chain_naive_transaction) return signed_typed_transaction.encode() signed_transaction = Transaction(v=v, r=r, s=s, **chain_naive_transaction) return rlp.encode(signed_transaction)
def test_build_transaction_with_gas_price_strategy_set(web3, math_contract, buildTransaction): def my_gas_price_strategy(web3, transaction_params): return 5 web3.eth.setGasPriceStrategy(my_gas_price_strategy) txn = buildTransaction(contract=math_contract, contract_function='increment') assert dissoc(txn, 'gas') == { 'to': math_contract.address, 'data': '0xd09de08a', 'value': 0, 'gasPrice': 5, 'chainId': 1 }
def test_build_transaction_with_contract_class_method(web3, MathContract, math_contract, buildTransaction): txn = buildTransaction( contract=MathContract, contract_function='increment', tx_params={'to': math_contract.address}, ) assert dissoc(txn, 'gas') == { 'to': math_contract.address, 'data': '0xd09de08a', 'value': 0, 'gasPrice': 1, 'chainId': 1 }
def inner(*args, **kwargs): print(args, kwargs) try: log_queue = kwargs['log_queue'] except KeyError: raise KeyError( "The `log_queue` argument is required when calling `{0}`". format(fn.__name__, )) else: log_level = kwargs.get('log_level', logging.INFO) setup_queue_logging(log_queue, level=log_level) inner_kwargs = dissoc(kwargs, 'log_queue', 'log_level') return fn(*args, **inner_kwargs)
def inner(*args, **kwargs): print(args, kwargs) try: log_queue = kwargs['log_queue'] except KeyError: raise KeyError("The `log_queue` argument is required when calling `{0}`".format( fn.__name__, )) else: log_level = kwargs.get('log_level', logging.INFO) setup_queue_logging(log_queue, level=log_level) inner_kwargs = dissoc(kwargs, 'log_queue', 'log_level') return fn(*args, **inner_kwargs)
def test_build_transaction_with_contract_class_method( web3, MathContract, math_contract, buildTransaction): txn = buildTransaction( contract=MathContract, contract_function='increment', tx_params={'to': math_contract.address}, ) assert dissoc(txn, 'gas') == { 'to': math_contract.address, 'data': '0xd09de08a', 'value': 0, 'gasPrice': 1, 'chainId': 1 }
def test_wan_account_sign_transaction_from_eth_test(acct, transaction): expected_raw_txn = transaction['signed'] key = transaction['key'] unsigned_txn = dissoc(transaction, 'key', 'signed', 'unsigned') # validate r, in order to validate the transaction hash # There is some ambiguity about whether `r` will always be deterministically # generated from the transaction hash and private key, mostly due to code # author's ignorance. The example test fixtures and implementations seem to agree, so far. # See ecdsa_raw_sign() in /eth_keys/backends/native/ecdsa.py signed = acct.sign_transaction(unsigned_txn, key) assert signed.r == to_int(hexstr=expected_raw_txn[-130:-66]) # confirm that signed transaction can be recovered to the sender expected_sender = acct.from_key(key).address assert acct.recover_transaction(signed.rawTransaction) == expected_sender
def test_build_transaction_with_contract_with_arguments( web3, skip_if_testrpc, math_contract, transaction_args, method_args, method_kwargs, expected, skip_testrpc, buildTransaction): if skip_testrpc: skip_if_testrpc(web3) txn = buildTransaction(contract=math_contract, contract_function='increment', func_args=method_args, func_kwargs=method_kwargs, tx_params=transaction_args) expected['to'] = math_contract.address assert txn is not None if 'gas' in transaction_args: assert txn['gas'] == transaction_args['gas'] else: assert 'gas' in txn assert dissoc(txn, 'gas') == expected
def middleware(method, params): result = make_request(method, params) # As of v1.8, Geth returns errors when you request a # receipt for a transaction that is not in the chain. # It used to return a result of None, so we simulate the old behavior. if method == 'eth_getTransactionReceipt' and 'error' in result: is_geth = web3.version.node.startswith('Geth') if is_geth and result['error']['code'] == -32000: return assoc( dissoc(result, 'error'), 'result', None, ) else: return result else: return result
def middleware(method, params): result = make_request(method, params) # As of v1.8, Ghuc returns errors when you request a # receipt for a transaction that is not in the chain. # It used to return a result of None, so we simulate the old behavior. if method == 'eth_getTransactionReceipt' and 'error' in result: is_ghuc = webu.version.node.startswith('Ghuc') if is_ghuc and result['error']['code'] == -32000: return assoc( dissoc(result, 'error'), 'result', None, ) else: return result else: return result
def hash(self) -> bytes: """ Hashes this DynamicFeeTransaction to prepare it for signing. As per the EIP-1559 specifications, the signature is a secp256k1 signature over keccak256(0x02 || rlp([chainId, nonce, maxPriorityFeePerGas, maxFeePerGas, gasLimit, to, value, data, accessList])). Here, we compute the keccak256(...) hash. """ # Remove signature fields. transaction_without_signature_fields = dissoc(self.dictionary, 'v', 'r', 's') # RPC-structured transaction to rlp-structured transaction rlp_structured_txn_without_sig_fields = transaction_rpc_to_rlp_structure( transaction_without_signature_fields ) rlp_serializer = self.__class__._unsigned_transaction_serializer hash = pipe( rlp_serializer.from_dict(rlp_structured_txn_without_sig_fields), # type: ignore lambda val: rlp.encode(val), # rlp([...]) lambda val: bytes([self.__class__.transaction_type]) + val, # (0x02 || rlp([...])) keccak, # keccak256(0x02 || rlp([...])) ) return cast(bytes, hash)
def sanitize_transaction(transaction_dict, private_key): '''remove the originating address from the dict and convert chainId to int''' account = Account.from_key( private_key ) # get account, from which you can derive public + private key transaction_dict = transaction_dict.copy( ) # do not alter the original dictionary if 'from' in transaction_dict: transaction_dict['from'] = convert_one_to_hex(transaction_dict['from']) if transaction_dict[ 'from'] == account.address: # https://github.com/ethereum/eth-account/blob/00e7b10005c5fa7090086fcef37a76296c524e17/eth_account/account.py#L650 sanitized_transaction = dissoc(transaction_dict, 'from') else: raise TypeError("from field must match key's %s, but it was %s" % ( account.address, transaction_dict['from'], )) if 'chainId' in transaction_dict: transaction_dict['chainId'] = chain_id_to_int( transaction_dict['chainId']) return account, transaction_dict
def test_build_transaction_with_contract_with_arguments(web3, skip_if_testrpc, math_contract, transaction_args, method_args, method_kwargs, expected, skip_testrpc, buildTransaction): if skip_testrpc: skip_if_testrpc(web3) txn = buildTransaction(contract=math_contract, contract_function='increment', func_args=method_args, func_kwargs=method_kwargs, tx_params=transaction_args) expected['to'] = math_contract.address assert txn is not None if 'gas' in transaction_args: assert txn['gas'] == transaction_args['gas'] else: assert 'gas' in txn assert dissoc(txn, 'gas') == expected
def encode_transaction(unsigned_transaction, vrs): (v, r, s) = vrs chain_naive_transaction = dissoc(vars(unsigned_transaction), 'v', 'r', 's') signed_transaction = Transaction(v=v, r=r, s=s, **chain_naive_transaction) return rlp.encode(signed_transaction)
def sign_transaction(self, transaction_dict, private_key): """ Sign a transaction using a local private key. It produces signature details and the hex-encoded transaction suitable for broadcast using :meth:`w3.eth.sendRawTransaction() <web3.eth.Eth.sendRawTransaction>`. To create the transaction dict that calls a contract, use contract object: `my_contract.functions.my_function().buildTransaction() <http://web3py.readthedocs.io/en/latest/contracts.html#methods>`_ Note: For non-legacy (typed) transactions, if the transaction type is not explicitly provided, it may be determined from the transaction parameters of a well-formed transaction. See below for examples on how to sign with different transaction types. :param dict transaction_dict: the transaction with available keys, depending on the type of transaction: nonce, chainId, to, data, value, gas, gasPrice, type, accessList, maxFeePerGas, and maxPriorityFeePerGas :param private_key: the private key to sign the data with :type private_key: hex str, bytes, int or :class:`eth_keys.datatypes.PrivateKey` :returns: Various details about the signature - most importantly the fields: v, r, and s :rtype: AttributeDict .. code-block:: python >>> # EIP-1559 dynamic fee transaction (more efficient and preferred over legacy txn) >>> dynamic_fee_transaction = { "type": 2, # optional - can be implicitly determined based on max fee params # noqa: E501 "gas": 100000, "maxFeePerGas": 2000000000, "maxPriorityFeePerGas": 2000000000, "data": "0x616263646566", "nonce": 34, "to": "0x09616C3d61b3331fc4109a9E41a8BDB7d9776609", "value": "0x5af3107a4000", "accessList": ( # optional { "address": "0x0000000000000000000000000000000000000001", "storageKeys": ( "0x0100000000000000000000000000000000000000000000000000000000000000", # noqa: E501 ) }, ), "chainId": 1900, } >>> key = '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318' >>> signed = Account.sign_transaction(dynamic_fee_transaction, key) {'hash': HexBytes('0x126431f2a7fda003aada7c2ce52b0ce3cbdbb1896230d3333b9eea24f42d15b0'), 'r': 110093478023675319011132687961420618950720745285952062287904334878381994888509, 'rawTransaction': HexBytes('0x02f8b282076c2284773594008477359400830186a09409616c3d61b3331fc4109a9e41a8bdb7d9776609865af3107a400086616263646566f838f7940000000000000000000000000000000000000001e1a0010000000000000000000000000000000000000000000000000000000000000080a0f366b34a5c206859b9778b4c909207e53443cca9e0b82e0b94bc4b47e6434d3da04a731eda413a944d4ea2d2236671e586e57388d0e9d40db53044ae4089f2aec8'), # noqa: E501 's': 33674551144139401179914073499472892825822542092106065756005379322302694600392, 'v': 0} >>> w3.eth.sendRawTransaction(signed.rawTransaction) .. code-block:: python >>> # legacy transaction (less efficient than EIP-1559 dynamic fee txn) >>> legacy_transaction = { # Note that the address must be in checksum format or native bytes: 'to': '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55', 'value': 1000000000, 'gas': 2000000, 'gasPrice': 234567897654321, 'nonce': 0, 'chainId': 1 } >>> key = '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318' >>> signed = Account.sign_transaction(legacy_transaction, key) {'hash': HexBytes('0x6893a6ee8df79b0f5d64a180cd1ef35d030f3e296a5361cf04d02ce720d32ec5'), 'r': 4487286261793418179817841024889747115779324305375823110249149479905075174044, 'rawTransaction': HexBytes('0xf86a8086d55698372431831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a009ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9ca0440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428'), # noqa: E501 's': 30785525769477805655994251009256770582792548537338581640010273753578382951464, 'v': 37} >>> w3.eth.sendRawTransaction(signed.rawTransaction) .. code-block:: python >>> access_list_transaction = { "type": 1, # optional - can be implicitly determined based on 'accessList' and 'gasPrice' params # noqa: E501 "gas": 100000, "gasPrice": 1000000000, "data": "0x616263646566", "nonce": 34, "to": "0x09616C3d61b3331fc4109a9E41a8BDB7d9776609", "value": "0x5af3107a4000", "accessList": ( { "address": "0x0000000000000000000000000000000000000001", "storageKeys": ( "0x0100000000000000000000000000000000000000000000000000000000000000", # noqa: E501 ) }, ), "chainId": 1900, } >>> key = '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318' >>> signed = Account.sign_transaction(access_list_transaction, key) {'hash': HexBytes('0x2864ca20a74ca5e044067ad4139a22ff5a0853434f5f1dc00108f24ef5f1f783'), 'r': 105940705063391628472351883894091935317142890114440570831409400676736873197702, 'rawTransaction': HexBytes('0x01f8ad82076c22843b9aca00830186a09409616c3d61b3331fc4109a9e41a8bdb7d9776609865af3107a400086616263646566f838f7940000000000000000000000000000000000000001e1a0010000000000000000000000000000000000000000000000000000000000000080a0ea38506c4afe4bb402e030877fbe1011fa1da47aabcf215db8da8fee5d3af086a051e9af653b8eb98e74e894a766cf88904dbdb10b0bc1fbd12f18f661fa2797a4'), # noqa: E501 's': 37050226636175381535892585331727388340134760347943439553552848647212419749796, 'v': 0} >>> w3.eth.sendRawTransaction(signed.rawTransaction) """ if not isinstance(transaction_dict, Mapping): raise TypeError("transaction_dict must be dict-like, got %r" % transaction_dict) account = self.from_key(private_key) # allow from field, *only* if it matches the private key if 'from' in transaction_dict: if transaction_dict['from'] == account.address: sanitized_transaction = dissoc(transaction_dict, 'from') else: raise TypeError("from field must match key's %s, but it was %s" % ( account.address, transaction_dict['from'], )) else: sanitized_transaction = transaction_dict # sign transaction ( v, r, s, encoded_transaction, ) = sign_transaction_dict(account._key_obj, sanitized_transaction) transaction_hash = keccak(encoded_transaction) return SignedTransaction( rawTransaction=HexBytes(encoded_transaction), hash=HexBytes(transaction_hash), r=r, s=s, v=v, )
(assoc(GOOD_TXN, 'from', '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf'), {'from'}), (dict(GOOD_TXN, gas='0e1'), {'gas'}), (dict(GOOD_TXN, gasPrice='0e1'), {'gasPrice'}), (dict(GOOD_TXN, value='0e1'), {'value'}), (dict(GOOD_TXN, nonce='0e1'), {'nonce'}), (dict(GOOD_TXN, gas='0b1'), {'gas'}), (dict(GOOD_TXN, gasPrice='0b1'), {'gasPrice'}), (dict(GOOD_TXN, value='0b1'), {'value'}), (dict(GOOD_TXN, nonce='0b1'), {'nonce'}), (dict(GOOD_TXN, chainId=None), {}), (dict(GOOD_TXN, chainId='0x1'), {}), (dict(GOOD_TXN, chainId='1'), {'chainId'}), # superfluous keys will be rejected (note the lower case p) (dict(GOOD_TXN, gasprice=1), {'gasprice'}), # missing keys will be called out explicitly (dissoc(GOOD_TXN, 'gasPrice'), {'gasPrice'}), (dissoc(GOOD_TXN, 'gas'), {'gas'}), (dissoc(GOOD_TXN, 'nonce'), {'nonce'}), ), ) def test_invalid_transaction_fields(txn_dict, bad_fields): if not bad_fields: Account.signTransaction(txn_dict, TEST_PRIVATE_KEY) else: with pytest.raises(TypeError) as excinfo: Account.signTransaction(txn_dict, TEST_PRIVATE_KEY) for field in bad_fields: assert field in str(excinfo.value)
def transaction_normalizer(transaction): return dissoc(transaction, 'chainId')
def remove_key_if(key, remove_if, input_dict): if key in input_dict and remove_if(input_dict): return dissoc(input_dict, key) else: return input_dict
def strip_id(result): if result is not None: return dissoc(result, "_id") else: return None
def sign_transaction(self, transaction_dict, private_key): """ Sign a transaction using a local private key. Produces signature details and the hex-encoded transaction suitable for broadcast using :meth:`w3.eth.sendRawTransaction() <web3.eth.Eth.sendRawTransaction>`. Create the transaction dict for a contract method with `my_contract.functions.my_function().buildTransaction() <http://web3py.readthedocs.io/en/latest/contracts.html#methods>`_ :param dict transaction_dict: the transaction with keys: nonce, chainId, to, data, value, gas, and gasPrice. :param private_key: the private key to sign the data with :type private_key: hex str, bytes, int or :class:`eth_keys.datatypes.PrivateKey` :returns: Various details about the signature - most importantly the fields: v, r, and s :rtype: AttributeDict .. code-block:: python >>> transaction = { # Note that the address must be in checksum format or native bytes: 'to': '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55', 'value': 1000000000, 'gas': 2000000, 'gasPrice': 234567897654321, 'nonce': 0, 'chainId': 1 } >>> key = '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318' >>> signed = Account.sign_transaction(transaction, key) {'hash': HexBytes('0x6893a6ee8df79b0f5d64a180cd1ef35d030f3e296a5361cf04d02ce720d32ec5'), 'r': 4487286261793418179817841024889747115779324305375823110249149479905075174044, 'rawTransaction': HexBytes('0xf86a8086d55698372431831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a009ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9ca0440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428'), # noqa: E501 's': 30785525769477805655994251009256770582792548537338581640010273753578382951464, 'v': 37} >>> w3.eth.sendRawTransaction(signed.rawTransaction) """ if not isinstance(transaction_dict, Mapping): raise TypeError("transaction_dict must be dict-like, got %r" % transaction_dict) account = self.from_key(private_key) # allow from field, *only* if it matches the private key if 'from' in transaction_dict: if transaction_dict['from'] == account.address: sanitized_transaction = dissoc(transaction_dict, 'from') else: raise TypeError( "from field must match key's %s, but it was %s" % ( account.address, transaction_dict['from'], )) else: sanitized_transaction = transaction_dict # sign transaction ( v, r, s, rlp_encoded, ) = sign_transaction_dict(account._key_obj, sanitized_transaction) transaction_hash = keccak(rlp_encoded) return AttributeDict({ 'rawTransaction': HexBytes(rlp_encoded), 'hash': HexBytes(transaction_hash), 'r': r, 's': s, 'v': v, })
def transaction_normalizer(transaction): return dissoc(transaction, 'chainId')
def split_data(ctx): return merge(dissoc(ctx, 'data'), {'independent': segaux.independent(ctx['data']), 'dependent': segaux.dependent(ctx['data'])})