Full Code of aclindsa/ofxgo for AI

master b2d1132f5987 cached
57 files
574.2 KB
187.0k tokens
946 symbols
1 requests
Download .txt
Showing preview only (597K chars total). Download the full file or copy to clipboard to get everything.
Repository: aclindsa/ofxgo
Branch: master
Commit: b2d1132f5987
Files: 57
Total size: 574.2 KB

Directory structure:
gitextract_ipheoeo0/

├── .github/
│   └── workflows/
│       └── test.yml
├── LICENSE
├── README.md
├── bank.go
├── bank_test.go
├── basic_client.go
├── basic_client_test.go
├── client.go
├── cmd/
│   └── ofx/
│       ├── bankdownload.go
│       ├── banktransactions.go
│       ├── ccdownload.go
│       ├── cctransactions.go
│       ├── command.go
│       ├── detect_settings.go
│       ├── get_accounts.go
│       ├── invdownload.go
│       ├── invtransactions.go
│       ├── main.go
│       ├── profiledownload.go
│       └── util.go
├── common.go
├── common_test.go
├── constants.go
├── constants_test.go
├── creditcard.go
├── creditcard_test.go
├── discovercard_client.go
├── doc.go
├── generate_constants.py
├── go.mod
├── go.sum
├── invstmt.go
├── invstmt_test.go
├── leaf_elements.go
├── profile.go
├── profile_test.go
├── request.go
├── request_test.go
├── response.go
├── response_test.go
├── samples/
│   ├── busted_responses/
│   │   ├── bmo_v102__no_header_newline.qfx
│   │   └── wellsfargo.qfx
│   └── valid_responses/
│       ├── 401k_v203.ofx
│       ├── inv_v202.ofx
│       ├── ira_v202.ofx
│       ├── moneymrkt1_v103.ofx
│       ├── moneymrkt1_v103_TYPE1.ofx
│       └── moneymrkt1_v203.ofx
├── seclist.go
├── signon.go
├── signon_test.go
├── signup.go
├── signup_test.go
├── types.go
├── types_test.go
├── util.go
└── vanguard_client.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/test.yml
================================================
name: ofxgo CI Test

on: [push, pull_request]

jobs:
  test:
    strategy:
      matrix:
        go-version: [1.19.x, 1.22.x, 1.24.x]
        os: [ubuntu-latest, macos-latest, windows-latest]
        include:
          - os: ubuntu-latest
            go-version: 1.14.x
          - os: windows-latest
            go-version: 1.14.x
    runs-on: ${{ matrix.os }}
    steps:
    - name: Install Go
      uses: actions/setup-go@v5
      with:
        go-version: ${{ matrix.go-version }}
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Test
      run: go test -v -covermode=count -coverprofile="profile.cov" ./...
    - name: Send Coverage
      uses: shogo82148/actions-goveralls@v1
      with:
        path-to-profile: "profile.cov"
        flag-name: ${{ matrix.os }}-go-${{ matrix.go-version }}
        parallel: true
  # notifies that all test jobs are finished.
  finish:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: shogo82148/actions-goveralls@v1
        with:
          parallel-finished: true


================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

                    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                            NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

                     END OF TERMS AND CONDITIONS


================================================
FILE: README.md
================================================
# OFXGo

[![Go Report Card](https://goreportcard.com/badge/github.com/aclindsa/ofxgo)](https://goreportcard.com/report/github.com/aclindsa/ofxgo)
[![Build Status](https://github.com/aclindsa/ofxgo/workflows/ofxgo%20CI%20Test/badge.svg?branch=master)](https://github.com/aclindsa/ofxgo/actions?query=workflow%3A%22ofxgo+CI+Test%22+branch%3Amaster)
[![Coverage Status](https://coveralls.io/repos/github/aclindsa/ofxgo/badge.svg?branch=master)](https://coveralls.io/github/aclindsa/ofxgo?branch=master)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/aclindsa?ofxgo)](https://pkg.go.dev/github.com/aclindsa/ofxgo)

**OFXGo** is a library for querying OFX servers and/or parsing the responses. It
also provides an example command-line client to demonstrate the use of the
library.

## Goals

The main purpose of this project is to provide a library to make it easier to
query financial information with OFX from the comfort of Golang, without having
to marshal/unmarshal to SGML or XML. The library does _not_ intend to abstract
away all of the details of the OFX specification, which would be difficult to do
well. Instead, it exposes the OFX SGML/XML hierarchy as structs which mostly
resemble it. Its primary goal is to enable the creation of other personal
finance software in Go (as it was created to allow me to fetch OFX transactions
for my own project, [MoneyGo](https://github.com/aclindsa/moneygo)).

Because the OFX specification is rather... 'comprehensive,' it can be difficult
for those unfamiliar with it to figure out where to start. To that end, I have
created a sample command-line client which uses the library to do simple tasks
(currently it does little more than list accounts and query for balances and
transactions). My hope is that by studying its code, new users will be able to
figure out how to use the library much faster than staring at the OFX
specification (or this library's [API
documentation](https://pkg.go.dev/github.com/aclindsa/ofxgo)). The command-line client
also serves as an easy way for me to test/debug the library with actual
financial institutions, which frequently have 'quirks' in their implementations.
The command-line client can be found in the [cmd/ofx
directory](https://github.com/aclindsa/ofxgo/tree/master/cmd/ofx) of this
repository.

## Library documentation

Documentation can be found with the `go doc` tool, or at
https://pkg.go.dev/github.com/aclindsa/ofxgo

## Example Usage

The following code snippet demonstrates how to use OFXGo to query and parse
OFX code from a checking account, printing the balance and returned transactions:

```go
client := ofxgo.BasicClient{} // Accept the default Client settings

// These values are specific to your bank
var query ofxgo.Request
query.URL = "https://secu.example.com/ofx"
query.Signon.Org = ofxgo.String("SECU")
query.Signon.Fid = ofxgo.String("1234")

// Set your username/password
query.Signon.UserID = ofxgo.String("username")
query.Signon.UserPass = ofxgo.String("hunter2")

uid, _ := ofxgo.RandomUID() // Handle error in real code
query.Bank = append(query.Bank, &ofxgo.StatementRequest{
	TrnUID: *uid,
	BankAcctFrom: ofxgo.BankAcct{
		BankID:   ofxgo.String("123456789"),   // Possibly your routing number
		AcctID:   ofxgo.String("00011122233"), // Possibly your account number
		AcctType: ofxgo.AcctTypeChecking,
	},
	Include: true, // Include transactions (instead of only balance information)
})

response, _ := client.Request(&query) // Handle error in real code

// Was there an OFX error while processing our request?
if response.Signon.Status.Code != 0 {
	meaning, _ := response.Signon.Status.CodeMeaning()
	fmt.Printf("Nonzero signon status (%d: %s) with message: %s\n", response.Signon.Status.Code, meaning, response.Signon.Status.Message)
	os.Exit(1)
}

if len(response.Bank) < 1 {
	fmt.Println("No banking messages received")
	os.Exit(1)
}

if stmt, ok := response.Bank[0].(*ofxgo.StatementResponse); ok {
	fmt.Printf("Balance: %s %s (as of %s)\n", stmt.BalAmt, stmt.CurDef, stmt.DtAsOf)
	fmt.Println("Transactions:")
	for _, tran := range stmt.BankTranList.Transactions {
		currency := stmt.CurDef
		if ok, _ := tran.Currency.Valid(); ok {
			currency = tran.Currency.CurSym
		}
		fmt.Printf("%s %-15s %-11s %s%s%s\n", tran.DtPosted, tran.TrnAmt.String()+" "+currency.String(), tran.TrnType, tran.Name, tran.Payee.Name, tran.Memo)
	}
}
```

Similarly, if you have an OFX file available locally, you can parse it directly:

```go
func main() {
	f, err := os.Open("./transactions.qfx")
	if err != nil {
		fmt.Printf("can't open file: %v\n", err)
		return
	}
	defer f.Close()

	resp, err := ofxgo.ParseResponse(f)
	if err != nil {
		fmt.Printf("can't parse response: %v\n", err)
		return
	}

	// do something with resp (*ofxgo.Response)
}
```

## Requirements

OFXGo requires go >= 1.12

## Using the command-line client

To install the command-line client and test it out, you may do the following:

$ go get -v github.com/aclindsa/ofxgo/cmd/ofx && go install -v github.com/aclindsa/ofxgo/cmd/ofx

Once installed (at ~/go/bin/ofx by default, if you haven't set $GOPATH), the
command's usage should help you to use it (`./ofx --help` for a listing of the
available subcommands and their purposes, `./ofx subcommand --help` for
individual subcommand usage).


================================================
FILE: bank.go
================================================
package ofxgo

import (
	"errors"
	"github.com/aclindsa/xml"
)

// StatementRequest represents a request for a bank statement. It is used to
// request balances and/or transactions for checking, savings, money market,
// and line of credit accounts. See CCStatementRequest for the analog for
// credit card accounts.
type StatementRequest struct {
	XMLName   xml.Name `xml:"STMTTRNRQ"`
	TrnUID    UID      `xml:"TRNUID"`
	CltCookie String   `xml:"CLTCOOKIE,omitempty"`
	TAN       String   `xml:"TAN,omitempty"` // Transaction authorization number
	// TODO `xml:"OFXEXTENSION,omitempty"`
	BankAcctFrom   BankAcct `xml:"STMTRQ>BANKACCTFROM"`
	DtStart        *Date    `xml:"STMTRQ>INCTRAN>DTSTART,omitempty"`
	DtEnd          *Date    `xml:"STMTRQ>INCTRAN>DTEND,omitempty"`
	Include        Boolean  `xml:"STMTRQ>INCTRAN>INCLUDE"`          // Include transactions (instead of just balance)
	IncludePending Boolean  `xml:"STMTRQ>INCLUDEPENDING,omitempty"` // Include pending transactions
	IncTranImg     Boolean  `xml:"STMTRQ>INCTRANIMG,omitempty"`     // Include transaction images
}

// Name returns the name of the top-level transaction XML/SGML element
func (r *StatementRequest) Name() string {
	return "STMTTRNRQ"
}

// Valid returns (true, nil) if this struct would be valid OFX if marshalled
// into XML/SGML
func (r *StatementRequest) Valid(version ofxVersion) (bool, error) {
	if ok, err := r.TrnUID.Valid(); !ok {
		return false, err
	}
	if r.IncludePending && version < OfxVersion220 {
		return false, errors.New("StatementRequest.IncludePending invalid for OFX < 2.2")
	}
	if r.IncTranImg && version < OfxVersion210 {
		return false, errors.New("StatementRequest.IncTranImg invalid for OFX < 2.1")
	}
	return r.BankAcctFrom.Valid()
}

// Type returns which message set this message belongs to (which Request
// element of type []Message it should appended to)
func (r *StatementRequest) Type() messageType {
	return BankRq
}

// Payee specifies a complete billing address for a payee
type Payee struct {
	XMLName    xml.Name `xml:"PAYEE"`
	Name       String   `xml:"NAME"`
	Addr1      String   `xml:"ADDR1"`
	Addr2      String   `xml:"ADDR2,omitempty"`
	Addr3      String   `xml:"ADDR3,omitempty"`
	City       String   `xml:"CITY"`
	State      String   `xml:"STATE"`
	PostalCode String   `xml:"POSTALCODE"`
	Country    String   `xml:"COUNTRY,omitempty"`
	Phone      String   `xml:"PHONE"`
}

// Valid returns (true, nil) if this struct is valid OFX
func (p Payee) Valid() (bool, error) {
	if len(p.Name) == 0 {
		return false, errors.New("Payee.Name empty")
	} else if len(p.Addr1) == 0 {
		return false, errors.New("Payee.Addr1 empty")
	} else if len(p.City) == 0 {
		return false, errors.New("Payee.City empty")
	} else if len(p.State) == 0 {
		return false, errors.New("Payee.State empty")
	} else if len(p.PostalCode) == 0 {
		return false, errors.New("Payee.PostalCode empty")
	} else if len(p.Country) != 0 && len(p.Country) != 3 {
		return false, errors.New("Payee.Country invalid length")
	} else if len(p.Phone) == 0 {
		return false, errors.New("Payee.Phone empty")
	}
	return true, nil
}

// ImageData represents the metadata surrounding a check or other image file,
// including how to retrieve the image
type ImageData struct {
	XMLName      xml.Name     `xml:"IMAGEDATA"`
	ImageType    imageType    `xml:"IMAGETYPE"`    // One of STATEMENT, TRANSACTION, TAX
	ImageRef     String       `xml:"IMAGEREF"`     // URL or identifier, depending on IMAGEREFTYPE
	ImageRefType imageRefType `xml:"IMAGEREFTYPE"` // One of OPAQUE, URL, FORMURL (see spec for more details on how to access images of each of these types)
	// Only one of the next two should be valid at any given time
	ImageDelay   Int      `xml:"IMAGEDELAY,omitempty"`   // Number of calendar days from DTSERVER (for statement images) or DTPOSTED (for transaction image) the image will become available
	DtImageAvail *Date    `xml:"DTIMAGEAVAIL,omitempty"` // Date image will become available
	ImageTTL     Int      `xml:"IMAGETTL,omitempty"`     // Number of days after image becomes available that it will remain available
	CheckSup     checkSup `xml:"CHECKSUP,omitempty"`     // What is contained in check images. One of FRONTONLY, BACKONLY, FRONTANDBACK
}

// Transaction represents a single banking transaction. At a minimum, it
// identifies the type of transaction (TrnType) and the date it was posted
// (DtPosted). Ideally it also provides metadata to help the user recognize
// this transaction (i.e. CheckNum, Name or Payee, Memo, etc.)
type Transaction struct {
	XMLName       xml.Name      `xml:"STMTTRN"`
	TrnType       trnType       `xml:"TRNTYPE"` // One of CREDIT, DEBIT, INT (interest earned or paid. Note: Depends on signage of amount), DIV, FEE, SRVCHG (service charge), DEP (deposit), ATM (Note: Depends on signage of amount), POS (Note: Depends on signage of amount), XFER, CHECK, PAYMENT, CASH, DIRECTDEP, DIRECTDEBIT, REPEATPMT, OTHER
	DtPosted      Date          `xml:"DTPOSTED"`
	DtUser        *Date         `xml:"DTUSER,omitempty"`
	DtAvail       *Date         `xml:"DTAVAIL,omitempty"`
	TrnAmt        Amount        `xml:"TRNAMT"`
	FiTID         String        `xml:"FITID"`                   // Client uses FITID to detect whether it has previously downloaded the transaction
	CorrectFiTID  String        `xml:"CORRECTFITID,omitempty"`  // Transaction ID that this transaction corrects, if present
	CorrectAction correctAction `xml:"CORRECTACTION,omitempty"` // One of DELETE, REPLACE
	SrvrTID       String        `xml:"SRVRTID,omitempty"`
	CheckNum      String        `xml:"CHECKNUM,omitempty"`
	RefNum        String        `xml:"REFNUM,omitempty"`
	SIC           Int           `xml:"SIC,omitempty"` // Standard Industrial Code
	PayeeID       String        `xml:"PAYEEID,omitempty"`
	// Note: Servers should provide NAME or PAYEE, but not both
	Name       String      `xml:"NAME,omitempty"`
	Payee      *Payee      `xml:"PAYEE,omitempty"`
	ExtdName   String      `xml:"EXTDNAME,omitempty"`   // Extended name of payee or transaction description
	BankAcctTo *BankAcct   `xml:"BANKACCTTO,omitempty"` // If the transfer was to a bank account we have the account information for
	CCAcctTo   *CCAcct     `xml:"CCACCTTO,omitempty"`   // If the transfer was to a credit card account we have the account information for
	Memo       String      `xml:"MEMO,omitempty"`       // Extra information (not in NAME)
	ImageData  []ImageData `xml:"IMAGEDATA,omitempty"`

	// Only one of Currency and OrigCurrency can ever be Valid() for the same transaction
	Currency      *Currency     `xml:"CURRENCY,omitempty"`      // Represents the currency of TrnAmt (instead of CURDEF in STMTRS) if Valid
	OrigCurrency  *Currency     `xml:"ORIGCURRENCY,omitempty"`  // Represents the currency TrnAmt was converted to STMTRS' CURDEF from if Valid
	Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST (Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST.)
}

// Valid returns (true, nil) if this struct is valid OFX
func (t Transaction) Valid(version ofxVersion) (bool, error) {
	var emptyDate Date
	if !t.TrnType.Valid() || t.TrnType == TrnTypeHold {
		return false, errors.New("Transaction.TrnType invalid")
	} else if t.DtPosted.Equal(emptyDate) {
		return false, errors.New("Transaction.DtPosted not filled")
	} else if len(t.FiTID) == 0 {
		return false, errors.New("Transaction.FiTID empty")
	} else if len(t.CorrectFiTID) > 0 && t.CorrectAction.Valid() {
		return false, errors.New("Transaction.CorrectFiTID nonempty but CorrectAction invalid")
	} else if len(t.Name) > 0 && t.Payee != nil {
		return false, errors.New("Only one of Transaction.Name and Payee may be specified")
	}
	if t.Payee != nil {
		if ok, err := t.Payee.Valid(); !ok {
			return false, err
		}
	}
	if t.BankAcctTo != nil && t.CCAcctTo != nil {
		return false, errors.New("Only one of Transaction.BankAcctTo and CCAcctTo may be specified")
	} else if t.BankAcctTo != nil {
		if ok, err := t.BankAcctTo.Valid(); !ok {
			return false, err
		}
	} else if t.CCAcctTo != nil {
		if ok, err := t.CCAcctTo.Valid(); !ok {
			return false, err
		}
	}
	if version < OfxVersion220 && len(t.ImageData) > 0 {
		return false, errors.New("Transaction.ImageData only supportd for OFX > 220")
	} else if len(t.ImageData) > 2 {
		return false, errors.New("Only 2 of ImageData allowed in Transaction")
	}
	var ok1, ok2 bool
	if t.Currency != nil {
		ok1, _ = t.Currency.Valid()
	}
	if t.OrigCurrency != nil {
		ok2, _ = t.OrigCurrency.Valid()
	}
	if ok1 && ok2 {
		return false, errors.New("Currency and OrigCurrency both supplied for Pending Transaction, only one allowed")
	}
	return true, nil
}

// TransactionList represents a list of bank transactions, and also includes
// the date range its transactions cover.
type TransactionList struct {
	XMLName      xml.Name      `xml:"BANKTRANLIST"`
	DtStart      Date          `xml:"DTSTART"` // Start date for transaction data
	DtEnd        Date          `xml:"DTEND"`   // Value that client should send in next <DTSTART> request to ensure that it does not miss any transactions
	Transactions []Transaction `xml:"STMTTRN,omitempty"`
}

// Valid returns (true, nil) if this struct is valid OFX
func (l TransactionList) Valid(version ofxVersion) (bool, error) {
	var emptyDate Date
	if l.DtStart.Equal(emptyDate) {
		return false, errors.New("TransactionList.DtStart not filled")
	} else if l.DtEnd.Equal(emptyDate) {
		return false, errors.New("TransactionList.DtEnd not filled")
	}
	for _, t := range l.Transactions {
		if ok, err := t.Valid(version); !ok {
			return false, err
		}
	}

	return true, nil
}

// PendingTransaction represents a single pending transaction. It is similar to
// Transaction, but is not finalized (and may never be). For instance, it lacks
// FiTID and DtPosted fields.
type PendingTransaction struct {
	XMLName   xml.Name    `xml:"STMTTRNP"`
	TrnType   trnType     `xml:"TRNTYPE"` // One of CREDIT, DEBIT, INT (interest earned or paid. Note: Depends on signage of amount), DIV, FEE, SRVCHG (service charge), DEP (deposit), ATM (Note: Depends on signage of amount), POS (Note: Depends on signage of amount), XFER, CHECK, PAYMENT, CASH, DIRECTDEP, DIRECTDEBIT, REPEATPMT, HOLD, OTHER
	DtTran    Date        `xml:"DTTRAN"`
	DtExpire  *Date       `xml:"DTEXPIRE,omitempty"` // only valid for TrnType==HOLD, the date the hold will expire
	TrnAmt    Amount      `xml:"TRNAMT"`
	RefNum    String      `xml:"REFNUM,omitempty"`
	Name      String      `xml:"NAME,omitempty"`
	ExtdName  String      `xml:"EXTDNAME,omitempty"` // Extended name of payee or transaction description
	Memo      String      `xml:"MEMO,omitempty"`     // Extra information (not in NAME)
	ImageData []ImageData `xml:"IMAGEDATA,omitempty"`

	// Only one of Currency and OrigCurrency can ever be Valid() for the same transaction
	Currency     Currency `xml:"CURRENCY,omitempty"`     // Represents the currency of TrnAmt (instead of CURDEF in STMTRS) if Valid
	OrigCurrency Currency `xml:"ORIGCURRENCY,omitempty"` // Represents the currency TrnAmt was converted to STMTRS' CURDEF from if Valid
}

// Valid returns (true, nil) if this struct is valid OFX
func (t PendingTransaction) Valid() (bool, error) {
	var emptyDate Date
	if !t.TrnType.Valid() {
		return false, errors.New("PendingTransaction.TrnType invalid")
	} else if t.DtTran.Equal(emptyDate) {
		return false, errors.New("PendingTransaction.DtTran not filled")
	} else if len(t.Name) == 0 {
		return false, errors.New("PendingTransaction.Name empty")
	}
	ok1, _ := t.Currency.Valid()
	ok2, _ := t.OrigCurrency.Valid()
	if ok1 && ok2 {
		return false, errors.New("Currency and OrigCurrency both supplied for Pending Transaction, only one allowed")
	}
	return true, nil
}

// PendingTransactionList represents a list of pending transactions, along with
// the date they were generated
type PendingTransactionList struct {
	XMLName      xml.Name             `xml:"BANKTRANLISTP"`
	DtAsOf       Date                 `xml:"DTASOF"` // Date and time this set of pending transactions was generated
	Transactions []PendingTransaction `xml:"STMTTRNP,omitempty"`
}

// Valid returns (true, nil) if this struct is valid OFX
func (l PendingTransactionList) Valid() (bool, error) {
	var emptyDate Date
	if l.DtAsOf.Equal(emptyDate) {
		return false, errors.New("PendingTransactionList.DtAsOf not filled")
	}
	for _, t := range l.Transactions {
		if ok, err := t.Valid(); !ok {
			return false, err
		}
	}

	return true, nil
}

// Balance represents a generic (free-form) balance defined by an FI.
type Balance struct {
	XMLName xml.Name `xml:"BAL"`
	Name    String   `xml:"NAME"`
	Desc    String   `xml:"DESC"`

	// Balance type:
	// DOLLAR = dollar (value formatted DDDD.cc)
	// PERCENT = percentage (value formatted XXXX.YYYY)
	// NUMBER = number (value formatted as is)
	BalType balType `xml:"BALTYPE"`

	Value    Amount    `xml:"VALUE"`
	DtAsOf   *Date     `xml:"DTASOF,omitempty"`
	Currency *Currency `xml:"CURRENCY,omitempty"` // if BALTYPE is DOLLAR
}

// Valid returns (true, nil) if this struct is valid OFX
func (b Balance) Valid() (bool, error) {
	if len(b.Name) == 0 || len(b.Desc) == 0 {
		return false, errors.New("Balance Name and Desc not supplied")
	}
	if !b.BalType.Valid() {
		return false, errors.New("Balance BALTYPE not specified")
	}
	return true, nil
}

// StatementResponse represents a bank account statement, including its
// balances and possibly transactions. It is a response to StatementRequest, or
// sometimes provided as part of an OFX file downloaded manually from an FI.
type StatementResponse struct {
	XMLName   xml.Name `xml:"STMTTRNRS"`
	TrnUID    UID      `xml:"TRNUID"`
	Status    Status   `xml:"STATUS"`
	CltCookie String   `xml:"CLTCOOKIE,omitempty"`
	// TODO `xml:"OFXEXTENSION,omitempty"`
	CurDef        CurrSymbol              `xml:"STMTRS>CURDEF"`
	BankAcctFrom  BankAcct                `xml:"STMTRS>BANKACCTFROM"`
	BankTranList  *TransactionList        `xml:"STMTRS>BANKTRANLIST,omitempty"`
	BankTranListP *PendingTransactionList `xml:"STMTRS>BANKTRANLISTP,omitempty"`
	BalAmt        Amount                  `xml:"STMTRS>LEDGERBAL>BALAMT"`
	DtAsOf        Date                    `xml:"STMTRS>LEDGERBAL>DTASOF"`
	AvailBalAmt   *Amount                 `xml:"STMTRS>AVAILBAL>BALAMT,omitempty"`
	AvailDtAsOf   *Date                   `xml:"STMTRS>AVAILBAL>DTASOF,omitempty"`
	CashAdvBalAmt *Amount                 `xml:"STMTRS>CASHADVBALAMT,omitempty"` // Only for CREDITLINE accounts, available balance for cash advances
	IntRate       *Amount                 `xml:"STMTRS>INTRATE,omitempty"`       // Current interest rate
	BalList       []Balance               `xml:"STMTRS>BALLIST>BAL,omitempty"`
	MktgInfo      String                  `xml:"STMTRS>MKTGINFO,omitempty"` // Marketing information
}

// Name returns the name of the top-level transaction XML/SGML element
func (sr *StatementResponse) Name() string {
	return "STMTTRNRS"
}

// Valid returns (true, nil) if this struct was valid OFX when unmarshalled
func (sr *StatementResponse) Valid(version ofxVersion) (bool, error) {
	var emptyDate Date
	if ok, err := sr.TrnUID.Valid(); !ok {
		return false, err
	} else if ok, err := sr.Status.Valid(); !ok {
		return false, err
	} else if ok, err := sr.CurDef.Valid(); !ok {
		return false, err
	} else if ok, err := sr.BankAcctFrom.Valid(); !ok {
		return false, err
	} else if sr.DtAsOf.Equal(emptyDate) {
		return false, errors.New("StatementResponse.DtAsOf not filled")
	} else if (sr.AvailBalAmt == nil) != (sr.AvailDtAsOf == nil) {
		return false, errors.New("StatementResponse.Avail* must both either be present or absent")
	}
	if sr.BankTranList != nil {
		if ok, err := sr.BankTranList.Valid(version); !ok {
			return false, err
		}
	}
	if sr.BankTranListP != nil {
		if version < OfxVersion220 {
			return false, errors.New("StatementResponse.BankTranListP invalid for OFX < 2.2")
		}
		if ok, err := sr.BankTranListP.Valid(); !ok {
			return false, err
		}
	}
	for _, bal := range sr.BalList {
		if ok, err := bal.Valid(); !ok {
			return false, err
		}
	}
	return true, nil
}

// Type returns which message set this message belongs to (which Response
// element of type []Message it belongs to)
func (sr *StatementResponse) Type() messageType {
	return BankRs
}


================================================
FILE: bank_test.go
================================================
package ofxgo

import (
	"strings"
	"testing"
	"time"
)

func TestMarshalBankStatementRequest(t *testing.T) {
	var expectedString string = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?OFX OFXHEADER="200" VERSION="203" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>
<OFX>
	<SIGNONMSGSRQV1>
		<SONRQ>
			<DTCLIENT>20060115112300.000[-5:EST]</DTCLIENT>
			<USERID>myusername</USERID>
			<USERPASS>Pa$$word</USERPASS>
			<LANGUAGE>ENG</LANGUAGE>
			<FI>
				<ORG>BNK</ORG>
				<FID>1987</FID>
			</FI>
			<APPID>OFXGO</APPID>
			<APPVER>0001</APPVER>
		</SONRQ>
	</SIGNONMSGSRQV1>
	<BANKMSGSRQV1>
		<STMTTRNRQ>
			<TRNUID>123</TRNUID>
			<STMTRQ>
				<BANKACCTFROM>
					<BANKID>318398732</BANKID>
					<ACCTID>78346129</ACCTID>
					<ACCTTYPE>CHECKING</ACCTTYPE>
				</BANKACCTFROM>
				<INCTRAN>
					<INCLUDE>Y</INCLUDE>
				</INCTRAN>
			</STMTRQ>
		</STMTTRNRQ>
	</BANKMSGSRQV1>
</OFX>`

	var client = BasicClient{
		AppID:       "OFXGO",
		AppVer:      "0001",
		SpecVersion: OfxVersion203,
	}

	var request Request
	request.Signon.UserID = "myusername"
	request.Signon.UserPass = "Pa$$word"
	request.Signon.Org = "BNK"
	request.Signon.Fid = "1987"

	statementRequest := StatementRequest{
		TrnUID: "123",
		BankAcctFrom: BankAcct{
			BankID:   "318398732",
			AcctID:   "78346129",
			AcctType: AcctTypeChecking,
		},
		Include: true,
	}
	request.Bank = append(request.Bank, &statementRequest)

	request.SetClientFields(&client)
	// Overwrite the DtClient value set by SetClientFields to time.Now()
	EST := time.FixedZone("EST", -5*60*60)
	request.Signon.DtClient = *NewDate(2006, 1, 15, 11, 23, 0, 0, EST)

	marshalCheckRequest(t, &request, expectedString)
}

func TestMarshalBankStatementRequest103(t *testing.T) {
	var expectedString string = `OFXHEADER:100
DATA:OFXSGML
VERSION:103
SECURITY:NONE
ENCODING:USASCII
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE

<OFX>
	<SIGNONMSGSRQV1>
		<SONRQ>
			<DTCLIENT>20060115112300.000[-5:EST]
			<USERID>myusername
			<USERPASS>Pa$$word
			<LANGUAGE>ENG
			<FI>
				<ORG>BNK
				<FID>1987
			</FI>
			<APPID>OFXGO
			<APPVER>0001
		</SONRQ>
	</SIGNONMSGSRQV1>
	<BANKMSGSRQV1>
		<STMTTRNRQ>
			<TRNUID>123
			<STMTRQ>
				<BANKACCTFROM>
					<BANKID>318398732
					<ACCTID>78346129
					<ACCTTYPE>CHECKING
				</BANKACCTFROM>
				<INCTRAN>
					<INCLUDE>Y
				</INCTRAN>
			</STMTRQ>
		</STMTTRNRQ>
	</BANKMSGSRQV1>
</OFX>`

	var client = BasicClient{
		AppID:       "OFXGO",
		AppVer:      "0001",
		SpecVersion: OfxVersion103,
	}

	var request Request
	request.Signon.UserID = "myusername"
	request.Signon.UserPass = "Pa$$word"
	request.Signon.Org = "BNK"
	request.Signon.Fid = "1987"

	statementRequest := StatementRequest{
		TrnUID: "123",
		BankAcctFrom: BankAcct{
			BankID:   "318398732",
			AcctID:   "78346129",
			AcctType: AcctTypeChecking,
		},
		Include: true,
	}
	request.Bank = append(request.Bank, &statementRequest)

	request.SetClientFields(&client)
	// Overwrite the DtClient value set by SetClientFields to time.Now()
	EST := time.FixedZone("EST", -5*60*60)
	request.Signon.DtClient = *NewDate(2006, 1, 15, 11, 23, 0, 0, EST)

	marshalCheckRequest(t, &request, expectedString)
}

func TestUnmarshalBankStatementResponse(t *testing.T) {
	responseReader := strings.NewReader(`<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?OFX OFXHEADER="200" VERSION="203" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>
<OFX>
	<SIGNONMSGSRSV1>
		<SONRS>
			<STATUS>
				<CODE>0</CODE>
				<SEVERITY>INFO</SEVERITY>
			</STATUS>
			<DTSERVER>20060115112303</DTSERVER>
			<LANGUAGE>ENG</LANGUAGE>
			<DTPROFUP>20050221091300</DTPROFUP>
			<DTACCTUP>20060102160000</DTACCTUP>
			<FI>
				<ORG>BNK</ORG>
				<FID>1987</FID>
			</FI>
		</SONRS>
	</SIGNONMSGSRSV1>
	<BANKMSGSRSV1>
		<STMTTRNRS>
			<TRNUID>1001</TRNUID>
			<STATUS>
				<CODE>0</CODE>
				<SEVERITY>INFO</SEVERITY>
			</STATUS>
			<STMTRS>
				<CURDEF>USD</CURDEF>
				<BANKACCTFROM>
					<BANKID>318398732</BANKID>
					<ACCTID>78346129</ACCTID>
					<ACCTTYPE>CHECKING</ACCTTYPE>
				</BANKACCTFROM>
				<BANKTRANLIST>
					<DTSTART>20060101</DTSTART>
					<DTEND>20060115</DTEND>
					<STMTTRN>
						<TRNTYPE>CHECK</TRNTYPE>
						<DTPOSTED>20060104</DTPOSTED>
						<TRNAMT>-200.00</TRNAMT>
						<FITID>00592</FITID>
						<CHECKNUM>2002</CHECKNUM>
					</STMTTRN>
					<STMTTRN>
						<TRNTYPE>ATM</TRNTYPE>
						<DTPOSTED>20060112</DTPOSTED>
						<DTUSER>20060112</DTUSER>
						<TRNAMT>-300.00</TRNAMT>
						<FITID>00679</FITID>
					</STMTTRN>
				</BANKTRANLIST>
				<LEDGERBAL>
					<BALAMT>200.29</BALAMT>
					<DTASOF>200601141600</DTASOF>
				</LEDGERBAL>
				<AVAILBAL>
					<BALAMT>200.29</BALAMT>
					<DTASOF>200601141600</DTASOF>
				</AVAILBAL>
			</STMTRS>
		</STMTTRNRS>
	</BANKMSGSRSV1>
</OFX>`)
	var expected Response

	expected.Version = OfxVersion203
	expected.Signon.Status.Code = 0
	expected.Signon.Status.Severity = "INFO"
	expected.Signon.DtServer = *NewDateGMT(2006, 1, 15, 11, 23, 03, 0)
	expected.Signon.Language = "ENG"
	expected.Signon.DtProfUp = NewDateGMT(2005, 2, 21, 9, 13, 0, 0)
	expected.Signon.DtAcctUp = NewDateGMT(2006, 1, 2, 16, 0, 0, 0)
	expected.Signon.Org = "BNK"
	expected.Signon.Fid = "1987"

	var trnamt1, trnamt2 Amount
	trnamt1.SetFrac64(-20000, 100)
	trnamt2.SetFrac64(-30000, 100)

	banktranlist := TransactionList{
		DtStart: *NewDateGMT(2006, 1, 1, 0, 0, 0, 0),
		DtEnd:   *NewDateGMT(2006, 1, 15, 0, 0, 0, 0),
		Transactions: []Transaction{
			{
				TrnType:  TrnTypeCheck,
				DtPosted: *NewDateGMT(2006, 1, 4, 0, 0, 0, 0),
				TrnAmt:   trnamt1,
				FiTID:    "00592",
				CheckNum: "2002",
			},
			{
				TrnType:  TrnTypeATM,
				DtPosted: *NewDateGMT(2006, 1, 12, 0, 0, 0, 0),
				DtUser:   NewDateGMT(2006, 1, 12, 0, 0, 0, 0),
				TrnAmt:   trnamt2,
				FiTID:    "00679",
			},
		},
	}

	var balamt, availbalamt Amount
	balamt.SetFrac64(20029, 100)
	availbalamt.SetFrac64(20029, 100)

	usd, err := NewCurrSymbol("USD")
	if err != nil {
		t.Fatalf("Unexpected error creating CurrSymbol for USD\n")
	}

	statementResponse := StatementResponse{
		TrnUID: "1001",
		Status: Status{
			Code:     0,
			Severity: "INFO",
		},
		CurDef: *usd,
		BankAcctFrom: BankAcct{
			BankID:   "318398732",
			AcctID:   "78346129",
			AcctType: AcctTypeChecking,
		},
		BankTranList: &banktranlist,
		BalAmt:       balamt,
		DtAsOf:       *NewDateGMT(2006, 1, 14, 16, 0, 0, 0),
		AvailBalAmt:  &availbalamt,
		AvailDtAsOf:  NewDateGMT(2006, 1, 14, 16, 0, 0, 0),
	}
	expected.Bank = append(expected.Bank, &statementResponse)

	response, err := ParseResponse(responseReader)
	if err != nil {
		t.Fatalf("Unexpected error unmarshalling response: %s\n", err)
	}

	checkResponsesEqual(t, &expected, response)
	checkResponseRoundTrip(t, response)
}

func TestPayeeValid(t *testing.T) {
	p := Payee{
		Name:       "Jane",
		Addr1:      "Sesame Street",
		City:       "Mytown",
		State:      "AA",
		PostalCode: "12345",
		Phone:      "12345678901",
	}
	valid, err := p.Valid()
	if !valid {
		t.Fatalf("Unexpected error from calling Valid: %s\n", err)
	}

	// Ensure some empty fields trigger invalid response
	badp := p
	badp.Name = ""
	valid, err = badp.Valid()
	if valid || err == nil {
		t.Fatalf("Expected error from calling Valid with empty name\n")
	}

	badp = p
	badp.Addr1 = ""
	valid, err = badp.Valid()
	if valid || err == nil {
		t.Fatalf("Expected error from calling Valid with empty address\n")
	}

	badp = p
	badp.City = ""
	valid, err = badp.Valid()
	if valid || err == nil {
		t.Fatalf("Expected error from calling Valid with empty city\n")
	}

	badp = p
	badp.State = ""
	valid, err = badp.Valid()
	if valid || err == nil {
		t.Fatalf("Expected error from calling Valid with empty state\n")
	}

	badp = p
	badp.PostalCode = ""
	valid, err = badp.Valid()
	if valid || err == nil {
		t.Fatalf("Expected error from calling Valid with empty postal code\n")
	}

	badp = p
	badp.Phone = ""
	valid, err = badp.Valid()
	if valid || err == nil {
		t.Fatalf("Expected error from calling Valid with empty phone\n")
	}
}

func TestBalanceValid(t *testing.T) {
	var a Amount
	a.SetFrac64(8, 1)
	b := Balance{
		Name:    "Checking",
		Desc:    "Jane's Personal Checking",
		BalType: BalTypeDollar,
		Value:   a,
	}
	valid, err := b.Valid()
	if !valid {
		t.Fatalf("Unexpected error from calling Valid: %s\n", err)
	}

	badb := b
	badb.Name = ""
	valid, err = badb.Valid()
	if valid || err == nil {
		t.Fatalf("Expected error from calling Valid with empty name\n")
	}

	badb = b
	badb.Desc = ""
	valid, err = badb.Valid()
	if valid || err == nil {
		t.Fatalf("Expected error from calling Valid with empty description\n")
	}

	badb = Balance{
		Name:  "Checking",
		Desc:  "Jane's Personal Checking",
		Value: a,
	}
	valid, err = badb.Valid()
	if valid || err == nil {
		t.Fatalf("Expected error from calling Valid with unspecified balance type\n")
	}
}


================================================
FILE: basic_client.go
================================================
package ofxgo

import (
	"errors"
	"io"
	"net/http"
	"strings"
)

// BasicClient provides a standard Client implementation suitable for most
// financial institutions. BasicClient uses default, non-zero settings, even if
// its fields are not initialized.
type BasicClient struct {
	// Request fields to overwrite with the client's values. If nonempty,
	// defaults are used
	SpecVersion ofxVersion // VERSION in header
	AppID       string     // SONRQ>APPID
	AppVer      string     // SONRQ>APPVER

	// Don't insert newlines or indentation when marshalling to SGML/XML
	NoIndent bool
	// Use carriage returns on new lines
	CarriageReturn bool
	// Set User-Agent header to this string, if not empty
	UserAgent string

	HTTPClient *http.Client
}

// OfxVersion returns the OFX specification version this BasicClient will marshal
// Requests as. Defaults to "203" if the client's SpecVersion field is empty.
func (c *BasicClient) OfxVersion() ofxVersion {
	if c.SpecVersion.Valid() {
		return c.SpecVersion
	}
	return OfxVersion203
}

// ID returns this BasicClient's OFX AppID field, defaulting to "OFXGO" if
// unspecified.
func (c *BasicClient) ID() String {
	if len(c.AppID) > 0 {
		return String(c.AppID)
	}
	return String("OFXGO")
}

// Version returns this BasicClient's version number as a string, defaulting to
// "0001" if unspecified.
func (c *BasicClient) Version() String {
	if len(c.AppVer) > 0 {
		return String(c.AppVer)
	}
	return String("0001")
}

// IndentRequests returns true if the marshaled XML should be indented (and
// contain newlines, since the two are linked in the current implementation)
func (c *BasicClient) IndentRequests() bool {
	return !c.NoIndent
}

// CarriageReturnNewLines returns true if carriage returns should be used on new lines, false otherwise
func (c *BasicClient) CarriageReturnNewLines() bool {
	return c.CarriageReturn
}

// RawRequest is a convenience wrapper around http.Post. It is exposed only for
// when you need to read/inspect the raw HTTP response yourself.
func (c *BasicClient) RawRequest(URL string, r io.Reader) (*http.Response, error) {
	if !strings.HasPrefix(URL, "https://") {
		return nil, errors.New("Refusing to send OFX request with possible plain-text password over non-https protocol")
	}

	httpClient := c.HTTPClient
	if httpClient == nil {
		httpClient = http.DefaultClient
	}

	request, err := http.NewRequest("POST", URL, r)
	if err != nil {
		return nil, err
	}
	request.Header.Set("Content-Type", "application/x-ofx")
	request.Header.Add("Accept", "*/*, application/x-ofx")
	if c.UserAgent != "" {
		request.Header.Set("User-Agent", c.UserAgent)
	}
	response, err := httpClient.Do(request)
	if err != nil {
		return nil, err
	}

	if response.StatusCode != 200 {
		return response, errors.New("OFXQuery request status: " + response.Status)
	}

	return response, nil
}

// RequestNoParse marshals a Request to XML, makes an HTTP request, and returns
// the raw HTTP response
func (c *BasicClient) RequestNoParse(r *Request) (*http.Response, error) {
	return clientRequestNoParse(c, r)
}

// Request marshals a Request to XML, makes an HTTP request, and then
// unmarshals the response into a Response object.
func (c *BasicClient) Request(r *Request) (*Response, error) {
	return clientRequest(c, r)
}


================================================
FILE: basic_client_test.go
================================================
package ofxgo

import (
	"errors"
	"net"
	"net/http"
	"strings"
	"testing"
)

func TestBasicClient_HTTPClient(t *testing.T) {
	c := &BasicClient{
		HTTPClient: &http.Client{
			Transport: &http.Transport{
				Dial: func(network, addr string) (net.Conn, error) {
					return nil, errors.New("bad test client")
				},
			},
		},
	}
	_, err := c.Request(&Request{
		URL: "https://test",
		Signon: SignonRequest{
			UserID:   "test",
			UserPass: "test",
		},
	})
	if err == nil || !strings.Contains(err.Error(), "bad test client") {
		t.Fatalf("expected error containing 'bad test client', got: %v", err)
	}
}


================================================
FILE: client.go
================================================
package ofxgo

import (
	"io"
	"net/http"
	"strings"
)

// Client serves to aggregate OFX client settings that may be necessary to talk
// to a particular server due to quirks in that server's implementation.
// Client also provides the Request and RequestNoParse helper methods to aid in
// making and parsing requests.
type Client interface {
	// Used to fill out a Request object
	OfxVersion() ofxVersion
	ID() String
	Version() String
	IndentRequests() bool
	CarriageReturnNewLines() bool

	// Request marshals a Request object into XML, makes an HTTP request
	// against it's URL, and then unmarshals the response into a Response
	// object.
	//
	// Before being marshaled, some of the the Request object's values are
	// overwritten, namely those dictated by the BasicClient's configuration
	// (Version, AppID, AppVer fields), and the client's current time
	// (DtClient). These are updated in place in the supplied Request object so
	// they may later be inspected by the caller.
	Request(r *Request) (*Response, error)

	// RequestNoParse marshals a Request object into XML, makes an HTTP
	// request, and returns the raw HTTP response. Unlike RawRequest(), it
	// takes client settings into account. Unlike Request(), it doesn't parse
	// the response into  an ofxgo.Request object.
	//
	// Caveat: The caller is responsible for closing the http Response.Body
	// (see the http module's documentation for more information)
	RequestNoParse(r *Request) (*http.Response, error)

	// RawRequest is little more than a thin wrapper around http.Post
	//
	// In most cases, you should probably be using Request() instead, but
	// RawRequest can be useful if you need to read the raw unparsed http
	// response yourself (perhaps for downloading an OFX file for use by an
	// external program, or debugging server behavior), or have a handcrafted
	// request you'd like to try.
	//
	// Caveats: RawRequest does *not* take client settings into account as
	// Client.Request() does, so your particular server may or may not like
	// whatever we read from 'r'. The caller is responsible for closing the
	// http Response.Body (see the http module's documentation for more
	// information)
	RawRequest(URL string, r io.Reader) (*http.Response, error)
}

type clientCreationFunc func(*BasicClient) Client

// GetClient returns a new Client for a given URL. It attempts to find a
// specialized client for this URL, but simply returns the passed-in
// BasicClient if no such match is found.
func GetClient(URL string, bc *BasicClient) Client {
	clients := []struct {
		URL  string
		Func clientCreationFunc
	}{
		{"https://ofx.discovercard.com", NewDiscoverCardClient},
		{"https://vesnc.vanguard.com/us/OfxDirectConnectServlet", NewVanguardClient},
	}
	for _, client := range clients {
		if client.URL == strings.Trim(URL, "/") {
			return client.Func(bc)
		}
	}
	return bc
}

// clientRequestNoParse can be used for building clients' RequestNoParse
// methods if they require fairly standard behavior
func clientRequestNoParse(c Client, r *Request) (*http.Response, error) {
	r.SetClientFields(c)

	b, err := r.Marshal()
	if err != nil {
		return nil, err
	}

	return c.RawRequest(r.URL, b)
}

// clientRequest can be used for building clients' Request methods if they
// require fairly standard behavior
func clientRequest(c Client, r *Request) (*Response, error) {
	response, err := c.RequestNoParse(r)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	ofxresp, err := ParseResponse(response.Body)
	if err != nil {
		return nil, err
	}
	return ofxresp, nil
}


================================================
FILE: cmd/ofx/bankdownload.go
================================================
package main

import (
	"flag"
	"fmt"
	"github.com/aclindsa/ofxgo"
	"io"
	"os"
)

var downloadCommand = command{
	Name:        "download-bank",
	Description: "Download a bank account statement to a file",
	Flags:       flag.NewFlagSet("download-bank", flag.ExitOnError),
	CheckFlags:  downloadCheckFlags,
	Do:          download,
}

var filename, bankID, acctID, acctType string

func init() {
	defineServerFlags(downloadCommand.Flags)
	downloadCommand.Flags.StringVar(&filename, "filename", "./response.ofx", "The file to save to")
	downloadCommand.Flags.StringVar(&bankID, "bankid", "", "BankID (from `get-accounts` subcommand)")
	downloadCommand.Flags.StringVar(&acctID, "acctid", "", "AcctID (from `get-accounts` subcommand)")
	downloadCommand.Flags.StringVar(&acctType, "accttype", "CHECKING", "AcctType (from `get-accounts` subcommand)")
}

func downloadCheckFlags() bool {
	ret := checkServerFlags()

	if len(filename) == 0 {
		fmt.Println("Error: Filename empty")
		return false
	}

	return ret
}

func download() {
	client, query := newRequest()

	acctTypeEnum, err := ofxgo.NewAcctType(acctType)
	if err != nil {
		fmt.Println("Error parsing accttype:", err)
		os.Exit(1)
	}

	uid, err := ofxgo.RandomUID()
	if err != nil {
		fmt.Println("Error creating uid for transaction:", err)
		os.Exit(1)
	}

	statementRequest := ofxgo.StatementRequest{
		TrnUID: *uid,
		BankAcctFrom: ofxgo.BankAcct{
			BankID:   ofxgo.String(bankID),
			AcctID:   ofxgo.String(acctID),
			AcctType: acctTypeEnum,
		},
		Include: true,
	}

	query.Bank = append(query.Bank, &statementRequest)

	if dryrun {
		printRequest(client, query)
		return
	}

	response, err := client.RequestNoParse(query)
	if err != nil {
		fmt.Println("Error requesting account statement:", err)
		os.Exit(1)
	}
	defer response.Body.Close()

	file, err := os.Create(filename)
	if err != nil {
		fmt.Println("Error creating file to write to:", err)
		os.Exit(1)
	}
	defer file.Close()

	_, err = io.Copy(file, response.Body)
	if err != nil {
		fmt.Println("Error writing response to file:", err)
		os.Exit(1)
	}
}


================================================
FILE: cmd/ofx/banktransactions.go
================================================
package main

import (
	"flag"
	"fmt"
	"github.com/aclindsa/ofxgo"
	"os"
)

var bankTransactionsCommand = command{
	Name:        "transactions-bank",
	Description: "Print bank transactions and balance",
	Flags:       flag.NewFlagSet("transactions-bank", flag.ExitOnError),
	CheckFlags:  checkServerFlags,
	Do:          bankTransactions,
}

func init() {
	defineServerFlags(bankTransactionsCommand.Flags)
	bankTransactionsCommand.Flags.StringVar(&bankID, "bankid", "", "BankID (from `get-accounts` subcommand)")
	bankTransactionsCommand.Flags.StringVar(&acctID, "acctid", "", "AcctID (from `get-accounts` subcommand)")
	bankTransactionsCommand.Flags.StringVar(&acctType, "accttype", "CHECKING", "AcctType (from `get-accounts` subcommand)")
}

func bankTransactions() {
	client, query := newRequest()

	acctTypeEnum, err := ofxgo.NewAcctType(acctType)
	if err != nil {
		fmt.Println("Error parsing accttype:", err)
		os.Exit(1)
	}

	uid, err := ofxgo.RandomUID()
	if err != nil {
		fmt.Println("Error creating uid for transaction:", err)
		os.Exit(1)
	}

	statementRequest := ofxgo.StatementRequest{
		TrnUID: *uid,
		BankAcctFrom: ofxgo.BankAcct{
			BankID:   ofxgo.String(bankID),
			AcctID:   ofxgo.String(acctID),
			AcctType: acctTypeEnum,
		},
		Include: true,
	}

	query.Bank = append(query.Bank, &statementRequest)

	if dryrun {
		printRequest(client, query)
		return
	}

	response, err := client.Request(query)
	if err != nil {
		fmt.Println("Error requesting account statement:", err)
		os.Exit(1)
	}

	if response.Signon.Status.Code != 0 {
		meaning, _ := response.Signon.Status.CodeMeaning()
		fmt.Printf("Nonzero signon status (%d: %s) with message: %s\n", response.Signon.Status.Code, meaning, response.Signon.Status.Message)
		os.Exit(1)
	}

	if len(response.Bank) < 1 {
		fmt.Println("No banking messages received")
		return
	}

	if stmt, ok := response.Bank[0].(*ofxgo.StatementResponse); ok {
		fmt.Printf("Balance: %s %s (as of %s)\n", stmt.BalAmt, stmt.CurDef, stmt.DtAsOf)
		fmt.Println("Transactions:")
		for _, tran := range stmt.BankTranList.Transactions {
			printTransaction(stmt.CurDef, &tran)
		}
	}
}

func printTransaction(defCurrency ofxgo.CurrSymbol, tran *ofxgo.Transaction) {
	currency := defCurrency
	if tran.Currency != nil {
		currency = tran.Currency.CurSym
	}

	var name string
	if len(tran.Name) > 0 {
		name = string(tran.Name)
	} else if tran.Payee != nil {
		name = string(tran.Payee.Name)
	}

	if len(tran.Memo) > 0 {
		name = name + " - " + string(tran.Memo)
	}

	fmt.Printf("%s %-15s %-11s %s\n", tran.DtPosted, tran.TrnAmt.String()+" "+currency.String(), tran.TrnType, name)
}


================================================
FILE: cmd/ofx/ccdownload.go
================================================
package main

import (
	"flag"
	"fmt"
	"github.com/aclindsa/ofxgo"
	"io"
	"os"
)

var ccDownloadCommand = command{
	Name:        "download-cc",
	Description: "Download a credit card account statement to a file",
	Flags:       flag.NewFlagSet("download-cc", flag.ExitOnError),
	CheckFlags:  ccDownloadCheckFlags,
	Do:          ccDownload,
}

func init() {
	defineServerFlags(ccDownloadCommand.Flags)
	ccDownloadCommand.Flags.StringVar(&filename, "filename", "./response.ofx", "The file to save to")
	ccDownloadCommand.Flags.StringVar(&acctID, "acctid", "", "AcctID (from `get-accounts` subcommand)")
}

func ccDownloadCheckFlags() bool {
	ret := checkServerFlags()

	if len(filename) == 0 {
		fmt.Println("Error: Filename empty")
		return false
	}

	return ret
}

func ccDownload() {
	client, query := newRequest()

	uid, err := ofxgo.RandomUID()
	if err != nil {
		fmt.Println("Error creating uid for transaction:", err)
		os.Exit(1)
	}

	statementRequest := ofxgo.CCStatementRequest{
		TrnUID: *uid,
		CCAcctFrom: ofxgo.CCAcct{
			AcctID: ofxgo.String(acctID),
		},
		Include: true,
	}
	query.CreditCard = append(query.CreditCard, &statementRequest)

	if dryrun {
		printRequest(client, query)
		return
	}

	response, err := client.RequestNoParse(query)

	if err != nil {
		fmt.Println("Error requesting account statement:", err)
		os.Exit(1)
	}
	defer response.Body.Close()

	file, err := os.Create(filename)
	if err != nil {
		fmt.Println("Error creating file to write to:", err)
		os.Exit(1)
	}
	defer file.Close()

	_, err = io.Copy(file, response.Body)
	if err != nil {
		fmt.Println("Error writing response to file:", err)
		os.Exit(1)
	}
}


================================================
FILE: cmd/ofx/cctransactions.go
================================================
package main

import (
	"flag"
	"fmt"
	"github.com/aclindsa/ofxgo"
	"os"
)

var ccTransactionsCommand = command{
	Name:        "transactions-cc",
	Description: "Print credit card transactions and balance",
	Flags:       flag.NewFlagSet("transactions-cc", flag.ExitOnError),
	CheckFlags:  checkServerFlags,
	Do:          ccTransactions,
}

func init() {
	defineServerFlags(ccTransactionsCommand.Flags)
	ccTransactionsCommand.Flags.StringVar(&acctID, "acctid", "", "AcctID (from `get-accounts` subcommand)")
}

func ccTransactions() {
	client, query := newRequest()

	uid, err := ofxgo.RandomUID()
	if err != nil {
		fmt.Println("Error creating uid for transaction:", err)
		os.Exit(1)
	}

	statementRequest := ofxgo.CCStatementRequest{
		TrnUID: *uid,
		CCAcctFrom: ofxgo.CCAcct{
			AcctID: ofxgo.String(acctID),
		},
		Include: true,
	}
	query.CreditCard = append(query.CreditCard, &statementRequest)

	if dryrun {
		printRequest(client, query)
		return
	}

	response, err := client.Request(query)
	if err != nil {
		fmt.Println("Error requesting account statement:", err)
		os.Exit(1)
	}

	if response.Signon.Status.Code != 0 {
		meaning, _ := response.Signon.Status.CodeMeaning()
		fmt.Printf("Nonzero signon status (%d: %s) with message: %s\n", response.Signon.Status.Code, meaning, response.Signon.Status.Message)
		os.Exit(1)
	}

	if len(response.CreditCard) < 1 {
		fmt.Println("No banking messages received")
		return
	}

	if stmt, ok := response.CreditCard[0].(*ofxgo.CCStatementResponse); ok {
		fmt.Printf("Balance: %s %s (as of %s)\n", stmt.BalAmt, stmt.CurDef, stmt.DtAsOf)
		fmt.Println("Transactions:")
		for _, tran := range stmt.BankTranList.Transactions {
			currency := stmt.CurDef
			if tran.Currency != nil {
				currency = tran.Currency.CurSym
			}

			var name string
			if len(tran.Name) > 0 {
				name = string(tran.Name)
			} else {
				name = string(tran.Payee.Name)
			}

			if len(tran.Memo) > 0 {
				name = name + " - " + string(tran.Memo)
			}

			fmt.Printf("%s %-15s %-11s %s\n", tran.DtPosted, tran.TrnAmt.String()+" "+currency.String(), tran.TrnType, name)
		}
	}
}


================================================
FILE: cmd/ofx/command.go
================================================
package main

import (
	"flag"
	"fmt"
	"golang.org/x/term"
	"os"
)

type command struct {
	Name        string
	Description string
	Flags       *flag.FlagSet
	CheckFlags  func() bool // Check the flag values after they're parsed, printing errors and returning false if they're incorrect
	Do          func()      // Run the command (only called if CheckFlags returns true)
}

func (c *command) usage() {
	fmt.Printf("Usage of %s:\n", c.Name)
	c.Flags.PrintDefaults()
}

// flags common to all server transactions
var serverURL, username, password, org, fid, appID, appVer, ofxVersion, clientUID string
var noIndentRequests bool
var carriageReturn bool
var dryrun bool
var userAgent string

func defineServerFlags(f *flag.FlagSet) {
	f.StringVar(&serverURL, "url", "", "Financial institution's OFX Server URL (see ofxhome.com if you don't know it)")
	f.StringVar(&username, "username", "", "Your username at financial institution")
	f.StringVar(&password, "password", "", "Your password at financial institution")
	f.StringVar(&org, "org", "", "'ORG' for your financial institution")
	f.StringVar(&fid, "fid", "", "'FID' for your financial institution")
	f.StringVar(&appID, "appid", "QWIN", "'APPID' to pretend to be")
	f.StringVar(&appVer, "appver", "2400", "'APPVER' to pretend to be")
	f.StringVar(&ofxVersion, "ofxversion", "203", "OFX version to use")
	f.StringVar(&clientUID, "clientuid", "", "Client UID (only required by a few FIs, like Chase)")
	f.BoolVar(&noIndentRequests, "noindent", false, "Don't indent OFX requests")
	f.BoolVar(&carriageReturn, "carriagereturn", false, "Use carriage return as line separator")
	f.StringVar(&userAgent, "useragent", "", "Use string as User-Agent header when sending request")
	f.BoolVar(&dryrun, "dryrun", false, "Don't send request - print content of request instead")
}

func checkServerFlags() bool {
	var ret bool = true
	if len(serverURL) == 0 {
		fmt.Println("Error: Server URL empty")
		ret = false
	}
	if len(username) == 0 {
		fmt.Println("Error: Username empty")
		ret = false
	}

	if ret && len(password) == 0 {
		fmt.Printf("Password for %s: ", username)
		pass, err := term.ReadPassword(int(os.Stdin.Fd()))
		if err != nil {
			fmt.Printf("Error reading password: %s\n", err)
			ret = false
		} else {
			password = string(pass)
		}
	}
	return ret
}


================================================
FILE: cmd/ofx/detect_settings.go
================================================
package main

import (
	"flag"
	"fmt"
	"github.com/aclindsa/ofxgo"
	"os"
	"time"
)

var detectSettingsCommand = command{
	Name:        "detect-settings",
	Description: "Attempt to guess client settings needed for a particular financial institution",
	Flags:       flag.NewFlagSet("detect-settings", flag.ExitOnError),
	CheckFlags:  checkServerFlags,
	Do:          detectSettings,
}

var delay uint64

func init() {
	detectSettingsCommand.Flags.StringVar(&serverURL, "url", "", "Financial institution's OFX Server URL (see ofxhome.com if you don't know it)")
	detectSettingsCommand.Flags.StringVar(&username, "username", "", "Your username at financial institution")
	detectSettingsCommand.Flags.StringVar(&password, "password", "", "Your password at financial institution")
	detectSettingsCommand.Flags.StringVar(&org, "org", "", "'ORG' for your financial institution")
	detectSettingsCommand.Flags.StringVar(&fid, "fid", "", "'FID' for your financial institution")
	detectSettingsCommand.Flags.Uint64Var(&delay, "delay", 500, "How long to delay between two subsequent requests, in milliseconds")
}

// We keep a separate list of APPIDs to preserve the ordering (ordering isn't
// guaranteed in maps). We want to try them in order from 'best' and most
// likely to work to 'worse' and least likely to work
var appIDs = []string{
	"OFXGO", // ofxgo (this library)
	"QWIN",  // Intuit Quicken Windows
	"QMOFX", // Intuit Quicken Mac
	"QB",    // Intuit QuickBooks Windows
	"Money", // Microsoft Money 2007
}

var appVersions = map[string][]string{
	"OFXGO": { // ofxgo (this library)
		"0001",
	},
	"QWIN": { // Intuit Quicken Windows
		"2600", // 2017
		"2500", // 2016
		"2400", // 2015
		"2300", // 2014
		"2200", // 2013
		"2100", // 2012
		"2000", // 2011
		"1900", // 2010
		"1800", // 2009
		"1700", // 2008
		"1600", // 2007
		"1500", // 2006
		"1400", // 2005
	},
	"QMOFX": { // Intuit Quicken Mac
		"1700", // 2008
		"1600", // 2007
		"1500", // 2006
		"1400", // 2005
	},
	"QB": { // Intuit QuickBooks Windows
		"1800", // 2008
		"1700", // 2007
		"1600", // 2006
		"1500", // 2005
	},
	"Money": { // Microsoft Money 2007
		"1600", // 2007
		"1500", // 2006
		"1400", // 2005
		"1200", // 2004
		"1100", // 2003
	},
}

var versions = []string{
	"203",
	"103",
	"200",
	"201",
	"202",
	"210",
	"211",
	"102",
	"151",
	"160",
	"220",
}

func detectSettings() {
	var attempts uint
	for _, appID := range appIDs {
		for _, appVer := range appVersions[appID] {
			for _, version := range versions {
				for _, noIndent := range []bool{false, true} {
					if tryProfile(appID, appVer, version, noIndent) {
						fmt.Println("The following settings were found to work:")
						fmt.Printf("AppID: %s\n", appID)
						fmt.Printf("AppVer: %s\n", appVer)
						fmt.Printf("OFX Version: %s\n", version)
						fmt.Printf("noindent: %t\n", noIndent)
						os.Exit(0)
					} else {
						attempts++
						var noIndentString string
						if noIndent {
							noIndentString = " noindent"
						}
						fmt.Printf("Attempt %d failed (%s %s %s%s), trying again after %dms...\n", attempts, appID, appVer, version, noIndentString, delay)
						time.Sleep(time.Duration(delay) * time.Millisecond)
					}
				}
			}
		}
	}
}

const anonymous = "anonymous00000000000000000000000"

func tryProfile(appID, appVer, version string, noindent bool) bool {
	ver, err := ofxgo.NewOfxVersion(version)
	if err != nil {
		fmt.Println("Error creating new OfxVersion enum:", err)
		os.Exit(1)
	}
	var client = ofxgo.GetClient(serverURL,
		&ofxgo.BasicClient{
			AppID:       appID,
			AppVer:      appVer,
			SpecVersion: ver,
			NoIndent:    noindent,
		})

	var query ofxgo.Request
	query.URL = serverURL
	query.Signon.ClientUID = ofxgo.UID(clientUID)
	query.Signon.UserID = ofxgo.String(username)
	query.Signon.UserPass = ofxgo.String(password)
	query.Signon.Org = ofxgo.String(org)
	query.Signon.Fid = ofxgo.String(fid)

	uid, err := ofxgo.RandomUID()
	if err != nil {
		fmt.Println("Error creating uid for transaction:", err)
		os.Exit(1)
	}

	profileRequest := ofxgo.ProfileRequest{
		TrnUID:   *uid,
		DtProfUp: ofxgo.Date{Time: time.Unix(0, 0)},
	}
	query.Prof = append(query.Prof, &profileRequest)

	_, err = client.Request(&query)
	if err == nil {
		return true
	}

	// try again with anonymous logins
	query.Signon.UserID = ofxgo.String(anonymous)
	query.Signon.UserPass = ofxgo.String(anonymous)

	_, err = client.Request(&query)
	return err == nil
}


================================================
FILE: cmd/ofx/get_accounts.go
================================================
package main

import (
	"flag"
	"fmt"
	"github.com/aclindsa/ofxgo"
	"os"
	"time"
)

var getAccountsCommand = command{
	Name:        "get-accounts",
	Description: "List accounts at your financial institution",
	Flags:       flag.NewFlagSet("get-accounts", flag.ExitOnError),
	CheckFlags:  checkServerFlags,
	Do:          getAccounts,
}

func init() {
	defineServerFlags(getAccountsCommand.Flags)
}

func getAccounts() {
	client, query := newRequest()

	uid, err := ofxgo.RandomUID()
	if err != nil {
		fmt.Println("Error creating uid for transaction:", err)
		os.Exit(1)
	}

	acctInfo := ofxgo.AcctInfoRequest{
		TrnUID:   *uid,
		DtAcctUp: ofxgo.Date{Time: time.Unix(0, 0)},
	}
	query.Signup = append(query.Signup, &acctInfo)

	if dryrun {
		printRequest(client, query)
		return
	}

	response, err := client.Request(query)
	if err != nil {
		fmt.Println("Error requesting account information:", err)
		os.Exit(1)
	}

	if response.Signon.Status.Code != 0 {
		meaning, _ := response.Signon.Status.CodeMeaning()
		fmt.Printf("Nonzero signon status (%d: %s) with message: %s\n", response.Signon.Status.Code, meaning, response.Signon.Status.Message)
		os.Exit(1)
	}

	if len(response.Signup) < 1 {
		fmt.Println("No signup messages received")
		return
	}

	fmt.Printf("\nFound the following accounts:\n\n")

	if acctinfo, ok := response.Signup[0].(*ofxgo.AcctInfoResponse); ok {
		for _, acct := range acctinfo.AcctInfo {
			if acct.BankAcctInfo != nil {
				fmt.Printf("Bank Account:\n\tBankID: \"%s\"\n\tAcctID: \"%s\"\n\tAcctType: %s\n", acct.BankAcctInfo.BankAcctFrom.BankID, acct.BankAcctInfo.BankAcctFrom.AcctID, acct.BankAcctInfo.BankAcctFrom.AcctType)
			} else if acct.CCAcctInfo != nil {
				fmt.Printf("Credit card:\n\tAcctID: \"%s\"\n", acct.CCAcctInfo.CCAcctFrom.AcctID)
			} else if acct.InvAcctInfo != nil {
				fmt.Printf("Investment account:\n\tBrokerID: \"%s\"\n\tAcctID: \"%s\"\n", acct.InvAcctInfo.InvAcctFrom.BrokerID, acct.InvAcctInfo.InvAcctFrom.AcctID)
			} else {
				fmt.Printf("Unknown type: %s %s\n", acct.Name, acct.Desc)
			}
		}
	}
}


================================================
FILE: cmd/ofx/invdownload.go
================================================
package main

import (
	"flag"
	"fmt"
	"github.com/aclindsa/ofxgo"
	"io"
	"os"
)

var invDownloadCommand = command{
	Name:        "download-inv",
	Description: "Download a investment account statement to a file",
	Flags:       flag.NewFlagSet("download-inv", flag.ExitOnError),
	CheckFlags:  invDownloadCheckFlags,
	Do:          invDownload,
}

var brokerID string

func init() {
	defineServerFlags(invDownloadCommand.Flags)
	invDownloadCommand.Flags.StringVar(&filename, "filename", "./response.ofx", "The file to save to")
	invDownloadCommand.Flags.StringVar(&acctID, "acctid", "", "AcctID (from `get-accounts` subcommand)")
	invDownloadCommand.Flags.StringVar(&brokerID, "brokerid", "", "BrokerID (from `get-accounts` subcommand)")
}

func invDownloadCheckFlags() bool {
	ret := checkServerFlags()

	if len(filename) == 0 {
		fmt.Println("Error: Filename empty")
		return false
	}

	return ret
}

func invDownload() {
	client, query := newRequest()

	uid, err := ofxgo.RandomUID()
	if err != nil {
		fmt.Println("Error creating uid for transaction:", err)
		os.Exit(1)
	}

	statementRequest := ofxgo.InvStatementRequest{
		TrnUID: *uid,
		InvAcctFrom: ofxgo.InvAcct{
			BrokerID: ofxgo.String(brokerID),
			AcctID:   ofxgo.String(acctID),
		},
		Include:        true,
		IncludeOO:      true,
		IncludePos:     true,
		IncludeBalance: true,
		Include401K:    true,
		Include401KBal: true,
	}
	query.InvStmt = append(query.InvStmt, &statementRequest)

	if dryrun {
		printRequest(client, query)
		return
	}

	response, err := client.RequestNoParse(query)

	if err != nil {
		fmt.Println("Error requesting account statement:", err)

		os.Exit(1)
	}
	defer response.Body.Close()

	file, err := os.Create(filename)
	if err != nil {
		fmt.Println("Error creating file to write to:", err)
		os.Exit(1)
	}
	defer file.Close()

	_, err = io.Copy(file, response.Body)
	if err != nil {
		fmt.Println("Error writing response to file:", err)
		os.Exit(1)
	}
}


================================================
FILE: cmd/ofx/invtransactions.go
================================================
package main

import (
	"flag"
	"fmt"
	"github.com/aclindsa/ofxgo"
	"os"
)

var invTransactionsCommand = command{
	Name:        "transactions-inv",
	Description: "Print investment transactions",
	Flags:       flag.NewFlagSet("transactions-inv", flag.ExitOnError),
	CheckFlags:  checkServerFlags,
	Do:          invTransactions,
}

func init() {
	defineServerFlags(invTransactionsCommand.Flags)
	invTransactionsCommand.Flags.StringVar(&acctID, "acctid", "", "AcctID (from `get-accounts` subcommand)")
	invTransactionsCommand.Flags.StringVar(&brokerID, "brokerid", "", "BrokerID (from `get-accounts` subcommand)")
}

func invTransactions() {
	client, query := newRequest()

	uid, err := ofxgo.RandomUID()
	if err != nil {
		fmt.Println("Error creating uid for transaction:", err)
		os.Exit(1)
	}

	statementRequest := ofxgo.InvStatementRequest{
		TrnUID: *uid,
		InvAcctFrom: ofxgo.InvAcct{
			BrokerID: ofxgo.String(brokerID),
			AcctID:   ofxgo.String(acctID),
		},
		Include:        true,
		IncludeOO:      true,
		IncludePos:     true,
		IncludeBalance: true,
		Include401K:    true,
		Include401KBal: true,
	}
	query.InvStmt = append(query.InvStmt, &statementRequest)

	if dryrun {
		printRequest(client, query)
		return
	}

	response, err := client.Request(query)
	if err != nil {
		os.Exit(1)
	}

	if response.Signon.Status.Code != 0 {
		meaning, _ := response.Signon.Status.CodeMeaning()
		fmt.Printf("Nonzero signon status (%d: %s) with message: %s\n", response.Signon.Status.Code, meaning, response.Signon.Status.Message)
		os.Exit(1)
	}

	if len(response.InvStmt) < 1 {
		fmt.Println("No investment messages received")
		return
	}

	if stmt, ok := response.InvStmt[0].(*ofxgo.InvStatementResponse); ok {
		availCash := stmt.InvBal.AvailCash
		if availCash.IsInt() && availCash.Num().Int64() != 0 {
			fmt.Printf("Balance: %s %s (as of %s)\n", stmt.InvBal.AvailCash, stmt.CurDef, stmt.DtAsOf)
		}
		for _, banktrans := range stmt.InvTranList.BankTransactions {
			fmt.Printf("\nBank Transactions for %s subaccount:\n", banktrans.SubAcctFund)
			for _, tran := range banktrans.Transactions {
				printTransaction(stmt.CurDef, &tran)
			}
		}
		fmt.Printf("\nInvestment Transactions:\n")
		for _, t := range stmt.InvTranList.InvTransactions {
			fmt.Printf("%-14s", t.TransactionType())
			switch tran := t.(type) {
			case ofxgo.BuyDebt:
				printInvBuy(stmt.CurDef, &tran.InvBuy)
			case ofxgo.BuyMF:
				printInvBuy(stmt.CurDef, &tran.InvBuy)
			case ofxgo.BuyOpt:
				printInvBuy(stmt.CurDef, &tran.InvBuy)
			case ofxgo.BuyOther:
				printInvBuy(stmt.CurDef, &tran.InvBuy)
			case ofxgo.BuyStock:
				printInvBuy(stmt.CurDef, &tran.InvBuy)
			case ofxgo.ClosureOpt:
				printInvTran(&tran.InvTran)
				fmt.Printf("%s %s contracts (%d shares each)\n", tran.OptAction, tran.Units, tran.ShPerCtrct)
			case ofxgo.Income:
				printInvTran(&tran.InvTran)
				currency := stmt.CurDef
				if ok, _ := tran.Currency.Valid(); ok {
					currency = tran.Currency.CurSym
				}
				fmt.Printf(" %s %s %s (%s %s)\n", tran.IncomeType, tran.Total, currency, tran.SecID.UniqueIDType, tran.SecID.UniqueID)
				// TODO print ticker instead of CUSIP
			case ofxgo.InvExpense:
				printInvTran(&tran.InvTran)
				currency := stmt.CurDef
				if ok, _ := tran.Currency.Valid(); ok {
					currency = tran.Currency.CurSym
				}
				fmt.Printf(" %s %s (%s %s)\n", tran.Total, currency, tran.SecID.UniqueIDType, tran.SecID.UniqueID)
				// TODO print ticker instead of CUSIP
			case ofxgo.JrnlFund:
				printInvTran(&tran.InvTran)
				fmt.Printf(" %s %s (%s -> %s)\n", tran.Total, stmt.CurDef, tran.SubAcctFrom, tran.SubAcctTo)
			case ofxgo.JrnlSec:
				printInvTran(&tran.InvTran)
				fmt.Printf(" %s %s %s (%s -> %s)\n", tran.Units, tran.SecID.UniqueIDType, tran.SecID.UniqueID, tran.SubAcctFrom, tran.SubAcctTo)
				// TODO print ticker instead of CUSIP
			case ofxgo.MarginInterest:
				printInvTran(&tran.InvTran)
				currency := stmt.CurDef
				if ok, _ := tran.Currency.Valid(); ok {
					currency = tran.Currency.CurSym
				}
				fmt.Printf(" %s %s\n", tran.Total, currency)
			case ofxgo.Reinvest:
				printInvTran(&tran.InvTran)
				currency := stmt.CurDef
				if ok, _ := tran.Currency.Valid(); ok {
					currency = tran.Currency.CurSym
				}
				fmt.Printf(" %s (%s %s)@%s %s (Total: %s)\n", tran.Units, tran.SecID.UniqueIDType, tran.SecID.UniqueID, tran.UnitPrice, currency, tran.Total)
				// TODO print ticker instead of CUSIP
			case ofxgo.RetOfCap:
				printInvTran(&tran.InvTran)
				currency := stmt.CurDef
				if ok, _ := tran.Currency.Valid(); ok {
					currency = tran.Currency.CurSym
				}
				fmt.Printf(" %s %s (%s %s)\n", tran.Total, currency, tran.SecID.UniqueIDType, tran.SecID.UniqueID)
				// TODO print ticker instead of CUSIP
			case ofxgo.SellDebt:
				printInvSell(stmt.CurDef, &tran.InvSell)
			case ofxgo.SellMF:
				printInvSell(stmt.CurDef, &tran.InvSell)
			case ofxgo.SellOpt:
				printInvSell(stmt.CurDef, &tran.InvSell)
			case ofxgo.SellOther:
				printInvSell(stmt.CurDef, &tran.InvSell)
			case ofxgo.SellStock:
				printInvSell(stmt.CurDef, &tran.InvSell)
			case ofxgo.Split:
				printInvTran(&tran.InvTran)
				currency := stmt.CurDef
				if ok, _ := tran.Currency.Valid(); ok {
					currency = tran.Currency.CurSym
				}
				fmt.Printf(" %d/%d %s -> %s shares of %s %s (%s %s for fractional shares)\n", tran.Numerator, tran.Denominator, tran.OldUnits, tran.NewUnits, tran.SecID.UniqueIDType, tran.SecID.UniqueID, tran.FracCash, currency)
				// TODO print ticker instead of CUSIP
			case ofxgo.Transfer:
				printInvTran(&tran.InvTran)
				fmt.Printf(" %s (%s %s) %s\n", tran.Units, tran.SecID.UniqueIDType, tran.SecID.UniqueID, tran.TferAction)
				// TODO print ticker instead of CUSIP
			}
		}
	}
}

func printInvTran(it *ofxgo.InvTran) {
	fmt.Printf("%s", it.DtTrade)
}

func printInvBuy(defCurrency ofxgo.CurrSymbol, ib *ofxgo.InvBuy) {
	printInvTran(&ib.InvTran)
	currency := defCurrency
	if ok, _ := ib.Currency.Valid(); ok {
		currency = ib.Currency.CurSym
	}

	fmt.Printf("%s (%s %s)@%s %s (Total: %s)\n", ib.Units, ib.SecID.UniqueIDType, ib.SecID.UniqueID, ib.UnitPrice, currency, ib.Total)
	// TODO print ticker instead of CUSIP
}

func printInvSell(defCurrency ofxgo.CurrSymbol, is *ofxgo.InvSell) {
	printInvTran(&is.InvTran)
	currency := defCurrency
	if ok, _ := is.Currency.Valid(); ok {
		currency = is.Currency.CurSym
	}

	fmt.Printf(" %s (%s %s)@%s %s (Total: %s)\n", is.Units, is.SecID.UniqueIDType, is.SecID.UniqueID, is.UnitPrice, currency.String(), is.Total)
	// TODO print ticker instead of CUSIP
}


================================================
FILE: cmd/ofx/main.go
================================================
package main

import (
	"fmt"
	"os"
	"strconv"
)

var commands = []command{
	profileDownloadCommand,
	getAccountsCommand,
	downloadCommand,
	ccDownloadCommand,
	invDownloadCommand,
	bankTransactionsCommand,
	ccTransactionsCommand,
	invTransactionsCommand,
	detectSettingsCommand,
}

func usage() {
	fmt.Println(`The ofxgo command-line client provides a simple interface to
query, parse, and display financial data via the OFX specification.

Usage:
	ofx command [arguments]

The commands are:`)

	maxlen := 0
	for _, cmd := range commands {
		if len(cmd.Name) > maxlen {
			maxlen = len(cmd.Name)
		}
	}
	formatString := "    %-" + strconv.Itoa(maxlen) + "s    %s\n"

	for _, cmd := range commands {
		fmt.Printf(formatString, cmd.Name, cmd.Description)
	}
}

func runCmd(c *command) {
	err := c.Flags.Parse(os.Args[2:])
	if err != nil {
		fmt.Printf("Error parsing flags: %s\n", err)
		c.usage()
		os.Exit(1)
	}

	if !c.CheckFlags() {
		fmt.Println()
		c.usage()
		os.Exit(1)
	}

	c.Do()
}

func main() {
	if len(os.Args) < 2 {
		fmt.Printf("Error: Please supply a sub-command. Usage:\n\n")
		usage()
		os.Exit(1)
	}
	cmdName := os.Args[1]
	for _, cmd := range commands {
		if cmd.Name == cmdName {
			runCmd(&cmd)
			os.Exit(0)
		}
	}

	switch cmdName {
	case "-h", "-help", "--help", "help":
		usage()
	default:
		fmt.Println("Error: Invalid sub-command. Usage:")
		usage()
		os.Exit(1)
	}
}


================================================
FILE: cmd/ofx/profiledownload.go
================================================
package main

import (
	"flag"
	"fmt"
	"github.com/aclindsa/ofxgo"
	"io"
	"os"
)

var profileDownloadCommand = command{
	Name:        "download-profile",
	Description: "Download a FI profile to a file",
	Flags:       flag.NewFlagSet("download-profile", flag.ExitOnError),
	CheckFlags:  downloadProfileCheckFlags,
	Do:          downloadProfile,
}

func init() {
	defineServerFlags(profileDownloadCommand.Flags)
	profileDownloadCommand.Flags.StringVar(&filename, "filename", "./response.ofx", "The file to save to")
}

func downloadProfileCheckFlags() bool {
	// Assume if the user didn't specify username that we should use anonymous
	// values for it and password
	if len(username) == 0 {
		username = "anonymous00000000000000000000000"
		password = "anonymous00000000000000000000000"
	}

	ret := checkServerFlags()

	if len(filename) == 0 {
		fmt.Println("Error: Filename empty")
		return false
	}

	return ret
}

func downloadProfile() {
	client, query := newRequest()

	uid, err := ofxgo.RandomUID()
	if err != nil {
		fmt.Println("Error creating uid for transaction:", err)
		os.Exit(1)
	}

	profileRequest := ofxgo.ProfileRequest{
		TrnUID: *uid,
	}

	query.Prof = append(query.Prof, &profileRequest)

	if dryrun {
		printRequest(client, query)
		return
	}

	response, err := client.RequestNoParse(query)
	if err != nil {
		fmt.Println("Error requesting FI profile:", err)
		os.Exit(1)
	}
	defer response.Body.Close()

	file, err := os.Create(filename)
	if err != nil {
		fmt.Println("Error creating file to write to:", err)
		os.Exit(1)
	}
	defer file.Close()

	_, err = io.Copy(file, response.Body)
	if err != nil {
		fmt.Println("Error writing response to file:", err)
		os.Exit(1)
	}
}


================================================
FILE: cmd/ofx/util.go
================================================
package main

import (
	"fmt"
	"github.com/aclindsa/ofxgo"
	"os"
)

func newRequest() (ofxgo.Client, *ofxgo.Request) {
	ver, err := ofxgo.NewOfxVersion(ofxVersion)
	if err != nil {
		fmt.Println("Error creating new OfxVersion enum:", err)
		os.Exit(1)
	}
	var client = ofxgo.GetClient(serverURL,
		&ofxgo.BasicClient{
			AppID:          appID,
			AppVer:         appVer,
			SpecVersion:    ver,
			NoIndent:       noIndentRequests,
			CarriageReturn: carriageReturn,
			UserAgent:      userAgent,
		})

	var query ofxgo.Request
	query.URL = serverURL
	query.Signon.ClientUID = ofxgo.UID(clientUID)
	query.Signon.UserID = ofxgo.String(username)
	query.Signon.UserPass = ofxgo.String(password)
	query.Signon.Org = ofxgo.String(org)
	query.Signon.Fid = ofxgo.String(fid)

	return client, &query
}

func printRequest(c ofxgo.Client, r *ofxgo.Request) {
	r.SetClientFields(c)

	b, err := r.Marshal()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(b)
}


================================================
FILE: common.go
================================================
package ofxgo

//go:generate ./generate_constants.py

import (
	"bytes"
	"errors"
	"fmt"
	"strings"

	"github.com/aclindsa/xml"
)

func writeHeader(b *bytes.Buffer, v ofxVersion, carriageReturn bool) error {
	// Write the header appropriate to our version
	switch v {
	case OfxVersion102, OfxVersion103, OfxVersion151, OfxVersion160:
		header := `OFXHEADER:100
DATA:OFXSGML
VERSION:` + v.String() + `
SECURITY:NONE
ENCODING:USASCII
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE

`
		if carriageReturn {
			header = strings.Replace(header, "\n", "\r\n", -1)
		}
		b.WriteString(header)
	case OfxVersion200, OfxVersion201, OfxVersion202, OfxVersion203, OfxVersion210, OfxVersion211, OfxVersion220:
		b.WriteString(`<?xml version="1.0" encoding="UTF-8" standalone="no"?>`)
		if carriageReturn {
			b.WriteByte('\r')
		}
		b.WriteByte('\n')
		b.WriteString(`<?OFX OFXHEADER="200" VERSION="` + v.String() + `" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>`)
		if carriageReturn {
			b.WriteByte('\r')
		}
		b.WriteByte('\n')
	default:
		return fmt.Errorf("%d is not a valid OFX version string", v)
	}
	return nil
}

// Message represents an OFX message in a message set. it is used to ease
// marshalling and unmarshalling.
type Message interface {
	Name() string                           // The name of the OFX transaction wrapper element this represents
	Valid(version ofxVersion) (bool, error) // Called before a Message is marshaled and after it's unmarshaled to ensure the request or response is valid
	Type() messageType                      // The message set this message belongs to
}

type messageType uint

// These constants are returned by Messages' Type() functions to determine
// which message set they belong to
const (
	// Requests
	SignonRq messageType = iota
	SignupRq
	BankRq
	CreditCardRq
	LoanRq
	InvStmtRq
	InterXferRq
	WireXferRq
	BillpayRq
	EmailRq
	SecListRq
	PresDirRq
	PresDlvRq
	ProfRq
	ImageRq

	// Responses
	SignonRs
	SignupRs
	BankRs
	CreditCardRs
	LoanRs
	InvStmtRs
	InterXferRs
	WireXferRs
	BillpayRs
	EmailRs
	SecListRs
	PresDirRs
	PresDlvRs
	ProfRs
	ImageRs
)

func (t messageType) String() string {
	switch t {
	case SignonRq:
		return "SIGNONMSGSRQV1"
	case SignupRq:
		return "SIGNUPMSGSRQV1"
	case BankRq:
		return "BANKMSGSRQV1"
	case CreditCardRq:
		return "CREDITCARDMSGSRQV1"
	case LoanRq:
		return "LOANMSGSRQV1"
	case InvStmtRq:
		return "INVSTMTMSGSRQV1"
	case InterXferRq:
		return "INTERXFERMSGSRQV1"
	case WireXferRq:
		return "WIREXFERMSGSRQV1"
	case BillpayRq:
		return "BILLPAYMSGSRQV1"
	case EmailRq:
		return "EMAILMSGSRQV1"
	case SecListRq:
		return "SECLISTMSGSRQV1"
	case PresDirRq:
		return "PRESDIRMSGSRQV1"
	case PresDlvRq:
		return "PRESDLVMSGSRQV1"
	case ProfRq:
		return "PROFMSGSRQV1"
	case ImageRq:
		return "IMAGEMSGSRQV1"
	case SignonRs:
		return "SIGNONMSGSRSV1"
	case SignupRs:
		return "SIGNUPMSGSRSV1"
	case BankRs:
		return "BANKMSGSRSV1"
	case CreditCardRs:
		return "CREDITCARDMSGSRSV1"
	case LoanRs:
		return "LOANMSGSRSV1"
	case InvStmtRs:
		return "INVSTMTMSGSRSV1"
	case InterXferRs:
		return "INTERXFERMSGSRSV1"
	case WireXferRs:
		return "WIREXFERMSGSRSV1"
	case BillpayRs:
		return "BILLPAYMSGSRSV1"
	case EmailRs:
		return "EMAILMSGSRSV1"
	case SecListRs:
		return "SECLISTMSGSRSV1"
	case PresDirRs:
		return "PRESDIRMSGSRSV1"
	case PresDlvRs:
		return "PRESDLVMSGSRSV1"
	case ProfRs:
		return "PROFMSGSRSV1"
	case ImageRs:
		return "IMAGEMSGSRSV1"
	}
	panic("Invalid messageType")
}

// Map of error codes to their meanings, SEVERITY, and conditions under which
// OFX servers are expected to return them
var statusMeanings = map[Int][3]string{
	0:     {"Success", "INFO", "The server successfully processed the request."},
	1:     {"Client is up-to-date", "INFO", "Based on the client timestamp, the client has the latest information. The response does not supply any additional information."},
	2000:  {"General error", "ERROR", "Error other than those specified by the remaining error codes. Note: Servers should provide a more specific error whenever possible. Error code 2000 should be reserved for cases in which a more specific code is not available."},
	2001:  {"Invalid account", "ERROR", ""},
	2002:  {"General account error", "ERROR", "Account error not specified by the remaining error codes."},
	2003:  {"Account not found", "ERROR", "The specified account number does not correspond to one of the user’s accounts."},
	2004:  {"Account closed", "ERROR", "The specified account number corresponds to an account that has been closed."},
	2005:  {"Account not authorized", "ERROR", "The user is not authorized to perform this action on the account, or the server does not allow this type of action to be performed on the account."},
	2006:  {"Source account not found", "ERROR", "The specified account number does not correspond to one of the user’s accounts."},
	2007:  {"Source account closed", "ERROR", "The specified account number corresponds to an account that has been closed."},
	2008:  {"Source account not authorized", "ERROR", "The user is not authorized to perform this action on the account, or the server does not allow this type of action to be performed on the account."},
	2009:  {"Destination account not found", "ERROR", "The specified account number does not correspond to one of the user’s accounts."},
	2010:  {"Destination account closed", "ERROR", "The specified account number corresponds to an account that has been closed."},
	2011:  {"Destination account not authorized", "ERROR", "The user is not authorized to perform this action on the account, or the server does not allow this type of action to be performed on the account."},
	2012:  {"Invalid amount", "ERROR", "The specified amount is not valid for this action; for example, the user specified a negative payment amount."},
	2014:  {"Date too soon", "ERROR", "The server cannot process the requested action by the date specified by the user."},
	2015:  {"Date too far in future", "ERROR", "The server cannot accept requests for an action that far in the future."},
	2016:  {"Transaction already committed", "ERROR", "Transaction has entered the processing loop and cannot be modified/cancelled using OFX.  The transaction may still be cancelled or modified using other means (for example, a phone call to Customer Service)."},
	2017:  {"Already canceled", "ERROR", "The transaction cannot be canceled or modified because it has already been canceled."},
	2018:  {"Unknown server ID", "ERROR", "The specified server ID does not exist or no longer exists."},
	2019:  {"Duplicate request", "ERROR", "A request with this <TRNUID> has already been received and processed."},
	2020:  {"Invalid date", "ERROR", "The specified datetime stamp cannot be parsed; for instance, the datetime stamp specifies 25:00 hours."},
	2021:  {"Unsupported version", "ERROR", "The server does not support the requested version. The version of the message set specified by the client is not supported by this server."},
	2022:  {"Invalid TAN", "ERROR", "The server was unable to validate the TAN sent in the request."},
	2023:  {"Unknown FITID", "ERROR", "The specified FITID/BILLID does not exist or no longer exists.  [BILLID not found (ERROR) in the billing message sets]"},
	2025:  {"Branch ID missing", "ERROR", "A <BRANCHID> value must be provided in the <BANKACCTFROM> aggregate for this country system, but this field is missing."},
	2026:  {"Bank name doesn’t match bank ID", "ERROR", "The value of <BANKNAME> in the <EXTBANKACCTTO> aggregate is inconsistent with the value of <BANKID> in the <BANKACCTTO> aggregate."},
	2027:  {"Invalid date range", "ERROR", "Response for non-overlapping dates, date ranges in the future, et cetera."},
	2028:  {"Requested element unknown", "WARN", "One or more elements of the request were not recognized by the server or the server (as noted in the FI Profile) does not support the elements. The server executed the element transactions it understood and supported. For example, the request file included private tags in a <PMTRQ> but the server was able to execute the rest of the request."},
	3000:  {"MFA Challenge authentication required", "ERROR", "User credentials are correct, but further authentication required. Client should send <MFACHALLENGERQ> in next request."},
	3001:  {"MFA Challenge information is invalid", "ERROR", "User or client information sent in MFACHALLENGEA contains invalid information"},
	6500:  {"<REJECTIFMISSING>Y invalid without <TOKEN>", "ERROR", "This error code may appear in the <SYNCERROR> element of an <xxxSYNCRS> wrapper (in <PRESDLVMSGSRSV1> and V2 message set responses) or the <CODE> contained in any embedded transaction wrappers within a sync response. The corresponding sync request wrapper included <REJECTIFMISSING>Y with <REFRESH>Y or <TOKENONLY>Y, which is illegal."},
	6501:  {"Embedded transactions in request failed to process: Out of date", "WARN", "<REJECTIFMISSING>Y and embedded transactions appeared in the request sync wrapper and the provided <TOKEN> was out of date. This code should be used in the <SYNCERROR> of the response sync wrapper."},
	6502:  {"Unable to process embedded transaction due to out-of-date <TOKEN>", "ERROR", "Used in response transaction wrapper for embedded transactions when <SYNCERROR>6501 appears in the surrounding sync wrapper."},
	10000: {"Stop check in process", "INFO", "Stop check is already in process."},
	10500: {"Too many checks to process", "ERROR", "The stop-payment request <STPCHKRQ> specifies too many checks."},
	10501: {"Invalid payee", "ERROR", "Payee error not specified by the remaining error codes."},
	10502: {"Invalid payee address", "ERROR", "Some portion of the payee’s address is incorrect or unknown."},
	10503: {"Invalid payee account number", "ERROR", "The account number <PAYACCT> of the requested payee is invalid."},
	10504: {"Insufficient funds", "ERROR", "The server cannot process the request because the specified account does not have enough funds."},
	10505: {"Cannot modify element", "ERROR", "The server does not allow modifications to one or more values in a modification request."},
	10506: {"Cannot modify source account", "ERROR", "Reserved for future use."},
	10507: {"Cannot modify destination account", "ERROR", "Reserved for future use."},
	10508: {"Invalid frequency", "ERROR", "The specified frequency <FREQ> does not match one of the accepted frequencies for recurring transactions."},
	10509: {"Model already canceled", "ERROR", "The server has already canceled the specified recurring model."},
	10510: {"Invalid payee ID", "ERROR", "The specified payee ID does not exist or no longer exists."},
	10511: {"Invalid payee city", "ERROR", "The specified city is incorrect or unknown."},
	10512: {"Invalid payee state", "ERROR", "The specified state is incorrect or unknown."},
	10513: {"Invalid payee postal code", "ERROR", "The specified postal code is incorrect or unknown."},
	10514: {"Transaction already processed", "ERROR", "Transaction has already been sent or date due is past"},
	10515: {"Payee not modifiable by client", "ERROR", "The server does not allow clients to change payee information."},
	10516: {"Wire beneficiary invalid", "ERROR", "The specified wire beneficiary does not exist or no longer exists."},
	10517: {"Invalid payee name", "ERROR", "The server does not recognize the specified payee name."},
	10518: {"Unknown model ID", "ERROR", "The specified model ID does not exist or no longer exists."},
	10519: {"Invalid payee list ID", "ERROR", "The specified payee list ID does not exist or no longer exists."},
	10600: {"Table type not found", "ERROR", "The specified table type is not recognized or does not exist."},
	12250: {"Investment transaction download not supported", "WARN", "The server does not support investment transaction download."},
	12251: {"Investment position download not supported", "WARN", "The server does not support investment position download."},
	12252: {"Investment positions for specified date not available", "WARN", "The server does not support investment positions for the specified date."},
	12253: {"Investment open order download not supported", "WARN", "The server does not support open order download."},
	12254: {"Investment balances download not supported", "WARN", "The server does not support investment balances download."},
	12255: {"401(k) not available for this account", "ERROR", "401(k) information requested from a non- 401(k) account."},
	12500: {"One or more securities not found", "ERROR", "The server could not find the requested securities."},
	13000: {"User ID & password will be sent out-of-band", "INFO", "The server will send the user ID and password via postal mail, e-mail, or another means. The accompanying message will provide details."},
	13500: {"Unable to enroll user", "ERROR", "The server could not enroll the user."},
	13501: {"User already enrolled", "ERROR", "The server has already enrolled the user."},
	13502: {"Invalid service", "ERROR", "The server does not support the service <SVC> specified in the service-activation request."},
	13503: {"Cannot change user information", "ERROR", "The server does not support the <CHGUSERINFORQ> request."},
	13504: {"<FI> Missing or Invalid in <SONRQ>", "ERROR", "The FI requires the client to provide the <FI> aggregate in the <SONRQ> request, but either none was provided, or the one provided was invalid."},
	14500: {"1099 forms not available", "ERROR", "1099 forms are not yet available for the tax year requested."},
	14501: {"1099 forms not available for user ID", "ERROR", "This user does not have any 1099 forms available."},
	14600: {"W2 forms not available", "ERROR", "W2 forms are not yet available for the tax year requested."},
	14601: {"W2 forms not available for user ID", "ERROR", "The user does not have any W2 forms available."},
	14700: {"1098 forms not available", "ERROR", "1098 forms are not yet available for the tax year requested."},
	14701: {"1098 forms not available for user ID", "ERROR", "The user does not have any 1098 forms available."},
	15000: {"Must change USERPASS", "INFO", "The user must change his or her <USERPASS> number as part of the next OFX request."},
	15500: {"Signon invalid", "ERROR", "The user cannot signon because he or she entered an invalid user ID or password."},
	15501: {"Customer account already in use", "ERROR", "The server allows only one connection at a time, and another user is already signed on.  Please try again later."},
	15502: {"USERPASS lockout", "ERROR", "The server has received too many failed signon attempts for this user. Please call the FI’s technical support number."},
	15503: {"Could not change USERPASS", "ERROR", "The server does not support the <PINCHRQ> request."},
	15504: {"Could not provide random data", "ERROR", "The server could not generate random data as requested by the <CHALLENGERQ>."},
	15505: {"Country system not supported", "ERROR", "The server does not support the country specified in the <COUNTRY> field of the <SONRQ> aggregate."},
	15506: {"Empty signon not supported", "ERROR", "The server does not support signons not accompanied by some other transaction."},
	15507: {"Signon invalid without supporting pin change request", "ERROR", "The OFX block associated with the signon does not contain a pin change request and should."},
	15508: {"Transaction not authorized. ", "ERROR", "Current user is not authorized to perform this action on behalf of the <USERID>."},
	15510: {"CLIENTUID error", "ERROR", "The CLIENTUID sent by the client was incorrect. User must register the Client UID."},
	15511: {"MFA error", "ERROR", "User should contact financial institution."},
	15512: {"AUTHTOKEN required", "ERROR", "User needs to contact financial institution to obtain AUTHTOKEN. Client should send it in the next request."},
	15513: {"AUTHTOKEN invalid", "ERROR", "The AUTHTOKEN sent by the client was invalid."},
	16500: {"HTML not allowed", "ERROR", "The server does not accept HTML formatting in the request."},
	16501: {"Unknown mail To:", "ERROR", "The server was unable to send mail to the specified Internet address."},
	16502: {"Invalid URL", "ERROR", "The server could not parse the URL."},
	16503: {"Unable to get URL", "ERROR", "The server was unable to retrieve the information at this URL (e.g., an HTTP 400 or 500 series error)."},
}

// Status represents the status of a Response (both top-level Request objects,
// and *Response objects)
type Status struct {
	XMLName  xml.Name `xml:"STATUS"`
	Code     Int      `xml:"CODE"`
	Severity String   `xml:"SEVERITY"`
	Message  String   `xml:"MESSAGE,omitempty"`
}

// Valid returns whether the Status is valid according to the OFX spec
func (s *Status) Valid() (bool, error) {
	switch s.Severity {
	case "INFO", "WARN", "ERROR":
	default:
		return false, errors.New("Invalid STATUS>SEVERITY")
	}

	if arr, ok := statusMeanings[s.Code]; ok {
		if arr[1] != string(s.Severity) {
			return false, errors.New("Unexpected SEVERITY for STATUS>CODE")
		}
	} else {
		return false, errors.New("Unknown OFX status code")
	}

	return true, nil
}

// CodeMeaning returns the meaning of the current status Code
func (s *Status) CodeMeaning() (string, error) {
	if arr, ok := statusMeanings[s.Code]; ok {
		return arr[0], nil
	}
	return "", errors.New("Unknown OFX status code")
}

// CodeConditions returns the conditions under which an OFX server is expected
// to return the current status Code
func (s *Status) CodeConditions() (string, error) {
	if arr, ok := statusMeanings[s.Code]; ok {
		return arr[2], nil
	}
	return "", errors.New("Unknown OFX status code")
}

// BankAcct represents the identifying information for one bank account
type BankAcct struct {
	XMLName  xml.Name // BANKACCTTO or BANKACCTFROM
	BankID   String   `xml:"BANKID"`
	BranchID String   `xml:"BRANCHID,omitempty"` // Unused in USA
	AcctID   String   `xml:"ACCTID"`
	AcctType acctType `xml:"ACCTTYPE"`          // One of CHECKING, SAVINGS, MONEYMRKT, CREDITLINE, CD
	AcctKey  String   `xml:"ACCTKEY,omitempty"` // Unused in USA
}

// Valid returns whether the BankAcct is valid according to the OFX spec
func (b BankAcct) Valid() (bool, error) {
	if len(b.BankID) == 0 {
		return false, errors.New("BankAcct.BankID empty")
	}
	if len(b.AcctID) == 0 {
		return false, errors.New("BankAcct.AcctID empty")
	}
	if !b.AcctType.Valid() {
		return false, errors.New("Invalid or unspecified BankAcct.AcctType")
	}
	return true, nil
}

// CCAcct represents the identifying information for one checking account
type CCAcct struct {
	XMLName xml.Name // CCACCTTO or CCACCTFROM
	AcctID  String   `xml:"ACCTID"`
	AcctKey String   `xml:"ACCTKEY,omitempty"` // Unused in USA
}

// Valid returns whether the CCAcct is valid according to the OFX spec
func (c CCAcct) Valid() (bool, error) {
	if len(c.AcctID) == 0 {
		return false, errors.New("CCAcct.AcctID empty")
	}
	return true, nil
}

// InvAcct represents the identifying information for one investment account
type InvAcct struct {
	XMLName  xml.Name // INVACCTTO or INVACCTFROM
	BrokerID String   `xml:"BROKERID"`
	AcctID   String   `xml:"ACCTID"`
}

// Currency represents one ISO-4217 currency. CURRENCY elements signify that
// the transaction containing this Currency struct is in this currency instead
// of being converted to the statement's default. ORIGCURRENCY elements signify
// that the transaction containing this Currency struct was converted to the
// statement's default from the specified currency.
type Currency struct {
	XMLName xml.Name   // CURRENCY or ORIGCURRENCY
	CurRate Amount     `xml:"CURRATE"` // Ratio of statement's currency (CURDEF) to transaction currency (CURSYM)
	CurSym  CurrSymbol `xml:"CURSYM"`  // ISO-4217 3-character currency identifier
}

// Valid returns whether the Currency is valid according to the OFX spec
func (c Currency) Valid() (bool, error) {
	if c.CurRate.IsInt() && c.CurRate.Num().Int64() == 0 {
		return false, errors.New("CurRate may not be zero")
	} else if ok, err := c.CurSym.Valid(); !ok {
		return false, err
	}
	return true, nil
}


================================================
FILE: common_test.go
================================================
package ofxgo

import (
	"testing"
)

func TestStatusValid(t *testing.T) {
	s := Status{
		Code:     0,
		Severity: "INFO",
		Message:  "Success",
	}
	if ok, err := s.Valid(); !ok {
		t.Fatalf("Status unexpectedly invalid: %s\n", err)
	}

	s.Severity = "INVALID"
	if ok, err := s.Valid(); ok || err == nil {
		t.Fatalf("Status unexpectedly valid invalid Severity\n")
	}

	s.Severity = "WARN"
	if ok, err := s.Valid(); ok || err == nil {
		t.Fatalf("Status unexpectedly valid with wrong Severity for Code 0\n")
	}

	s.Code = 9
	if ok, err := s.Valid(); ok || err == nil {
		t.Fatalf("Status unexpectedly valid with invalid Code\n")
	}
}

func TestStatusCodeMeaning(t *testing.T) {
	s := Status{
		Code:     15500,
		Severity: "ERROR",
	}
	meaning, err := s.CodeMeaning()
	if err != nil {
		t.Fatalf("Status.CodeMeaning unexpectedly failed: %s\n", err)
	}
	if meaning != "Signon invalid" {
		t.Fatalf("Unexpected meaning for Code 15500: \"%s\"\n", meaning)
	}

	s.Code = 999
	if meaning, err := s.CodeMeaning(); len(meaning) != 0 || err == nil {
		t.Fatalf("Status.CodeMeaning unexpectedly succeeded with invalid Code\n")
	}
}

func TestStatusCodeConditions(t *testing.T) {
	s := Status{
		Code:     2006,
		Severity: "ERROR",
	}
	if conditions, err := s.CodeConditions(); len(conditions) == 0 || err != nil {
		t.Fatalf("Status.CodeConditions unexpectedly failed: %s\n", err)
	}

	s.Code = 999
	if conditions, err := s.CodeConditions(); len(conditions) != 0 || err == nil {
		t.Fatalf("Status.CodeConditions unexpectedly succeeded with invalid Code\n")
	}
}


================================================
FILE: constants.go
================================================
package ofxgo

/*
 * Do not edit this file by hand. It is auto-generated by calling `go generate`.
 * To make changes, edit generate_constants.py, re-run `go generate`, and check
 * in the result.
 */

import (
	"errors"
	"fmt"
	"strings"

	"github.com/aclindsa/xml"
)

type ofxVersion uint

// OfxVersion* constants represent the OFX specification version in use
const (
	OfxVersion102 ofxVersion = 1 + iota
	OfxVersion103
	OfxVersion151
	OfxVersion160
	OfxVersion200
	OfxVersion201
	OfxVersion202
	OfxVersion203
	OfxVersion210
	OfxVersion211
	OfxVersion220
)

var ofxVersions = [...]string{"102", "103", "151", "160", "200", "201", "202", "203", "210", "211", "220"}

func (e ofxVersion) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= OfxVersion102 && e <= OfxVersion220
}

func (e ofxVersion) String() string {
	if e.Valid() {
		return ofxVersions[e-1]
	}
	return fmt.Sprintf("invalid ofxVersion (%d)", e)
}

func (e *ofxVersion) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range ofxVersions {
		if s == value {
			*e = ofxVersion(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid OfxVersion: \"" + in + "\"")
}

func (e *ofxVersion) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e ofxVersion) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(ofxVersions[e-1], start)
	return nil
}

// NewOfxVersion returns returns an 'enum' value of type ofxVersion given its
// string representation
func NewOfxVersion(s string) (ofxVersion, error) {
	var e ofxVersion
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type acctType uint

// AcctType* constants represent types of bank accounts
const (
	AcctTypeChecking acctType = 1 + iota
	AcctTypeSavings
	AcctTypeMoneyMrkt
	AcctTypeCreditLine
	AcctTypeCD
)

var acctTypes = [...]string{"CHECKING", "SAVINGS", "MONEYMRKT", "CREDITLINE", "CD"}

func (e acctType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= AcctTypeChecking && e <= AcctTypeCD
}

func (e acctType) String() string {
	if e.Valid() {
		return acctTypes[e-1]
	}
	return fmt.Sprintf("invalid acctType (%d)", e)
}

func (e *acctType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range acctTypes {
		if s == value {
			*e = acctType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid AcctType: \"" + in + "\"")
}

func (e *acctType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e acctType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(acctTypes[e-1], start)
	return nil
}

// NewAcctType returns returns an 'enum' value of type acctType given its
// string representation
func NewAcctType(s string) (acctType, error) {
	var e acctType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type trnType uint

// TrnType* constants represent types of transactions. INT, ATM, and POS depend on the signage of the account.
const (
	TrnTypeCredit trnType = 1 + iota
	TrnTypeDebit
	TrnTypeInt
	TrnTypeDiv
	TrnTypeFee
	TrnTypeSrvChg
	TrnTypeDep
	TrnTypeATM
	TrnTypePOS
	TrnTypeXfer
	TrnTypeCheck
	TrnTypePayment
	TrnTypeCash
	TrnTypeDirectDep
	TrnTypeDirectDebit
	TrnTypeRepeatPmt
	TrnTypeHold
	TrnTypeOther
)

var trnTypes = [...]string{"CREDIT", "DEBIT", "INT", "DIV", "FEE", "SRVCHG", "DEP", "ATM", "POS", "XFER", "CHECK", "PAYMENT", "CASH", "DIRECTDEP", "DIRECTDEBIT", "REPEATPMT", "HOLD", "OTHER"}

func (e trnType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= TrnTypeCredit && e <= TrnTypeOther
}

func (e trnType) String() string {
	if e.Valid() {
		return trnTypes[e-1]
	}
	return fmt.Sprintf("invalid trnType (%d)", e)
}

func (e *trnType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range trnTypes {
		if s == value {
			*e = trnType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid TrnType: \"" + in + "\"")
}

func (e *trnType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e trnType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(trnTypes[e-1], start)
	return nil
}

// NewTrnType returns returns an 'enum' value of type trnType given its
// string representation
func NewTrnType(s string) (trnType, error) {
	var e trnType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type imageType uint

// ImageType* constants represent what this image contains
const (
	ImageTypeStatement imageType = 1 + iota
	ImageTypeTransaction
	ImageTypeTax
)

var imageTypes = [...]string{"STATEMENT", "TRANSACTION", "TAX"}

func (e imageType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= ImageTypeStatement && e <= ImageTypeTax
}

func (e imageType) String() string {
	if e.Valid() {
		return imageTypes[e-1]
	}
	return fmt.Sprintf("invalid imageType (%d)", e)
}

func (e *imageType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range imageTypes {
		if s == value {
			*e = imageType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid ImageType: \"" + in + "\"")
}

func (e *imageType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e imageType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(imageTypes[e-1], start)
	return nil
}

// NewImageType returns returns an 'enum' value of type imageType given its
// string representation
func NewImageType(s string) (imageType, error) {
	var e imageType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type imageRefType uint

// ImageRefType* constants represent the type of reference to the image
const (
	ImageRefTypeOpaque imageRefType = 1 + iota
	ImageRefTypeURL
	ImageRefTypeFormURL
)

var imageRefTypes = [...]string{"OPAQUE", "URL", "FORMURL"}

func (e imageRefType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= ImageRefTypeOpaque && e <= ImageRefTypeFormURL
}

func (e imageRefType) String() string {
	if e.Valid() {
		return imageRefTypes[e-1]
	}
	return fmt.Sprintf("invalid imageRefType (%d)", e)
}

func (e *imageRefType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range imageRefTypes {
		if s == value {
			*e = imageRefType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid ImageRefType: \"" + in + "\"")
}

func (e *imageRefType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e imageRefType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(imageRefTypes[e-1], start)
	return nil
}

// NewImageRefType returns returns an 'enum' value of type imageRefType given its
// string representation
func NewImageRefType(s string) (imageRefType, error) {
	var e imageRefType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type checkSup uint

// CheckSup* constants represent what portions of the check this image contains
const (
	CheckSupFrontOnly checkSup = 1 + iota
	CheckSupBackOnly
	CheckSupFrontAndBack
)

var checkSups = [...]string{"FRONTONLY", "BACKONLY", "FRONTANDBACK"}

func (e checkSup) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= CheckSupFrontOnly && e <= CheckSupFrontAndBack
}

func (e checkSup) String() string {
	if e.Valid() {
		return checkSups[e-1]
	}
	return fmt.Sprintf("invalid checkSup (%d)", e)
}

func (e *checkSup) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range checkSups {
		if s == value {
			*e = checkSup(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid CheckSup: \"" + in + "\"")
}

func (e *checkSup) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e checkSup) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(checkSups[e-1], start)
	return nil
}

// NewCheckSup returns returns an 'enum' value of type checkSup given its
// string representation
func NewCheckSup(s string) (checkSup, error) {
	var e checkSup
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type correctAction uint

// CorrectAction* constants represent whether this transaction correction replaces or deletes the transaction matching its CORRECTFITID
const (
	CorrectActionDelete correctAction = 1 + iota
	CorrectActionReplace
)

var correctActions = [...]string{"DELETE", "REPLACE"}

func (e correctAction) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= CorrectActionDelete && e <= CorrectActionReplace
}

func (e correctAction) String() string {
	if e.Valid() {
		return correctActions[e-1]
	}
	return fmt.Sprintf("invalid correctAction (%d)", e)
}

func (e *correctAction) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range correctActions {
		if s == value {
			*e = correctAction(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid CorrectAction: \"" + in + "\"")
}

func (e *correctAction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e correctAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(correctActions[e-1], start)
	return nil
}

// NewCorrectAction returns returns an 'enum' value of type correctAction given its
// string representation
func NewCorrectAction(s string) (correctAction, error) {
	var e correctAction
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type balType uint

// BalType* constants represent how this BAL's VALUE field should be interpreted
const (
	BalTypeDollar balType = 1 + iota
	BalTypePercent
	BalTypeNumber
)

var balTypes = [...]string{"DOLLAR", "PERCENT", "NUMBER"}

func (e balType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= BalTypeDollar && e <= BalTypeNumber
}

func (e balType) String() string {
	if e.Valid() {
		return balTypes[e-1]
	}
	return fmt.Sprintf("invalid balType (%d)", e)
}

func (e *balType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range balTypes {
		if s == value {
			*e = balType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid BalType: \"" + in + "\"")
}

func (e *balType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e balType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(balTypes[e-1], start)
	return nil
}

// NewBalType returns returns an 'enum' value of type balType given its
// string representation
func NewBalType(s string) (balType, error) {
	var e balType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type inv401kSource uint

// Inv401kSource* constants represent the source of money used for this security in a 401(k) account. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST.
const (
	Inv401kSourcePreTax inv401kSource = 1 + iota
	Inv401kSourceAfterTax
	Inv401kSourceMatch
	Inv401kSourceProfitSharing
	Inv401kSourceRollover
	Inv401kSourceOtherVest
	Inv401kSourceOtherNonVest
)

var inv401kSources = [...]string{"PRETAX", "AFTERTAX", "MATCH", "PROFITSHARING", "ROLLOVER", "OTHERVEST", "OTHERNONVEST"}

func (e inv401kSource) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= Inv401kSourcePreTax && e <= Inv401kSourceOtherNonVest
}

func (e inv401kSource) String() string {
	if e.Valid() {
		return inv401kSources[e-1]
	}
	return fmt.Sprintf("invalid inv401kSource (%d)", e)
}

func (e *inv401kSource) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range inv401kSources {
		if s == value {
			*e = inv401kSource(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid Inv401kSource: \"" + in + "\"")
}

func (e *inv401kSource) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e inv401kSource) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(inv401kSources[e-1], start)
	return nil
}

// NewInv401kSource returns returns an 'enum' value of type inv401kSource given its
// string representation
func NewInv401kSource(s string) (inv401kSource, error) {
	var e inv401kSource
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type subAcctType uint

// SubAcctType* constants represent the sub-account type for a source and/or destination of a transaction. Used in fields named SubAcctFrom, SubAcctTo, SubAcctSec, SubAcctFund, HeldInAcct.
const (
	SubAcctTypeCash subAcctType = 1 + iota
	SubAcctTypeMargin
	SubAcctTypeShort
	SubAcctTypeOther
)

var subAcctTypes = [...]string{"CASH", "MARGIN", "SHORT", "OTHER"}

func (e subAcctType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= SubAcctTypeCash && e <= SubAcctTypeOther
}

func (e subAcctType) String() string {
	if e.Valid() {
		return subAcctTypes[e-1]
	}
	return fmt.Sprintf("invalid subAcctType (%d)", e)
}

func (e *subAcctType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range subAcctTypes {
		if s == value {
			*e = subAcctType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid SubAcctType: \"" + in + "\"")
}

func (e *subAcctType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e subAcctType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(subAcctTypes[e-1], start)
	return nil
}

// NewSubAcctType returns returns an 'enum' value of type subAcctType given its
// string representation
func NewSubAcctType(s string) (subAcctType, error) {
	var e subAcctType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type buyType uint

// BuyType* constants represent types of purchases
const (
	BuyTypeBuy buyType = 1 + iota
	BuyTypeBuyToCover
)

var buyTypes = [...]string{"BUY", "BUYTOCOVER"}

func (e buyType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= BuyTypeBuy && e <= BuyTypeBuyToCover
}

func (e buyType) String() string {
	if e.Valid() {
		return buyTypes[e-1]
	}
	return fmt.Sprintf("invalid buyType (%d)", e)
}

func (e *buyType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range buyTypes {
		if s == value {
			*e = buyType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid BuyType: \"" + in + "\"")
}

func (e *buyType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e buyType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(buyTypes[e-1], start)
	return nil
}

// NewBuyType returns returns an 'enum' value of type buyType given its
// string representation
func NewBuyType(s string) (buyType, error) {
	var e buyType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type optAction uint

// OptAction* constants represent types of actions for options
const (
	OptActionExercise optAction = 1 + iota
	OptActionAssign
	OptActionExpire
)

var optActions = [...]string{"EXERCISE", "ASSIGN", "EXPIRE"}

func (e optAction) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= OptActionExercise && e <= OptActionExpire
}

func (e optAction) String() string {
	if e.Valid() {
		return optActions[e-1]
	}
	return fmt.Sprintf("invalid optAction (%d)", e)
}

func (e *optAction) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range optActions {
		if s == value {
			*e = optAction(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid OptAction: \"" + in + "\"")
}

func (e *optAction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e optAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(optActions[e-1], start)
	return nil
}

// NewOptAction returns returns an 'enum' value of type optAction given its
// string representation
func NewOptAction(s string) (optAction, error) {
	var e optAction
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type tferAction uint

// TferAction* constants represent whether the transfer is into or out of this account
const (
	TferActionIn tferAction = 1 + iota
	TferActionOut
)

var tferActions = [...]string{"IN", "OUT"}

func (e tferAction) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= TferActionIn && e <= TferActionOut
}

func (e tferAction) String() string {
	if e.Valid() {
		return tferActions[e-1]
	}
	return fmt.Sprintf("invalid tferAction (%d)", e)
}

func (e *tferAction) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range tferActions {
		if s == value {
			*e = tferAction(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid TferAction: \"" + in + "\"")
}

func (e *tferAction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e tferAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(tferActions[e-1], start)
	return nil
}

// NewTferAction returns returns an 'enum' value of type tferAction given its
// string representation
func NewTferAction(s string) (tferAction, error) {
	var e tferAction
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type posType uint

// PosType* constants represent position type
const (
	PosTypeLong posType = 1 + iota
	PosTypeShort
)

var posTypes = [...]string{"LONG", "SHORT"}

func (e posType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= PosTypeLong && e <= PosTypeShort
}

func (e posType) String() string {
	if e.Valid() {
		return posTypes[e-1]
	}
	return fmt.Sprintf("invalid posType (%d)", e)
}

func (e *posType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range posTypes {
		if s == value {
			*e = posType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid PosType: \"" + in + "\"")
}

func (e *posType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e posType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(posTypes[e-1], start)
	return nil
}

// NewPosType returns returns an 'enum' value of type posType given its
// string representation
func NewPosType(s string) (posType, error) {
	var e posType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type secured uint

// Secured* constants represent how an option is secured
const (
	SecuredNaked secured = 1 + iota
	SecuredCovered
)

var secureds = [...]string{"NAKED", "COVERED"}

func (e secured) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= SecuredNaked && e <= SecuredCovered
}

func (e secured) String() string {
	if e.Valid() {
		return secureds[e-1]
	}
	return fmt.Sprintf("invalid secured (%d)", e)
}

func (e *secured) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range secureds {
		if s == value {
			*e = secured(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid Secured: \"" + in + "\"")
}

func (e *secured) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e secured) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(secureds[e-1], start)
	return nil
}

// NewSecured returns returns an 'enum' value of type secured given its
// string representation
func NewSecured(s string) (secured, error) {
	var e secured
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type duration uint

// Duration* constants represent how long the investment order is good for
const (
	DurationDay duration = 1 + iota
	DurationGoodTilCancel
	DurationImmediate
)

var durations = [...]string{"DAY", "GOODTILCANCEL", "IMMEDIATE"}

func (e duration) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= DurationDay && e <= DurationImmediate
}

func (e duration) String() string {
	if e.Valid() {
		return durations[e-1]
	}
	return fmt.Sprintf("invalid duration (%d)", e)
}

func (e *duration) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range durations {
		if s == value {
			*e = duration(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid Duration: \"" + in + "\"")
}

func (e *duration) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e duration) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(durations[e-1], start)
	return nil
}

// NewDuration returns returns an 'enum' value of type duration given its
// string representation
func NewDuration(s string) (duration, error) {
	var e duration
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type restriction uint

// Restriction* constants represent a special restriction on an investment order
const (
	RestrictionAllOrNone restriction = 1 + iota
	RestrictionMinUnits
	RestrictionNone
)

var restrictions = [...]string{"ALLORNONE", "MINUNITS", "NONE"}

func (e restriction) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= RestrictionAllOrNone && e <= RestrictionNone
}

func (e restriction) String() string {
	if e.Valid() {
		return restrictions[e-1]
	}
	return fmt.Sprintf("invalid restriction (%d)", e)
}

func (e *restriction) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range restrictions {
		if s == value {
			*e = restriction(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid Restriction: \"" + in + "\"")
}

func (e *restriction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e restriction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(restrictions[e-1], start)
	return nil
}

// NewRestriction returns returns an 'enum' value of type restriction given its
// string representation
func NewRestriction(s string) (restriction, error) {
	var e restriction
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type unitType uint

// UnitType* constants represent type of the UNITS value
const (
	UnitTypeShares unitType = 1 + iota
	UnitTypeCurrency
)

var unitTypes = [...]string{"SHARES", "CURRENCY"}

func (e unitType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= UnitTypeShares && e <= UnitTypeCurrency
}

func (e unitType) String() string {
	if e.Valid() {
		return unitTypes[e-1]
	}
	return fmt.Sprintf("invalid unitType (%d)", e)
}

func (e *unitType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range unitTypes {
		if s == value {
			*e = unitType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid UnitType: \"" + in + "\"")
}

func (e *unitType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e unitType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(unitTypes[e-1], start)
	return nil
}

// NewUnitType returns returns an 'enum' value of type unitType given its
// string representation
func NewUnitType(s string) (unitType, error) {
	var e unitType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type optBuyType uint

// OptBuyType* constants represent types of purchases for options
const (
	OptBuyTypeBuyToOpen optBuyType = 1 + iota
	OptBuyTypeBuyToClose
)

var optBuyTypes = [...]string{"BUYTOOPEN", "BUYTOCLOSE"}

func (e optBuyType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= OptBuyTypeBuyToOpen && e <= OptBuyTypeBuyToClose
}

func (e optBuyType) String() string {
	if e.Valid() {
		return optBuyTypes[e-1]
	}
	return fmt.Sprintf("invalid optBuyType (%d)", e)
}

func (e *optBuyType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range optBuyTypes {
		if s == value {
			*e = optBuyType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid OptBuyType: \"" + in + "\"")
}

func (e *optBuyType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e optBuyType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(optBuyTypes[e-1], start)
	return nil
}

// NewOptBuyType returns returns an 'enum' value of type optBuyType given its
// string representation
func NewOptBuyType(s string) (optBuyType, error) {
	var e optBuyType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type sellType uint

// SellType* constants represent types of sales
const (
	SellTypeSell sellType = 1 + iota
	SellTypeSellShort
)

var sellTypes = [...]string{"SELL", "SELLSHORT"}

func (e sellType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= SellTypeSell && e <= SellTypeSellShort
}

func (e sellType) String() string {
	if e.Valid() {
		return sellTypes[e-1]
	}
	return fmt.Sprintf("invalid sellType (%d)", e)
}

func (e *sellType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range sellTypes {
		if s == value {
			*e = sellType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid SellType: \"" + in + "\"")
}

func (e *sellType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e sellType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(sellTypes[e-1], start)
	return nil
}

// NewSellType returns returns an 'enum' value of type sellType given its
// string representation
func NewSellType(s string) (sellType, error) {
	var e sellType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type loanPmtFreq uint

// LoanPmtFreq* constants represent the frequency of loan payments
const (
	LoanPmtFreqWeekly loanPmtFreq = 1 + iota
	LoanPmtFreqBiweekly
	LoanPmtFreqTwiceMonthly
	LoanPmtFreqMonthly
	LoanPmtFreqFourWeeks
	LoanPmtFreqBiMonthly
	LoanPmtFreqQuarterly
	LoanPmtFreqSemiannually
	LoanPmtFreqAnnually
	LoanPmtFreqOther
)

var loanPmtFreqs = [...]string{"WEEKLY", "BIWEEKLY", "TWICEMONTHLY", "MONTHLY", "FOURWEEKS", "BIMONTHLY", "QUARTERLY", "SEMIANNUALLY", "ANNUALLY", "OTHER"}

func (e loanPmtFreq) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= LoanPmtFreqWeekly && e <= LoanPmtFreqOther
}

func (e loanPmtFreq) String() string {
	if e.Valid() {
		return loanPmtFreqs[e-1]
	}
	return fmt.Sprintf("invalid loanPmtFreq (%d)", e)
}

func (e *loanPmtFreq) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range loanPmtFreqs {
		if s == value {
			*e = loanPmtFreq(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid LoanPmtFreq: \"" + in + "\"")
}

func (e *loanPmtFreq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e loanPmtFreq) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(loanPmtFreqs[e-1], start)
	return nil
}

// NewLoanPmtFreq returns returns an 'enum' value of type loanPmtFreq given its
// string representation
func NewLoanPmtFreq(s string) (loanPmtFreq, error) {
	var e loanPmtFreq
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type incomeType uint

// IncomeType* constants represent types of investment income
const (
	IncomeTypeCGLong incomeType = 1 + iota
	IncomeTypeCGShort
	IncomeTypeDiv
	IncomeTypeInterest
	IncomeTypeMisc
)

var incomeTypes = [...]string{"CGLONG", "CGSHORT", "DIV", "INTEREST", "MISC"}

func (e incomeType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= IncomeTypeCGLong && e <= IncomeTypeMisc
}

func (e incomeType) String() string {
	if e.Valid() {
		return incomeTypes[e-1]
	}
	return fmt.Sprintf("invalid incomeType (%d)", e)
}

func (e *incomeType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range incomeTypes {
		if s == value {
			*e = incomeType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid IncomeType: \"" + in + "\"")
}

func (e *incomeType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e incomeType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(incomeTypes[e-1], start)
	return nil
}

// NewIncomeType returns returns an 'enum' value of type incomeType given its
// string representation
func NewIncomeType(s string) (incomeType, error) {
	var e incomeType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type sellReason uint

// SellReason* constants represent the reason the sell of a debt security was generated: CALL (the debt was called), SELL (the debt was sold), MATURITY (the debt reached maturity)
const (
	SellReasonCall sellReason = 1 + iota
	SellReasonSell
	SellReasonMaturity
)

var sellReasons = [...]string{"CALL", "SELL", "MATURITY"}

func (e sellReason) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= SellReasonCall && e <= SellReasonMaturity
}

func (e sellReason) String() string {
	if e.Valid() {
		return sellReasons[e-1]
	}
	return fmt.Sprintf("invalid sellReason (%d)", e)
}

func (e *sellReason) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range sellReasons {
		if s == value {
			*e = sellReason(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid SellReason: \"" + in + "\"")
}

func (e *sellReason) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e sellReason) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(sellReasons[e-1], start)
	return nil
}

// NewSellReason returns returns an 'enum' value of type sellReason given its
// string representation
func NewSellReason(s string) (sellReason, error) {
	var e sellReason
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type optSellType uint

// OptSellType* constants represent types of sales for options
const (
	OptSellTypeSellToClose optSellType = 1 + iota
	OptSellTypeSellToOpen
)

var optSellTypes = [...]string{"SELLTOCLOSE", "SELLTOOPEN"}

func (e optSellType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= OptSellTypeSellToClose && e <= OptSellTypeSellToOpen
}

func (e optSellType) String() string {
	if e.Valid() {
		return optSellTypes[e-1]
	}
	return fmt.Sprintf("invalid optSellType (%d)", e)
}

func (e *optSellType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range optSellTypes {
		if s == value {
			*e = optSellType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid OptSellType: \"" + in + "\"")
}

func (e *optSellType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e optSellType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(optSellTypes[e-1], start)
	return nil
}

// NewOptSellType returns returns an 'enum' value of type optSellType given its
// string representation
func NewOptSellType(s string) (optSellType, error) {
	var e optSellType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type relType uint

// RelType* constants represent related option transaction types
const (
	RelTypeSpread relType = 1 + iota
	RelTypeStraddle
	RelTypeNone
	RelTypeOther
)

var relTypes = [...]string{"SPREAD", "STRADDLE", "NONE", "OTHER"}

func (e relType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= RelTypeSpread && e <= RelTypeOther
}

func (e relType) String() string {
	if e.Valid() {
		return relTypes[e-1]
	}
	return fmt.Sprintf("invalid relType (%d)", e)
}

func (e *relType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range relTypes {
		if s == value {
			*e = relType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid RelType: \"" + in + "\"")
}

func (e *relType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e relType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(relTypes[e-1], start)
	return nil
}

// NewRelType returns returns an 'enum' value of type relType given its
// string representation
func NewRelType(s string) (relType, error) {
	var e relType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type charType uint

// CharType* constants represent types of characters allowed in password
const (
	CharTypeAlphaOnly charType = 1 + iota
	CharTypeNumericOnly
	CharTypeAlphaOrNumeric
	CharTypeAlphaAndNumeric
)

var charTypes = [...]string{"ALPHAONLY", "NUMERICONLY", "ALPHAORNUMERIC", "ALPHAANDNUMERIC"}

func (e charType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= CharTypeAlphaOnly && e <= CharTypeAlphaAndNumeric
}

func (e charType) String() string {
	if e.Valid() {
		return charTypes[e-1]
	}
	return fmt.Sprintf("invalid charType (%d)", e)
}

func (e *charType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range charTypes {
		if s == value {
			*e = charType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid CharType: \"" + in + "\"")
}

func (e *charType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e charType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(charTypes[e-1], start)
	return nil
}

// NewCharType returns returns an 'enum' value of type charType given its
// string representation
func NewCharType(s string) (charType, error) {
	var e charType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type syncMode uint

// SyncMode* constants represent data synchronization mode supported (see OFX spec for more details)
const (
	SyncModeFull syncMode = 1 + iota
	SyncModeLite
)

var syncModes = [...]string{"FULL", "LITE"}

func (e syncMode) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= SyncModeFull && e <= SyncModeLite
}

func (e syncMode) String() string {
	if e.Valid() {
		return syncModes[e-1]
	}
	return fmt.Sprintf("invalid syncMode (%d)", e)
}

func (e *syncMode) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range syncModes {
		if s == value {
			*e = syncMode(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid SyncMode: \"" + in + "\"")
}

func (e *syncMode) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e syncMode) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(syncModes[e-1], start)
	return nil
}

// NewSyncMode returns returns an 'enum' value of type syncMode given its
// string representation
func NewSyncMode(s string) (syncMode, error) {
	var e syncMode
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type ofxSec uint

// OfxSec* constants represent the type of application-level security required for the message set
const (
	OfxSecNone ofxSec = 1 + iota
	OfxSecType1
)

var ofxSecs = [...]string{"NONE", "TYPE 1"}

func (e ofxSec) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= OfxSecNone && e <= OfxSecType1
}

func (e ofxSec) String() string {
	if e.Valid() {
		return ofxSecs[e-1]
	}
	return fmt.Sprintf("invalid ofxSec (%d)", e)
}

func (e *ofxSec) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range ofxSecs {
		if s == value {
			*e = ofxSec(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid OfxSec: \"" + in + "\"")
}

func (e *ofxSec) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e ofxSec) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(ofxSecs[e-1], start)
	return nil
}

// NewOfxSec returns returns an 'enum' value of type ofxSec given its
// string representation
func NewOfxSec(s string) (ofxSec, error) {
	var e ofxSec
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type debtType uint

// DebtType* constants represent debt type
const (
	DebtTypeCoupon debtType = 1 + iota
	DebtTypeZero
)

var debtTypes = [...]string{"COUPON", "ZERO"}

func (e debtType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= DebtTypeCoupon && e <= DebtTypeZero
}

func (e debtType) String() string {
	if e.Valid() {
		return debtTypes[e-1]
	}
	return fmt.Sprintf("invalid debtType (%d)", e)
}

func (e *debtType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range debtTypes {
		if s == value {
			*e = debtType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid DebtType: \"" + in + "\"")
}

func (e *debtType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e debtType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(debtTypes[e-1], start)
	return nil
}

// NewDebtType returns returns an 'enum' value of type debtType given its
// string representation
func NewDebtType(s string) (debtType, error) {
	var e debtType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type debtClass uint

// DebtClass* constants represent the class of debt
const (
	DebtClassTreasury debtClass = 1 + iota
	DebtClassMunicipal
	DebtClassCorporate
	DebtClassOther
)

var debtClasss = [...]string{"TREASURY", "MUNICIPAL", "CORPORATE", "OTHER"}

func (e debtClass) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= DebtClassTreasury && e <= DebtClassOther
}

func (e debtClass) String() string {
	if e.Valid() {
		return debtClasss[e-1]
	}
	return fmt.Sprintf("invalid debtClass (%d)", e)
}

func (e *debtClass) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range debtClasss {
		if s == value {
			*e = debtClass(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid DebtClass: \"" + in + "\"")
}

func (e *debtClass) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e debtClass) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(debtClasss[e-1], start)
	return nil
}

// NewDebtClass returns returns an 'enum' value of type debtClass given its
// string representation
func NewDebtClass(s string) (debtClass, error) {
	var e debtClass
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type couponFreq uint

// CouponFreq* constants represent when debt coupons mature
const (
	CouponFreqMonthly couponFreq = 1 + iota
	CouponFreqQuarterly
	CouponFreqSemiannual
	CouponFreqAnnual
	CouponFreqOther
)

var couponFreqs = [...]string{"MONTHLY", "QUARTERLY", "SEMIANNUAL", "ANNUAL", "OTHER"}

func (e couponFreq) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= CouponFreqMonthly && e <= CouponFreqOther
}

func (e couponFreq) String() string {
	if e.Valid() {
		return couponFreqs[e-1]
	}
	return fmt.Sprintf("invalid couponFreq (%d)", e)
}

func (e *couponFreq) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range couponFreqs {
		if s == value {
			*e = couponFreq(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid CouponFreq: \"" + in + "\"")
}

func (e *couponFreq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e couponFreq) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(couponFreqs[e-1], start)
	return nil
}

// NewCouponFreq returns returns an 'enum' value of type couponFreq given its
// string representation
func NewCouponFreq(s string) (couponFreq, error) {
	var e couponFreq
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type callType uint

// CallType* constants represent type of next call (for a debt)
const (
	CallTypeCall callType = 1 + iota
	CallTypePut
	CallTypePrefund
	CallTypeMaturity
)

var callTypes = [...]string{"CALL", "PUT", "PREFUND", "MATURITY"}

func (e callType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= CallTypeCall && e <= CallTypeMaturity
}

func (e callType) String() string {
	if e.Valid() {
		return callTypes[e-1]
	}
	return fmt.Sprintf("invalid callType (%d)", e)
}

func (e *callType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range callTypes {
		if s == value {
			*e = callType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid CallType: \"" + in + "\"")
}

func (e *callType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e callType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(callTypes[e-1], start)
	return nil
}

// NewCallType returns returns an 'enum' value of type callType given its
// string representation
func NewCallType(s string) (callType, error) {
	var e callType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type assetClass uint

// AssetClass* constants represent type of asset classes
const (
	AssetClassDomesticBond assetClass = 1 + iota
	AssetClassIntlBond
	AssetClassLargeStock
	AssetClassSmallStock
	AssetClassIntlStock
	AssetClassMoneyMrkt
	AssetClassOther
)

var assetClasss = [...]string{"DOMESTICBOND", "INTLBOND", "LARGESTOCK", "SMALLSTOCK", "INTLSTOCK", "MONEYMRKT", "OTHER"}

func (e assetClass) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= AssetClassDomesticBond && e <= AssetClassOther
}

func (e assetClass) String() string {
	if e.Valid() {
		return assetClasss[e-1]
	}
	return fmt.Sprintf("invalid assetClass (%d)", e)
}

func (e *assetClass) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range assetClasss {
		if s == value {
			*e = assetClass(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid AssetClass: \"" + in + "\"")
}

func (e *assetClass) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e assetClass) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(assetClasss[e-1], start)
	return nil
}

// NewAssetClass returns returns an 'enum' value of type assetClass given its
// string representation
func NewAssetClass(s string) (assetClass, error) {
	var e assetClass
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type mfType uint

// MfType* constants represent types of mutual funds
const (
	MfTypeOpenEnd mfType = 1 + iota
	MfTypeCloseEnd
	MfTypeOther
)

var mfTypes = [...]string{"OPENEND", "CLOSEEND", "OTHER"}

func (e mfType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= MfTypeOpenEnd && e <= MfTypeOther
}

func (e mfType) String() string {
	if e.Valid() {
		return mfTypes[e-1]
	}
	return fmt.Sprintf("invalid mfType (%d)", e)
}

func (e *mfType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range mfTypes {
		if s == value {
			*e = mfType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid MfType: \"" + in + "\"")
}

func (e *mfType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e mfType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(mfTypes[e-1], start)
	return nil
}

// NewMfType returns returns an 'enum' value of type mfType given its
// string representation
func NewMfType(s string) (mfType, error) {
	var e mfType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type optType uint

// OptType* constants represent whether the option is a PUT or a CALL
const (
	OptTypePut optType = 1 + iota
	OptTypeCall
)

var optTypes = [...]string{"PUT", "CALL"}

func (e optType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= OptTypePut && e <= OptTypeCall
}

func (e optType) String() string {
	if e.Valid() {
		return optTypes[e-1]
	}
	return fmt.Sprintf("invalid optType (%d)", e)
}

func (e *optType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range optTypes {
		if s == value {
			*e = optType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid OptType: \"" + in + "\"")
}

func (e *optType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e optType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(optTypes[e-1], start)
	return nil
}

// NewOptType returns returns an 'enum' value of type optType given its
// string representation
func NewOptType(s string) (optType, error) {
	var e optType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type stockType uint

// StockType* constants represent types of stock
const (
	StockTypeCommon stockType = 1 + iota
	StockTypePreferred
	StockTypeConvertible
	StockTypeOther
)

var stockTypes = [...]string{"COMMON", "PREFERRED", "CONVERTIBLE", "OTHER"}

func (e stockType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= StockTypeCommon && e <= StockTypeOther
}

func (e stockType) String() string {
	if e.Valid() {
		return stockTypes[e-1]
	}
	return fmt.Sprintf("invalid stockType (%d)", e)
}

func (e *stockType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range stockTypes {
		if s == value {
			*e = stockType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid StockType: \"" + in + "\"")
}

func (e *stockType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e stockType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(stockTypes[e-1], start)
	return nil
}

// NewStockType returns returns an 'enum' value of type stockType given its
// string representation
func NewStockType(s string) (stockType, error) {
	var e stockType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type holderType uint

// HolderType* constants represent how the account is held
const (
	HolderTypeIndividual holderType = 1 + iota
	HolderTypeJoint
	HolderTypeCustodial
	HolderTypeTrust
	HolderTypeOther
)

var holderTypes = [...]string{"INDIVIDUAL", "JOINT", "CUSTODIAL", "TRUST", "OTHER"}

func (e holderType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= HolderTypeIndividual && e <= HolderTypeOther
}

func (e holderType) String() string {
	if e.Valid() {
		return holderTypes[e-1]
	}
	return fmt.Sprintf("invalid holderType (%d)", e)
}

func (e *holderType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range holderTypes {
		if s == value {
			*e = holderType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid HolderType: \"" + in + "\"")
}

func (e *holderType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e holderType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(holderTypes[e-1], start)
	return nil
}

// NewHolderType returns returns an 'enum' value of type holderType given its
// string representation
func NewHolderType(s string) (holderType, error) {
	var e holderType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type acctClassification uint

// AcctClassification* constants represent the type of an account
const (
	AcctClassificationPersonal acctClassification = 1 + iota
	AcctClassificationBusiness
	AcctClassificationCorporate
	AcctClassificationOther
)

var acctClassifications = [...]string{"PERSONAL", "BUSINESS", "CORPORATE", "OTHER"}

func (e acctClassification) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= AcctClassificationPersonal && e <= AcctClassificationOther
}

func (e acctClassification) String() string {
	if e.Valid() {
		return acctClassifications[e-1]
	}
	return fmt.Sprintf("invalid acctClassification (%d)", e)
}

func (e *acctClassification) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range acctClassifications {
		if s == value {
			*e = acctClassification(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid AcctClassification: \"" + in + "\"")
}

func (e *acctClassification) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e acctClassification) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(acctClassifications[e-1], start)
	return nil
}

// NewAcctClassification returns returns an 'enum' value of type acctClassification given its
// string representation
func NewAcctClassification(s string) (acctClassification, error) {
	var e acctClassification
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type svcStatus uint

// SvcStatus* constants represent the status of the account: AVAIL = Available, but not yet requested, PEND = Requested, but not yet available, ACTIVE = In use
const (
	SvcStatusAvail svcStatus = 1 + iota
	SvcStatusPend
	SvcStatusActive
)

var svcStatuss = [...]string{"AVAIL", "PEND", "ACTIVE"}

func (e svcStatus) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= SvcStatusAvail && e <= SvcStatusActive
}

func (e svcStatus) String() string {
	if e.Valid() {
		return svcStatuss[e-1]
	}
	return fmt.Sprintf("invalid svcStatus (%d)", e)
}

func (e *svcStatus) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range svcStatuss {
		if s == value {
			*e = svcStatus(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid SvcStatus: \"" + in + "\"")
}

func (e *svcStatus) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e svcStatus) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(svcStatuss[e-1], start)
	return nil
}

// NewSvcStatus returns returns an 'enum' value of type svcStatus given its
// string representation
func NewSvcStatus(s string) (svcStatus, error) {
	var e svcStatus
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}

type usProductType uint

// UsProductType* constants represent type of investment account (in the US)
const (
	UsProductType401K usProductType = 1 + iota
	UsProductType403B
	UsProductTypeIRA
	UsProductTypeKEOGH
	UsProductTypeOther
	UsProductTypeSARSEP
	UsProductTypeSimple
	UsProductTypeNormal
	UsProductTypeTDA
	UsProductTypeTrust
	UsProductTypeUGMA
)

var usProductTypes = [...]string{"401K", "403B", "IRA", "KEOGH", "OTHER", "SARSEP", "SIMPLE", "NORMAL", "TDA", "TRUST", "UGMA"}

func (e usProductType) Valid() bool {
	// This check is mostly out of paranoia, ensuring e != 0 should be
	// sufficient
	return e >= UsProductType401K && e <= UsProductTypeUGMA
}

func (e usProductType) String() string {
	if e.Valid() {
		return usProductTypes[e-1]
	}
	return fmt.Sprintf("invalid usProductType (%d)", e)
}

func (e *usProductType) FromString(in string) error {
	value := strings.TrimSpace(in)

	for i, s := range usProductTypes {
		if s == value {
			*e = usProductType(i + 1)
			return nil
		}
	}
	*e = 0
	return errors.New("Invalid UsProductType: \"" + in + "\"")
}

func (e *usProductType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	var value string
	err := d.DecodeElement(&value, &start)
	if err != nil {
		return err
	}

	return e.FromString(value)
}

func (e usProductType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
	if !e.Valid() {
		return nil
	}
	enc.EncodeElement(usProductTypes[e-1], start)
	return nil
}

// NewUsProductType returns returns an 'enum' value of type usProductType given its
// string representation
func NewUsProductType(s string) (usProductType, error) {
	var e usProductType
	err := e.FromString(s)
	if err != nil {
		return 0, err
	}
	return e, nil
}


================================================
FILE: constants_test.go
================================================
package ofxgo

/*
 * Do not edit this file by hand. It is auto-generated by calling `go generate`.
 * To make changes, edit generate_constants.py, re-run `go generate`, and check
 * in the result.
 */

import (
	"strings"
	"testing"

	"github.com/aclindsa/xml"
)

func TestOfxVersion(t *testing.T) {
	e, err := NewOfxVersion("102")
	if err != nil {
		t.Fatalf("Unexpected error creating new OfxVersion from string \"102\"\n")
	}
	if !e.Valid() {
		t.Fatalf("OfxVersion unexpectedly invalid\n")
	}
	err = e.FromString("220")
	if err != nil {
		t.Fatalf("Unexpected error on OfxVersion.FromString(\"220\")\n")
	}
	if e.String() != "220" {
		t.Fatalf("OfxVersion.String() expected to be \"220\"\n")
	}

	marshalHelper(t, "220", &e)

	overwritten, err := NewOfxVersion("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new OfxVersion from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("OfxVersion created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("OfxVersion created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(OfxVersion): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "220", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E ofxVersion
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct OfxVersion): %s\n", err)
	}
	if string(b) != "<SC><E>220</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>220</E></SC>", string(b))
	}
}

func TestAcctType(t *testing.T) {
	e, err := NewAcctType("CHECKING")
	if err != nil {
		t.Fatalf("Unexpected error creating new AcctType from string \"CHECKING\"\n")
	}
	if !e.Valid() {
		t.Fatalf("AcctType unexpectedly invalid\n")
	}
	err = e.FromString("CD")
	if err != nil {
		t.Fatalf("Unexpected error on AcctType.FromString(\"CD\")\n")
	}
	if e.String() != "CD" {
		t.Fatalf("AcctType.String() expected to be \"CD\"\n")
	}

	marshalHelper(t, "CD", &e)

	overwritten, err := NewAcctType("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new AcctType from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("AcctType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("AcctType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(AcctType): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "CD", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E acctType
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct AcctType): %s\n", err)
	}
	if string(b) != "<SC><E>CD</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>CD</E></SC>", string(b))
	}
}

func TestTrnType(t *testing.T) {
	e, err := NewTrnType("CREDIT")
	if err != nil {
		t.Fatalf("Unexpected error creating new TrnType from string \"CREDIT\"\n")
	}
	if !e.Valid() {
		t.Fatalf("TrnType unexpectedly invalid\n")
	}
	err = e.FromString("OTHER")
	if err != nil {
		t.Fatalf("Unexpected error on TrnType.FromString(\"OTHER\")\n")
	}
	if e.String() != "OTHER" {
		t.Fatalf("TrnType.String() expected to be \"OTHER\"\n")
	}

	marshalHelper(t, "OTHER", &e)

	overwritten, err := NewTrnType("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new TrnType from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("TrnType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("TrnType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(TrnType): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "OTHER", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E trnType
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct TrnType): %s\n", err)
	}
	if string(b) != "<SC><E>OTHER</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
	}
}

func TestImageType(t *testing.T) {
	e, err := NewImageType("STATEMENT")
	if err != nil {
		t.Fatalf("Unexpected error creating new ImageType from string \"STATEMENT\"\n")
	}
	if !e.Valid() {
		t.Fatalf("ImageType unexpectedly invalid\n")
	}
	err = e.FromString("TAX")
	if err != nil {
		t.Fatalf("Unexpected error on ImageType.FromString(\"TAX\")\n")
	}
	if e.String() != "TAX" {
		t.Fatalf("ImageType.String() expected to be \"TAX\"\n")
	}

	marshalHelper(t, "TAX", &e)

	overwritten, err := NewImageType("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new ImageType from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("ImageType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("ImageType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(ImageType): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "TAX", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E imageType
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct ImageType): %s\n", err)
	}
	if string(b) != "<SC><E>TAX</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>TAX</E></SC>", string(b))
	}
}

func TestImageRefType(t *testing.T) {
	e, err := NewImageRefType("OPAQUE")
	if err != nil {
		t.Fatalf("Unexpected error creating new ImageRefType from string \"OPAQUE\"\n")
	}
	if !e.Valid() {
		t.Fatalf("ImageRefType unexpectedly invalid\n")
	}
	err = e.FromString("FORMURL")
	if err != nil {
		t.Fatalf("Unexpected error on ImageRefType.FromString(\"FORMURL\")\n")
	}
	if e.String() != "FORMURL" {
		t.Fatalf("ImageRefType.String() expected to be \"FORMURL\"\n")
	}

	marshalHelper(t, "FORMURL", &e)

	overwritten, err := NewImageRefType("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new ImageRefType from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("ImageRefType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("ImageRefType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(ImageRefType): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "FORMURL", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E imageRefType
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct ImageRefType): %s\n", err)
	}
	if string(b) != "<SC><E>FORMURL</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>FORMURL</E></SC>", string(b))
	}
}

func TestCheckSup(t *testing.T) {
	e, err := NewCheckSup("FRONTONLY")
	if err != nil {
		t.Fatalf("Unexpected error creating new CheckSup from string \"FRONTONLY\"\n")
	}
	if !e.Valid() {
		t.Fatalf("CheckSup unexpectedly invalid\n")
	}
	err = e.FromString("FRONTANDBACK")
	if err != nil {
		t.Fatalf("Unexpected error on CheckSup.FromString(\"FRONTANDBACK\")\n")
	}
	if e.String() != "FRONTANDBACK" {
		t.Fatalf("CheckSup.String() expected to be \"FRONTANDBACK\"\n")
	}

	marshalHelper(t, "FRONTANDBACK", &e)

	overwritten, err := NewCheckSup("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new CheckSup from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("CheckSup created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("CheckSup created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(CheckSup): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "FRONTANDBACK", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E checkSup
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct CheckSup): %s\n", err)
	}
	if string(b) != "<SC><E>FRONTANDBACK</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>FRONTANDBACK</E></SC>", string(b))
	}
}

func TestCorrectAction(t *testing.T) {
	e, err := NewCorrectAction("DELETE")
	if err != nil {
		t.Fatalf("Unexpected error creating new CorrectAction from string \"DELETE\"\n")
	}
	if !e.Valid() {
		t.Fatalf("CorrectAction unexpectedly invalid\n")
	}
	err = e.FromString("REPLACE")
	if err != nil {
		t.Fatalf("Unexpected error on CorrectAction.FromString(\"REPLACE\")\n")
	}
	if e.String() != "REPLACE" {
		t.Fatalf("CorrectAction.String() expected to be \"REPLACE\"\n")
	}

	marshalHelper(t, "REPLACE", &e)

	overwritten, err := NewCorrectAction("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new CorrectAction from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("CorrectAction created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("CorrectAction created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(CorrectAction): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "REPLACE", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E correctAction
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct CorrectAction): %s\n", err)
	}
	if string(b) != "<SC><E>REPLACE</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>REPLACE</E></SC>", string(b))
	}
}

func TestBalType(t *testing.T) {
	e, err := NewBalType("DOLLAR")
	if err != nil {
		t.Fatalf("Unexpected error creating new BalType from string \"DOLLAR\"\n")
	}
	if !e.Valid() {
		t.Fatalf("BalType unexpectedly invalid\n")
	}
	err = e.FromString("NUMBER")
	if err != nil {
		t.Fatalf("Unexpected error on BalType.FromString(\"NUMBER\")\n")
	}
	if e.String() != "NUMBER" {
		t.Fatalf("BalType.String() expected to be \"NUMBER\"\n")
	}

	marshalHelper(t, "NUMBER", &e)

	overwritten, err := NewBalType("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new BalType from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("BalType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("BalType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(BalType): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "NUMBER", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E balType
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct BalType): %s\n", err)
	}
	if string(b) != "<SC><E>NUMBER</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>NUMBER</E></SC>", string(b))
	}
}

func TestInv401kSource(t *testing.T) {
	e, err := NewInv401kSource("PRETAX")
	if err != nil {
		t.Fatalf("Unexpected error creating new Inv401kSource from string \"PRETAX\"\n")
	}
	if !e.Valid() {
		t.Fatalf("Inv401kSource unexpectedly invalid\n")
	}
	err = e.FromString("OTHERNONVEST")
	if err != nil {
		t.Fatalf("Unexpected error on Inv401kSource.FromString(\"OTHERNONVEST\")\n")
	}
	if e.String() != "OTHERNONVEST" {
		t.Fatalf("Inv401kSource.String() expected to be \"OTHERNONVEST\"\n")
	}

	marshalHelper(t, "OTHERNONVEST", &e)

	overwritten, err := NewInv401kSource("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new Inv401kSource from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("Inv401kSource created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("Inv401kSource created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(Inv401kSource): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "OTHERNONVEST", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E inv401kSource
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct Inv401kSource): %s\n", err)
	}
	if string(b) != "<SC><E>OTHERNONVEST</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHERNONVEST</E></SC>", string(b))
	}
}

func TestSubAcctType(t *testing.T) {
	e, err := NewSubAcctType("CASH")
	if err != nil {
		t.Fatalf("Unexpected error creating new SubAcctType from string \"CASH\"\n")
	}
	if !e.Valid() {
		t.Fatalf("SubAcctType unexpectedly invalid\n")
	}
	err = e.FromString("OTHER")
	if err != nil {
		t.Fatalf("Unexpected error on SubAcctType.FromString(\"OTHER\")\n")
	}
	if e.String() != "OTHER" {
		t.Fatalf("SubAcctType.String() expected to be \"OTHER\"\n")
	}

	marshalHelper(t, "OTHER", &e)

	overwritten, err := NewSubAcctType("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new SubAcctType from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("SubAcctType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("SubAcctType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(SubAcctType): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "OTHER", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E subAcctType
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct SubAcctType): %s\n", err)
	}
	if string(b) != "<SC><E>OTHER</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
	}
}

func TestBuyType(t *testing.T) {
	e, err := NewBuyType("BUY")
	if err != nil {
		t.Fatalf("Unexpected error creating new BuyType from string \"BUY\"\n")
	}
	if !e.Valid() {
		t.Fatalf("BuyType unexpectedly invalid\n")
	}
	err = e.FromString("BUYTOCOVER")
	if err != nil {
		t.Fatalf("Unexpected error on BuyType.FromString(\"BUYTOCOVER\")\n")
	}
	if e.String() != "BUYTOCOVER" {
		t.Fatalf("BuyType.String() expected to be \"BUYTOCOVER\"\n")
	}

	marshalHelper(t, "BUYTOCOVER", &e)

	overwritten, err := NewBuyType("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new BuyType from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("BuyType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("BuyType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(BuyType): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "BUYTOCOVER", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E buyType
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct BuyType): %s\n", err)
	}
	if string(b) != "<SC><E>BUYTOCOVER</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>BUYTOCOVER</E></SC>", string(b))
	}
}

func TestOptAction(t *testing.T) {
	e, err := NewOptAction("EXERCISE")
	if err != nil {
		t.Fatalf("Unexpected error creating new OptAction from string \"EXERCISE\"\n")
	}
	if !e.Valid() {
		t.Fatalf("OptAction unexpectedly invalid\n")
	}
	err = e.FromString("EXPIRE")
	if err != nil {
		t.Fatalf("Unexpected error on OptAction.FromString(\"EXPIRE\")\n")
	}
	if e.String() != "EXPIRE" {
		t.Fatalf("OptAction.String() expected to be \"EXPIRE\"\n")
	}

	marshalHelper(t, "EXPIRE", &e)

	overwritten, err := NewOptAction("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new OptAction from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("OptAction created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("OptAction created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(OptAction): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "EXPIRE", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E optAction
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct OptAction): %s\n", err)
	}
	if string(b) != "<SC><E>EXPIRE</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>EXPIRE</E></SC>", string(b))
	}
}

func TestTferAction(t *testing.T) {
	e, err := NewTferAction("IN")
	if err != nil {
		t.Fatalf("Unexpected error creating new TferAction from string \"IN\"\n")
	}
	if !e.Valid() {
		t.Fatalf("TferAction unexpectedly invalid\n")
	}
	err = e.FromString("OUT")
	if err != nil {
		t.Fatalf("Unexpected error on TferAction.FromString(\"OUT\")\n")
	}
	if e.String() != "OUT" {
		t.Fatalf("TferAction.String() expected to be \"OUT\"\n")
	}

	marshalHelper(t, "OUT", &e)

	overwritten, err := NewTferAction("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new TferAction from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("TferAction created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("TferAction created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(TferAction): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "OUT", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E tferAction
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct TferAction): %s\n", err)
	}
	if string(b) != "<SC><E>OUT</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OUT</E></SC>", string(b))
	}
}

func TestPosType(t *testing.T) {
	e, err := NewPosType("LONG")
	if err != nil {
		t.Fatalf("Unexpected error creating new PosType from string \"LONG\"\n")
	}
	if !e.Valid() {
		t.Fatalf("PosType unexpectedly invalid\n")
	}
	err = e.FromString("SHORT")
	if err != nil {
		t.Fatalf("Unexpected error on PosType.FromString(\"SHORT\")\n")
	}
	if e.String() != "SHORT" {
		t.Fatalf("PosType.String() expected to be \"SHORT\"\n")
	}

	marshalHelper(t, "SHORT", &e)

	overwritten, err := NewPosType("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new PosType from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("PosType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("PosType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(PosType): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "SHORT", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E posType
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct PosType): %s\n", err)
	}
	if string(b) != "<SC><E>SHORT</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>SHORT</E></SC>", string(b))
	}
}

func TestSecured(t *testing.T) {
	e, err := NewSecured("NAKED")
	if err != nil {
		t.Fatalf("Unexpected error creating new Secured from string \"NAKED\"\n")
	}
	if !e.Valid() {
		t.Fatalf("Secured unexpectedly invalid\n")
	}
	err = e.FromString("COVERED")
	if err != nil {
		t.Fatalf("Unexpected error on Secured.FromString(\"COVERED\")\n")
	}
	if e.String() != "COVERED" {
		t.Fatalf("Secured.String() expected to be \"COVERED\"\n")
	}

	marshalHelper(t, "COVERED", &e)

	overwritten, err := NewSecured("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new Secured from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("Secured created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("Secured created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(Secured): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "COVERED", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E secured
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct Secured): %s\n", err)
	}
	if string(b) != "<SC><E>COVERED</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>COVERED</E></SC>", string(b))
	}
}

func TestDuration(t *testing.T) {
	e, err := NewDuration("DAY")
	if err != nil {
		t.Fatalf("Unexpected error creating new Duration from string \"DAY\"\n")
	}
	if !e.Valid() {
		t.Fatalf("Duration unexpectedly invalid\n")
	}
	err = e.FromString("IMMEDIATE")
	if err != nil {
		t.Fatalf("Unexpected error on Duration.FromString(\"IMMEDIATE\")\n")
	}
	if e.String() != "IMMEDIATE" {
		t.Fatalf("Duration.String() expected to be \"IMMEDIATE\"\n")
	}

	marshalHelper(t, "IMMEDIATE", &e)

	overwritten, err := NewDuration("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new Duration from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("Duration created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("Duration created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(Duration): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "IMMEDIATE", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E duration
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct Duration): %s\n", err)
	}
	if string(b) != "<SC><E>IMMEDIATE</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>IMMEDIATE</E></SC>", string(b))
	}
}

func TestRestriction(t *testing.T) {
	e, err := NewRestriction("ALLORNONE")
	if err != nil {
		t.Fatalf("Unexpected error creating new Restriction from string \"ALLORNONE\"\n")
	}
	if !e.Valid() {
		t.Fatalf("Restriction unexpectedly invalid\n")
	}
	err = e.FromString("NONE")
	if err != nil {
		t.Fatalf("Unexpected error on Restriction.FromString(\"NONE\")\n")
	}
	if e.String() != "NONE" {
		t.Fatalf("Restriction.String() expected to be \"NONE\"\n")
	}

	marshalHelper(t, "NONE", &e)

	overwritten, err := NewRestriction("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new Restriction from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("Restriction created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("Restriction created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(Restriction): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "NONE", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E restriction
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct Restriction): %s\n", err)
	}
	if string(b) != "<SC><E>NONE</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>NONE</E></SC>", string(b))
	}
}

func TestUnitType(t *testing.T) {
	e, err := NewUnitType("SHARES")
	if err != nil {
		t.Fatalf("Unexpected error creating new UnitType from string \"SHARES\"\n")
	}
	if !e.Valid() {
		t.Fatalf("UnitType unexpectedly invalid\n")
	}
	err = e.FromString("CURRENCY")
	if err != nil {
		t.Fatalf("Unexpected error on UnitType.FromString(\"CURRENCY\")\n")
	}
	if e.String() != "CURRENCY" {
		t.Fatalf("UnitType.String() expected to be \"CURRENCY\"\n")
	}

	marshalHelper(t, "CURRENCY", &e)

	overwritten, err := NewUnitType("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new UnitType from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("UnitType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("UnitType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(UnitType): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "CURRENCY", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbage value\n")
	}

	type SC struct {
		E unitType
	}
	sc := SC{E: e}
	b, err = xml.Marshal(sc)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(struct UnitType): %s\n", err)
	}
	if string(b) != "<SC><E>CURRENCY</E></SC>" {
		t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>CURRENCY</E></SC>", string(b))
	}
}

func TestOptBuyType(t *testing.T) {
	e, err := NewOptBuyType("BUYTOOPEN")
	if err != nil {
		t.Fatalf("Unexpected error creating new OptBuyType from string \"BUYTOOPEN\"\n")
	}
	if !e.Valid() {
		t.Fatalf("OptBuyType unexpectedly invalid\n")
	}
	err = e.FromString("BUYTOCLOSE")
	if err != nil {
		t.Fatalf("Unexpected error on OptBuyType.FromString(\"BUYTOCLOSE\")\n")
	}
	if e.String() != "BUYTOCLOSE" {
		t.Fatalf("OptBuyType.String() expected to be \"BUYTOCLOSE\"\n")
	}

	marshalHelper(t, "BUYTOCLOSE", &e)

	overwritten, err := NewOptBuyType("THISWILLNEVERBEAVALIDENUMSTRING")
	if err == nil {
		t.Fatalf("Expected error creating new OptBuyType from string \"THISWILLNEVERBEAVALIDENUMSTRING\"\n")
	}
	if overwritten.Valid() {
		t.Fatalf("OptBuyType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not be valid\n")
	}
	if !strings.Contains(strings.ToLower(overwritten.String()), "invalid") {
		t.Fatalf("OptBuyType created with string \"THISWILLNEVERBEAVALIDENUMSTRING\" should not return valid string from String()\n")
	}

	b, err := xml.Marshal(&overwritten)
	if err != nil {
		t.Fatalf("Unexpected error on xml.Marshal(OptBuyType): %s\n", err)
	}
	if string(b) != "" {
		t.Fatalf("Expected empty string, got '%s'\n", string(b))
	}

	unmarshalHelper(t, "BUYTOCLOSE", &e, &overwritten)

	err = xml.Unmarshal([]byte("<GARBAGE><!LALDK>"), &overwritten)
	if err == nil {
		t.Fatalf("Expected error unmarshalling garbag
Download .txt
gitextract_ipheoeo0/

├── .github/
│   └── workflows/
│       └── test.yml
├── LICENSE
├── README.md
├── bank.go
├── bank_test.go
├── basic_client.go
├── basic_client_test.go
├── client.go
├── cmd/
│   └── ofx/
│       ├── bankdownload.go
│       ├── banktransactions.go
│       ├── ccdownload.go
│       ├── cctransactions.go
│       ├── command.go
│       ├── detect_settings.go
│       ├── get_accounts.go
│       ├── invdownload.go
│       ├── invtransactions.go
│       ├── main.go
│       ├── profiledownload.go
│       └── util.go
├── common.go
├── common_test.go
├── constants.go
├── constants_test.go
├── creditcard.go
├── creditcard_test.go
├── discovercard_client.go
├── doc.go
├── generate_constants.py
├── go.mod
├── go.sum
├── invstmt.go
├── invstmt_test.go
├── leaf_elements.go
├── profile.go
├── profile_test.go
├── request.go
├── request_test.go
├── response.go
├── response_test.go
├── samples/
│   ├── busted_responses/
│   │   ├── bmo_v102__no_header_newline.qfx
│   │   └── wellsfargo.qfx
│   └── valid_responses/
│       ├── 401k_v203.ofx
│       ├── inv_v202.ofx
│       ├── ira_v202.ofx
│       ├── moneymrkt1_v103.ofx
│       ├── moneymrkt1_v103_TYPE1.ofx
│       └── moneymrkt1_v203.ofx
├── seclist.go
├── signon.go
├── signon_test.go
├── signup.go
├── signup_test.go
├── types.go
├── types_test.go
├── util.go
└── vanguard_client.go
Download .txt
SYMBOL INDEX (946 symbols across 41 files)

FILE: bank.go
  type StatementRequest (line 12) | type StatementRequest struct
    method Name (line 27) | func (r *StatementRequest) Name() string {
    method Valid (line 33) | func (r *StatementRequest) Valid(version ofxVersion) (bool, error) {
    method Type (line 48) | func (r *StatementRequest) Type() messageType {
  type Payee (line 53) | type Payee struct
    method Valid (line 67) | func (p Payee) Valid() (bool, error) {
  type ImageData (line 88) | type ImageData struct
  type Transaction (line 104) | type Transaction struct
    method Valid (line 135) | func (t Transaction) Valid(version ofxVersion) (bool, error) {
  type TransactionList (line 184) | type TransactionList struct
    method Valid (line 192) | func (l TransactionList) Valid(version ofxVersion) (bool, error) {
  type PendingTransaction (line 211) | type PendingTransaction struct
    method Valid (line 229) | func (t PendingTransaction) Valid() (bool, error) {
  type PendingTransactionList (line 248) | type PendingTransactionList struct
    method Valid (line 255) | func (l PendingTransactionList) Valid() (bool, error) {
  type Balance (line 270) | type Balance struct
    method Valid (line 287) | func (b Balance) Valid() (bool, error) {
  type StatementResponse (line 300) | type StatementResponse struct
    method Name (line 321) | func (sr *StatementResponse) Name() string {
    method Valid (line 326) | func (sr *StatementResponse) Valid(version ofxVersion) (bool, error) {
    method Type (line 364) | func (sr *StatementResponse) Type() messageType {

FILE: bank_test.go
  function TestMarshalBankStatementRequest (line 9) | func TestMarshalBankStatementRequest(t *testing.T) {
  function TestMarshalBankStatementRequest103 (line 75) | func TestMarshalBankStatementRequest103(t *testing.T) {
  function TestUnmarshalBankStatementResponse (line 149) | func TestUnmarshalBankStatementResponse(t *testing.T) {
  function TestPayeeValid (line 288) | func TestPayeeValid(t *testing.T) {
  function TestBalanceValid (line 346) | func TestBalanceValid(t *testing.T) {

FILE: basic_client.go
  type BasicClient (line 13) | type BasicClient struct
    method OfxVersion (line 32) | func (c *BasicClient) OfxVersion() ofxVersion {
    method ID (line 41) | func (c *BasicClient) ID() String {
    method Version (line 50) | func (c *BasicClient) Version() String {
    method IndentRequests (line 59) | func (c *BasicClient) IndentRequests() bool {
    method CarriageReturnNewLines (line 64) | func (c *BasicClient) CarriageReturnNewLines() bool {
    method RawRequest (line 70) | func (c *BasicClient) RawRequest(URL string, r io.Reader) (*http.Respo...
    method RequestNoParse (line 103) | func (c *BasicClient) RequestNoParse(r *Request) (*http.Response, erro...
    method Request (line 109) | func (c *BasicClient) Request(r *Request) (*Response, error) {

FILE: basic_client_test.go
  function TestBasicClient_HTTPClient (line 11) | func TestBasicClient_HTTPClient(t *testing.T) {

FILE: client.go
  type Client (line 13) | type Client interface
  type clientCreationFunc (line 57) | type clientCreationFunc
  function GetClient (line 62) | func GetClient(URL string, bc *BasicClient) Client {
  function clientRequestNoParse (line 80) | func clientRequestNoParse(c Client, r *Request) (*http.Response, error) {
  function clientRequest (line 93) | func clientRequest(c Client, r *Request) (*Response, error) {

FILE: cmd/ofx/bankdownload.go
  function init (line 21) | func init() {
  function downloadCheckFlags (line 29) | func downloadCheckFlags() bool {
  function download (line 40) | func download() {

FILE: cmd/ofx/banktransactions.go
  function init (line 18) | func init() {
  function bankTransactions (line 25) | func bankTransactions() {
  function printTransaction (line 83) | func printTransaction(defCurrency ofxgo.CurrSymbol, tran *ofxgo.Transact...

FILE: cmd/ofx/ccdownload.go
  function init (line 19) | func init() {
  function ccDownloadCheckFlags (line 25) | func ccDownloadCheckFlags() bool {
  function ccDownload (line 36) | func ccDownload() {

FILE: cmd/ofx/cctransactions.go
  function init (line 18) | func init() {
  function ccTransactions (line 23) | func ccTransactions() {

FILE: cmd/ofx/command.go
  type command (line 10) | type command struct
    method usage (line 18) | func (c *command) usage() {
  function defineServerFlags (line 30) | func defineServerFlags(f *flag.FlagSet) {
  function checkServerFlags (line 46) | func checkServerFlags() bool {

FILE: cmd/ofx/detect_settings.go
  function init (line 21) | func init() {
  function detectSettings (line 95) | func detectSettings() {
  constant anonymous (line 123) | anonymous = "anonymous00000000000000000000000"
  function tryProfile (line 125) | func tryProfile(appID, appVer, version string, noindent bool) bool {

FILE: cmd/ofx/get_accounts.go
  function init (line 19) | func init() {
  function getAccounts (line 23) | func getAccounts() {

FILE: cmd/ofx/invdownload.go
  function init (line 21) | func init() {
  function invDownloadCheckFlags (line 28) | func invDownloadCheckFlags() bool {
  function invDownload (line 39) | func invDownload() {

FILE: cmd/ofx/invtransactions.go
  function init (line 18) | func init() {
  function invTransactions (line 24) | func invTransactions() {
  function printInvTran (line 170) | func printInvTran(it *ofxgo.InvTran) {
  function printInvBuy (line 174) | func printInvBuy(defCurrency ofxgo.CurrSymbol, ib *ofxgo.InvBuy) {
  function printInvSell (line 185) | func printInvSell(defCurrency ofxgo.CurrSymbol, is *ofxgo.InvSell) {

FILE: cmd/ofx/main.go
  function usage (line 21) | func usage() {
  function runCmd (line 43) | func runCmd(c *command) {
  function main (line 60) | func main() {

FILE: cmd/ofx/profiledownload.go
  function init (line 19) | func init() {
  function downloadProfileCheckFlags (line 24) | func downloadProfileCheckFlags() bool {
  function downloadProfile (line 42) | func downloadProfile() {

FILE: cmd/ofx/util.go
  function newRequest (line 9) | func newRequest() (ofxgo.Client, *ofxgo.Request) {
  function printRequest (line 36) | func printRequest(c ofxgo.Client, r *ofxgo.Request) {

FILE: common.go
  function writeHeader (line 14) | func writeHeader(b *bytes.Buffer, v ofxVersion, carriageReturn bool) err...
  type Message (line 52) | type Message interface
  type messageType (line 58) | type messageType
    method String (line 98) | func (t messageType) String() string {
  constant SignonRq (line 64) | SignonRq messageType = iota
  constant SignupRq (line 65) | SignupRq
  constant BankRq (line 66) | BankRq
  constant CreditCardRq (line 67) | CreditCardRq
  constant LoanRq (line 68) | LoanRq
  constant InvStmtRq (line 69) | InvStmtRq
  constant InterXferRq (line 70) | InterXferRq
  constant WireXferRq (line 71) | WireXferRq
  constant BillpayRq (line 72) | BillpayRq
  constant EmailRq (line 73) | EmailRq
  constant SecListRq (line 74) | SecListRq
  constant PresDirRq (line 75) | PresDirRq
  constant PresDlvRq (line 76) | PresDlvRq
  constant ProfRq (line 77) | ProfRq
  constant ImageRq (line 78) | ImageRq
  constant SignonRs (line 81) | SignonRs
  constant SignupRs (line 82) | SignupRs
  constant BankRs (line 83) | BankRs
  constant CreditCardRs (line 84) | CreditCardRs
  constant LoanRs (line 85) | LoanRs
  constant InvStmtRs (line 86) | InvStmtRs
  constant InterXferRs (line 87) | InterXferRs
  constant WireXferRs (line 88) | WireXferRs
  constant BillpayRs (line 89) | BillpayRs
  constant EmailRs (line 90) | EmailRs
  constant SecListRs (line 91) | SecListRs
  constant PresDirRs (line 92) | PresDirRs
  constant PresDlvRs (line 93) | PresDlvRs
  constant ProfRs (line 94) | ProfRs
  constant ImageRs (line 95) | ImageRs
  type Status (line 264) | type Status struct
    method Valid (line 272) | func (s *Status) Valid() (bool, error) {
    method CodeMeaning (line 291) | func (s *Status) CodeMeaning() (string, error) {
    method CodeConditions (line 300) | func (s *Status) CodeConditions() (string, error) {
  type BankAcct (line 308) | type BankAcct struct
    method Valid (line 318) | func (b BankAcct) Valid() (bool, error) {
  type CCAcct (line 332) | type CCAcct struct
    method Valid (line 339) | func (c CCAcct) Valid() (bool, error) {
  type InvAcct (line 347) | type InvAcct struct
  type Currency (line 358) | type Currency struct
    method Valid (line 365) | func (c Currency) Valid() (bool, error) {

FILE: common_test.go
  function TestStatusValid (line 7) | func TestStatusValid(t *testing.T) {
  function TestStatusCodeMeaning (line 33) | func TestStatusCodeMeaning(t *testing.T) {
  function TestStatusCodeConditions (line 52) | func TestStatusCodeConditions(t *testing.T) {

FILE: constants.go
  type ofxVersion (line 17) | type ofxVersion
    method Valid (line 36) | func (e ofxVersion) Valid() bool {
    method String (line 42) | func (e ofxVersion) String() string {
    method FromString (line 49) | func (e *ofxVersion) FromString(in string) error {
    method UnmarshalXML (line 62) | func (e *ofxVersion) UnmarshalXML(d *xml.Decoder, start xml.StartEleme...
    method MarshalXML (line 72) | func (e ofxVersion) MarshalXML(enc *xml.Encoder, start xml.StartElemen...
  constant OfxVersion102 (line 21) | OfxVersion102 ofxVersion = 1 + iota
  constant OfxVersion103 (line 22) | OfxVersion103
  constant OfxVersion151 (line 23) | OfxVersion151
  constant OfxVersion160 (line 24) | OfxVersion160
  constant OfxVersion200 (line 25) | OfxVersion200
  constant OfxVersion201 (line 26) | OfxVersion201
  constant OfxVersion202 (line 27) | OfxVersion202
  constant OfxVersion203 (line 28) | OfxVersion203
  constant OfxVersion210 (line 29) | OfxVersion210
  constant OfxVersion211 (line 30) | OfxVersion211
  constant OfxVersion220 (line 31) | OfxVersion220
  function NewOfxVersion (line 82) | func NewOfxVersion(s string) (ofxVersion, error) {
  type acctType (line 91) | type acctType
    method Valid (line 104) | func (e acctType) Valid() bool {
    method String (line 110) | func (e acctType) String() string {
    method FromString (line 117) | func (e *acctType) FromString(in string) error {
    method UnmarshalXML (line 130) | func (e *acctType) UnmarshalXML(d *xml.Decoder, start xml.StartElement...
    method MarshalXML (line 140) | func (e acctType) MarshalXML(enc *xml.Encoder, start xml.StartElement)...
  constant AcctTypeChecking (line 95) | AcctTypeChecking acctType = 1 + iota
  constant AcctTypeSavings (line 96) | AcctTypeSavings
  constant AcctTypeMoneyMrkt (line 97) | AcctTypeMoneyMrkt
  constant AcctTypeCreditLine (line 98) | AcctTypeCreditLine
  constant AcctTypeCD (line 99) | AcctTypeCD
  function NewAcctType (line 150) | func NewAcctType(s string) (acctType, error) {
  type trnType (line 159) | type trnType
    method Valid (line 185) | func (e trnType) Valid() bool {
    method String (line 191) | func (e trnType) String() string {
    method FromString (line 198) | func (e *trnType) FromString(in string) error {
    method UnmarshalXML (line 211) | func (e *trnType) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
    method MarshalXML (line 221) | func (e trnType) MarshalXML(enc *xml.Encoder, start xml.StartElement) ...
  constant TrnTypeCredit (line 163) | TrnTypeCredit trnType = 1 + iota
  constant TrnTypeDebit (line 164) | TrnTypeDebit
  constant TrnTypeInt (line 165) | TrnTypeInt
  constant TrnTypeDiv (line 166) | TrnTypeDiv
  constant TrnTypeFee (line 167) | TrnTypeFee
  constant TrnTypeSrvChg (line 168) | TrnTypeSrvChg
  constant TrnTypeDep (line 169) | TrnTypeDep
  constant TrnTypeATM (line 170) | TrnTypeATM
  constant TrnTypePOS (line 171) | TrnTypePOS
  constant TrnTypeXfer (line 172) | TrnTypeXfer
  constant TrnTypeCheck (line 173) | TrnTypeCheck
  constant TrnTypePayment (line 174) | TrnTypePayment
  constant TrnTypeCash (line 175) | TrnTypeCash
  constant TrnTypeDirectDep (line 176) | TrnTypeDirectDep
  constant TrnTypeDirectDebit (line 177) | TrnTypeDirectDebit
  constant TrnTypeRepeatPmt (line 178) | TrnTypeRepeatPmt
  constant TrnTypeHold (line 179) | TrnTypeHold
  constant TrnTypeOther (line 180) | TrnTypeOther
  function NewTrnType (line 231) | func NewTrnType(s string) (trnType, error) {
  type imageType (line 240) | type imageType
    method Valid (line 251) | func (e imageType) Valid() bool {
    method String (line 257) | func (e imageType) String() string {
    method FromString (line 264) | func (e *imageType) FromString(in string) error {
    method UnmarshalXML (line 277) | func (e *imageType) UnmarshalXML(d *xml.Decoder, start xml.StartElemen...
    method MarshalXML (line 287) | func (e imageType) MarshalXML(enc *xml.Encoder, start xml.StartElement...
  constant ImageTypeStatement (line 244) | ImageTypeStatement imageType = 1 + iota
  constant ImageTypeTransaction (line 245) | ImageTypeTransaction
  constant ImageTypeTax (line 246) | ImageTypeTax
  function NewImageType (line 297) | func NewImageType(s string) (imageType, error) {
  type imageRefType (line 306) | type imageRefType
    method Valid (line 317) | func (e imageRefType) Valid() bool {
    method String (line 323) | func (e imageRefType) String() string {
    method FromString (line 330) | func (e *imageRefType) FromString(in string) error {
    method UnmarshalXML (line 343) | func (e *imageRefType) UnmarshalXML(d *xml.Decoder, start xml.StartEle...
    method MarshalXML (line 353) | func (e imageRefType) MarshalXML(enc *xml.Encoder, start xml.StartElem...
  constant ImageRefTypeOpaque (line 310) | ImageRefTypeOpaque imageRefType = 1 + iota
  constant ImageRefTypeURL (line 311) | ImageRefTypeURL
  constant ImageRefTypeFormURL (line 312) | ImageRefTypeFormURL
  function NewImageRefType (line 363) | func NewImageRefType(s string) (imageRefType, error) {
  type checkSup (line 372) | type checkSup
    method Valid (line 383) | func (e checkSup) Valid() bool {
    method String (line 389) | func (e checkSup) String() string {
    method FromString (line 396) | func (e *checkSup) FromString(in string) error {
    method UnmarshalXML (line 409) | func (e *checkSup) UnmarshalXML(d *xml.Decoder, start xml.StartElement...
    method MarshalXML (line 419) | func (e checkSup) MarshalXML(enc *xml.Encoder, start xml.StartElement)...
  constant CheckSupFrontOnly (line 376) | CheckSupFrontOnly checkSup = 1 + iota
  constant CheckSupBackOnly (line 377) | CheckSupBackOnly
  constant CheckSupFrontAndBack (line 378) | CheckSupFrontAndBack
  function NewCheckSup (line 429) | func NewCheckSup(s string) (checkSup, error) {
  type correctAction (line 438) | type correctAction
    method Valid (line 448) | func (e correctAction) Valid() bool {
    method String (line 454) | func (e correctAction) String() string {
    method FromString (line 461) | func (e *correctAction) FromString(in string) error {
    method UnmarshalXML (line 474) | func (e *correctAction) UnmarshalXML(d *xml.Decoder, start xml.StartEl...
    method MarshalXML (line 484) | func (e correctAction) MarshalXML(enc *xml.Encoder, start xml.StartEle...
  constant CorrectActionDelete (line 442) | CorrectActionDelete correctAction = 1 + iota
  constant CorrectActionReplace (line 443) | CorrectActionReplace
  function NewCorrectAction (line 494) | func NewCorrectAction(s string) (correctAction, error) {
  type balType (line 503) | type balType
    method Valid (line 514) | func (e balType) Valid() bool {
    method String (line 520) | func (e balType) String() string {
    method FromString (line 527) | func (e *balType) FromString(in string) error {
    method UnmarshalXML (line 540) | func (e *balType) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
    method MarshalXML (line 550) | func (e balType) MarshalXML(enc *xml.Encoder, start xml.StartElement) ...
  constant BalTypeDollar (line 507) | BalTypeDollar balType = 1 + iota
  constant BalTypePercent (line 508) | BalTypePercent
  constant BalTypeNumber (line 509) | BalTypeNumber
  function NewBalType (line 560) | func NewBalType(s string) (balType, error) {
  type inv401kSource (line 569) | type inv401kSource
    method Valid (line 584) | func (e inv401kSource) Valid() bool {
    method String (line 590) | func (e inv401kSource) String() string {
    method FromString (line 597) | func (e *inv401kSource) FromString(in string) error {
    method UnmarshalXML (line 610) | func (e *inv401kSource) UnmarshalXML(d *xml.Decoder, start xml.StartEl...
    method MarshalXML (line 620) | func (e inv401kSource) MarshalXML(enc *xml.Encoder, start xml.StartEle...
  constant Inv401kSourcePreTax (line 573) | Inv401kSourcePreTax inv401kSource = 1 + iota
  constant Inv401kSourceAfterTax (line 574) | Inv401kSourceAfterTax
  constant Inv401kSourceMatch (line 575) | Inv401kSourceMatch
  constant Inv401kSourceProfitSharing (line 576) | Inv401kSourceProfitSharing
  constant Inv401kSourceRollover (line 577) | Inv401kSourceRollover
  constant Inv401kSourceOtherVest (line 578) | Inv401kSourceOtherVest
  constant Inv401kSourceOtherNonVest (line 579) | Inv401kSourceOtherNonVest
  function NewInv401kSource (line 630) | func NewInv401kSource(s string) (inv401kSource, error) {
  type subAcctType (line 639) | type subAcctType
    method Valid (line 651) | func (e subAcctType) Valid() bool {
    method String (line 657) | func (e subAcctType) String() string {
    method FromString (line 664) | func (e *subAcctType) FromString(in string) error {
    method UnmarshalXML (line 677) | func (e *subAcctType) UnmarshalXML(d *xml.Decoder, start xml.StartElem...
    method MarshalXML (line 687) | func (e subAcctType) MarshalXML(enc *xml.Encoder, start xml.StartEleme...
  constant SubAcctTypeCash (line 643) | SubAcctTypeCash subAcctType = 1 + iota
  constant SubAcctTypeMargin (line 644) | SubAcctTypeMargin
  constant SubAcctTypeShort (line 645) | SubAcctTypeShort
  constant SubAcctTypeOther (line 646) | SubAcctTypeOther
  function NewSubAcctType (line 697) | func NewSubAcctType(s string) (subAcctType, error) {
  type buyType (line 706) | type buyType
    method Valid (line 716) | func (e buyType) Valid() bool {
    method String (line 722) | func (e buyType) String() string {
    method FromString (line 729) | func (e *buyType) FromString(in string) error {
    method UnmarshalXML (line 742) | func (e *buyType) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
    method MarshalXML (line 752) | func (e buyType) MarshalXML(enc *xml.Encoder, start xml.StartElement) ...
  constant BuyTypeBuy (line 710) | BuyTypeBuy buyType = 1 + iota
  constant BuyTypeBuyToCover (line 711) | BuyTypeBuyToCover
  function NewBuyType (line 762) | func NewBuyType(s string) (buyType, error) {
  type optAction (line 771) | type optAction
    method Valid (line 782) | func (e optAction) Valid() bool {
    method String (line 788) | func (e optAction) String() string {
    method FromString (line 795) | func (e *optAction) FromString(in string) error {
    method UnmarshalXML (line 808) | func (e *optAction) UnmarshalXML(d *xml.Decoder, start xml.StartElemen...
    method MarshalXML (line 818) | func (e optAction) MarshalXML(enc *xml.Encoder, start xml.StartElement...
  constant OptActionExercise (line 775) | OptActionExercise optAction = 1 + iota
  constant OptActionAssign (line 776) | OptActionAssign
  constant OptActionExpire (line 777) | OptActionExpire
  function NewOptAction (line 828) | func NewOptAction(s string) (optAction, error) {
  type tferAction (line 837) | type tferAction
    method Valid (line 847) | func (e tferAction) Valid() bool {
    method String (line 853) | func (e tferAction) String() string {
    method FromString (line 860) | func (e *tferAction) FromString(in string) error {
    method UnmarshalXML (line 873) | func (e *tferAction) UnmarshalXML(d *xml.Decoder, start xml.StartEleme...
    method MarshalXML (line 883) | func (e tferAction) MarshalXML(enc *xml.Encoder, start xml.StartElemen...
  constant TferActionIn (line 841) | TferActionIn tferAction = 1 + iota
  constant TferActionOut (line 842) | TferActionOut
  function NewTferAction (line 893) | func NewTferAction(s string) (tferAction, error) {
  type posType (line 902) | type posType
    method Valid (line 912) | func (e posType) Valid() bool {
    method String (line 918) | func (e posType) String() string {
    method FromString (line 925) | func (e *posType) FromString(in string) error {
    method UnmarshalXML (line 938) | func (e *posType) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
    method MarshalXML (line 948) | func (e posType) MarshalXML(enc *xml.Encoder, start xml.StartElement) ...
  constant PosTypeLong (line 906) | PosTypeLong posType = 1 + iota
  constant PosTypeShort (line 907) | PosTypeShort
  function NewPosType (line 958) | func NewPosType(s string) (posType, error) {
  type secured (line 967) | type secured
    method Valid (line 977) | func (e secured) Valid() bool {
    method String (line 983) | func (e secured) String() string {
    method FromString (line 990) | func (e *secured) FromString(in string) error {
    method UnmarshalXML (line 1003) | func (e *secured) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
    method MarshalXML (line 1013) | func (e secured) MarshalXML(enc *xml.Encoder, start xml.StartElement) ...
  constant SecuredNaked (line 971) | SecuredNaked secured = 1 + iota
  constant SecuredCovered (line 972) | SecuredCovered
  function NewSecured (line 1023) | func NewSecured(s string) (secured, error) {
  type duration (line 1032) | type duration
    method Valid (line 1043) | func (e duration) Valid() bool {
    method String (line 1049) | func (e duration) String() string {
    method FromString (line 1056) | func (e *duration) FromString(in string) error {
    method UnmarshalXML (line 1069) | func (e *duration) UnmarshalXML(d *xml.Decoder, start xml.StartElement...
    method MarshalXML (line 1079) | func (e duration) MarshalXML(enc *xml.Encoder, start xml.StartElement)...
  constant DurationDay (line 1036) | DurationDay duration = 1 + iota
  constant DurationGoodTilCancel (line 1037) | DurationGoodTilCancel
  constant DurationImmediate (line 1038) | DurationImmediate
  function NewDuration (line 1089) | func NewDuration(s string) (duration, error) {
  type restriction (line 1098) | type restriction
    method Valid (line 1109) | func (e restriction) Valid() bool {
    method String (line 1115) | func (e restriction) String() string {
    method FromString (line 1122) | func (e *restriction) FromString(in string) error {
    method UnmarshalXML (line 1135) | func (e *restriction) UnmarshalXML(d *xml.Decoder, start xml.StartElem...
    method MarshalXML (line 1145) | func (e restriction) MarshalXML(enc *xml.Encoder, start xml.StartEleme...
  constant RestrictionAllOrNone (line 1102) | RestrictionAllOrNone restriction = 1 + iota
  constant RestrictionMinUnits (line 1103) | RestrictionMinUnits
  constant RestrictionNone (line 1104) | RestrictionNone
  function NewRestriction (line 1155) | func NewRestriction(s string) (restriction, error) {
  type unitType (line 1164) | type unitType
    method Valid (line 1174) | func (e unitType) Valid() bool {
    method String (line 1180) | func (e unitType) String() string {
    method FromString (line 1187) | func (e *unitType) FromString(in string) error {
    method UnmarshalXML (line 1200) | func (e *unitType) UnmarshalXML(d *xml.Decoder, start xml.StartElement...
    method MarshalXML (line 1210) | func (e unitType) MarshalXML(enc *xml.Encoder, start xml.StartElement)...
  constant UnitTypeShares (line 1168) | UnitTypeShares unitType = 1 + iota
  constant UnitTypeCurrency (line 1169) | UnitTypeCurrency
  function NewUnitType (line 1220) | func NewUnitType(s string) (unitType, error) {
  type optBuyType (line 1229) | type optBuyType
    method Valid (line 1239) | func (e optBuyType) Valid() bool {
    method String (line 1245) | func (e optBuyType) String() string {
    method FromString (line 1252) | func (e *optBuyType) FromString(in string) error {
    method UnmarshalXML (line 1265) | func (e *optBuyType) UnmarshalXML(d *xml.Decoder, start xml.StartEleme...
    method MarshalXML (line 1275) | func (e optBuyType) MarshalXML(enc *xml.Encoder, start xml.StartElemen...
  constant OptBuyTypeBuyToOpen (line 1233) | OptBuyTypeBuyToOpen optBuyType = 1 + iota
  constant OptBuyTypeBuyToClose (line 1234) | OptBuyTypeBuyToClose
  function NewOptBuyType (line 1285) | func NewOptBuyType(s string) (optBuyType, error) {
  type sellType (line 1294) | type sellType
    method Valid (line 1304) | func (e sellType) Valid() bool {
    method String (line 1310) | func (e sellType) String() string {
    method FromString (line 1317) | func (e *sellType) FromString(in string) error {
    method UnmarshalXML (line 1330) | func (e *sellType) UnmarshalXML(d *xml.Decoder, start xml.StartElement...
    method MarshalXML (line 1340) | func (e sellType) MarshalXML(enc *xml.Encoder, start xml.StartElement)...
  constant SellTypeSell (line 1298) | SellTypeSell sellType = 1 + iota
  constant SellTypeSellShort (line 1299) | SellTypeSellShort
  function NewSellType (line 1350) | func NewSellType(s string) (sellType, error) {
  type loanPmtFreq (line 1359) | type loanPmtFreq
    method Valid (line 1377) | func (e loanPmtFreq) Valid() bool {
    method String (line 1383) | func (e loanPmtFreq) String() string {
    method FromString (line 1390) | func (e *loanPmtFreq) FromString(in string) error {
    method UnmarshalXML (line 1403) | func (e *loanPmtFreq) UnmarshalXML(d *xml.Decoder, start xml.StartElem...
    method MarshalXML (line 1413) | func (e loanPmtFreq) MarshalXML(enc *xml.Encoder, start xml.StartEleme...
  constant LoanPmtFreqWeekly (line 1363) | LoanPmtFreqWeekly loanPmtFreq = 1 + iota
  constant LoanPmtFreqBiweekly (line 1364) | LoanPmtFreqBiweekly
  constant LoanPmtFreqTwiceMonthly (line 1365) | LoanPmtFreqTwiceMonthly
  constant LoanPmtFreqMonthly (line 1366) | LoanPmtFreqMonthly
  constant LoanPmtFreqFourWeeks (line 1367) | LoanPmtFreqFourWeeks
  constant LoanPmtFreqBiMonthly (line 1368) | LoanPmtFreqBiMonthly
  constant LoanPmtFreqQuarterly (line 1369) | LoanPmtFreqQuarterly
  constant LoanPmtFreqSemiannually (line 1370) | LoanPmtFreqSemiannually
  constant LoanPmtFreqAnnually (line 1371) | LoanPmtFreqAnnually
  constant LoanPmtFreqOther (line 1372) | LoanPmtFreqOther
  function NewLoanPmtFreq (line 1423) | func NewLoanPmtFreq(s string) (loanPmtFreq, error) {
  type incomeType (line 1432) | type incomeType
    method Valid (line 1445) | func (e incomeType) Valid() bool {
    method String (line 1451) | func (e incomeType) String() string {
    method FromString (line 1458) | func (e *incomeType) FromString(in string) error {
    method UnmarshalXML (line 1471) | func (e *incomeType) UnmarshalXML(d *xml.Decoder, start xml.StartEleme...
    method MarshalXML (line 1481) | func (e incomeType) MarshalXML(enc *xml.Encoder, start xml.StartElemen...
  constant IncomeTypeCGLong (line 1436) | IncomeTypeCGLong incomeType = 1 + iota
  constant IncomeTypeCGShort (line 1437) | IncomeTypeCGShort
  constant IncomeTypeDiv (line 1438) | IncomeTypeDiv
  constant IncomeTypeInterest (line 1439) | IncomeTypeInterest
  constant IncomeTypeMisc (line 1440) | IncomeTypeMisc
  function NewIncomeType (line 1491) | func NewIncomeType(s string) (incomeType, error) {
  type sellReason (line 1500) | type sellReason
    method Valid (line 1511) | func (e sellReason) Valid() bool {
    method String (line 1517) | func (e sellReason) String() string {
    method FromString (line 1524) | func (e *sellReason) FromString(in string) error {
    method UnmarshalXML (line 1537) | func (e *sellReason) UnmarshalXML(d *xml.Decoder, start xml.StartEleme...
    method MarshalXML (line 1547) | func (e sellReason) MarshalXML(enc *xml.Encoder, start xml.StartElemen...
  constant SellReasonCall (line 1504) | SellReasonCall sellReason = 1 + iota
  constant SellReasonSell (line 1505) | SellReasonSell
  constant SellReasonMaturity (line 1506) | SellReasonMaturity
  function NewSellReason (line 1557) | func NewSellReason(s string) (sellReason, error) {
  type optSellType (line 1566) | type optSellType
    method Valid (line 1576) | func (e optSellType) Valid() bool {
    method String (line 1582) | func (e optSellType) String() string {
    method FromString (line 1589) | func (e *optSellType) FromString(in string) error {
    method UnmarshalXML (line 1602) | func (e *optSellType) UnmarshalXML(d *xml.Decoder, start xml.StartElem...
    method MarshalXML (line 1612) | func (e optSellType) MarshalXML(enc *xml.Encoder, start xml.StartEleme...
  constant OptSellTypeSellToClose (line 1570) | OptSellTypeSellToClose optSellType = 1 + iota
  constant OptSellTypeSellToOpen (line 1571) | OptSellTypeSellToOpen
  function NewOptSellType (line 1622) | func NewOptSellType(s string) (optSellType, error) {
  type relType (line 1631) | type relType
    method Valid (line 1643) | func (e relType) Valid() bool {
    method String (line 1649) | func (e relType) String() string {
    method FromString (line 1656) | func (e *relType) FromString(in string) error {
    method UnmarshalXML (line 1669) | func (e *relType) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
    method MarshalXML (line 1679) | func (e relType) MarshalXML(enc *xml.Encoder, start xml.StartElement) ...
  constant RelTypeSpread (line 1635) | RelTypeSpread relType = 1 + iota
  constant RelTypeStraddle (line 1636) | RelTypeStraddle
  constant RelTypeNone (line 1637) | RelTypeNone
  constant RelTypeOther (line 1638) | RelTypeOther
  function NewRelType (line 1689) | func NewRelType(s string) (relType, error) {
  type charType (line 1698) | type charType
    method Valid (line 1710) | func (e charType) Valid() bool {
    method String (line 1716) | func (e charType) String() string {
    method FromString (line 1723) | func (e *charType) FromString(in string) error {
    method UnmarshalXML (line 1736) | func (e *charType) UnmarshalXML(d *xml.Decoder, start xml.StartElement...
    method MarshalXML (line 1746) | func (e charType) MarshalXML(enc *xml.Encoder, start xml.StartElement)...
  constant CharTypeAlphaOnly (line 1702) | CharTypeAlphaOnly charType = 1 + iota
  constant CharTypeNumericOnly (line 1703) | CharTypeNumericOnly
  constant CharTypeAlphaOrNumeric (line 1704) | CharTypeAlphaOrNumeric
  constant CharTypeAlphaAndNumeric (line 1705) | CharTypeAlphaAndNumeric
  function NewCharType (line 1756) | func NewCharType(s string) (charType, error) {
  type syncMode (line 1765) | type syncMode
    method Valid (line 1775) | func (e syncMode) Valid() bool {
    method String (line 1781) | func (e syncMode) String() string {
    method FromString (line 1788) | func (e *syncMode) FromString(in string) error {
    method UnmarshalXML (line 1801) | func (e *syncMode) UnmarshalXML(d *xml.Decoder, start xml.StartElement...
    method MarshalXML (line 1811) | func (e syncMode) MarshalXML(enc *xml.Encoder, start xml.StartElement)...
  constant SyncModeFull (line 1769) | SyncModeFull syncMode = 1 + iota
  constant SyncModeLite (line 1770) | SyncModeLite
  function NewSyncMode (line 1821) | func NewSyncMode(s string) (syncMode, error) {
  type ofxSec (line 1830) | type ofxSec
    method Valid (line 1840) | func (e ofxSec) Valid() bool {
    method String (line 1846) | func (e ofxSec) String() string {
    method FromString (line 1853) | func (e *ofxSec) FromString(in string) error {
    method UnmarshalXML (line 1866) | func (e *ofxSec) UnmarshalXML(d *xml.Decoder, start xml.StartElement) ...
    method MarshalXML (line 1876) | func (e ofxSec) MarshalXML(enc *xml.Encoder, start xml.StartElement) e...
  constant OfxSecNone (line 1834) | OfxSecNone ofxSec = 1 + iota
  constant OfxSecType1 (line 1835) | OfxSecType1
  function NewOfxSec (line 1886) | func NewOfxSec(s string) (ofxSec, error) {
  type debtType (line 1895) | type debtType
    method Valid (line 1905) | func (e debtType) Valid() bool {
    method String (line 1911) | func (e debtType) String() string {
    method FromString (line 1918) | func (e *debtType) FromString(in string) error {
    method UnmarshalXML (line 1931) | func (e *debtType) UnmarshalXML(d *xml.Decoder, start xml.StartElement...
    method MarshalXML (line 1941) | func (e debtType) MarshalXML(enc *xml.Encoder, start xml.StartElement)...
  constant DebtTypeCoupon (line 1899) | DebtTypeCoupon debtType = 1 + iota
  constant DebtTypeZero (line 1900) | DebtTypeZero
  function NewDebtType (line 1951) | func NewDebtType(s string) (debtType, error) {
  type debtClass (line 1960) | type debtClass
    method Valid (line 1972) | func (e debtClass) Valid() bool {
    method String (line 1978) | func (e debtClass) String() string {
    method FromString (line 1985) | func (e *debtClass) FromString(in string) error {
    method UnmarshalXML (line 1998) | func (e *debtClass) UnmarshalXML(d *xml.Decoder, start xml.StartElemen...
    method MarshalXML (line 2008) | func (e debtClass) MarshalXML(enc *xml.Encoder, start xml.StartElement...
  constant DebtClassTreasury (line 1964) | DebtClassTreasury debtClass = 1 + iota
  constant DebtClassMunicipal (line 1965) | DebtClassMunicipal
  constant DebtClassCorporate (line 1966) | DebtClassCorporate
  constant DebtClassOther (line 1967) | DebtClassOther
  function NewDebtClass (line 2018) | func NewDebtClass(s string) (debtClass, error) {
  type couponFreq (line 2027) | type couponFreq
    method Valid (line 2040) | func (e couponFreq) Valid() bool {
    method String (line 2046) | func (e couponFreq) String() string {
    method FromString (line 2053) | func (e *couponFreq) FromString(in string) error {
    method UnmarshalXML (line 2066) | func (e *couponFreq) UnmarshalXML(d *xml.Decoder, start xml.StartEleme...
    method MarshalXML (line 2076) | func (e couponFreq) MarshalXML(enc *xml.Encoder, start xml.StartElemen...
  constant CouponFreqMonthly (line 2031) | CouponFreqMonthly couponFreq = 1 + iota
  constant CouponFreqQuarterly (line 2032) | CouponFreqQuarterly
  constant CouponFreqSemiannual (line 2033) | CouponFreqSemiannual
  constant CouponFreqAnnual (line 2034) | CouponFreqAnnual
  constant CouponFreqOther (line 2035) | CouponFreqOther
  function NewCouponFreq (line 2086) | func NewCouponFreq(s string) (couponFreq, error) {
  type callType (line 2095) | type callType
    method Valid (line 2107) | func (e callType) Valid() bool {
    method String (line 2113) | func (e callType) String() string {
    method FromString (line 2120) | func (e *callType) FromString(in string) error {
    method UnmarshalXML (line 2133) | func (e *callType) UnmarshalXML(d *xml.Decoder, start xml.StartElement...
    method MarshalXML (line 2143) | func (e callType) MarshalXML(enc *xml.Encoder, start xml.StartElement)...
  constant CallTypeCall (line 2099) | CallTypeCall callType = 1 + iota
  constant CallTypePut (line 2100) | CallTypePut
  constant CallTypePrefund (line 2101) | CallTypePrefund
  constant CallTypeMaturity (line 2102) | CallTypeMaturity
  function NewCallType (line 2153) | func NewCallType(s string) (callType, error) {
  type assetClass (line 2162) | type assetClass
    method Valid (line 2177) | func (e assetClass) Valid() bool {
    method String (line 2183) | func (e assetClass) String() string {
    method FromString (line 2190) | func (e *assetClass) FromString(in string) error {
    method UnmarshalXML (line 2203) | func (e *assetClass) UnmarshalXML(d *xml.Decoder, start xml.StartEleme...
    method MarshalXML (line 2213) | func (e assetClass) MarshalXML(enc *xml.Encoder, start xml.StartElemen...
  constant AssetClassDomesticBond (line 2166) | AssetClassDomesticBond assetClass = 1 + iota
  constant AssetClassIntlBond (line 2167) | AssetClassIntlBond
  constant AssetClassLargeStock (line 2168) | AssetClassLargeStock
  constant AssetClassSmallStock (line 2169) | AssetClassSmallStock
  constant AssetClassIntlStock (line 2170) | AssetClassIntlStock
  constant AssetClassMoneyMrkt (line 2171) | AssetClassMoneyMrkt
  constant AssetClassOther (line 2172) | AssetClassOther
  function NewAssetClass (line 2223) | func NewAssetClass(s string) (assetClass, error) {
  type mfType (line 2232) | type mfType
    method Valid (line 2243) | func (e mfType) Valid() bool {
    method String (line 2249) | func (e mfType) String() string {
    method FromString (line 2256) | func (e *mfType) FromString(in string) error {
    method UnmarshalXML (line 2269) | func (e *mfType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) ...
    method MarshalXML (line 2279) | func (e mfType) MarshalXML(enc *xml.Encoder, start xml.StartElement) e...
  constant MfTypeOpenEnd (line 2236) | MfTypeOpenEnd mfType = 1 + iota
  constant MfTypeCloseEnd (line 2237) | MfTypeCloseEnd
  constant MfTypeOther (line 2238) | MfTypeOther
  function NewMfType (line 2289) | func NewMfType(s string) (mfType, error) {
  type optType (line 2298) | type optType
    method Valid (line 2308) | func (e optType) Valid() bool {
    method String (line 2314) | func (e optType) String() string {
    method FromString (line 2321) | func (e *optType) FromString(in string) error {
    method UnmarshalXML (line 2334) | func (e *optType) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
    method MarshalXML (line 2344) | func (e optType) MarshalXML(enc *xml.Encoder, start xml.StartElement) ...
  constant OptTypePut (line 2302) | OptTypePut optType = 1 + iota
  constant OptTypeCall (line 2303) | OptTypeCall
  function NewOptType (line 2354) | func NewOptType(s string) (optType, error) {
  type stockType (line 2363) | type stockType
    method Valid (line 2375) | func (e stockType) Valid() bool {
    method String (line 2381) | func (e stockType) String() string {
    method FromString (line 2388) | func (e *stockType) FromString(in string) error {
    method UnmarshalXML (line 2401) | func (e *stockType) UnmarshalXML(d *xml.Decoder, start xml.StartElemen...
    method MarshalXML (line 2411) | func (e stockType) MarshalXML(enc *xml.Encoder, start xml.StartElement...
  constant StockTypeCommon (line 2367) | StockTypeCommon stockType = 1 + iota
  constant StockTypePreferred (line 2368) | StockTypePreferred
  constant StockTypeConvertible (line 2369) | StockTypeConvertible
  constant StockTypeOther (line 2370) | StockTypeOther
  function NewStockType (line 2421) | func NewStockType(s string) (stockType, error) {
  type holderType (line 2430) | type holderType
    method Valid (line 2443) | func (e holderType) Valid() bool {
    method String (line 2449) | func (e holderType) String() string {
    method FromString (line 2456) | func (e *holderType) FromString(in string) error {
    method UnmarshalXML (line 2469) | func (e *holderType) UnmarshalXML(d *xml.Decoder, start xml.StartEleme...
    method MarshalXML (line 2479) | func (e holderType) MarshalXML(enc *xml.Encoder, start xml.StartElemen...
  constant HolderTypeIndividual (line 2434) | HolderTypeIndividual holderType = 1 + iota
  constant HolderTypeJoint (line 2435) | HolderTypeJoint
  constant HolderTypeCustodial (line 2436) | HolderTypeCustodial
  constant HolderTypeTrust (line 2437) | HolderTypeTrust
  constant HolderTypeOther (line 2438) | HolderTypeOther
  function NewHolderType (line 2489) | func NewHolderType(s string) (holderType, error) {
  type acctClassification (line 2498) | type acctClassification
    method Valid (line 2510) | func (e acctClassification) Valid() bool {
    method String (line 2516) | func (e acctClassification) String() string {
    method FromString (line 2523) | func (e *acctClassification) FromString(in string) error {
    method UnmarshalXML (line 2536) | func (e *acctClassification) UnmarshalXML(d *xml.Decoder, start xml.St...
    method MarshalXML (line 2546) | func (e acctClassification) MarshalXML(enc *xml.Encoder, start xml.Sta...
  constant AcctClassificationPersonal (line 2502) | AcctClassificationPersonal acctClassification = 1 + iota
  constant AcctClassificationBusiness (line 2503) | AcctClassificationBusiness
  constant AcctClassificationCorporate (line 2504) | AcctClassificationCorporate
  constant AcctClassificationOther (line 2505) | AcctClassificationOther
  function NewAcctClassification (line 2556) | func NewAcctClassification(s string) (acctClassification, error) {
  type svcStatus (line 2565) | type svcStatus
    method Valid (line 2576) | func (e svcStatus) Valid() bool {
    method String (line 2582) | func (e svcStatus) String() string {
    method FromString (line 2589) | func (e *svcStatus) FromString(in string) error {
    method UnmarshalXML (line 2602) | func (e *svcStatus) UnmarshalXML(d *xml.Decoder, start xml.StartElemen...
    method MarshalXML (line 2612) | func (e svcStatus) MarshalXML(enc *xml.Encoder, start xml.StartElement...
  constant SvcStatusAvail (line 2569) | SvcStatusAvail svcStatus = 1 + iota
  constant SvcStatusPend (line 2570) | SvcStatusPend
  constant SvcStatusActive (line 2571) | SvcStatusActive
  function NewSvcStatus (line 2622) | func NewSvcStatus(s string) (svcStatus, error) {
  type usProductType (line 2631) | type usProductType
    method Valid (line 2650) | func (e usProductType) Valid() bool {
    method String (line 2656) | func (e usProductType) String() string {
    method FromString (line 2663) | func (e *usProductType) FromString(in string) error {
    method UnmarshalXML (line 2676) | func (e *usProductType) UnmarshalXML(d *xml.Decoder, start xml.StartEl...
    method MarshalXML (line 2686) | func (e usProductType) MarshalXML(enc *xml.Encoder, start xml.StartEle...
  constant UsProductType401K (line 2635) | UsProductType401K usProductType = 1 + iota
  constant UsProductType403B (line 2636) | UsProductType403B
  constant UsProductTypeIRA (line 2637) | UsProductTypeIRA
  constant UsProductTypeKEOGH (line 2638) | UsProductTypeKEOGH
  constant UsProductTypeOther (line 2639) | UsProductTypeOther
  constant UsProductTypeSARSEP (line 2640) | UsProductTypeSARSEP
  constant UsProductTypeSimple (line 2641) | UsProductTypeSimple
  constant UsProductTypeNormal (line 2642) | UsProductTypeNormal
  constant UsProductTypeTDA (line 2643) | UsProductTypeTDA
  constant UsProductTypeTrust (line 2644) | UsProductTypeTrust
  constant UsProductTypeUGMA (line 2645) | UsProductTypeUGMA
  function NewUsProductType (line 2696) | func NewUsProductType(s string) (usProductType, error) {

FILE: constants_test.go
  function TestOfxVersion (line 16) | func TestOfxVersion(t *testing.T) {
  function TestAcctType (line 73) | func TestAcctType(t *testing.T) {
  function TestTrnType (line 130) | func TestTrnType(t *testing.T) {
  function TestImageType (line 187) | func TestImageType(t *testing.T) {
  function TestImageRefType (line 244) | func TestImageRefType(t *testing.T) {
  function TestCheckSup (line 301) | func TestCheckSup(t *testing.T) {
  function TestCorrectAction (line 358) | func TestCorrectAction(t *testing.T) {
  function TestBalType (line 415) | func TestBalType(t *testing.T) {
  function TestInv401kSource (line 472) | func TestInv401kSource(t *testing.T) {
  function TestSubAcctType (line 529) | func TestSubAcctType(t *testing.T) {
  function TestBuyType (line 586) | func TestBuyType(t *testing.T) {
  function TestOptAction (line 643) | func TestOptAction(t *testing.T) {
  function TestTferAction (line 700) | func TestTferAction(t *testing.T) {
  function TestPosType (line 757) | func TestPosType(t *testing.T) {
  function TestSecured (line 814) | func TestSecured(t *testing.T) {
  function TestDuration (line 871) | func TestDuration(t *testing.T) {
  function TestRestriction (line 928) | func TestRestriction(t *testing.T) {
  function TestUnitType (line 985) | func TestUnitType(t *testing.T) {
  function TestOptBuyType (line 1042) | func TestOptBuyType(t *testing.T) {
  function TestSellType (line 1099) | func TestSellType(t *testing.T) {
  function TestLoanPmtFreq (line 1156) | func TestLoanPmtFreq(t *testing.T) {
  function TestIncomeType (line 1213) | func TestIncomeType(t *testing.T) {
  function TestSellReason (line 1270) | func TestSellReason(t *testing.T) {
  function TestOptSellType (line 1327) | func TestOptSellType(t *testing.T) {
  function TestRelType (line 1384) | func TestRelType(t *testing.T) {
  function TestCharType (line 1441) | func TestCharType(t *testing.T) {
  function TestSyncMode (line 1498) | func TestSyncMode(t *testing.T) {
  function TestOfxSec (line 1555) | func TestOfxSec(t *testing.T) {
  function TestDebtType (line 1612) | func TestDebtType(t *testing.T) {
  function TestDebtClass (line 1669) | func TestDebtClass(t *testing.T) {
  function TestCouponFreq (line 1726) | func TestCouponFreq(t *testing.T) {
  function TestCallType (line 1783) | func TestCallType(t *testing.T) {
  function TestAssetClass (line 1840) | func TestAssetClass(t *testing.T) {
  function TestMfType (line 1897) | func TestMfType(t *testing.T) {
  function TestOptType (line 1954) | func TestOptType(t *testing.T) {
  function TestStockType (line 2011) | func TestStockType(t *testing.T) {
  function TestHolderType (line 2068) | func TestHolderType(t *testing.T) {
  function TestAcctClassification (line 2125) | func TestAcctClassification(t *testing.T) {
  function TestSvcStatus (line 2182) | func TestSvcStatus(t *testing.T) {
  function TestUsProductType (line 2239) | func TestUsProductType(t *testing.T) {

FILE: creditcard.go
  type CCStatementRequest (line 10) | type CCStatementRequest struct
    method Name (line 25) | func (r *CCStatementRequest) Name() string {
    method Valid (line 31) | func (r *CCStatementRequest) Valid(version ofxVersion) (bool, error) {
    method Type (line 41) | func (r *CCStatementRequest) Type() messageType {
  type CCStatementResponse (line 48) | type CCStatementResponse struct
    method Name (line 74) | func (sr *CCStatementResponse) Name() string {
    method Valid (line 79) | func (sr *CCStatementResponse) Valid(version ofxVersion) (bool, error) {
    method Type (line 89) | func (sr *CCStatementResponse) Type() messageType {

FILE: creditcard_test.go
  function TestMarshalCCStatementRequest (line 9) | func TestMarshalCCStatementRequest(t *testing.T) {
  function TestUnmarshalCCStatementResponse102 (line 72) | func TestUnmarshalCCStatementResponse102(t *testing.T) {

FILE: discovercard_client.go
  type DiscoverCardClient (line 18) | type DiscoverCardClient struct
    method RawRequest (line 82) | func (c *DiscoverCardClient) RawRequest(URL string, r io.Reader) (*htt...
    method RequestNoParse (line 101) | func (c *DiscoverCardClient) RequestNoParse(r *Request) (*http.Respons...
    method Request (line 107) | func (c *DiscoverCardClient) Request(r *Request) (*Response, error) {
  function NewDiscoverCardClient (line 24) | func NewDiscoverCardClient(bc *BasicClient) Client {
  function discoverCardHTTPPost (line 28) | func discoverCardHTTPPost(URL string, r io.Reader) (*http.Response, erro...

FILE: invstmt.go
  type InvStatementRequest (line 11) | type InvStatementRequest struct
    method Name (line 31) | func (r *InvStatementRequest) Name() string {
    method Valid (line 37) | func (r *InvStatementRequest) Valid(version ofxVersion) (bool, error) {
    method Type (line 47) | func (r *InvStatementRequest) Type() messageType {
  type InvTran (line 54) | type InvTran struct
  type InvBuy (line 66) | type InvBuy struct
  type InvSell (line 95) | type InvSell struct
  type BuyDebt (line 123) | type BuyDebt struct
    method TransactionType (line 130) | func (t BuyDebt) TransactionType() string {
    method InvTransaction (line 134) | func (t BuyDebt) InvTransaction() InvTran {
  type BuyMF (line 139) | type BuyMF struct
    method TransactionType (line 147) | func (t BuyMF) TransactionType() string {
    method InvTransaction (line 151) | func (t BuyMF) InvTransaction() InvTran {
  type BuyOpt (line 156) | type BuyOpt struct
    method TransactionType (line 164) | func (t BuyOpt) TransactionType() string {
    method InvTransaction (line 168) | func (t BuyOpt) InvTransaction() InvTran {
  type BuyOther (line 174) | type BuyOther struct
    method TransactionType (line 180) | func (t BuyOther) TransactionType() string {
    method InvTransaction (line 184) | func (t BuyOther) InvTransaction() InvTran {
  type BuyStock (line 189) | type BuyStock struct
    method TransactionType (line 196) | func (t BuyStock) TransactionType() string {
    method InvTransaction (line 200) | func (t BuyStock) InvTransaction() InvTran {
  type ClosureOpt (line 205) | type ClosureOpt struct
    method TransactionType (line 218) | func (t ClosureOpt) TransactionType() string {
    method InvTransaction (line 222) | func (t ClosureOpt) InvTransaction() InvTran {
  type Income (line 228) | type Income struct
    method TransactionType (line 244) | func (t Income) TransactionType() string {
    method InvTransaction (line 248) | func (t Income) InvTransaction() InvTran {
  type InvExpense (line 254) | type InvExpense struct
    method TransactionType (line 267) | func (t InvExpense) TransactionType() string {
    method InvTransaction (line 271) | func (t InvExpense) InvTransaction() InvTran {
  type JrnlFund (line 277) | type JrnlFund struct
    method TransactionType (line 286) | func (t JrnlFund) TransactionType() string {
    method InvTransaction (line 290) | func (t JrnlFund) InvTransaction() InvTran {
  type JrnlSec (line 296) | type JrnlSec struct
    method TransactionType (line 306) | func (t JrnlSec) TransactionType() string {
    method InvTransaction (line 310) | func (t JrnlSec) InvTransaction() InvTran {
  type MarginInterest (line 315) | type MarginInterest struct
    method TransactionType (line 325) | func (t MarginInterest) TransactionType() string {
    method InvTransaction (line 329) | func (t MarginInterest) InvTransaction() InvTran {
  type Reinvest (line 336) | type Reinvest struct
    method TransactionType (line 356) | func (t Reinvest) TransactionType() string {
    method InvTransaction (line 360) | func (t Reinvest) InvTransaction() InvTran {
  type RetOfCap (line 366) | type RetOfCap struct
    method TransactionType (line 379) | func (t RetOfCap) TransactionType() string {
    method InvTransaction (line 383) | func (t RetOfCap) InvTransaction() InvTran {
  type SellDebt (line 389) | type SellDebt struct
    method TransactionType (line 397) | func (t SellDebt) TransactionType() string {
    method InvTransaction (line 401) | func (t SellDebt) InvTransaction() InvTran {
  type SellMF (line 406) | type SellMF struct
    method TransactionType (line 415) | func (t SellMF) TransactionType() string {
    method InvTransaction (line 419) | func (t SellMF) InvTransaction() InvTran {
  type SellOpt (line 426) | type SellOpt struct
    method TransactionType (line 437) | func (t SellOpt) TransactionType() string {
    method InvTransaction (line 441) | func (t SellOpt) InvTransaction() InvTran {
  type SellOther (line 447) | type SellOther struct
    method TransactionType (line 453) | func (t SellOther) TransactionType() string {
    method InvTransaction (line 457) | func (t SellOther) InvTransaction() InvTran {
  type SellStock (line 462) | type SellStock struct
    method TransactionType (line 469) | func (t SellStock) TransactionType() string {
    method InvTransaction (line 473) | func (t SellStock) InvTransaction() InvTran {
  type Split (line 478) | type Split struct
    method TransactionType (line 495) | func (t Split) TransactionType() string {
    method InvTransaction (line 499) | func (t Split) InvTransaction() InvTran {
  type Transfer (line 504) | type Transfer struct
    method TransactionType (line 520) | func (t Transfer) TransactionType() string {
    method InvTransaction (line 524) | func (t Transfer) InvTransaction() InvTran {
  type InvTransaction (line 530) | type InvTransaction interface
  type InvBankTransaction (line 538) | type InvBankTransaction struct
  type InvTranList (line 548) | type InvTranList struct
    method UnmarshalXML (line 558) | func (l *InvTranList) UnmarshalXML(d *xml.Decoder, start xml.StartElem...
    method MarshalXML (line 716) | func (l *InvTranList) MarshalXML(e *xml.Encoder, start xml.StartElemen...
  type InvPosition (line 830) | type InvPosition struct
  type Position (line 846) | type Position interface
  type DebtPosition (line 852) | type DebtPosition struct
    method PositionType (line 858) | func (p DebtPosition) PositionType() string {
    method InvPosition (line 863) | func (p DebtPosition) InvPosition() InvPosition {
  type MFPosition (line 868) | type MFPosition struct
    method PositionType (line 878) | func (p MFPosition) PositionType() string {
    method InvPosition (line 883) | func (p MFPosition) InvPosition() InvPosition {
  type OptPosition (line 888) | type OptPosition struct
    method PositionType (line 895) | func (p OptPosition) PositionType() string {
    method InvPosition (line 900) | func (p OptPosition) InvPosition() InvPosition {
  type OtherPosition (line 906) | type OtherPosition struct
    method PositionType (line 912) | func (p OtherPosition) PositionType() string {
    method InvPosition (line 917) | func (p OtherPosition) InvPosition() InvPosition {
  type StockPosition (line 922) | type StockPosition struct
    method PositionType (line 931) | func (p StockPosition) PositionType() string {
    method InvPosition (line 936) | func (p StockPosition) InvPosition() InvPosition {
  type PositionList (line 942) | type PositionList
    method UnmarshalXML (line 945) | func (p *PositionList) UnmarshalXML(d *xml.Decoder, start xml.StartEle...
    method MarshalXML (line 995) | func (p PositionList) MarshalXML(e *xml.Encoder, start xml.StartElemen...
  type InvBalance (line 1036) | type InvBalance struct
  type OO (line 1047) | type OO struct
  type OpenOrder (line 1066) | type OpenOrder interface
  type OOBuyDebt (line 1071) | type OOBuyDebt struct
    method OrderType (line 1079) | func (o OOBuyDebt) OrderType() string {
  type OOBuyMF (line 1084) | type OOBuyMF struct
    method OrderType (line 1092) | func (o OOBuyMF) OrderType() string {
  type OOBuyOpt (line 1097) | type OOBuyOpt struct
    method OrderType (line 1104) | func (o OOBuyOpt) OrderType() string {
  type OOBuyOther (line 1110) | type OOBuyOther struct
    method OrderType (line 1117) | func (o OOBuyOther) OrderType() string {
  type OOBuyStock (line 1122) | type OOBuyStock struct
    method OrderType (line 1129) | func (o OOBuyStock) OrderType() string {
  type OOSellDebt (line 1134) | type OOSellDebt struct
    method OrderType (line 1140) | func (o OOSellDebt) OrderType() string {
  type OOSellMF (line 1145) | type OOSellMF struct
    method OrderType (line 1154) | func (o OOSellMF) OrderType() string {
  type OOSellOpt (line 1159) | type OOSellOpt struct
    method OrderType (line 1166) | func (o OOSellOpt) OrderType() string {
  type OOSellOther (line 1172) | type OOSellOther struct
    method OrderType (line 1179) | func (o OOSellOther) OrderType() string {
  type OOSellStock (line 1184) | type OOSellStock struct
    method OrderType (line 1191) | func (o OOSellStock) OrderType() string {
  type OOSwitchMF (line 1197) | type OOSwitchMF struct
    method OrderType (line 1206) | func (o OOSwitchMF) OrderType() string {
  type OOList (line 1211) | type OOList
    method UnmarshalXML (line 1214) | func (o *OOList) UnmarshalXML(d *xml.Decoder, start xml.StartElement) ...
    method MarshalXML (line 1300) | func (o OOList) MarshalXML(e *xml.Encoder, start xml.StartElement) err...
  type ContribSecurity (line 1364) | type ContribSecurity struct
  type VestInfo (line 1385) | type VestInfo struct
  type LoanInfo (line 1392) | type LoanInfo struct
  type Inv401KSummaryAggregate (line 1414) | type Inv401KSummaryAggregate struct
  type Inv401KSummaryPeriod (line 1428) | type Inv401KSummaryPeriod struct
  type Inv401K (line 1439) | type Inv401K struct
  type Inv401KBal (line 1467) | type Inv401KBal struct
  type InvStatementResponse (line 1485) | type InvStatementResponse struct
    method Name (line 1504) | func (sr *InvStatementResponse) Name() string {
    method Valid (line 1509) | func (sr *InvStatementResponse) Valid(version ofxVersion) (bool, error) {
    method Type (line 1519) | func (sr *InvStatementResponse) Type() messageType {

FILE: invstmt_test.go
  function TestMarshalInvStatementRequest (line 12) | func TestMarshalInvStatementRequest(t *testing.T) {
  function TestUnmarshalInvStatementResponse (line 87) | func TestUnmarshalInvStatementResponse(t *testing.T) {
  function TestUnmarshalInvStatementResponse102 (line 608) | func TestUnmarshalInvStatementResponse102(t *testing.T) {
  function TestUnmarshalInvTranList (line 964) | func TestUnmarshalInvTranList(t *testing.T) {
  function TestUnmarshalPositionList (line 1324) | func TestUnmarshalPositionList(t *testing.T) {
  function TestUnmarshalOOList (line 1497) | func TestUnmarshalOOList(t *testing.T) {
  function TestSecurityInfo (line 1871) | func TestSecurityInfo(t *testing.T) {
  function TestInvPosition (line 1893) | func TestInvPosition(t *testing.T) {
  function TestInvTransaction (line 1915) | func TestInvTransaction(t *testing.T) {

FILE: profile.go
  type ProfileRequest (line 12) | type ProfileRequest struct
    method Name (line 23) | func (r *ProfileRequest) Name() string {
    method Valid (line 29) | func (r *ProfileRequest) Valid(version ofxVersion) (bool, error) {
    method Type (line 40) | func (r *ProfileRequest) Type() messageType {
  type SignonInfo (line 48) | type SignonInfo struct
  type MessageSet (line 72) | type MessageSet struct
  type MessageSetList (line 90) | type MessageSetList
    method UnmarshalXML (line 93) | func (msl *MessageSetList) UnmarshalXML(d *xml.Decoder, start xml.Star...
    method MarshalXML (line 131) | func (msl *MessageSetList) MarshalXML(e *xml.Encoder, start xml.StartE...
  type ProfileResponse (line 164) | type ProfileResponse struct
    method Name (line 189) | func (pr *ProfileResponse) Name() string {
    method Valid (line 194) | func (pr *ProfileResponse) Valid(version ofxVersion) (bool, error) {
    method Type (line 204) | func (pr *ProfileResponse) Type() messageType {

FILE: profile_test.go
  function TestMarshalProfileRequest (line 9) | func TestMarshalProfileRequest(t *testing.T) {
  function TestUnmarshalProfileResponse102 (line 65) | func TestUnmarshalProfileResponse102(t *testing.T) {

FILE: request.go
  type Request (line 15) | type Request struct
    method SetClientFields (line 66) | func (oq *Request) SetClientFields(c Client) {
    method Marshal (line 80) | func (oq *Request) Marshal() (*bytes.Buffer, error) {
  function encodeMessageSet (line 38) | func encodeMessageSet(e *xml.Encoder, requests []Message, set messageTyp...

FILE: request_test.go
  function marshalCheckRequest (line 12) | func marshalCheckRequest(t *testing.T, request *Request, expected string) {

FILE: response.go
  type Response (line 19) | type Response struct
    method readSGMLHeaders (line 38) | func (or *Response) readSGMLHeaders(r *bufio.Reader) error {
    method readXMLHeaders (line 111) | func (or *Response) readXMLHeaders(decoder *xml.Decoder) error {
    method Valid (line 380) | func (or *Response) Valid() (bool, error) {
    method Marshal (line 414) | func (or *Response) Marshal() (*bytes.Buffer, error) {
  constant guessVersionCheckBytes (line 184) | guessVersionCheckBytes = 1024
  function guessVersion (line 189) | func guessVersion(r *bufio.Reader) (bool, error) {
  function decodeMessageSet (line 233) | func decodeMessageSet(d *xml.Decoder, start xml.StartElement, msgs *[]Me...
  function ParseResponse (line 273) | func ParseResponse(reader io.Reader) (*Response, error) {
  function DecodeResponse (line 284) | func DecodeResponse(reader io.Reader) (*Response, error) {
  type errInvalid (line 480) | type errInvalid
    method Error (line 482) | func (e errInvalid) Error() string {
    method AddErr (line 490) | func (e *errInvalid) AddErr(err error) {
    method ErrOrNil (line 500) | func (e errInvalid) ErrOrNil() error {

FILE: response_test.go
  function equalMethodOf (line 19) | func equalMethodOf(v reflect.Value) reflect.Value {
  function valueToString (line 37) | func valueToString(v reflect.Value) string {
  function checkEqual (line 55) | func checkEqual(t *testing.T, fieldName string, expected, actual reflect...
  function checkResponsesEqual (line 137) | func checkResponsesEqual(t *testing.T, expected, actual *Response) {
  function checkResponseRoundTrip (line 141) | func checkResponseRoundTrip(t *testing.T, response *Response) {
  function TestValidSamples (line 155) | func TestValidSamples(t *testing.T) {
  function TestInvalidResponse (line 177) | func TestInvalidResponse(t *testing.T) {
  function TestErrInvalidError (line 263) | func TestErrInvalidError(t *testing.T) {
  function TestErrInvalidAddErr (line 275) | func TestErrInvalidAddErr(t *testing.T) {
  function TestErrInvalidErrOrNil (line 305) | func TestErrInvalidErrOrNil(t *testing.T) {

FILE: seclist.go
  type SecurityID (line 10) | type SecurityID struct
  type SecurityRequest (line 19) | type SecurityRequest struct
  type SecListRequest (line 29) | type SecListRequest struct
    method Name (line 39) | func (r *SecListRequest) Name() string {
    method Valid (line 45) | func (r *SecListRequest) Valid(version ofxVersion) (bool, error) {
    method Type (line 55) | func (r *SecListRequest) Type() messageType {
  type SecListResponse (line 64) | type SecListResponse struct
    method Name (line 74) | func (r *SecListResponse) Name() string {
    method Valid (line 79) | func (r *SecListResponse) Valid(version ofxVersion) (bool, error) {
    method Type (line 89) | func (r *SecListResponse) Type() messageType {
  type Security (line 95) | type Security interface
  type SecInfo (line 102) | type SecInfo struct
  type DebtInfo (line 116) | type DebtInfo struct
    method SecurityType (line 136) | func (i DebtInfo) SecurityType() string {
    method SecurityInfo (line 141) | func (i DebtInfo) SecurityInfo() SecInfo {
  type AssetPortion (line 147) | type AssetPortion struct
  type FiAssetPortion (line 156) | type FiAssetPortion struct
  type MFInfo (line 163) | type MFInfo struct
    method SecurityType (line 174) | func (i MFInfo) SecurityType() string {
    method SecurityInfo (line 179) | func (i MFInfo) SecurityInfo() SecInfo {
  type OptInfo (line 184) | type OptInfo struct
    method SecurityType (line 197) | func (i OptInfo) SecurityType() string {
    method SecurityInfo (line 202) | func (i OptInfo) SecurityInfo() SecInfo {
  type OtherInfo (line 208) | type OtherInfo struct
    method SecurityType (line 217) | func (i OtherInfo) SecurityType() string {
    method SecurityInfo (line 222) | func (i OtherInfo) SecurityInfo() SecInfo {
  type StockInfo (line 227) | type StockInfo struct
    method SecurityType (line 238) | func (i StockInfo) SecurityType() string {
    method SecurityInfo (line 243) | func (i StockInfo) SecurityInfo() SecInfo {
  type SecurityList (line 249) | type SecurityList struct
    method Name (line 255) | func (r *SecurityList) Name() string {
    method Valid (line 260) | func (r *SecurityList) Valid(version ofxVersion) (bool, error) {
    method Type (line 267) | func (r *SecurityList) Type() messageType {
    method UnmarshalXML (line 272) | func (r *SecurityList) UnmarshalXML(d *xml.Decoder, start xml.StartEle...
    method MarshalXML (line 322) | func (r *SecurityList) MarshalXML(e *xml.Encoder, start xml.StartEleme...

FILE: signon.go
  type SignonRequest (line 11) | type SignonRequest struct
    method Name (line 27) | func (r *SignonRequest) Name() string {
    method Valid (line 33) | func (r *SignonRequest) Valid(version ofxVersion) (bool, error) {
  type SignonResponse (line 62) | type SignonResponse struct
    method Name (line 78) | func (r *SignonResponse) Name() string {
    method Valid (line 83) | func (r *SignonResponse) Valid(version ofxVersion) (bool, error) {

FILE: signon_test.go
  function TestMarshalInvalidSignons (line 7) | func TestMarshalInvalidSignons(t *testing.T) {

FILE: signup.go
  type AcctInfoRequest (line 10) | type AcctInfoRequest struct
    method Name (line 20) | func (r *AcctInfoRequest) Name() string {
    method Valid (line 26) | func (r *AcctInfoRequest) Valid(version ofxVersion) (bool, error) {
    method Type (line 36) | func (r *AcctInfoRequest) Type() messageType {
  type HolderInfo (line 41) | type HolderInfo struct
  type BankAcctInfo (line 62) | type BankAcctInfo struct
    method String (line 77) | func (bai *BankAcctInfo) String() string {
  type CCAcctInfo (line 84) | type CCAcctInfo struct
    method String (line 95) | func (ci *CCAcctInfo) String() string {
  type InvAcctInfo (line 102) | type InvAcctInfo struct
    method String (line 113) | func (iai *InvAcctInfo) String() string {
  type AcctInfo (line 120) | type AcctInfo struct
  type AcctInfoResponse (line 138) | type AcctInfoResponse struct
    method Name (line 149) | func (air *AcctInfoResponse) Name() string {
    method Valid (line 154) | func (air *AcctInfoResponse) Valid(version ofxVersion) (bool, error) {
    method Type (line 164) | func (air *AcctInfoResponse) Type() messageType {

FILE: signup_test.go
  function TestMarshalAcctInfoRequest (line 9) | func TestMarshalAcctInfoRequest(t *testing.T) {
  function TestUnmarshalAcctInfoResponse (line 64) | func TestUnmarshalAcctInfoResponse(t *testing.T) {

FILE: types.go
  type Int (line 17) | type Int
    method UnmarshalXML (line 21) | func (i *Int) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err...
    method Equal (line 41) | func (i Int) Equal(o Int) bool {
  type Amount (line 47) | type Amount struct
    method UnmarshalXML (line 53) | func (a *Amount) UnmarshalXML(d *xml.Decoder, start xml.StartElement) ...
    method String (line 74) | func (a Amount) String() string {
    method MarshalXML (line 79) | func (a Amount) MarshalXML(e *xml.Encoder, start xml.StartElement) err...
    method Equal (line 84) | func (a Amount) Equal(o Amount) bool {
  type Date (line 89) | type Date struct
    method UnmarshalXML (line 106) | func (od *Date) UnmarshalXML(d *xml.Decoder, start xml.StartElement) e...
    method String (line 169) | func (od Date) String() string {
    method MarshalXML (line 191) | func (od Date) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
    method Equal (line 197) | func (od Date) Equal(o Date) bool {
  function NewDate (line 202) | func NewDate(year int, month time.Month, day, hour, min, sec, nsec int, ...
  function NewDateGMT (line 210) | func NewDateGMT(year int, month time.Month, day, hour, min, sec, nsec in...
  type String (line 215) | type String
    method UnmarshalXML (line 219) | func (os *String) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
    method String (line 230) | func (os *String) String() string {
    method Equal (line 235) | func (os String) Equal(o String) bool {
  type Boolean (line 240) | type Boolean
    method UnmarshalXML (line 244) | func (ob *Boolean) UnmarshalXML(d *xml.Decoder, start xml.StartElement...
    method MarshalXML (line 263) | func (ob Boolean) MarshalXML(e *xml.Encoder, start xml.StartElement) e...
    method String (line 271) | func (ob *Boolean) String() string {
    method Equal (line 276) | func (ob Boolean) Equal(o Boolean) bool {
  type UID (line 281) | type UID
    method UnmarshalXML (line 285) | func (ou *UID) UnmarshalXML(d *xml.Decoder, start xml.StartElement) er...
    method RecommendedFormat (line 297) | func (ou UID) RecommendedFormat() (bool, error) {
    method Valid (line 309) | func (ou UID) Valid() (bool, error) {
    method Equal (line 317) | func (ou UID) Equal(o UID) bool {
  function RandomUID (line 322) | func RandomUID() (*UID, error) {
  type CurrSymbol (line 336) | type CurrSymbol struct
    method UnmarshalXML (line 342) | func (c *CurrSymbol) UnmarshalXML(d *xml.Decoder, start xml.StartEleme...
    method MarshalXML (line 361) | func (c CurrSymbol) MarshalXML(e *xml.Encoder, start xml.StartElement)...
    method Equal (line 366) | func (c CurrSymbol) Equal(o CurrSymbol) bool {
    method Valid (line 371) | func (c CurrSymbol) Valid() (bool, error) {
  function NewCurrSymbol (line 380) | func NewCurrSymbol(s string) (*CurrSymbol, error) {

FILE: types_test.go
  function getTypeName (line 11) | func getTypeName(i interface{}) string {
  function marshalHelper (line 24) | func marshalHelper(t *testing.T, expected string, i interface{}) {
  function unmarshalHelper2 (line 37) | func unmarshalHelper2(t *testing.T, input string, expected interface{}, ...
  function unmarshalHelper (line 50) | func unmarshalHelper(t *testing.T, input string, expected interface{}, o...
  function TestMarshalInt (line 58) | func TestMarshalInt(t *testing.T) {
  function TestUnmarshalInt (line 67) | func TestUnmarshalInt(t *testing.T) {
  function TestMarshalAmount (line 79) | func TestMarshalAmount(t *testing.T) {
  function TestUnmarshalAmount (line 103) | func TestUnmarshalAmount(t *testing.T) {
  function TestAmountEqual (line 135) | func TestAmountEqual(t *testing.T) {
  function TestMarshalDate (line 162) | func TestMarshalDate(t *testing.T) {
  function TestUnmarshalDate (line 204) | func TestUnmarshalDate(t *testing.T) {
  function TestDateEqual (line 275) | func TestDateEqual(t *testing.T) {
  function TestMarshalString (line 306) | func TestMarshalString(t *testing.T) {
  function TestUnmarshalString (line 317) | func TestUnmarshalString(t *testing.T) {
  function TestStringString (line 333) | func TestStringString(t *testing.T) {
  function TestMarshalBoolean (line 340) | func TestMarshalBoolean(t *testing.T) {
  function TestUnmarshalBoolean (line 353) | func TestUnmarshalBoolean(t *testing.T) {
  function TestStringBoolean (line 363) | func TestStringBoolean(t *testing.T) {
  function TestMarshalUID (line 374) | func TestMarshalUID(t *testing.T) {
  function TestUnmarshalUID (line 379) | func TestUnmarshalUID(t *testing.T) {
  function TestUIDRecommendedFormat (line 388) | func TestUIDRecommendedFormat(t *testing.T) {
  function TestUIDValid (line 407) | func TestUIDValid(t *testing.T) {
  function TestRandomUID (line 422) | func TestRandomUID(t *testing.T) {
  function TestMarshalCurrSymbol (line 432) | func TestMarshalCurrSymbol(t *testing.T) {
  function TestUnmarshalCurrSymbol (line 443) | func TestUnmarshalCurrSymbol(t *testing.T) {
  function TestCurrSymbolEqual (line 453) | func TestCurrSymbolEqual(t *testing.T) {
  function TestCurrSymbolValid (line 465) | func TestCurrSymbolValid(t *testing.T) {
  function TestNewCurrSymbol (line 485) | func TestNewCurrSymbol(t *testing.T) {

FILE: util.go
  function nextNonWhitespaceToken (line 11) | func nextNonWhitespaceToken(decoder *xml.Decoder) (xml.Token, error) {

FILE: vanguard_client.go
  type VanguardClient (line 15) | type VanguardClient struct
    method RawRequest (line 53) | func (c *VanguardClient) RawRequest(URL string, r io.Reader) (*http.Re...
    method RequestNoParse (line 111) | func (c *VanguardClient) RequestNoParse(r *Request) (*http.Response, e...
    method Request (line 140) | func (c *VanguardClient) Request(r *Request) (*Response, error) {
  function NewVanguardClient (line 21) | func NewVanguardClient(bc *BasicClient) Client {
  function vanguardHttpClient (line 27) | func vanguardHttpClient() *http.Client {
  function rawRequestCookiesInsecureCiphers (line 82) | func rawRequestCookiesInsecureCiphers(URL string, r io.Reader, cookies [...
Condensed preview — 57 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (639K chars).
[
  {
    "path": ".github/workflows/test.yml",
    "chars": 1045,
    "preview": "name: ofxgo CI Test\n\non: [push, pull_request]\n\njobs:\n  test:\n    strategy:\n      matrix:\n        go-version: [1.19.x, 1."
  },
  {
    "path": "LICENSE",
    "chars": 15220,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
  },
  {
    "path": "README.md",
    "chars": 5281,
    "preview": "# OFXGo\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/aclindsa/ofxgo)](https://goreportcard.com/report/g"
  },
  {
    "path": "bank.go",
    "chars": 16419,
    "preview": "package ofxgo\n\nimport (\n\t\"errors\"\n\t\"github.com/aclindsa/xml\"\n)\n\n// StatementRequest represents a request for a bank stat"
  },
  {
    "path": "bank_test.go",
    "chars": 8860,
    "preview": "package ofxgo\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestMarshalBankStatementRequest(t *testing.T) {\n\tvar expec"
  },
  {
    "path": "basic_client.go",
    "chars": 3278,
    "preview": "package ofxgo\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\n// BasicClient provides a standard Client implementati"
  },
  {
    "path": "basic_client_test.go",
    "chars": 607,
    "preview": "package ofxgo\n\nimport (\n\t\"errors\"\n\t\"net\"\n\t\"net/http\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestBasicClient_HTTPClient(t *testing"
  },
  {
    "path": "client.go",
    "chars": 3576,
    "preview": "package ofxgo\n\nimport (\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\n// Client serves to aggregate OFX client settings that may be ne"
  },
  {
    "path": "cmd/ofx/bankdownload.go",
    "chars": 2072,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"github.com/aclindsa/ofxgo\"\n\t\"io\"\n\t\"os\"\n)\n\nvar downloadCommand = command{\n\tName: "
  },
  {
    "path": "cmd/ofx/banktransactions.go",
    "chars": 2622,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"github.com/aclindsa/ofxgo\"\n\t\"os\"\n)\n\nvar bankTransactionsCommand = command{\n\tName"
  },
  {
    "path": "cmd/ofx/ccdownload.go",
    "chars": 1648,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"github.com/aclindsa/ofxgo\"\n\t\"io\"\n\t\"os\"\n)\n\nvar ccDownloadCommand = command{\n\tName"
  },
  {
    "path": "cmd/ofx/cctransactions.go",
    "chars": 2101,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"github.com/aclindsa/ofxgo\"\n\t\"os\"\n)\n\nvar ccTransactionsCommand = command{\n\tName: "
  },
  {
    "path": "cmd/ofx/command.go",
    "chars": 2309,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"golang.org/x/term\"\n\t\"os\"\n)\n\ntype command struct {\n\tName        string\n\tDescripti"
  },
  {
    "path": "cmd/ofx/detect_settings.go",
    "chars": 4436,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"github.com/aclindsa/ofxgo\"\n\t\"os\"\n\t\"time\"\n)\n\nvar detectSettingsCommand = command{"
  },
  {
    "path": "cmd/ofx/get_accounts.go",
    "chars": 2060,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"github.com/aclindsa/ofxgo\"\n\t\"os\"\n\t\"time\"\n)\n\nvar getAccountsCommand = command{\n\tN"
  },
  {
    "path": "cmd/ofx/invdownload.go",
    "chars": 1950,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"github.com/aclindsa/ofxgo\"\n\t\"io\"\n\t\"os\"\n)\n\nvar invDownloadCommand = command{\n\tNam"
  },
  {
    "path": "cmd/ofx/invtransactions.go",
    "chars": 6555,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"github.com/aclindsa/ofxgo\"\n\t\"os\"\n)\n\nvar invTransactionsCommand = command{\n\tName:"
  },
  {
    "path": "cmd/ofx/main.go",
    "chars": 1395,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n)\n\nvar commands = []command{\n\tprofileDownloadCommand,\n\tgetAccountsCommand"
  },
  {
    "path": "cmd/ofx/profiledownload.go",
    "chars": 1695,
    "preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"github.com/aclindsa/ofxgo\"\n\t\"io\"\n\t\"os\"\n)\n\nvar profileDownloadCommand = command{\n"
  },
  {
    "path": "cmd/ofx/util.go",
    "chars": 961,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"github.com/aclindsa/ofxgo\"\n\t\"os\"\n)\n\nfunc newRequest() (ofxgo.Client, *ofxgo.Request) {\n\t"
  },
  {
    "path": "common.go",
    "chars": 20064,
    "preview": "package ofxgo\n\n//go:generate ./generate_constants.py\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/aclind"
  },
  {
    "path": "common_test.go",
    "chars": 1557,
    "preview": "package ofxgo\n\nimport (\n\t\"testing\"\n)\n\nfunc TestStatusValid(t *testing.T) {\n\ts := Status{\n\t\tCode:     0,\n\t\tSeverity: \"INF"
  },
  {
    "path": "constants.go",
    "chars": 58742,
    "preview": "package ofxgo\n\n/*\n * Do not edit this file by hand. It is auto-generated by calling `go generate`.\n * To make changes, e"
  },
  {
    "path": "constants_test.go",
    "chars": 68906,
    "preview": "package ofxgo\n\n/*\n * Do not edit this file by hand. It is auto-generated by calling `go generate`.\n * To make changes, e"
  },
  {
    "path": "creditcard.go",
    "chars": 4095,
    "preview": "package ofxgo\n\nimport (\n\t\"github.com/aclindsa/xml\"\n)\n\n// CCStatementRequest represents a request for a credit card state"
  },
  {
    "path": "creditcard_test.go",
    "chars": 5257,
    "preview": "package ofxgo\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestMarshalCCStatementRequest(t *testing.T) {\n\tvar expecte"
  },
  {
    "path": "discovercard_client.go",
    "chars": 2812,
    "preview": "package ofxgo\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"crypto/tls\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// D"
  },
  {
    "path": "doc.go",
    "chars": 5880,
    "preview": "/*\nPackage ofxgo seeks to provide a library to make it easier to query and/or\nparse financial information with OFX from "
  },
  {
    "path": "generate_constants.py",
    "chars": 10104,
    "preview": "#!/usr/bin/env python\n\nenums = {\n    # OFX spec version\n    \"OfxVersion\": ([\"102\", \"103\", \"151\", \"160\", \"200\", \"201\", \"2"
  },
  {
    "path": "go.mod",
    "chars": 194,
    "preview": "module github.com/aclindsa/ofxgo\n\nrequire (\n\tgithub.com/aclindsa/xml v0.0.0-20201125035057-bbd5c9ec99ac\n\tgolang.org/x/te"
  },
  {
    "path": "go.sum",
    "chars": 2935,
    "preview": "github.com/aclindsa/xml v0.0.0-20201125035057-bbd5c9ec99ac h1:xCNSfPWpcx3Sdz/+aB/Re4L8oA6Y4kRRRuTh1CHCDEw=\ngithub.com/ac"
  },
  {
    "path": "invstmt.go",
    "chars": 70539,
    "preview": "package ofxgo\n\nimport (\n\t\"errors\"\n\t\"github.com/aclindsa/xml\"\n)\n\n// InvStatementRequest allows a customer to request tran"
  },
  {
    "path": "invstmt_test.go",
    "chars": 48082,
    "preview": "package ofxgo\n\nimport (\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/aclindsa/xml\"\n)\n\nfunc TestMarshalInvState"
  },
  {
    "path": "leaf_elements.go",
    "chars": 4966,
    "preview": "package ofxgo\n\n// A list of all the leaf elements in OFX 1.0.3 (the last SGML version of the\n// spec). These are all the"
  },
  {
    "path": "profile.go",
    "chars": 9875,
    "preview": "package ofxgo\n\nimport (\n\t\"errors\"\n\t\"github.com/aclindsa/xml\"\n\t\"strings\"\n)\n\n// ProfileRequest represents a request for a "
  },
  {
    "path": "profile_test.go",
    "chars": 7364,
    "preview": "package ofxgo\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestMarshalProfileRequest(t *testing.T) {\n\tvar expectedStr"
  },
  {
    "path": "request.go",
    "chars": 4418,
    "preview": "package ofxgo\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"github.com/aclindsa/xml\"\n\t\"time\"\n)\n\n// Request is the top-level object mars"
  },
  {
    "path": "request_test.go",
    "chars": 1643,
    "preview": "package ofxgo\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n)\n\n// match leading and trailing whitespace on each line\nvar ign"
  },
  {
    "path": "response.go",
    "chars": 14538,
    "preview": "package ofxgo\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/aclindsa/"
  },
  {
    "path": "response_test.go",
    "chars": 10185,
    "preview": "package ofxgo\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/aclindsa/xm"
  },
  {
    "path": "samples/busted_responses/bmo_v102__no_header_newline.qfx",
    "chars": 982,
    "preview": "OFXHEADER:100\nDATA:OFXSGML\nVERSION:102\nSECURITY:NONE\nENCODING:USASCII\nCHARSET:1252\nCOMPRESSION:NONE\nOLDFILEUID:NONE\nNEWF"
  },
  {
    "path": "samples/busted_responses/wellsfargo.qfx",
    "chars": 973,
    "preview": "OFXHEADER:100DATA:OFXSGMLVERSION:102SECURITY:NONEENCODING:USASCIICHARSET:1252COMPRESSION:NONEOLDFILEUID:NONENEWFILEUID:N"
  },
  {
    "path": "samples/valid_responses/401k_v203.ofx",
    "chars": 6316,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><?OFX OFXHEADER=\"200\" VERSION=\"203\" SECURITY=\"NONE\" OLDFILEUID=\"NO"
  },
  {
    "path": "samples/valid_responses/inv_v202.ofx",
    "chars": 42104,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\" ?><?OFX OFXHEADER=\"200\" VERSION=\"202\" SECURITY=\"NONE\" OLDFILEUID=\"NONE\" NEWFILEUID="
  },
  {
    "path": "samples/valid_responses/ira_v202.ofx",
    "chars": 33923,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\" ?><?OFX OFXHEADER=\"200\" VERSION=\"202\" SECURITY=\"NONE\" OLDFILEUID=\"NONE\" NEWFILEUID="
  },
  {
    "path": "samples/valid_responses/moneymrkt1_v103.ofx",
    "chars": 1348,
    "preview": "OFXHEADER:100\nDATA:OFXSGML\nVERSION:103\nSECURITY:NONE\nENCODING:USASCII\nCHARSET:1252\nCOMPRESSION:NONE\nOLDFILEUID:NONE\nNEWF"
  },
  {
    "path": "samples/valid_responses/moneymrkt1_v103_TYPE1.ofx",
    "chars": 1349,
    "preview": "OFXHEADER:100\nDATA:OFXSGML\nVERSION:103\nSECURITY:TYPE1\nENCODING:USASCII\nCHARSET:1252\nCOMPRESSION:NONE\nOLDFILEUID:NONE\nNEW"
  },
  {
    "path": "samples/valid_responses/moneymrkt1_v203.ofx",
    "chars": 1864,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<?OFX OFXHEADER=\"200\" VERSION=\"203\" SECURITY=\"NONE\" OLDFILEUID=\"NONE\" NEWFILEUID"
  },
  {
    "path": "seclist.go",
    "chars": 13530,
    "preview": "package ofxgo\n\nimport (\n\t\"errors\"\n\t\"github.com/aclindsa/xml\"\n)\n\n// SecurityID identifies a security by its CUSIP (for US"
  },
  {
    "path": "signon.go",
    "chars": 3066,
    "preview": "package ofxgo\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"github.com/aclindsa/xml\"\n)\n\n// SignonRequest identifies and authenticates a u"
  },
  {
    "path": "signon_test.go",
    "chars": 3177,
    "preview": "package ofxgo\n\nimport (\n\t\"testing\"\n)\n\nfunc TestMarshalInvalidSignons(t *testing.T) {\n\tvar client = BasicClient{\n\t\tAppID:"
  },
  {
    "path": "signup.go",
    "chars": 7486,
    "preview": "package ofxgo\n\nimport (\n\t\"fmt\"\n\t\"github.com/aclindsa/xml\"\n)\n\n// AcctInfoRequest represents a request for the server to p"
  },
  {
    "path": "signup_test.go",
    "chars": 4042,
    "preview": "package ofxgo\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestMarshalAcctInfoRequest(t *testing.T) {\n\tvar expectedSt"
  },
  {
    "path": "types.go",
    "chars": 10553,
    "preview": "package ofxgo\n\nimport (\n\t\"crypto/rand\"\n\t\"errors\"\n\t\"fmt\"\n\t\"github.com/aclindsa/xml\"\n\t\"golang.org/x/text/currency\"\n\t\"math/"
  },
  {
    "path": "types_test.go",
    "chars": 16260,
    "preview": "package ofxgo\n\nimport (\n\t\"fmt\"\n\t\"github.com/aclindsa/xml\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc getTypeName(i interface{"
  },
  {
    "path": "util.go",
    "chars": 579,
    "preview": "package ofxgo\n\nimport (\n\t\"bytes\"\n\t\"github.com/aclindsa/xml\"\n)\n\n// Returns the next available Token from the xml.Decoder "
  },
  {
    "path": "vanguard_client.go",
    "chars": 4143,
    "preview": "package ofxgo\n\nimport (\n\t\"crypto/tls\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n)\n\n// VanguardClient provides a Client impl"
  }
]

About this extraction

This page contains the full source code of the aclindsa/ofxgo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 57 files (574.2 KB), approximately 187.0k tokens, and a symbol index with 946 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.

Copied to clipboard!