async def serialize(self, jsontx):
        """Create a signed raw transaction from a json tx template.

        Example value for "jsontx" arg: {
            "inputs": [
                {"prevout_hash": "9d221a69ca3997cbeaf5624d723e7dc5f829b1023078c177d37bdae95f37c539", "prevout_n": 1,
                 "value_sats": 1000000, "privkey": "p2wpkh:cVDXzzQg6RoCTfiKpe8MBvmm5d5cJc6JLuFApsFDKwWa6F5TVHpD"}
            ],
            "outputs": [
                {"address": "tb1q4s8z6g5jqzllkgt8a4har94wl8tg0k9m8kv5zd", "value_sats": 990000}
            ]
        }
        :arg:json:jsontx:Transaction in json
        """
        keypairs = {}
        inputs = []  # type: List[PartialTxInput]
        locktime = jsontx.get('locktime', 0)
        for txin_idx, txin_dict in enumerate(jsontx.get('inputs')):
            if txin_dict.get('prevout_hash') is not None and txin_dict.get('prevout_n') is not None:
                prevout = TxOutpoint(txid=bfh(txin_dict['prevout_hash']), out_idx=int(txin_dict['prevout_n']))
            elif txin_dict.get('output'):
                prevout = TxOutpoint.from_str(txin_dict['output'])
            else:
                raise UserFacingException(f"missing prevout for txin {txin_idx}")
            txin = PartialTxInput(prevout=prevout)
            try:
                txin._trusted_value_sats = int(txin_dict.get('value') or txin_dict['value_sats'])
            except KeyError:
                raise UserFacingException(f"missing 'value_sats' field for txin {txin_idx}")
            nsequence = txin_dict.get('nsequence', None)
            if nsequence is not None:
                txin.nsequence = nsequence
            sec = txin_dict.get('privkey')
            if sec:
                txin_type, privkey, compressed = bitcoin.deserialize_privkey(sec)
                pubkey = ecc.ECPrivkey(privkey).get_public_key_bytes(compressed=compressed)
                keypairs[pubkey] = privkey
                desc = descriptor.get_singlesig_descriptor_from_legacy_leaf(pubkey=pubkey.hex(), script_type=txin_type)
                txin.script_descriptor = desc
            inputs.append(txin)

        outputs = []  # type: List[PartialTxOutput]
        for txout_idx, txout_dict in enumerate(jsontx.get('outputs')):
            try:
                txout_addr = txout_dict['address']
            except KeyError:
                raise UserFacingException(f"missing 'address' field for txout {txout_idx}")
            try:
                txout_val = int(txout_dict.get('value') or txout_dict['value_sats'])
            except KeyError:
                raise UserFacingException(f"missing 'value_sats' field for txout {txout_idx}")
            txout = PartialTxOutput.from_address_and_value(txout_addr, txout_val)
            outputs.append(txout)

        tx = PartialTransaction.from_io(inputs, outputs, locktime=locktime)
        tx.sign(keypairs)
        return tx.serialize()
Create a signed raw transaction from a json tx template.

        Example value for "jsontx" arg: {
            "inputs": [
                {"prevout_hash": "9d221a69ca3997cbeaf5624d723e7dc5f829b1023078c177d37bdae95f37c539", "prevout_n": 1,
                 "value_sats": 1000000, "privkey": "p2wpkh:cVDXzzQg6RoCTfiKpe8MBvmm5d5cJc6JLuFApsFDKwWa6F5TVHpD"}
            ],
            "outputs": [
                {"address": "tb1q4s8z6g5jqzllkgt8a4har94wl8tg0k9m8kv5zd", "value_sats": 990000}
            ]
        }
        :arg:json:jsontx:Transaction in json
        
electrum/commands.py