├── .gitignore ├── .travis.yml ├── LICENSE ├── shapeshift_coins.go ├── shapeshift_test.go ├── shapeshift.go └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .idea/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | os: 4 | - linux 5 | 6 | go: 7 | - 1.7 8 | - 1.8 9 | 10 | script: 11 | - go get golang.org/x/tools/cmd/cover 12 | - go get github.com/mattn/goveralls 13 | - go install github.com/mattn/goveralls 14 | - go test -v -covermode=count -coverprofile=coverage.out 15 | - $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Hunter Long 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /shapeshift_coins.go: -------------------------------------------------------------------------------- 1 | package shapeshift 2 | 3 | type Coin struct { 4 | Name string `json:"name"` 5 | Symbol string `json:"symbol"` 6 | Status string `json:"status"` 7 | Image string `json:"image,omitempty"` 8 | SpecialReturn bool `json:"specialReturn,omitempty"` 9 | SpecialOutgoing bool `json:"specialOutgoing,omitempty"` 10 | SpecialIncoming bool `json:"specialIncoming,omitempty"` 11 | FieldName string `json:"fieldName,omitempty"` 12 | FieldKey string `json:"fieldKey,omitempty"` 13 | QrName string `json:"qrName,omitempty"` 14 | } 15 | 16 | type CoinsResponse struct { 17 | FIRST struct { 18 | Coin 19 | } `json:"1ST"` 20 | ANT struct { 21 | Coin 22 | } `json:"ANT"` 23 | BAT struct { 24 | Coin 25 | } `json:"BAT"` 26 | BCH struct { 27 | Coin 28 | } `json:"BCH"` 29 | BCY struct { 30 | Coin 31 | } `json:"BCY"` 32 | BLK struct { 33 | Coin 34 | } `json:"BLK"` 35 | BNT struct { 36 | Coin 37 | } `json:"BNT"` 38 | BTC struct { 39 | Coin 40 | } `json:"BTC"` 41 | BTCD struct { 42 | Coin 43 | } `json:"BTCD"` 44 | BTG struct { 45 | Coin 46 | } `json:"BTG"` 47 | BTS struct { 48 | Coin 49 | } `json:"BTS"` 50 | CLAM struct { 51 | Coin 52 | } `json:"CLAM"` 53 | CVC struct { 54 | Coin 55 | } `json:"CVC"` 56 | DASH struct { 57 | Coin 58 | } `json:"DASH"` 59 | DCR struct { 60 | Coin 61 | } `json:"DCR"` 62 | DGB struct { 63 | Coin 64 | } `json:"DGB"` 65 | DNT struct { 66 | Coin 67 | } `json:"DNT"` 68 | DOGE struct { 69 | Coin 70 | } `json:"DOGE"` 71 | EDG struct { 72 | Coin 73 | } `json:"EDG"` 74 | EMC struct { 75 | Coin 76 | } `json:"EMC"` 77 | EOS struct { 78 | Coin 79 | } `json:"EOS"` 80 | ETC struct { 81 | Coin 82 | } `json:"ETC"` 83 | ETH struct { 84 | Coin 85 | } `json:"ETH"` 86 | FCT struct { 87 | Coin 88 | } `json:"FCT"` 89 | FUN struct { 90 | Coin 91 | } `json:"FUN"` 92 | GAME struct { 93 | Coin 94 | } `json:"GAME"` 95 | GNO struct { 96 | Coin 97 | } `json:"GNO"` 98 | GNT struct { 99 | Coin 100 | } `json:"GNT"` 101 | GUP struct { 102 | Coin 103 | } `json:"GUP"` 104 | KMD struct { 105 | Coin 106 | } `json:"KMD"` 107 | LBC struct { 108 | Coin 109 | } `json:"LBC"` 110 | LSK struct { 111 | Coin 112 | } `json:"LSK"` 113 | LTC struct { 114 | Coin 115 | } `json:"LTC"` 116 | MAID struct { 117 | Coin 118 | } `json:"MAID"` 119 | MLN struct { 120 | Coin 121 | } `json:"MLN"` 122 | MONA struct { 123 | Coin 124 | } `json:"MONA"` 125 | MSC struct { 126 | Coin 127 | } `json:"MSC"` 128 | MTL struct { 129 | Coin 130 | } `json:"MTL"` 131 | NBT struct { 132 | Coin 133 | } `json:"NBT"` 134 | NEO struct { 135 | Coin 136 | } `json:"NEO"` 137 | NMC struct { 138 | Coin 139 | } `json:"NMC"` 140 | NMR struct { 141 | Coin 142 | } `json:"NMR"` 143 | NVC struct { 144 | Coin 145 | } `json:"NVC"` 146 | NXT struct { 147 | Coin 148 | } `json:"NXT"` 149 | OMG struct { 150 | Coin 151 | } `json:"OMG"` 152 | POT struct { 153 | Coin 154 | } `json:"POT"` 155 | PPC struct { 156 | Coin 157 | } `json:"PPC"` 158 | QTUM struct { 159 | Coin 160 | } `json:"QTUM"` 161 | RCN struct { 162 | Coin 163 | } `json:"RCN"` 164 | RDD struct { 165 | Coin 166 | } `json:"RDD"` 167 | REP struct { 168 | Coin 169 | } `json:"REP"` 170 | RLC struct { 171 | Coin 172 | } `json:"RLC"` 173 | SALT struct { 174 | Coin 175 | } `json:"SALT"` 176 | SC struct { 177 | Coin 178 | } `json:"SC"` 179 | SNGLS struct { 180 | Coin 181 | } `json:"SNGLS"` 182 | SNT struct { 183 | Coin 184 | } `json:"SNT"` 185 | START struct { 186 | Coin 187 | } `json:"START"` 188 | STEEM struct { 189 | Coin 190 | } `json:"STEEM"` 191 | STORJ struct { 192 | Coin 193 | } `json:"STORJ"` 194 | SWT struct { 195 | Coin 196 | } `json:"SWT"` 197 | TRST struct { 198 | Coin 199 | } `json:"TRST"` 200 | USDT struct { 201 | Coin 202 | } `json:"USDT"` 203 | VOX struct { 204 | Coin 205 | } `json:"VOX"` 206 | VRC struct { 207 | Coin 208 | } `json:"VRC"` 209 | VTC struct { 210 | Coin 211 | } `json:"VTC"` 212 | WAVES struct { 213 | Coin 214 | } `json:"WAVES"` 215 | WINGS struct { 216 | Coin 217 | } `json:"WINGS"` 218 | XCP struct { 219 | Coin 220 | } `json:"XCP"` 221 | XEM struct { 222 | Coin 223 | } `json:"XEM"` 224 | XMR struct { 225 | Coin 226 | } `json:"XMR"` 227 | XRP struct { 228 | Coin 229 | } `json:"XRP"` 230 | ZEC struct { 231 | Coin 232 | } `json:"ZEC"` 233 | ZRX struct { 234 | Coin 235 | } `json:"ZRX"` 236 | } 237 | -------------------------------------------------------------------------------- /shapeshift_test.go: -------------------------------------------------------------------------------- 1 | package shapeshift 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var newSendToAddress string 8 | var newSendToAddress2 string 9 | var newTranxId string 10 | 11 | func TestPairs(t *testing.T) { 12 | 13 | pair := Pair{"eth_btc"} 14 | 15 | rate, err := pair.GetRates() 16 | if err != nil { 17 | t.Fail() 18 | } 19 | 20 | t.Log("Rate: ", rate) 21 | 22 | } 23 | 24 | func TestErrorPairs(t *testing.T) { 25 | 26 | pair := Pair{"xxx_btc"} 27 | 28 | rate, err := pair.GetRates() 29 | if err != nil { 30 | t.Fail() 31 | } 32 | 33 | t.Log("Rate: ", rate) 34 | 35 | } 36 | 37 | func TestLimits(t *testing.T) { 38 | 39 | pair := Pair{"eth_btc"} 40 | 41 | limits, err := pair.GetLimits() 42 | 43 | if err != nil { 44 | t.Fail() 45 | } 46 | 47 | t.Log("Limit: ", limits) 48 | 49 | } 50 | 51 | func TestMarketInfo(t *testing.T) { 52 | 53 | pair := Pair{"btc_eth"} 54 | 55 | info, err := pair.GetInfo() 56 | if err != nil { 57 | t.Fail() 58 | } 59 | 60 | if !info.isOk() { 61 | t.Log(info.ErrorMsg()) 62 | } 63 | 64 | t.Log("Pair: ", info.Pair) 65 | t.Log("Min: ", info.Min) 66 | t.Log("Miner Fee: ", info.MinerFee) 67 | t.Log("Limit: ", info.Limit) 68 | t.Log("Rate: ", info.Rate) 69 | 70 | } 71 | 72 | func TestRecentTransactions(t *testing.T) { 73 | 74 | recent, err := RecentTransactions("5") 75 | if err != nil { 76 | t.Fail() 77 | } 78 | 79 | for _, v := range *recent { 80 | t.Log("In: ", v.CurIn) 81 | t.Log("Out: ", v.CurOut) 82 | t.Log("Amount: ", v.Amount) 83 | t.Log("Timestamp: ", v.Timestamp) 84 | t.Log("-------------------------------") 85 | } 86 | 87 | } 88 | 89 | func TestValidateAddress(t *testing.T) { 90 | 91 | address, err := Validate("16FdfRFVPUwiKAceRSqgEfn1tmB4sVUmLh", "btc") 92 | if err != nil { 93 | t.Fail() 94 | } 95 | t.Log("Address is: ", address.Valid) 96 | 97 | address2, err := Validate("1JP7QWC9GbpKEHSvefygWk5woFy9xeQHKc", "btc") 98 | if err != nil { 99 | t.Fail() 100 | } 101 | t.Log("Second Address is: ", address2.Valid) 102 | t.Log("Second Error: ", address2.ErrorMsg()) 103 | 104 | } 105 | 106 | func TestDepositStatus(t *testing.T) { 107 | 108 | status, err := DepositStatus("1JP7QWC9GbpKEHSvefygWk5woFy9xeQHKc") 109 | if err != nil { 110 | t.Fail() 111 | } 112 | 113 | if status.isOk() { 114 | 115 | t.Log("Deposit Status: ", status.Status) 116 | 117 | t.Log("Incoming Coin: ", status.IncomingCoin) 118 | t.Log("Incoming Type: ", status.IncomingType) 119 | t.Log("Outgoing Coin: ", status.OutgoingCoin) 120 | t.Log("Outgoing Type: ", status.OutgoingType) 121 | t.Log("Address: ", status.Address) 122 | t.Log("Transaction ID: ", status.Transaction) 123 | t.Log("Withdraw: ", status.Withdraw) 124 | 125 | } 126 | 127 | if status.Status != "complete" { 128 | t.Fail() 129 | } 130 | 131 | newTranxId = status.Transaction 132 | 133 | } 134 | 135 | func TestGetCoinsAsList(t *testing.T) { 136 | 137 | coins, err := CoinsAsList() 138 | if err != nil || len(coins) == 0 { 139 | t.Fail() 140 | } 141 | 142 | t.Log("Coin: ", coins[0].Name) 143 | t.Log("Status: ", coins[0].Status) 144 | 145 | } 146 | 147 | func TestGetSupportedCoins(t *testing.T) { 148 | 149 | coins, err := Coins() 150 | if err != nil { 151 | t.Fail() 152 | } 153 | 154 | eth := coins.ETH 155 | t.Log("Coin: ", eth.Name) 156 | t.Log("Status: ", eth.Status) 157 | 158 | } 159 | 160 | func TestNewTransaction(t *testing.T) { 161 | 162 | new := New{ 163 | Pair: "eth_btc", 164 | ToAddress: "16FdfRFVPUwiKAceRSqgEfn1tmB4sVUmLh", 165 | FromAddress: "0xcf2f204aC8D7714990912fA422874371c001217D", 166 | } 167 | 168 | response, err := new.Shift() 169 | if err != nil { 170 | t.Fail() 171 | } 172 | 173 | if response.isOk() { 174 | 175 | t.Log("Send To Address: ", response.SendTo) 176 | t.Log("Send Type: ", response.SendType) 177 | t.Log("Receiving at Address: ", response.ReturnTo) 178 | t.Log("Receiving Type: ", response.ReturnType) 179 | t.Log("Send Type: ", response.SendType) 180 | t.Log("API Key: ", response.ApiKey) 181 | t.Log("Public Data: ", response.Public) 182 | t.Log("XrpDestTag: ", response.XrpDestTag) 183 | 184 | if response.SendType != "ETH" || response.ReturnType != "BTC" { 185 | t.Fail() 186 | } 187 | 188 | } 189 | 190 | newSendToAddress = response.SendTo 191 | 192 | } 193 | 194 | func TestEmailReceipt(t *testing.T) { 195 | 196 | info := Receipt{ 197 | Email: "info@socialeck.com", 198 | TransactionID: newTranxId, 199 | } 200 | 201 | response, err := info.Send() 202 | if err != nil { 203 | t.Fail() 204 | } 205 | 206 | if response.isOk() { 207 | t.Log("Response was good!") 208 | } else { 209 | t.Log(response.ErrorMsg()) 210 | } 211 | 212 | t.Log(response) 213 | 214 | } 215 | 216 | func TestNewFixedTransaction(t *testing.T) { 217 | 218 | new := New{ 219 | Pair: "eth_btc", 220 | Amount: 0.25, 221 | ToAddress: "16FdfRFVPUwiKAceRSqgEfn1tmB4sVUmLh", 222 | FromAddress: "0xcf2f204aC8D7714990912fA422874371c001217D", 223 | } 224 | 225 | response, err := new.FixedShift() 226 | if err != nil { 227 | t.Fail() 228 | } 229 | 230 | if response.isOk() { 231 | 232 | t.Log("Pair: ", response.Pair) 233 | t.Log("Quoted Rate: ", response.QuotedRate) 234 | t.Log("Deposit Address: ", response.Deposit) 235 | t.Log("Deposit Amount: ", response.DepositAmount) 236 | t.Log("Withdraw Amount: ", response.WithdrawalAmount) 237 | t.Log("Withdraw Address: ", response.Withdrawal) 238 | t.Log("Expiration: ", response.Expiration) 239 | 240 | } else { 241 | t.Log(response.ErrorMsg()) 242 | } 243 | 244 | newSendToAddress2 = response.Deposit 245 | 246 | if response.Withdrawal != "16FdfRFVPUwiKAceRSqgEfn1tmB4sVUmLh" { 247 | t.Fail() 248 | } 249 | 250 | if response.WithdrawalAmount != "0.25" { 251 | t.Fail() 252 | } 253 | 254 | if response.Pair != "eth_btc" { 255 | t.Fail() 256 | } 257 | } 258 | 259 | func TestTimeRemaining(t *testing.T) { 260 | 261 | status, err := TimeRemaining("1JP7QWC9GbpKEHSvefygWk5woFy9xeQHKc") 262 | if err != nil { 263 | panic(err) 264 | } 265 | 266 | if status.isOk() { 267 | t.Log("Seconds Remaining: ", status.Seconds) 268 | t.Log("Status: ", status.Status) 269 | } else { 270 | t.Log(status.ErrorMsg()) 271 | } 272 | 273 | } 274 | 275 | func TestCancelTransaction(t *testing.T) { 276 | 277 | old := Address{ 278 | Id: newSendToAddress, 279 | } 280 | 281 | response, err := old.Cancel() 282 | if err != nil { 283 | t.Fail() 284 | } 285 | 286 | if response.isOk() { 287 | t.Log(response.Success) 288 | } else { 289 | t.Log(response.ErrorMsg()) 290 | } 291 | 292 | } 293 | 294 | func TestListTransactionsFromAPI(t *testing.T) { 295 | 296 | api := API{ 297 | Key: "oskdfoijsfuhsdhufhewhuf", 298 | } 299 | 300 | list, err := api.ListTransactions() 301 | if err != nil { 302 | t.Fail() 303 | } 304 | 305 | for _, v := range list { 306 | t.Log("Input: ", v.InputAddress) 307 | t.Log("Amount: ", v.InputAmount) 308 | } 309 | 310 | t.Log(list) 311 | 312 | } 313 | 314 | func TestListAddressTransactionsFromAPI(t *testing.T) { 315 | 316 | api := API{ 317 | Key: "oskdfoijsfuhsdhufhewhuf", 318 | Address: "1JP7QWC9GbpKEHSvefygWk5woFy9xeQHKc", 319 | } 320 | 321 | list, err := api.ListTransactions() 322 | if err != nil { 323 | t.Fail() 324 | } 325 | 326 | for _, v := range list { 327 | t.Log("Input: ", v.InputAddress) 328 | t.Log("Amount: ", v.InputAmount) 329 | } 330 | 331 | t.Log(list) 332 | } 333 | -------------------------------------------------------------------------------- /shapeshift.go: -------------------------------------------------------------------------------- 1 | package shapeshift 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "errors" 7 | "io/ioutil" 8 | "net/http" 9 | "strconv" 10 | ) 11 | 12 | var apiUrl string = "https://shapeshift.io" 13 | 14 | // ShapeShift's API responds in float and string for decimals for different functions. 15 | // Since we arn't really using 'big numbers' I think it's ok to be using this. 16 | // This golang package is not doing any math, just responding back from ShapeShift API. 17 | func ToFloat(s string) float64 { 18 | f, err := strconv.ParseFloat(s, 64) 19 | if err != nil { 20 | return 0.0 21 | } 22 | return f 23 | } 24 | 25 | type Pair struct { 26 | Name string `json:"pair,omitempty"` 27 | } 28 | 29 | type RateResponse struct { 30 | Pair string `json:"pair,omitempty"` 31 | Rate string `json:"rate"` 32 | Error 33 | } 34 | 35 | type LimitResponse struct { 36 | Pair string `json:"pair,omitempty"` 37 | Limit string `json:"limit"` 38 | Error 39 | } 40 | 41 | type MarketInfoResponse struct { 42 | Pair string `json:"pair,omitempty"` 43 | Rate float64 `json:"rate,string,omitempty"` 44 | Limit float64 `json:"limit,omitempty"` 45 | Min float64 `json:"min,omitempty"` 46 | MinerFee float64 `json:"minerFee,omitempty"` 47 | Error 48 | } 49 | 50 | type RecentTranxResponse []struct { 51 | CurIn string `json:"curIn"` 52 | CurOut string `json:"curOut"` 53 | Timestamp float64 `json:"timestamp"` 54 | Amount float64 `json:"amount"` 55 | Error 56 | } 57 | 58 | type DepositStatusResponse struct { 59 | Status string `json:"status"` 60 | Address string `json:"address"` 61 | Withdraw string `json:"withdraw,omitempty"` 62 | IncomingCoin float64 `json:"incomingCoin,omitempty"` 63 | IncomingType string `json:"incomingType,omitempty"` 64 | OutgoingCoin string `json:"outgoingCoin,omitempty"` 65 | OutgoingType string `json:"outgoingType,omitempty"` 66 | Transaction string `json:"transaction,omitempty"` 67 | Error 68 | } 69 | 70 | type Receipt struct { 71 | Email string `json:"email"` 72 | TransactionID string `json:"txid"` 73 | } 74 | 75 | type ValidateResponse struct { 76 | Valid bool `json:"isValid"` 77 | Error 78 | } 79 | 80 | type CancelResponse struct { 81 | Success string `json:"success,omitempty"` 82 | Error 83 | } 84 | 85 | type Address struct { 86 | Id string `json:"address"` 87 | } 88 | 89 | type New struct { 90 | Pair string `json:"pair,omitempty"` 91 | ToAddress string `json:"withdrawal"` 92 | FromAddress string `json:"returnAddress,omitempty"` 93 | DestTag string `json:"destTag,omitempty"` 94 | RsAddress string `json:"rsAddress,omitempty"` 95 | ApiKey string `json:"apiKey,omitempty"` 96 | Amount float64 `json:"amount,omitempty"` 97 | } 98 | 99 | type NewTransactionResponse struct { 100 | SendTo string `json:"deposit"` 101 | SendType string `json:"depositType"` 102 | ReturnTo string `json:"withdrawal"` 103 | ReturnType string `json:"withdrawalType"` 104 | Public string `json:"public"` 105 | XrpDestTag string `json:"xrpDestTag"` 106 | ApiKey string `json:"apiPubKey"` 107 | Error 108 | } 109 | 110 | type FixedTransactionResponse struct { 111 | Response NewFixedTransactionResponse `json:"success"` 112 | Error 113 | } 114 | 115 | type NewFixedTransactionResponse struct { 116 | OrderID string `json:"orderId"` 117 | Pair string `json:"pair,omitempty"` 118 | Withdrawal string `json:"withdrawal"` 119 | WithdrawalAmount string `json:"withdrawalAmount"` 120 | Deposit string `json:"deposit"` 121 | DepositAmount string `json:"depositAmount"` 122 | Expiration int64 `json:"expiration"` 123 | QuotedRate string `json:"quotedRate"` 124 | MaxLimit float64 `json:"maxLimit"` 125 | ReturnAddress string `json:"returnAddress"` 126 | APIPubKey string `json:"apiPubKey"` 127 | MinerFee string `json:"minerFee"` 128 | Error 129 | } 130 | 131 | type ListTransactionsAPIResponse struct { 132 | Transactions []Transaction 133 | Error 134 | } 135 | 136 | type ErrorMsg interface { 137 | ErrorMsg() string 138 | isOk() bool 139 | } 140 | 141 | func (e Error) ErrorMsg() string { 142 | return e.Message 143 | } 144 | 145 | func (e Error) isOk() bool { 146 | if e.Message == "" { 147 | return true 148 | } 149 | return false 150 | } 151 | 152 | type Error struct { 153 | Message string `json:"error,omitempty"` 154 | } 155 | 156 | type Transaction struct { 157 | InputTXID string `json:"inputTXID"` 158 | InputAddress string `json:"inputAddress"` 159 | InputCurrency string `json:"inputCurrency,omitempty"` 160 | InputAmount float64 `json:"inputAmount,omitempty"` 161 | OutputTXID string `json:"outputTXID,omitempty"` 162 | OutputAddress string `json:"outputAddress,omitempty"` 163 | OutputCurrency string `json:"outputCurrency,omitempty"` 164 | OutputAmount string `json:"outputAmount,omitempty"` 165 | ShiftRate string `json:"shiftRate,omitempty"` 166 | Status string `json:"status,omitempty"` 167 | } 168 | 169 | type ReceiptResponse struct { 170 | Email struct { 171 | Status string `json:"status"` 172 | Message string `json:"message"` 173 | } `json:"email"` 174 | Error 175 | } 176 | 177 | type API struct { 178 | Key string 179 | Address string 180 | } 181 | 182 | type TimeRemainingResponse struct { 183 | Status string `json:"status"` 184 | Seconds string `json:"seconds_remaining"` 185 | Error 186 | } 187 | 188 | func (p Pair) GetRates() (float64, error) { 189 | r, err := DoHttp("GET", "rate", p.Name) 190 | if err != nil { 191 | return 0.0, err 192 | } 193 | var g RateResponse 194 | err = json.Unmarshal(r, &g) 195 | return ToFloat(g.Rate), err 196 | } 197 | 198 | func (p Pair) GetLimits() (float64, error) { 199 | r, err := DoHttp("GET", "limit", p.Name) 200 | if err != nil { 201 | return 0.0, err 202 | } 203 | var g LimitResponse 204 | err = json.Unmarshal(r, &g) 205 | return ToFloat(g.Limit), err 206 | } 207 | 208 | func MarketInfo() ([]MarketInfoResponse, error) { 209 | r, err := DoHttp("GET", "marketinfo", "") 210 | if err != nil { 211 | return nil, err 212 | } 213 | var arr []MarketInfoResponse 214 | err = json.Unmarshal(r, &arr) 215 | return arr, err 216 | } 217 | 218 | func (p Pair) GetInfo() (*MarketInfoResponse, error) { 219 | r, err := DoHttp("GET", "marketinfo", p.Name) 220 | if err != nil { 221 | return nil, err 222 | } 223 | var g MarketInfoResponse 224 | err = json.Unmarshal(r, &g) 225 | return &g, err 226 | } 227 | 228 | func RecentTransactions(count string) (*RecentTranxResponse, error) { 229 | r, err := DoHttp("GET", "recenttx", count) 230 | if err != nil { 231 | return nil, err 232 | } 233 | var g RecentTranxResponse 234 | err = json.Unmarshal(r, &g) 235 | return &g, err 236 | } 237 | 238 | func DepositStatus(addr string) (*DepositStatusResponse, error) { 239 | r, err := DoHttp("GET", "txStat", addr) 240 | if err != nil { 241 | return nil, err 242 | } 243 | var g DepositStatusResponse 244 | err = json.Unmarshal(r, &g) 245 | return &g, err 246 | } 247 | 248 | func TimeRemaining(addr string) (*TimeRemainingResponse, error) { 249 | r, err := DoHttp("GET", "timeremaining", addr) 250 | if err != nil { 251 | return nil, err 252 | } 253 | var g TimeRemainingResponse 254 | err = json.Unmarshal(r, &g) 255 | return &g, err 256 | } 257 | 258 | func CoinsAsList() ([]Coin, error) { 259 | var coins []Coin 260 | r, err := DoHttp("GET", "getcoins", "") 261 | if err != nil { 262 | return nil, err 263 | } 264 | 265 | // Use json.RawMessage to delay marshalling to support arbitrary top level keys 266 | var coinmap map[string]*json.RawMessage 267 | if err := json.Unmarshal(r, &coinmap); err != nil { 268 | return coins, err 269 | } 270 | 271 | for _, coinJSON := range coinmap { 272 | var c Coin 273 | err := json.Unmarshal([]byte(*coinJSON), &c) 274 | if err != nil { 275 | //log.Println("Error unmarshalling coin:", err) 276 | continue 277 | } 278 | coins = append(coins, c) 279 | } 280 | 281 | return coins, nil 282 | } 283 | 284 | func Coins() (*CoinsResponse, error) { 285 | r, err := DoHttp("GET", "getcoins", "") 286 | if err != nil { 287 | return nil, err 288 | } 289 | var g CoinsResponse 290 | err = json.Unmarshal(r, &g) 291 | return &g, err 292 | } 293 | 294 | func (r Receipt) Send() (*ReceiptResponse, error) { 295 | q, err := DoPostHttp("POST", "mail", r) 296 | if err != nil { 297 | return nil, err 298 | } 299 | var g ReceiptResponse 300 | err = json.Unmarshal(q, &g) 301 | return &g, err 302 | } 303 | 304 | func (n New) Shift() (*NewTransactionResponse, error) { 305 | r, err := DoPostHttp("POST", "shift", n) 306 | if err != nil { 307 | return nil, err 308 | } 309 | var g NewTransactionResponse 310 | err = json.Unmarshal(r, &g) 311 | return &g, err 312 | } 313 | 314 | func (n New) FixedShift() (*NewFixedTransactionResponse, error) { 315 | r, err := DoPostHttp("POST", "sendamount", n) 316 | if err != nil { 317 | return nil, err 318 | } 319 | var g FixedTransactionResponse 320 | err = json.Unmarshal(r, &g) 321 | return &g.Response, err 322 | } 323 | 324 | func (n Address) Cancel() (*CancelResponse, error) { 325 | r, err := DoPostHttp("POST", "cancelpending", n) 326 | if err != nil { 327 | return nil, err 328 | } 329 | var g CancelResponse 330 | err = json.Unmarshal(r, &g) 331 | return &g, err 332 | } 333 | 334 | func Validate(addr string, coin string) (*ValidateResponse, error) { 335 | r, err := DoHttp("GET", "validateAddress/"+addr, coin) 336 | if err != nil { 337 | return nil, err 338 | } 339 | var g ValidateResponse 340 | err = json.Unmarshal(r, &g) 341 | return &g, err 342 | } 343 | 344 | func (i API) ListTransactions() ([]Transaction, error) { 345 | var r []byte 346 | var err error 347 | var g []Transaction 348 | if i.Address != "" { 349 | r, err = DoHttp("GET", "txbyaddress/"+i.Address, i.Key) 350 | } else { 351 | r, err = DoHttp("GET", "txbyapikey", i.Key) 352 | } 353 | err = json.Unmarshal(r, &g) 354 | return g, err 355 | } 356 | 357 | func DoPostHttp(method string, apimethod string, data interface{}) ([]byte, error) { 358 | new, err := json.Marshal(data) 359 | if err != nil { 360 | return nil, err 361 | } 362 | req, err := http.NewRequest(method, apiUrl+"/"+apimethod, bytes.NewBuffer(new)) 363 | if err != nil { 364 | return nil, err 365 | } 366 | req.Header.Set("Content-Type", "application/json") 367 | client := &http.Client{} 368 | resp, err := client.Do(req) 369 | if err != nil { 370 | return nil, err 371 | } 372 | if resp.StatusCode != 200 { 373 | return nil, errors.New("There was an error creating your order, Please try again later") 374 | } 375 | defer resp.Body.Close() 376 | body, err := ioutil.ReadAll(resp.Body) 377 | body = bytes.TrimPrefix(body, []byte("\xef\xbb\xbf")) 378 | return body, err 379 | } 380 | 381 | func DoHttp(method string, apimethod string, url string) ([]byte, error) { 382 | req, err := http.NewRequest(method, apiUrl+"/"+apimethod+"/"+url, bytes.NewBuffer([]byte(""))) 383 | if err != nil { 384 | return nil, err 385 | } 386 | client := &http.Client{} 387 | resp, err := client.Do(req) 388 | if err != nil { 389 | return nil, err 390 | } 391 | defer resp.Body.Close() 392 | body, err := ioutil.ReadAll(resp.Body) 393 | body = bytes.TrimPrefix(body, []byte("\xef\xbb\xbf")) 394 | return body, err 395 | } 396 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |