├── README.md ├── go.mod ├── .gitignore ├── go.sum ├── fireblocks_sdk.go └── fireblocks_domain.go /README.md: -------------------------------------------------------------------------------- 1 | # fireblocks-sdk-go 2 | 3 | A Golang wrapper for the [Fireblocks API](https://docs.fireblocks.com/api) 4 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/caxqueiroz/fireblocks-sdk/v2 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/gojek/heimdall/v7 v7.0.2 7 | github.com/golang-jwt/jwt v3.2.2+incompatible 8 | github.com/shopspring/decimal v1.2.0 9 | github.com/sirupsen/logrus v1.8.1 10 | github.com/stretchr/testify v1.7.0 11 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect 12 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | .idea/ 3 | 4 | # File-based project format 5 | *.iws 6 | 7 | # IntelliJ 8 | out/ 9 | 10 | # mpeltonen/sbt-idea plugin 11 | .idea_modules/ 12 | 13 | keys/ 14 | scripts/ 15 | 16 | 17 | # Crashlytics plugin (for Android Studio and IntelliJ) 18 | com_crashlytics_export_strings.xml 19 | crashlytics.properties 20 | crashlytics-build.properties 21 | fabric.properties 22 | 23 | 24 | 25 | ### Go template 26 | # Binaries for programs and plugins 27 | *.exe 28 | *.exe~ 29 | *.dll 30 | *.so 31 | *.dylib 32 | 33 | # Test binary, built with `go test -c` 34 | *.test 35 | *_test.go 36 | 37 | # Output of the go coverage tool, specifically when used with LiteIDE 38 | *.out 39 | 40 | # Dependency directories (remove the comment below to include it) 41 | # vendor/ 42 | 43 | *.env 44 | 45 | certs/ 46 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/DataDog/datadog-go v3.7.1+incompatible h1:HmA9qHVrHIAqpSvoCYJ+c6qst0lgqEhNW6/KwfkHbS8= 2 | github.com/DataDog/datadog-go v3.7.1+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= 3 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw= 4 | github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= 5 | github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c h1:HIGF0r/56+7fuIZw2V4isE22MK6xpxWx7BbV8dJ290w= 6 | github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c/go.mod h1:l/bIBLeOl9eX+wxJAzxS4TveKRtAqlyDpHjhkfO0MEI= 7 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 8 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 9 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 10 | github.com/gojek/heimdall/v7 v7.0.2 h1:+YutGXZ8oEWbCJIwjRnkKmoTl+Oxt1Urs3hc/FR0sxU= 11 | github.com/gojek/heimdall/v7 v7.0.2/go.mod h1:Z43HtMid7ysSjmsedPTXAki6jcdcNVnjn5pmsTyiMic= 12 | github.com/gojek/valkyrie v0.0.0-20180215180059-6aee720afcdf h1:5xRGbUdOmZKoDXkGx5evVLehuCMpuO1hl701bEQqXOM= 13 | github.com/gojek/valkyrie v0.0.0-20180215180059-6aee720afcdf/go.mod h1:QzhUKaYKJmcbTnCYCAVQrroCOY7vOOI8cSQ4NbuhYf0= 14 | github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= 15 | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 16 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 17 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 18 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 19 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 20 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 21 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 22 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 23 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 24 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= 25 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= 26 | github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= 27 | github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= 28 | github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= 29 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 30 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= 31 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 32 | github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= 33 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 34 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 35 | github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As= 36 | github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 37 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 38 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 39 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 40 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 41 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 42 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 43 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 44 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 45 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= 46 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 47 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 48 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 49 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 50 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 51 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 52 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 53 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 54 | -------------------------------------------------------------------------------- /fireblocks_sdk.go: -------------------------------------------------------------------------------- 1 | package fireblocks 2 | 3 | import ( 4 | "bytes" 5 | crand "crypto/rand" 6 | "crypto/rsa" 7 | "crypto/sha256" 8 | "crypto/tls" 9 | "encoding/binary" 10 | "encoding/hex" 11 | "encoding/json" 12 | "errors" 13 | "fmt" 14 | "github.com/gojek/heimdall/v7/hystrix" 15 | "github.com/golang-jwt/jwt" 16 | "github.com/shopspring/decimal" 17 | log "github.com/sirupsen/logrus" 18 | "io" 19 | "io/ioutil" 20 | "math/rand" 21 | "net/http" 22 | "net/url" 23 | "strings" 24 | "time" 25 | ) 26 | 27 | type FbKeyMgmt struct { 28 | privateKey *rsa.PrivateKey 29 | apiKey string 30 | rnd *rand.Rand 31 | } 32 | 33 | func NewInstanceKeyMgmt(pk *rsa.PrivateKey, apiKey string) *FbKeyMgmt { 34 | var s secrets 35 | k := new(FbKeyMgmt) 36 | k.privateKey = pk 37 | k.apiKey = apiKey 38 | k.rnd = rand.New(s) 39 | return k 40 | } 41 | 42 | const timeout = 5 * time.Millisecond 43 | 44 | type secrets struct{} 45 | 46 | func (s secrets) Seed(seed int64) {} 47 | 48 | func (s secrets) Uint64() (r uint64) { 49 | err := binary.Read(crand.Reader, binary.BigEndian, &r) 50 | if err != nil { 51 | log.Error(err) 52 | } 53 | return r 54 | } 55 | 56 | func (s secrets) Int63() int64 { 57 | return int64(s.Uint64() & ^uint64(1<<63)) 58 | } 59 | 60 | func (k *FbKeyMgmt) createAndSignJWTToken(path string, bodyJSON string) (string, error) { 61 | 62 | token := &jwt.MapClaims{ 63 | "uri": path, 64 | "nonce": k.rnd.Int63(), 65 | "iat": time.Now().Unix(), 66 | "exp": time.Now().Add(time.Second * 55).Unix(), 67 | "sub": k.apiKey, 68 | "bodyHash": createHash(bodyJSON), 69 | } 70 | 71 | j := jwt.NewWithClaims(jwt.SigningMethodRS256, token) 72 | signedToken, err := j.SignedString(k.privateKey) 73 | if err != nil { 74 | log.Error(err) 75 | } 76 | 77 | return signedToken, err 78 | } 79 | 80 | func createHash(data string) string { 81 | h := sha256.New() 82 | h.Write([]byte(data)) 83 | hashed := h.Sum(nil) 84 | return hex.EncodeToString(hashed) 85 | } 86 | 87 | type SDK struct { 88 | httpClient *hystrix.Client 89 | apiBaseURL string 90 | kto *FbKeyMgmt 91 | } 92 | 93 | // NewInstance - create new type to handle Fireblocks API requests 94 | func NewInstance(pk []byte, ak string, url string, t time.Duration) *SDK { 95 | 96 | if t == time.Duration(0) { 97 | // use default 98 | t = timeout 99 | } 100 | 101 | s := new(SDK) 102 | s.apiBaseURL = url 103 | privateK, err := jwt.ParseRSAPrivateKeyFromPEM(pk) 104 | if err != nil { 105 | log.Error(err) 106 | } 107 | 108 | s.kto = NewInstanceKeyMgmt(privateK, ak) 109 | s.httpClient = newCircuitBreakerHttpClient(t) 110 | return s 111 | } 112 | 113 | func newCircuitBreakerHttpClient(t time.Duration) *hystrix.Client { 114 | 115 | http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{ 116 | InsecureSkipVerify: false, 117 | } 118 | c := hystrix.NewClient(hystrix.WithHTTPTimeout(t), 119 | hystrix.WithFallbackFunc(func(err error) error { 120 | log.Errorf("no fallback func implemented: %s", err) 121 | return err 122 | })) 123 | return c 124 | } 125 | 126 | // getRequest - internal method to handle API call to Fireblocks 127 | func (s *SDK) getRequest(path string) (string, error) { 128 | 129 | urlEndPoint := s.apiBaseURL + path 130 | token, err := s.kto.createAndSignJWTToken(path, "") 131 | if err != nil { 132 | log.Error(err) 133 | return fmt.Sprintf("{message: \"%s.\"}", "error signing JWT token"), err 134 | } 135 | 136 | request, err := http.NewRequest(http.MethodGet, urlEndPoint, nil) 137 | if err != nil { 138 | log.Error(err) 139 | return fmt.Sprintf("{message: \"%s.\"}", "error creating NewRequest"), err 140 | } 141 | 142 | request.Header.Add("X-API-Key", s.kto.apiKey) 143 | request.Header.Add("Authorization", fmt.Sprintf("Bearer %v", token)) 144 | 145 | response, err := s.httpClient.Do(request) 146 | if err != nil { 147 | log.Error(err) 148 | return "", err 149 | } 150 | defer func(Body io.ReadCloser) { 151 | err := Body.Close() 152 | if err != nil { 153 | log.Error(err) 154 | } 155 | }(response.Body) 156 | 157 | data, err := ioutil.ReadAll(response.Body) 158 | if err != nil { 159 | log.Errorf("error communicating with fireblocks: %v", err) 160 | return "", err 161 | } 162 | 163 | if response.StatusCode >= 300 { 164 | errMsg := fmt.Sprintf("fireblocks server: %s \n %s", response.Status, string(data)) 165 | log.Warning(errMsg) 166 | } 167 | 168 | return string(data), err 169 | } 170 | 171 | func (s *SDK) changeRequest(path string, payload []byte, idempotencyKey string, requestType string) (string, error) { 172 | 173 | urlEndPoint := s.apiBaseURL + path 174 | token, err := s.kto.createAndSignJWTToken(path, string(payload)) 175 | if err != nil { 176 | log.Error(err) 177 | return fmt.Sprintf("{message: \"%s.\"}", "error signing JWT token"), err 178 | } 179 | 180 | request, err := http.NewRequest(requestType, urlEndPoint, bytes.NewBuffer(payload)) 181 | if err != nil { 182 | log.Error(err) 183 | return fmt.Sprintf("{message: \"%s.\"}", "error creating NewRequest"), err 184 | } 185 | request.Header.Add("X-API-Key", string(s.kto.apiKey)) 186 | request.Header.Add("Authorization", fmt.Sprintf("Bearer %v", token)) 187 | request.Header.Add("Content-Type", "application/json") 188 | 189 | if len(idempotencyKey) > 0 { 190 | request.Header.Add("Idempotency-Key", idempotencyKey) 191 | } 192 | response, err := s.httpClient.Do(request) 193 | if err != nil { 194 | log.Error(err) 195 | return "", err 196 | } 197 | defer func(Body io.ReadCloser) { 198 | err := Body.Close() 199 | if err != nil { 200 | log.Error(err) 201 | } 202 | }(response.Body) 203 | 204 | data, err := ioutil.ReadAll(response.Body) 205 | if err != nil { 206 | log.Errorf("error on communicating with Fireblocks: %v \n data: %s", err, data) 207 | return "", err 208 | } 209 | 210 | if response.StatusCode >= 300 { 211 | errMsg := fmt.Sprintf("fireblocks server: %s \n %s", response.Status, string(data)) 212 | log.Warning(errMsg) 213 | } 214 | 215 | return string(data), err 216 | 217 | } 218 | 219 | func (s *SDK) GetUsers() ([]User, error) { 220 | 221 | returnedData, err := s.getRequest("/v1/users") 222 | if err != nil { 223 | log.Error(err) 224 | return nil, err 225 | } 226 | 227 | var users []User 228 | err = json.Unmarshal([]byte(returnedData), &users) 229 | if err != nil { 230 | log.Error(err) 231 | return nil, err 232 | } 233 | 234 | return users, nil 235 | } 236 | 237 | // GetSupportedAssets - Gets all assets that are currently supported by Fireblocks API. 238 | func (s *SDK) GetSupportedAssets() ([]AssetTypeResponse, error) { 239 | 240 | returnedData, err := s.getRequest("/v1/supported_assets") 241 | if err != nil { 242 | log.Error(err) 243 | return nil, err 244 | } 245 | var assetsTypeResponse []AssetTypeResponse 246 | err = json.Unmarshal([]byte(returnedData), &assetsTypeResponse) 247 | if err != nil { 248 | log.Error(err) 249 | return nil, err 250 | } 251 | 252 | return assetsTypeResponse, nil 253 | } 254 | 255 | // GetVaultAccounts - gets all vault accounts for the tenant. 256 | func (s *SDK) GetVaultAccounts(namePrefix string, nameSuffix string, minAmountThreshold decimal.Decimal) ([]VaultAccount, error) { 257 | 258 | query := "/v1/vault/accounts" 259 | params := url.Values{} 260 | 261 | if namePrefix != "" { 262 | params.Add("namePrefix", namePrefix) 263 | } 264 | if nameSuffix != "" { 265 | params.Add("nameSuffix", nameSuffix) 266 | } 267 | if minAmountThreshold.GreaterThan(decimal.NewFromFloat(0.0)) { 268 | params.Add("minAmountThreshold", fmt.Sprintf("%s", minAmountThreshold)) 269 | } 270 | if len(params) > 0 { 271 | query = query + "?" + params.Encode() 272 | } 273 | 274 | returnedData, err := s.getRequest(query) 275 | if err != nil { 276 | return nil, err 277 | } 278 | var vaultAccounts []VaultAccount 279 | err = json.Unmarshal([]byte(returnedData), &vaultAccounts) 280 | if err != nil { 281 | log.Error(err) 282 | return nil, err 283 | } 284 | 285 | return vaultAccounts, nil 286 | } 287 | 288 | // GetVaultAccount - retrieve the vault account for the specified id. 289 | 290 | func (s *SDK) GetVaultAccount(vaultAccountID string) (VaultAccount, error) { 291 | 292 | query := fmt.Sprintf("/v1/vault/accounts/%s", vaultAccountID) 293 | 294 | returnedData, err := s.getRequest(query) 295 | if err != nil { 296 | return VaultAccount{}, err 297 | } 298 | 299 | var vaultAccount VaultAccount 300 | err = json.Unmarshal([]byte(returnedData), &vaultAccount) 301 | if err != nil { 302 | log.Error(err) 303 | return VaultAccount{}, err 304 | } 305 | 306 | if vaultAccount.Id == "" { 307 | return VaultAccount{}, errors.New(returnedData) 308 | } 309 | 310 | return vaultAccount, err 311 | 312 | } 313 | 314 | // GetVaultAccountAsset - Gets a single vault account asset 315 | func (s *SDK) GetVaultAccountAsset(vaultAccountID string, assetID string) (VaultAsset, error) { 316 | 317 | query := fmt.Sprintf("/v1/vault/accounts/%s/%s", vaultAccountID, assetID) 318 | 319 | var vaultAsset VaultAsset 320 | returnedData, err := s.getRequest(query) 321 | if err != nil { 322 | log.Error(err) 323 | } 324 | err = json.Unmarshal([]byte(returnedData), &vaultAsset) 325 | if err != nil { 326 | log.Errorf("failed to parse payload: %s. %v", returnedData, err) 327 | return VaultAsset{}, err 328 | } 329 | return vaultAsset, err 330 | 331 | } 332 | 333 | // GetAddresses - Gets deposit addresses for an asset in a vault account 334 | func (s *SDK) GetAddresses(vaultAccountID string, assetID string) ([]VaultAccountAssetAddress, error) { 335 | 336 | query := fmt.Sprintf("/v1/vault/accounts/%s/%s/addresses", vaultAccountID, assetID) 337 | returnedData, err := s.getRequest(query) 338 | if err != nil { 339 | return nil, err 340 | } 341 | 342 | var assetAddress []VaultAccountAssetAddress 343 | err = json.Unmarshal([]byte(returnedData), &assetAddress) 344 | if err != nil { 345 | log.Errorf("failed to parse payload: %s. %v", returnedData, err) 346 | return nil, err 347 | } 348 | 349 | return assetAddress, nil 350 | 351 | } 352 | 353 | // GetUnspentInputs - Gets utxo list for an asset in a vault account 354 | func (s *SDK) GetUnspentInputs(vaultAccountID string, assetID string) (string, error) { 355 | query := fmt.Sprintf("/v1/vault/accounts/%s/%s/unspent_inouts", vaultAccountID, assetID) 356 | return s.getRequest(query) 357 | } 358 | 359 | // GenerateNewAddress - Generates a new address for an asset in a vault account 360 | func (s *SDK) GenerateNewAddress(vaultAccountID string, assetID string, description string, customerRefID string, 361 | idempotencyKey string, 362 | ) (CreateAddressResponse, error) { 363 | query := fmt.Sprintf("/v1/vault/accounts/%s/%s/addresses", vaultAccountID, assetID) 364 | 365 | payload := make(map[string]interface{}) 366 | 367 | if len(description) > 0 { 368 | payload["description"] = description 369 | } 370 | if len(customerRefID) > 0 { 371 | payload["customerRefId"] = customerRefID 372 | } 373 | marshalled, err := json.Marshal(payload) 374 | if err != nil { 375 | return CreateAddressResponse{}, err 376 | } 377 | 378 | returnedData, err := s.changeRequest(query, marshalled, idempotencyKey, http.MethodPost) 379 | if err != nil { 380 | log.Error(err) 381 | log.Errorf("returned payload: %s", returnedData) 382 | return CreateAddressResponse{}, err 383 | } 384 | 385 | var createdAddress CreateAddressResponse 386 | err = json.Unmarshal([]byte(returnedData), &createdAddress) 387 | if err != nil { 388 | log.Errorf("failed to parse payload: %s. %v", returnedData, err) 389 | return CreateAddressResponse{}, err 390 | } 391 | 392 | return createdAddress, nil 393 | 394 | } 395 | 396 | // SetAddressDescription - Sets the description of an existing address 397 | func (s *SDK) SetAddressDescription(vaultAccountID string, assetID string, description string, address string, tag string) (string, error) { 398 | 399 | payload := make(map[string]interface{}) 400 | 401 | if len(description) > 0 { 402 | payload["description"] = description 403 | } 404 | var query string 405 | if len(tag) > 0 { 406 | query = fmt.Sprintf("/v1/vault/accounts/%s/%s/addresses/%s:%s", vaultAccountID, assetID, address, tag) 407 | } else { 408 | query = fmt.Sprintf("/v1/vault/accounts/%s/%s/addresses/%s", vaultAccountID, assetID, address) 409 | } 410 | marshalled, err := json.Marshal(payload) 411 | if err != nil { 412 | return "", err 413 | } 414 | return s.changeRequest(query, marshalled, "", http.MethodPut) 415 | } 416 | 417 | // GetNetworkConnections - Gets all network connections for your tenant 418 | func (s *SDK) GetNetworkConnections() (string, error) { 419 | return s.getRequest("/v1/network_connections") 420 | } 421 | 422 | // GetNetworkConnectionByID - Gets a single network connection by id 423 | func (s *SDK) GetNetworkConnectionByID(connectionID string) (string, error) { 424 | query := fmt.Sprintf("/v1/network_connections/%s", connectionID) 425 | return s.getRequest(query) 426 | } 427 | 428 | // GetExchangeAccounts - Gets all exchange accounts for your tenant 429 | func (s *SDK) GetExchangeAccounts() ([]ExchangeAccount, error) { 430 | 431 | returnedData, err := s.getRequest("/v1/exchange_accounts") 432 | if err != nil { 433 | log.Error(err) 434 | } 435 | var exchangeAccounts []ExchangeAccount 436 | err = json.Unmarshal([]byte(returnedData), &exchangeAccounts) 437 | if err != nil { 438 | log.Error(err) 439 | return nil, err 440 | } 441 | return exchangeAccounts, nil 442 | 443 | } 444 | 445 | // GetExchangeAccount - Gets an exchange account for your tenant 446 | func (s *SDK) GetExchangeAccount(exchangeID string) (ExchangeAccount, error) { 447 | 448 | query := fmt.Sprintf("/v1/exchange_accounts/%s", exchangeID) 449 | 450 | returnedData, err := s.getRequest(query) 451 | if err != nil { 452 | log.Error(err) 453 | return ExchangeAccount{}, err 454 | } 455 | 456 | var exchangeAccount ExchangeAccount 457 | err = json.Unmarshal([]byte(returnedData), &exchangeAccount) 458 | if err != nil { 459 | log.Error(err) 460 | return ExchangeAccount{}, err 461 | } 462 | 463 | return exchangeAccount, nil 464 | 465 | } 466 | 467 | // GetExchangeAccountAsset - Get a specific asset from an exchange account 468 | func (s *SDK) GetExchangeAccountAsset(exchangeID string, assetID string) (ExchangeAsset, error) { 469 | 470 | query := fmt.Sprintf("/v1/exchange_accounts/%s/%s", exchangeID, assetID) 471 | 472 | returnedData, err := s.getRequest(query) 473 | if err != nil { 474 | log.Error(err) 475 | return ExchangeAsset{}, err 476 | } 477 | 478 | var exchangeAsset ExchangeAsset 479 | err = json.Unmarshal([]byte(returnedData), &exchangeAsset) 480 | if err != nil { 481 | log.Error(err) 482 | return ExchangeAsset{}, err 483 | } 484 | 485 | return exchangeAsset, nil 486 | 487 | } 488 | 489 | func (s *SDK) SetCustomerRefId(vaultAccountId string, customerRefId string, idempotencyKey string) error { 490 | 491 | payload := map[string]interface{}{ 492 | "customerRefId": customerRefId, 493 | } 494 | 495 | marshalled, err := json.Marshal(payload) 496 | if err != nil { 497 | return err 498 | } 499 | 500 | query := fmt.Sprintf("/v1/vault/accounts/%s", vaultAccountId) 501 | _, err = s.changeRequest(query, marshalled, idempotencyKey, http.MethodPost) 502 | if err != nil { 503 | log.Error(err) 504 | return err 505 | } 506 | 507 | return nil 508 | 509 | } 510 | 511 | //POST /v1/webhooks/resend 512 | 513 | func (s *SDK) ResendFailedWebhookEvents() error { 514 | 515 | _, err := s.changeRequest("/v1/webhooks/resend", nil, "", http.MethodPost) 516 | if err != nil { 517 | log.Error(err) 518 | } 519 | return err 520 | 521 | } 522 | 523 | // CreateVaultAccount 524 | // name - vaultaccount name - usually we use as a join of userid + product_id (XXXX_YYYY) 525 | func (s *SDK) CreateVaultAccount(name string, hiddenOnUI bool, customerRefID string, autoFuel bool, idempotencyKey string) (VaultAccount, error) { 526 | 527 | payload := map[string]interface{}{ 528 | "name": name, 529 | "hiddenOnUI": hiddenOnUI, 530 | "autoFuel": autoFuel, 531 | } 532 | 533 | if len(customerRefID) > 0 { 534 | payload["customerRefId"] = customerRefID 535 | } 536 | marshalled, err := json.Marshal(payload) 537 | if err != nil { 538 | return VaultAccount{}, err 539 | } 540 | 541 | returnedData, err := s.changeRequest("/v1/vault/accounts", marshalled, idempotencyKey, http.MethodPost) 542 | if err != nil { 543 | log.Error(err) 544 | } 545 | var vaultAccount VaultAccount 546 | err = json.Unmarshal([]byte(returnedData), &vaultAccount) 547 | if err != nil { 548 | log.Error(err) 549 | } 550 | 551 | if vaultAccount.Id == "" { 552 | return vaultAccount, errors.New(returnedData) 553 | } 554 | 555 | return vaultAccount, err 556 | 557 | } 558 | 559 | //CreateVaultAsset 560 | // creates a new wallet under the VaultAccount 561 | // args: 562 | // vaultAccountId 563 | // assetId 564 | func (s *SDK) CreateVaultAsset(vaultAccountId string, assetId string, idempotencyKey string) (CreateVaultAssetResponse, error) { 565 | 566 | cmd := fmt.Sprintf("/v1/vault/accounts/%s/%s", vaultAccountId, assetId) 567 | 568 | var createVaultAssetResponse CreateVaultAssetResponse 569 | returnedData, err := s.changeRequest(cmd, nil, idempotencyKey, http.MethodPost) 570 | if err != nil { 571 | log.Error(err) 572 | } 573 | 574 | err = json.Unmarshal([]byte(returnedData), &createVaultAssetResponse) 575 | if err != nil { 576 | log.Error(err) 577 | } 578 | 579 | if createVaultAssetResponse.Id == "" { 580 | return createVaultAssetResponse, errors.New(returnedData) 581 | } 582 | 583 | return createVaultAssetResponse, err 584 | 585 | } 586 | 587 | // CreateExternalWallet 588 | // customerRefId - used for identifying our clients. 589 | func (s *SDK) CreateExternalWallet(name string, customerRefId string, idempotencyKey string) (ExternalWallet, error) { 590 | 591 | payload := map[string]interface{}{ 592 | "name": name, 593 | } 594 | 595 | if len(customerRefId) > 0 { 596 | payload["customerRefId"] = customerRefId 597 | } 598 | marshalled, err := json.Marshal(payload) 599 | if err != nil { 600 | log.Error(err) 601 | return ExternalWallet{}, err 602 | } 603 | 604 | returnedData, err := s.changeRequest("/v1/external_wallets", marshalled, idempotencyKey, http.MethodPost) 605 | if err != nil { 606 | log.Error(err) 607 | return ExternalWallet{}, err 608 | } 609 | 610 | var externalWallet ExternalWallet 611 | err = json.Unmarshal([]byte(returnedData), &externalWallet) 612 | if err != nil { 613 | log.Error(err) 614 | return ExternalWallet{}, err 615 | } 616 | 617 | return externalWallet, nil 618 | 619 | } 620 | 621 | func (s *SDK) CreateExternalWalletAsset(walletId string, assetId string, address string, tag string, idempotencyKey string) (ExternalWalletAsset, error) { 622 | 623 | cmd := fmt.Sprintf("/v1/external_wallets/%s/%s", walletId, assetId) 624 | 625 | payload := map[string]interface{}{ 626 | "address": address, 627 | } 628 | 629 | if len(tag) > 0 { 630 | payload["tag"] = tag 631 | } 632 | marshalled, err := json.Marshal(payload) 633 | if err != nil { 634 | return ExternalWalletAsset{}, err 635 | } 636 | 637 | returnedData, err := s.changeRequest(cmd, marshalled, idempotencyKey, http.MethodPost) 638 | if err != nil { 639 | log.Error(err) 640 | return ExternalWalletAsset{}, err 641 | } 642 | var extWalletAsset ExternalWalletAsset 643 | 644 | err = json.Unmarshal([]byte(returnedData), &extWalletAsset) 645 | if err != nil { 646 | log.Error(err) 647 | return ExternalWalletAsset{}, err 648 | } 649 | 650 | return extWalletAsset, nil 651 | 652 | } 653 | 654 | //CreateInternalWallet 655 | 656 | func (s *SDK) CreateInternalWallet(name string, customerRefId string, idempotencyKey string) (UnmanagedWallet, error) { 657 | 658 | payload := map[string]interface{}{ 659 | "name": name, 660 | "customerRefId": customerRefId, 661 | } 662 | marshalled, err := json.Marshal(payload) 663 | if err != nil { 664 | return UnmanagedWallet{}, err 665 | } 666 | 667 | returnedData, err := s.changeRequest("/v1/internal_wallets", marshalled, idempotencyKey, http.MethodPost) 668 | if err != nil { 669 | log.Error(err) 670 | return UnmanagedWallet{}, err 671 | } 672 | var unmanagedWallet UnmanagedWallet 673 | err = json.Unmarshal([]byte(returnedData), &unmanagedWallet) 674 | if err != nil { 675 | log.Error(err) 676 | return UnmanagedWallet{}, err 677 | } 678 | 679 | return unmanagedWallet, nil 680 | } 681 | 682 | // CreateInternalWalletAsset 683 | 684 | func (s *SDK) CreateInternalWalletAsset(walletId string, assetId string, address string, tag string, idempotencyKey string) (WalletAsset, error) { 685 | 686 | cmd := fmt.Sprintf("/v1/internal_wallets/%s/%s", walletId, assetId) 687 | payload := map[string]interface{}{ 688 | "address": address, 689 | } 690 | if len(tag) > 0 { 691 | payload["tag"] = tag 692 | } 693 | marshalled, err := json.Marshal(payload) 694 | if err != nil { 695 | return WalletAsset{}, err 696 | } 697 | 698 | returnedData, err := s.changeRequest(cmd, marshalled, idempotencyKey, http.MethodPost) 699 | if err != nil { 700 | log.Error(err) 701 | return WalletAsset{}, err 702 | } 703 | var walletAsset WalletAsset 704 | err = json.Unmarshal([]byte(returnedData), &walletAsset) 705 | if err != nil { 706 | log.Error(err) 707 | return WalletAsset{}, err 708 | } 709 | 710 | return walletAsset, nil 711 | 712 | } 713 | 714 | //GetEstimateTxFee 715 | // Get the estimate fee for a tx. 716 | func (s *SDK) GetEstimateTxFee(assetId string, amount string, source TransferPeerPath, destination DestinationTransferPeerPath, operation string) (EstimatedTransactionFeeResponse, error) { 717 | 718 | payload := map[string]interface{}{ 719 | "assetId": assetId, 720 | "amount": amount, 721 | "source": source, 722 | "destination": destination, 723 | "operation": operation, 724 | } 725 | 726 | marshalled, err := json.Marshal(payload) 727 | if err != nil { 728 | return EstimatedTransactionFeeResponse{}, err 729 | } 730 | 731 | returnedData, err := s.changeRequest("/v1/transactions/estimate_fee", marshalled, "", http.MethodPost) 732 | if err != nil { 733 | log.Error(err) 734 | return EstimatedTransactionFeeResponse{}, err 735 | } 736 | 737 | if strings.Contains(returnedData, "message") { 738 | // {"message":"The asset is not supported by Fireblocks, please check the supported assets endpoint.","code":1025} 739 | errMsg := fmt.Sprintf("Request failed: %s", returnedData) 740 | return EstimatedTransactionFeeResponse{}, errors.New(errMsg) 741 | } 742 | 743 | var estimatedTxFee EstimatedTransactionFeeResponse 744 | err = json.Unmarshal([]byte(returnedData), &estimatedTxFee) 745 | if err != nil { 746 | log.Error(err) 747 | return EstimatedTransactionFeeResponse{}, err 748 | } 749 | 750 | return estimatedTxFee, nil 751 | 752 | } 753 | 754 | // CreateTransaction - 755 | func (s *SDK) CreateTransaction(assetId string, amount decimal.Decimal, source TransferPeerPath, 756 | destination DestinationTransferPeerPath, fee decimal.Decimal, gasPrice decimal.Decimal, waitForStatus bool, 757 | txType TransactionType, note string, cpuStaking string, networkStaking string, 758 | autoStaking string, customerRefId string, extraParams ExtraParameters, destinations []DestinationTransferPeerPath, 759 | feeLevel FeeLevel, failOnFee bool, maxFee string, gasLimit decimal.Decimal, replaceTxByHash string, idempotencyKey string, 760 | 761 | ) (CreateTransactionResponse, error) { 762 | 763 | payload := CreateTransactionPayload{ 764 | AssetId: assetId, 765 | Source: source, 766 | Destination: destination, 767 | Amount: amount.String(), 768 | TreatAsGrossAmount: false, 769 | FailOnLowFee: false, 770 | Operation: string(txType), 771 | WaitForStatus: waitForStatus, 772 | } 773 | 774 | if fee.IsPositive() { 775 | payload.Fee = fee.String() 776 | } 777 | 778 | if len(feeLevel) > 0 { 779 | payload.FeeLevel = string(feeLevel) 780 | } 781 | 782 | if len(note) > 0 { 783 | payload.Note = note 784 | } 785 | 786 | if len(maxFee) > 0 { 787 | payload.MaxFee = maxFee 788 | } 789 | 790 | if gasPrice.IsPositive() { 791 | payload.GasPrice = gasPrice.String() 792 | } 793 | 794 | if gasLimit.IsPositive() { 795 | payload.GasLimit = gasLimit.String() 796 | } 797 | 798 | if len(cpuStaking) > 0 { 799 | payload.CpuStaking = cpuStaking 800 | } 801 | 802 | if len(networkStaking) > 0 { 803 | payload.NetworkStaking = networkStaking 804 | } 805 | 806 | if len(autoStaking) > 0 { 807 | payload.AutoStaking = autoStaking 808 | } 809 | if len(customerRefId) > 0 { 810 | payload.CustomerRefId = customerRefId 811 | } 812 | 813 | if len(replaceTxByHash) > 0 { 814 | payload.ReplacedTxHash = replaceTxByHash 815 | } 816 | 817 | if extraParams != (ExtraParameters{}) { 818 | payload.ExtraParameters = extraParams 819 | } 820 | 821 | if len(destinations) > 0 { 822 | payload.Destinations = destinations 823 | } 824 | 825 | return s.CreateTransactionWithPayload(payload, idempotencyKey) 826 | } 827 | 828 | func (s *SDK) CreateTransactionWithPayload(payload CreateTransactionPayload, idempotencyKey string) (CreateTransactionResponse, error) { 829 | 830 | marshalled, err := json.Marshal(payload) 831 | if err != nil { 832 | return CreateTransactionResponse{}, err 833 | } 834 | returnedData, err := s.changeRequest("/v1/transactions", marshalled, idempotencyKey, http.MethodPost) 835 | 836 | if err != nil { 837 | log.Error(err) 838 | } 839 | 840 | var transactionResponse CreateTransactionResponse 841 | err = json.Unmarshal([]byte(returnedData), &transactionResponse) 842 | if err != nil { 843 | log.Error(err) 844 | return CreateTransactionResponse{}, errors.New(returnedData) 845 | } 846 | 847 | return transactionResponse, err 848 | } 849 | 850 | func (s *SDK) GetVaultAssetsBalance(accountNamePrefix string, accountNameSuffix string) (string, error) { 851 | 852 | params := url.Values{} 853 | if len(accountNamePrefix) > 0 { 854 | params.Add("accountNamePrefix", accountNamePrefix) 855 | } 856 | if len(accountNameSuffix) > 0 { 857 | params.Add("accountNameSuffix", accountNameSuffix) 858 | } 859 | uri := "/v1/vault/assets" 860 | if len(params) > 0 { 861 | query := fmt.Sprintf(uri+"?%s", params.Encode()) 862 | return s.getRequest(query) 863 | } else { 864 | return s.getRequest(uri) 865 | } 866 | } 867 | 868 | func (s *SDK) GetVaultBalanceByAsset(assetId string) (string, error) { 869 | 870 | query := fmt.Sprintf("/v1/vault/assets/%s", assetId) 871 | return s.getRequest(query) 872 | } 873 | 874 | // ValidateAddress - validates the address of a given asset. 875 | // assetId - the id of the asset to validate the address 876 | // address - the address to validate 877 | func (s *SDK) ValidateAddress(assetId string, address string) (AddressStatus, error) { 878 | 879 | query := fmt.Sprintf("/v1/transactions/validate_address/%s/%s", assetId, address) 880 | 881 | returnedData, err := s.getRequest(query) 882 | if err != nil { 883 | log.Error(err) 884 | return AddressStatus{}, err 885 | } 886 | var addressStatus AddressStatus 887 | err = json.Unmarshal([]byte(returnedData), &addressStatus) 888 | if err != nil { 889 | log.Error(err) 890 | return AddressStatus{}, err 891 | } 892 | 893 | return addressStatus, nil 894 | } 895 | 896 | // GetTransactionById - get the transaction details 897 | // txId - transaction id 898 | func (s *SDK) GetTransactionById(txId string) (TransactionDetails, error) { 899 | 900 | query := fmt.Sprintf("/v1/transactions/%s", txId) 901 | returnedData, err := s.getRequest(query) 902 | if err != nil { 903 | log.Error(err) 904 | return TransactionDetails{}, err 905 | } 906 | var transactionDetails TransactionDetails 907 | err = json.Unmarshal([]byte(returnedData), &transactionDetails) 908 | if err != nil { 909 | log.Error(err) 910 | return TransactionDetails{}, err 911 | } 912 | 913 | return transactionDetails, nil 914 | 915 | } 916 | 917 | func (s *SDK) GetExternalWallets() ([]ExternalWallet, error) { 918 | 919 | returnedData, err := s.getRequest("/v1/external_wallets") 920 | if err != nil { 921 | log.Error(err) 922 | return nil, err 923 | } 924 | 925 | var extWallets []ExternalWallet 926 | err = json.Unmarshal([]byte(returnedData), &extWallets) 927 | if err != nil { 928 | log.Error(err) 929 | return nil, err 930 | } 931 | 932 | return extWallets, nil 933 | 934 | } 935 | 936 | func (s *SDK) GetExternalWallet(externalWalletId string) (ExternalWallet, error) { 937 | 938 | query := fmt.Sprintf("/v1/external_wallets/%s", externalWalletId) 939 | 940 | returnedData, err := s.getRequest(query) 941 | if err != nil { 942 | log.Error(err) 943 | return ExternalWallet{}, err 944 | } 945 | 946 | extWallet, err2 := getExtWallet(returnedData) 947 | if err2 != nil { 948 | return ExternalWallet{}, err2 949 | } 950 | 951 | return extWallet, nil 952 | 953 | } 954 | 955 | func getExtWallet(returnedData string) (ExternalWallet, error) { 956 | var extWallet ExternalWallet 957 | err := json.Unmarshal([]byte(returnedData), &extWallet) 958 | if err != nil { 959 | log.Error(err) 960 | return ExternalWallet{}, err 961 | } 962 | return extWallet, nil 963 | } 964 | -------------------------------------------------------------------------------- /fireblocks_domain.go: -------------------------------------------------------------------------------- 1 | package fireblocks 2 | 3 | import ( 4 | "github.com/shopspring/decimal" 5 | ) 6 | 7 | type CreateTransactionPayload struct { 8 | AssetId string `json:"assetId"` 9 | Source TransferPeerPath `json:"source"` // source of the transaction 10 | Destination DestinationTransferPeerPath `json:"destination"` // Destination of the transaction 11 | Destinations []DestinationTransferPeerPath `json:"destinations,omitempty"` // Destination of the transaction 12 | Amount string `json:"amount"` // If the transfer is a withdrawal from an exchange, the actual amount that was requested to be transferred. Otherwise, the requested amount 13 | Fee string `json:"fee,omitempty"` // The total fee deducted by the exchange from the actual requested amount (serviceFee = amount - netAmount) 14 | TreatAsGrossAmount bool `json:"treatAsGrossAmount,omitempty"` // For outgoing transactions, if true, the network fee is deducted from the requested amount 15 | FailOnLowFee bool `json:"failOnLowFee,omitempty"` 16 | NetworkFee string `json:"networkFee,omitempty"` //The fee paid to the network 17 | PriorityFee string `json:"priorityFee,omitempty"` 18 | FeeLevel string `json:"feeLevel,omitempty"` 19 | MaxFee string `json:"maxFee,omitempty"` 20 | Note string `json:"note,omitempty"` // Customer note of the transaction 21 | Operation string `json:"operation"` // Default operation is "TRANSFER" 22 | CustomerRefId string `json:"customerRefId,omitempty"` // The ID for AML providers to associate the owner of funds with transactions 23 | ReplacedTxHash string `json:"replacedTxHash,omitempty"` // 24 | ExtraParameters ExtraParameters `json:"extraParameters,omitempty"` // Protocol / operation specific parameters. 25 | ExternalTxId string `json:"externalTxId,omitempty"` 26 | WaitForStatus bool `json:"waitForStatus,omitempty"` 27 | GasPrice string `json:"gasPrice,omitempty"` 28 | GasLimit string `json:"gasLimit,omitempty"` 29 | CpuStaking string `json:"cpuStaking,omitempty"` 30 | NetworkStaking string `json:"networkStaking,omitempty"` 31 | AutoStaking string `json:"autoStaking,omitempty"` 32 | } 33 | 34 | type ExternalWalletAsset struct { 35 | Id string `json:"id"` // the id of the asset 36 | Status ConfigChangeRequestStatus `json:"status"` // Status of the External Wallet 37 | ActivationTime string `json:"activationTime"` // The time the wallet will be activated in case wallets activation posponed according to workspace definition 38 | Address string `json:"address"` // The address of the wallet 39 | Tag string `json:"tag"` // Destination tag (for XRP, used as memo for EOS/XLM) of the wallet, for SEN/Signet used as Bank Transfer Description 40 | 41 | } 42 | 43 | type ExternalWallet struct { 44 | Id string `json:"id"` //The ID of the Unmanaged Wallet 45 | Name string `json:"name"` // Name of the Wallet Container 46 | CustomerRefId string `json:"customerRefId,omitempty"` //[optional] The ID for AML providers to associate the owner of funds with transactions 47 | Assets []ExternalWalletAsset `json:"assets"` //Array of the assets available in the exteral wallet 48 | } 49 | 50 | type UnmanagedWallet struct { 51 | Id string 52 | Name string 53 | CustomerRefId string 54 | Assets []WalletAsset 55 | } 56 | 57 | type WalletAsset struct { 58 | Id string `json:"id"` // the id of the asset 59 | Balance string `json:"balance"` // the balance of the wallet 60 | LockedAmount string `json:"lockedAmount"` // locked amount in the wallet 61 | Status ConfigChangeRequestStatus `json:"status"` // Status of the External Wallet 62 | ActivationTime string `json:"activationTime"` // The time the wallet will be activated in case wallets activation posponed according to workspace definition 63 | Address string `json:"address"` // The address of the wallet 64 | Tag string `json:"tag"` // Destination tag (for XRP, used as memo for EOS/XLM) of the wallet, for SEN/Signet used as Bank Transfer Description 65 | 66 | } 67 | 68 | type User struct { 69 | Id string `json:"id"` // User ID on the Fireblocks platform 70 | FirstName string `json:"firstName"` // First name 71 | LastName string `json:"lastName"` // Last name 72 | Role string `json:"role"` // The role of the user in the workspace 73 | Email string `json:"email"` // The email of the user 74 | Enabled bool `json:"enabled"` //The status of the user in the workspace 75 | } 76 | 77 | type ConfigChangeRequestStatus string 78 | 79 | const ( 80 | WaitingForApproval ConfigChangeRequestStatus = "WAITING_FOR_APPROVAL" 81 | Approved = "APPROVED" 82 | Cancelled = "CANCELLED" 83 | Rejected = "REJECTED" 84 | Failed = "FAILED" 85 | ) 86 | 87 | type CreateAddressResponse struct { 88 | Address string `json:"address"` //Address of the asset in a Vault Account, for BTC/LTC the address is in Segwit (Bech32) format, cash address format for BCH 89 | LegacyAddress string `json:"legacyAddress"` // Legacy address format for BTC/LTC/BCH 90 | Tag string `json:"tag"` // Destination tag for XRP, used as memo for EOS/XLM 91 | } 92 | 93 | type ExtraParameters struct { 94 | ContractCallData string `json:"contractCallData"` 95 | } 96 | 97 | type ErrorMessage struct { 98 | Code int `json:"code"` 99 | Message string `json:"message"` 100 | } 101 | 102 | type TransactionStatus string 103 | 104 | const ( 105 | TransactionStatusSubmitted TransactionStatus = "SUBMITTED" 106 | TransactionStatusQueued = "QUEUED" 107 | TransactionPendingSignature = "PENDING_SIGNATURE" 108 | TransactionPendingAuthorization = "PENDING_AUTHORIZATION" 109 | TransactionPending3rdPartyManualApproval = "PENDING_3RD_PARTY_MANUAL_APPROVAL" 110 | TransactionPending3rdParty = "PENDING_3RD_PARTY" 111 | TransactionPending = "PENDING" // Deprecated 112 | TransactionBroadcasting = "BROADCASTING" 113 | TransactionConfirming = "CONFIRMING" 114 | TransactionConfirmed = "CONFIRMED" // Deprecated 115 | TransactionCompleted = "COMPLETED" 116 | TransactionPendingAmlCheckup = "PENDING_AML_CHECKUP" 117 | TransactionPartiallyCompleted = "PARTIALLY_COMPLETED" 118 | TransactionCancelling = "CANCELLING" 119 | TransactionCancelled = "CANCELLED" 120 | TransactionRejected = "REJECTED" 121 | TransactionFailed = "FAILED" 122 | TransactionTimeout = "TIMEOUT" 123 | TransactionBlocked = "BLOCKED" 124 | ) 125 | 126 | type TransactionSubStatus string 127 | 128 | const ( 129 | InsufficientFunds TransactionSubStatus = "INSUFFICIENT_FUNDS" 130 | AmountTooSmall = "AMOUNT_TOO_SMALL" 131 | UnsupportedAsset = "UNSUPPORTED_ASSET" 132 | UnauthorisedMissingPermission = "UNAUTHORISED__MISSING_PERMISSION" 133 | InvalidSignature = "INVALID_SIGNATURE" 134 | ApiInvalidSignature = "API_INVALID_SIGNATURE" 135 | UnauthorisedMissingCredentials = "UNAUTHORISED__MISSING_CREDENTIALS" 136 | UnauthorisedUser = "UNAUTHORISED__USER" 137 | UnauthorisedDevice = "UNAUTHORISED__DEVICE" 138 | InvalidUnmanagedWallet = "INVALID_UNMANAGED_WALLET" 139 | InvalidExchangeAccount = "INVALID_EXCHANGE_ACCOUNT" 140 | InsufficientFundsForFee = "INSUFFICIENT_FUNDS_FOR_FEE" 141 | InvalidAddress = "INVALID_ADDRESS" 142 | WithdrawLimit = "WITHDRAW_LIMIT" 143 | ApiCallLimit = "API_CALL_LIMIT" 144 | AddressNotWhitelisted = "ADDRESS_NOT_WHITELISTED" 145 | TIMEOUT = "TIMEOUT" 146 | ConnectivityError = "CONNECTIVITY_ERROR" 147 | ThirdPartyInternalError = "THIRD_PARTY_INTERNAL_ERROR" 148 | CancelledExternally = "CANCELLED_EXTERNALLY" 149 | InvalidThirdPartyResponse = "INVALID_THIRD_PARTY_RESPONSE" 150 | VaultWalletNotReady = "VAULT_WALLET_NOT_READY" 151 | MissingDepositAddress = "MISSING_DEPOSIT_ADDRESS" 152 | OneTimeAddressDisabled = "ONE_TIME_ADDRESS_DISABLED" 153 | InternalError = "INTERNAL_ERROR" 154 | UnknownError = "UNKNOWN_ERROR" 155 | AuthorizerNotFound = "AUTHORIZER_NOT_FOUND" 156 | InsufficientReservedFunding = "INSUFFICIENT_RESERVED_FUNDING" 157 | ManualDepositAddressRequired = "MANUAL_DEPOSIT_ADDRESS_REQUIRED" 158 | InvalidFee = "INVALID_FEE" 159 | ErrorUnsupportedTransactionType = "ERROR_UNSUPPORTED_TRANSACTION_TYPE" 160 | UnsupportedOperation = "UNSUPPORTED_OPERATION" 161 | T3rdPartyProcessing = "3RD_PARTY_PROCESSING" 162 | PendingBlockchainConfirmations = "PENDING_BLOCKCHAIN_CONFIRMATIONS" 163 | T3rdPartyConfirming = "3RD_PARTY_CONFIRMING" 164 | CONFIRMED = "CONFIRMED" 165 | T3rdPartyCompleted = "3RD_PARTY_COMPLETED" 166 | RejectedByUser = "REJECTED_BY_USER" 167 | CancelledByUser = "CANCELLED_BY_USER" 168 | T3rdPartyCancelled = "3RD_PARTY_CANCELLED" 169 | T3rdPartyRejected = "3RD_PARTY_REJECTED" 170 | AmlScreeningRejected = "AML_SCREENING_REJECTED" 171 | BlockedByPolicy = "BLOCKED_BY_POLICY" 172 | FailedAmlScreening = "FAILED_AML_SCREENING" 173 | PartiallyFailed = "PARTIALLY_FAILED" 174 | T3rdPartyFailed = "3RD_PARTY_FAILED" 175 | DroppedByBlockchain = "DROPPED_BY_BLOCKCHAIN" 176 | TooManyInputs = "TOO_MANY_INPUTS" 177 | SigningError = "SIGNING_ERROR" 178 | InvalidFeeParams = "INVALID_FEE_PARAMS" 179 | MissingTagOrMemo = "MISSING_TAG_OR_MEMO" 180 | GasLimitTooLow = "GAS_LIMIT_TOO_LOW" 181 | MaxFeeExceeded = "MAX_FEE_EXCEEDED" 182 | ActualFeeTooHigh = "ACTUAL_FEE_TOO_HIGH" 183 | InvalidContractCallData = "INVALID_CONTRACT_CALL_DATA" 184 | InvalidNonceTooLow = "INVALID_NONCE_TOO_LOW" 185 | InvalidNonceTooHigh = "INVALID_NONCE_TOO_HIGH" 186 | InvalidNonceForRbf = "INVALID_NONCE_FOR_RBF" 187 | FailOnLowFee = "FAIL_ON_LOW_FEE" 188 | TooLongMempoolChain = "TOO_LONG_MEMPOOL_CHAIN" 189 | TxOutdated = "TX_OUTDATED" 190 | IncompleteUserSetup = "INCOMPLETE_USER_SETUP" 191 | SignerNotFound = "SIGNER_NOT_FOUND" 192 | InvalidTagOrMemo = "INVALID_TAG_OR_MEMO" 193 | ZeroBalanceInPermanentAddress = "ZERO_BALANCE_IN_PERMANENT_ADDRESS" 194 | NeedMoreToCreateDestination = "NEED_MORE_TO_CREATE_DESTINATION" 195 | NonExistingAccountName = "NON_EXISTING_ACCOUNT_NAME" 196 | EnvUnsupportedAsset = "ENV_UNSUPPORTED_ASSET" 197 | ) 198 | 199 | type TransactionDetails struct { 200 | Id string `json:"id"` // ID of the transaction 201 | AssetId string `json:"AssetId"` 202 | Source TransferPeerPathResponse `json:"source"` // source of the transaction 203 | Destination TransferPeerPathResponse `json:"destination"` // Destination of the transaction 204 | RequestedAmount decimal.Decimal `json:"RequestedAmount"` // the amount requested by the user 205 | AmountInfo AmountInfo `json:"amountInfo"` // Details of the transaction's amount in string format 206 | FeeInfo FeeInfo `json:"feeInfo"` // Details of the transaction's fee in string format 207 | Amount decimal.Decimal `json:"amount"` // If the transfer is a withdrawal from an exchange, the actual amount that was requested to be transferred. Otherwise, the requested amount 208 | NetAmount decimal.Decimal `json:"netAmount"` // The net amount of the transaction, after fee deduction 209 | AmountUSD decimal.Decimal `json:"amountUSD"` // The USD value of the requested amount 210 | ServiceFee decimal.Decimal `json:"ServiceFee"` // The total fee deducted by the exchange from the actual requested amount (serviceFee = amount - netAmount) 211 | TreatAsGrossAmount bool `json:"treatAsGrossAmount"` // For outgoing transactions, if true, the network fee is deducted from the requested amount 212 | NetworkFee decimal.Decimal `json:"networkFee"` //The fee paid to the network 213 | CreatedAt int64 `json:"createdAt"` // Unix timestamp 214 | LastUpdated int64 `json:"lastUpdated"` // Unix timestamp 215 | Status TransactionStatus `json:"status"` // The current status of the transaction 216 | TxHash string `json:"txHash"` // Blockchain hash of the transaction 217 | SubStatus TransactionSubStatus `json:"subStatus"` // More detailed status of the transaction 218 | SourceAddress string `json:"sourceAddress"` // For account based assets only, the source address of the transaction 219 | DestinationAddress string `json:"destinationAddress"` // Address where the asset were transfered 220 | DestinationAddressDescription string `json:"destinationAddressDescription"` // Description of the address 221 | DestinationTag string `json:"destinationTag"` // Destination tag (for XRP, used as memo for EOS/XLM) or Bank Transfer Description for Signet/SEN 222 | SignedBy []string `json:"signedBy"` //Signers of the transaction 223 | CreatedBy string `json:"createdBy"` // Initiator of the transaction 224 | RejectedBy string `json:"rejectedBy"` // User ID of the user that rejected the transaction (in case it was rejected) 225 | AddressType string `json:"addressType"` // [ ONE_TIME, WHITELISTED ] 226 | Note string `json:"note"` // Customer note of the transaction 227 | ExchangeTxId string `json:"exchangeTxId"` // If the transaction originated from an exchange, this is the exchange tx ID 228 | FeeCurrency string `json:"feeCurrency"` // The asset which was taken to pay the fee (ETH for ERC-20 tokens, BTC for Tether Omni) 229 | Operation string `json:"operation"` // Default operation is "TRANSFER" 230 | AmlScreeningResult AmlScreeningResult `json:"amlScreeningResult"` // The result of the AML screening 231 | CustomerRefId string `json:"customerRefId"` // The ID for AML providers to associate the owner of funds with transactions 232 | NumberOfConfirmations int `json:"numberOfConfirmations"` // The number of confirmations of the transaction. The number will increase until the transaction will be considered completed according to the confirmation policy. 233 | NetworkRecords []NetworkRecord `json:"networkRecords"` // Transaction on the Fireblocks platform can aggregate several blockchain transactions, in such a case these records specify all the transactions that took place on the blockchain. 234 | ReplacedTxHash string `json:"replacedTxHash"` // In case of an RBF transaction, the hash of the dropped transaction 235 | ExternalTxId string `json:"externalTxId"` // Unique transaction ID provided by the user 236 | Destinations []DestinationsResponse `json:"destinations"` // For UTXO based assets, all outputs specified here 237 | BlockInfo BlockInfo `json:"blockInfo"` //The information of the block that this transaction was mined in, the blocks's hash and height 238 | SignedMessages []SignedMessage `json:"signedMessages"` // A list of signed messages returned for raw signing 239 | ExtraParameters map[string]interface{} `json:"extraParameters"` // Protocol / operation specific parameters. 240 | 241 | } 242 | 243 | type BlockInfo struct { 244 | BlockHeight string `json:"blockHeight"` 245 | BlockHash string `json:"blockHash"` 246 | } 247 | 248 | type TransactionFee struct { 249 | FeePerByte string `json:"feePerByte"` // [optional] For UTXOs, 250 | GasPrice string `json:"gasPrice"` // [optional] For Ethereum assets (ETH and Tokens) 251 | GasLimit string ` json:"gasLimit"` // [optional] For Ethereum assets (ETH and Tokens), the limit for how much can be used 252 | NetworkFee string `json:"networkFee"` // [optional] Transaction fee 253 | } 254 | 255 | type EstimatedTransactionFeeResponse struct { 256 | Low TransactionFee `json:"low"` //Transactions with this fee will probably take longer to be mined 257 | Medium TransactionFee `json:"medium"` // Average transactions fee 258 | High TransactionFee `json:"high"` //Transactions with this fee should be mined the fastest 259 | 260 | } 261 | 262 | type AddressStatus struct { 263 | IsValid bool `json:"isValid"` 264 | IsActive bool `json:"isActive"` 265 | RequiresTag bool `json:"requiresTag"` 266 | } 267 | 268 | type SignedMessage struct { 269 | Content string `json:"content"` // The message for signing (hex-formatted) 270 | Algorithm string `json:"algorithm"` // The algorithm that was used for signing, one of the SigningAlgorithms 271 | DerivationPath string `json:"derivationPath"` // BIP32 derivation path of the signing key. E.g. [44,0,46,0,0] 272 | Signature map[string]interface{} `json:"signature"` // The message signature 273 | PublicKey string `json:"publicKey"` // Signature's public key that can be used for verification. 274 | } 275 | 276 | type DestinationsResponse struct { 277 | Amount decimal.Decimal `json:"amount"` // The amount to be sent to this destination 278 | Destination TransferPeerPathResponse `json:"destination"` // Destination of the transaction 279 | AmountUSD decimal.Decimal `json:"amountUSD"` // The USD value of the requested amount 280 | DestinationAddress string `json:"destinationAddress"` // Address where the asset were transfered 281 | DestinationAddressDescription string `json:"destinationAddressDescription"` // Description of the address 282 | AmlScreeningResult AmlScreeningResult `json:"amlScreeningResult"` // The result of the AML screening 283 | CustomerRefId string `json:"customerRefId"` // The ID for AML providers to associate the owner of funds with transactions 284 | 285 | } 286 | 287 | type NetworkRecord struct { 288 | Source TransferPeerPathResponse `json:"source"` // Source of the transaction 289 | Destination TransferPeerPathResponse `json:"destination"` // Destination of the transaction 290 | TxHash string `json:"txHash"` // Blockchain hash of the transaction 291 | NetworkFee decimal.Decimal `json:"networkFee"` // The fee paid to the network 292 | AssetId string `json:"assetId"` // transaction asset 293 | NetAmount decimal.Decimal `json:"netAmount"` // The net amount of the transaction, after fee deduction 294 | Status NetworkStatus `json:"status"` // Status of the blockchain transaction 295 | OpType string `json:"type"` // Type of the operation 296 | DestinationAddress string `json:"destinationAddress"` // Destination address 297 | SourceAddress string `json:"sourceAddress"` // For account based assets only, the source address of the transaction 298 | 299 | } 300 | 301 | type NetworkStatus string 302 | 303 | const ( 304 | DROPPED NetworkStatus = "DROPPED" 305 | BROADCASTING = "BROADCASTING" 306 | CONFIRMING = "CONFIRMING" 307 | FAILED = "FAILED" 308 | NsConfirmed = "CONFIRMED" 309 | ) 310 | 311 | type AmlScreeningResult struct { 312 | Provider string `json:"provider"` // The AML service provider 313 | Payload string `json:"payload"` // The response of the AML service provider 314 | } 315 | 316 | type AmountInfo struct { 317 | Amount string `json:"amount"` // If the transfer is a withdrawal from an exchange, the actual amount that was requested to be transferred. Otherwise, the requested amount 318 | RequestedAmount string `json:"requestedAmount"` //The amount requested by the user 319 | NetAmount string `json:"NetAmount"` // The net amount of the transaction, after fee deduction 320 | AmountUSD string `json:"amountUSD"` // The USD value of the requested amount 321 | } 322 | 323 | type FeeInfo struct { 324 | NetworkFee string `json:"NetworkFee"` // The fee paid to the network 325 | ServiceFee string `json:"ServiceFee"` // The total fee deducted by the exchange from the actual requested amount (serviceFee = amount - netAmount) 326 | } 327 | 328 | type CreateTransactionResponse struct { 329 | Id string `json:"Id"` 330 | Status TransactionStatus `json:"status"` 331 | Error error 332 | } 333 | 334 | type CreateVaultAssetResponse struct { 335 | Id string `json:"Id"` // the Id of the asset 336 | Address string `json:"address"` // Address of the asset in a Vault Account, for BTC/LTC the address is in segwit (Bech32) format, cash address format BCH 337 | LegacyAddress string `json:"legacyAddress"` // legacy address format for BTC/LTC/BCH 338 | Tag string `json:"tag"` // destination tag for XRP, memo for EOS/XLM 339 | EosAccountName string `json:"eosAccountName"` // returned for EOS, the acct name. 340 | } 341 | 342 | type AssetTypeResponse struct { 343 | Id string `json:"Id"` 344 | Name string `json:"name"` 345 | AssetType string `json:"type"` 346 | ContractAddress string `json:"contractAddress"` 347 | NativeAsset string `json:"nativeAsset"` 348 | } 349 | 350 | type VaultAccountAssetAddress struct { 351 | AssetId string `json:"assetId"` // The ID of the asset 352 | Address string `json:"address"` // Address of the asset in a Vault Account, for BTC/LTC the address is in Segwit (Bech32) format, for BCH cash format 353 | LegacyAddress string `json:"legacyAddress"` // For BTC/LTC/BCH the legacy format address 354 | Description string `json:"description"` // Description of the address 355 | Tag string `json:"tag"` // Destination tag for XRP, used as memo for EOS/XLM, for Signet/SEN it is the Bank Transfer Description 356 | Type string `json:"type"` // Address type 357 | CustomerRefId string `json:" customerRefId"` // [optional] The ID for AML providers to associate the owner of funds with transactions 358 | AddressFormat string `json:"addressFormat"` 359 | EnterpriseAddress string `json:"enterpriseAddress"` 360 | } 361 | 362 | type UnsignedMessage struct { 363 | Content string `json:"content"` //message to be signed - hex format. 364 | Bip44AddressIndex int `json:"bip44AddressIndex"` // 365 | Bib44Change int `json:"bib44Change"` //bit44 change path level 366 | DerivationPath []int `json:"derivationPath"` 367 | } 368 | 369 | type RawMessage struct { 370 | messages []UnsignedMessage 371 | algorithm SigningAlgorithm 372 | } 373 | 374 | type OneTimeAddress struct { 375 | Address string `json:"address"` 376 | Tag string `json:"tag"` 377 | } 378 | 379 | type TransferPeerPathResponse struct { 380 | TransferType string `json:"type"` //[ PTVaultAccount, EXCHANGE_ACCOUNT, INTERNAL_WALLET, EXTERNAL_WALLET, ONE_TIME_ADDRESS, NETWORK_CONNECTION, FIAT_ACCOUNT, COMPOUND ] 381 | Id string `json:"id"` // The ID of the exchange account to return 382 | Name string `json:"name"` // The name of the exchange account 383 | Subtype string `json:"subType"` 384 | } 385 | 386 | type TransferPeerPath struct { 387 | TPeerId string `json:"id"` 388 | TPeerType PeerType `json:"type"` 389 | } 390 | 391 | type DestinationTransferPeerPath struct { 392 | TPeerId string `json:"id"` 393 | TPeerType PeerType `json:"type"` 394 | Ota OneTimeAddress `json:"oneTimeAddress"` 395 | } 396 | 397 | type VaultAccount struct { 398 | Id string `json:"id"` 399 | Name string `json:"name"` 400 | HiddenOnUI bool `json:"hiddenOnUI"` 401 | CustomerRefId string `json:"customerRefId"` 402 | AutoFuel bool `json:"autoFuel"` 403 | Assets []VaultAsset `json:"assets"` 404 | } 405 | 406 | type VaultAsset struct { 407 | Id string `json:"id"` 408 | Total string `json:"total"` 409 | Available string `json:"available"` 410 | Pending string `json:"pending"` 411 | LockedAmount string `json:"lockedAmount"` 412 | TotalStackedCPU string `json:"totalStackedCPU"` 413 | TotalStackedNetwork string `json:"totalStackedNetwork"` 414 | SelfStackedCPU string `json:"selfStackedCPU"` 415 | SelfStakedNetwork string `json:"selfStakedNetwork"` 416 | PendingRefundCPU string `json:"pendingRefundCPU"` 417 | PendingRefundNetwork string `json:"pendingRefundNetwork"` 418 | } 419 | 420 | type ExchangeAccount struct { 421 | Id string `json:"id"` 422 | Type ExchangeType `json:"type"` 423 | Name string `json:"name"` 424 | Status ConfigChangeRequestStatus `json:"status"` 425 | Assets []ExchangeAsset `json:"assets"` 426 | IsSubAccount bool `json:"isSubaccount"` 427 | MainAccountId string `json:"mainAccountId"` 428 | } 429 | 430 | type TradingAccount struct { 431 | Type TradingAccountType `json:"type"` 432 | Assets []ExchangeAsset `json:"assets"` 433 | } 434 | 435 | type ExchangeAsset struct { 436 | Id string `json:"id"` 437 | Total string `json:"total"` 438 | Available string `json:"available"` 439 | LockedAmount string `json:"lockedAmount"` 440 | Balance string `json:"balance"` 441 | } 442 | 443 | type ExchangeType struct { 444 | Type string `json:"type"` 445 | } 446 | 447 | type TradingAccountType ExchangeType 448 | 449 | type AssetAddedData struct { 450 | AccountId string `json:"accountId"` // The ID of the vault account under which the wallet was added 451 | TenantId string `json:"tenantId"` // Unique id of your Fireblocks' workspace 452 | AccountName string `json:"accountName"` // The name of the vault account under which the wallet was added 453 | AssetId string `json:"assetId"` // Wallet's asset 454 | } 455 | 456 | type WalletAssetWebhook struct { 457 | AssetId string `json:"assetId"` // Wallet's asset 458 | Id string `json:"id"` // The ID of the wallet 459 | Name string `json:"name"` // The name of wallet 460 | Address string `json:"address"` // The address of the wallet 461 | Tag string `json:"tag"` //Destination tag (for XRP, used as memo for EOS/XLM and as Bank Transfer Description for Signet/SEN) of the wallet 462 | ActivationTime string `json:"activationTime"` // The time the wallet will be activated in case wallets activation posponed according to workspace definition 463 | 464 | } 465 | 466 | type ThirdPartyWebhook struct { 467 | Id string `json:"id"` // Id of the thirdparty account on the Fireblocks platform 468 | SubType string `json:"subType"` // Subtype of the third party, ie. exchange or fiat name 469 | Name string `json:"name"` // Account name 470 | } 471 | 472 | type ObjectAdded struct { 473 | Type string `json:"type"` 474 | TenantId string `json:"tenantId"` 475 | Timestamp int64 `json:"timestamp"` 476 | Data interface{} `json:"data"` 477 | } 478 | 479 | type ExternalWalletAssetAdded ObjectAdded 480 | type ExchangeAccountAdded ObjectAdded 481 | type FiatAccountAdded ObjectAdded 482 | type NetworkConnectionAdded ObjectAdded 483 | 484 | type PeerType string 485 | 486 | const ( 487 | PTVaultAccount PeerType = "VAULT_ACCOUNT" 488 | PTExchangeAccount = "EXCHANGE_ACCOUNT" 489 | PTInternalWallet = "INTERNAL_WALLET" 490 | PTExternalWallet = "EXTERNAL_WALLET" 491 | PTUnknownPeer = "UNKNOWN" 492 | PTFiatAccount = "FIAT_ACCOUNT" 493 | PTNetworkConnection = "NETWORK_CONNECTION" 494 | PTCompound = "COMPOUND" 495 | ) 496 | 497 | type EventType string 498 | 499 | const ( 500 | EventTransactionCreated EventType = "TRANSACTION_CREATED" 501 | EventTransactionStatusUpdated = "TRANSACTION_STATUS_UPDATED" 502 | EventVaultAccountAdded = "VAULT_ACCOUNT_ADDED" 503 | EventVaultAccountAssetAdded = "VAULT_ACCOUNT_ASSET_ADDED" 504 | EventInternalWalletAssetAdded = "INTERNAL_WALLET_ASSET_ADDED" 505 | EventExternalWalletAssetAdded = "EXTERNAL_WALLET_ASSET_ADDED" 506 | EventExchangeAccountAdded = "EXCHANGE_ACCOUNT_ADDED" 507 | EventFiatAccountAdded = "FIAT_ACCOUNT_ADDED" 508 | EventNetworkConnectionAdded = "NETWORK_CONNECTION_ADDED" 509 | ) 510 | 511 | type SigningAlgorithm string 512 | 513 | const ( 514 | MpcEcdsaSecp256k1 SigningAlgorithm = "MPC_ECDSA_SECP256K1" 515 | MpcEddsaEd25519 = "MPC_EDDSA_ED25519" 516 | ) 517 | 518 | type FeeLevel string 519 | 520 | const ( 521 | HIGH FeeLevel = "HIGH" 522 | MEDIUM = "MEDIUM" 523 | LOW = "LOW" 524 | ) 525 | 526 | type TransactionType string 527 | 528 | const ( 529 | TxTransfer TransactionType = "TRANSFER" 530 | TxMint = "MINT" 531 | TxBurn = "BURN" 532 | TxSupplyToCompound = "SUPPLY_TO_COMPOUND" 533 | TxnRedeemFromCompound = "REDEEM_FROM_COMPOUND" 534 | TxRaw = "RAW" 535 | TxContractCall = "CONTRACT_CALL" 536 | TxOneTimeAddress = "ONE_TIME_ADDRESS" 537 | ) 538 | --------------------------------------------------------------------------------