You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
8.2 KiB

  1. package api
  2. import (
  3. "encoding/base64"
  4. "strconv"
  5. "time"
  6. ethCommon "github.com/ethereum/go-ethereum/common"
  7. "github.com/hermeznetwork/hermez-node/common"
  8. "github.com/hermeznetwork/hermez-node/db"
  9. "github.com/hermeznetwork/hermez-node/db/historydb"
  10. "github.com/iden3/go-iden3-crypto/babyjub"
  11. "github.com/iden3/go-merkletree"
  12. )
  13. type errorMsg struct {
  14. Message string
  15. }
  16. func bjjToString(bjj *babyjub.PublicKey) string {
  17. pkComp := [32]byte(bjj.Compress())
  18. sum := pkComp[0]
  19. for i := 1; i < len(pkComp); i++ {
  20. sum += pkComp[i]
  21. }
  22. bjjSum := append(pkComp[:], sum)
  23. return "hez:" + base64.RawURLEncoding.EncodeToString(bjjSum)
  24. }
  25. func ethAddrToHez(addr ethCommon.Address) string {
  26. return "hez:" + addr.String()
  27. }
  28. func idxToHez(idx common.Idx, tokenSymbol string) string {
  29. return "hez:" + tokenSymbol + ":" + strconv.Itoa(int(idx))
  30. }
  31. // History Tx
  32. type historyTxsAPI struct {
  33. Txs []historyTxAPI `json:"transactions"`
  34. Pagination *db.Pagination `json:"pagination"`
  35. }
  36. func (htx *historyTxsAPI) GetPagination() *db.Pagination {
  37. if htx.Txs[0].ItemID < htx.Txs[len(htx.Txs)-1].ItemID {
  38. htx.Pagination.FirstReturnedItem = htx.Txs[0].ItemID
  39. htx.Pagination.LastReturnedItem = htx.Txs[len(htx.Txs)-1].ItemID
  40. } else {
  41. htx.Pagination.LastReturnedItem = htx.Txs[0].ItemID
  42. htx.Pagination.FirstReturnedItem = htx.Txs[len(htx.Txs)-1].ItemID
  43. }
  44. return htx.Pagination
  45. }
  46. func (htx *historyTxsAPI) Len() int { return len(htx.Txs) }
  47. type l1Info struct {
  48. ToForgeL1TxsNum *int64 `json:"toForgeL1TransactionsNum"`
  49. UserOrigin bool `json:"userOrigin"`
  50. FromEthAddr string `json:"fromHezEthereumAddress"`
  51. FromBJJ string `json:"fromBJJ"`
  52. LoadAmount string `json:"loadAmount"`
  53. HistoricLoadAmountUSD *float64 `json:"historicLoadAmountUSD"`
  54. EthBlockNum int64 `json:"ethereumBlockNum"`
  55. }
  56. type l2Info struct {
  57. Fee common.FeeSelector `json:"fee"`
  58. HistoricFeeUSD *float64 `json:"historicFeeUSD"`
  59. Nonce common.Nonce `json:"nonce"`
  60. }
  61. type historyTxAPI struct {
  62. IsL1 string `json:"L1orL2"`
  63. TxID string `json:"id"`
  64. ItemID int `json:"itemId"`
  65. Type common.TxType `json:"type"`
  66. Position int `json:"position"`
  67. FromIdx *string `json:"fromAccountIndex"`
  68. ToIdx string `json:"toAccountIndex"`
  69. Amount string `json:"amount"`
  70. BatchNum *common.BatchNum `json:"batchNum"`
  71. HistoricUSD *float64 `json:"historicUSD"`
  72. Timestamp time.Time `json:"timestamp"`
  73. L1Info *l1Info `json:"L1Info"`
  74. L2Info *l2Info `json:"L2Info"`
  75. Token tokenAPI `json:"token"`
  76. }
  77. func historyTxsToAPI(dbTxs []historydb.HistoryTx) []historyTxAPI {
  78. apiTxs := []historyTxAPI{}
  79. for i := 0; i < len(dbTxs); i++ {
  80. apiTx := historyTxAPI{
  81. TxID: dbTxs[i].TxID.String(),
  82. ItemID: dbTxs[i].ItemID,
  83. Type: dbTxs[i].Type,
  84. Position: dbTxs[i].Position,
  85. ToIdx: idxToHez(dbTxs[i].ToIdx, dbTxs[i].TokenSymbol),
  86. Amount: dbTxs[i].Amount.String(),
  87. HistoricUSD: dbTxs[i].HistoricUSD,
  88. BatchNum: dbTxs[i].BatchNum,
  89. Timestamp: dbTxs[i].Timestamp,
  90. Token: tokenAPI{
  91. TokenID: dbTxs[i].TokenID,
  92. EthBlockNum: dbTxs[i].TokenEthBlockNum,
  93. EthAddr: dbTxs[i].TokenEthAddr,
  94. Name: dbTxs[i].TokenName,
  95. Symbol: dbTxs[i].TokenSymbol,
  96. Decimals: dbTxs[i].TokenDecimals,
  97. USD: dbTxs[i].TokenUSD,
  98. USDUpdate: dbTxs[i].TokenUSDUpdate,
  99. },
  100. L1Info: nil,
  101. L2Info: nil,
  102. }
  103. if dbTxs[i].FromIdx != nil {
  104. fromIdx := new(string)
  105. *fromIdx = idxToHez(*dbTxs[i].FromIdx, dbTxs[i].TokenSymbol)
  106. apiTx.FromIdx = fromIdx
  107. }
  108. if dbTxs[i].IsL1 {
  109. apiTx.IsL1 = "L1"
  110. apiTx.L1Info = &l1Info{
  111. ToForgeL1TxsNum: dbTxs[i].ToForgeL1TxsNum,
  112. UserOrigin: *dbTxs[i].UserOrigin,
  113. FromEthAddr: ethAddrToHez(*dbTxs[i].FromEthAddr),
  114. FromBJJ: bjjToString(dbTxs[i].FromBJJ),
  115. LoadAmount: dbTxs[i].LoadAmount.String(),
  116. HistoricLoadAmountUSD: dbTxs[i].HistoricLoadAmountUSD,
  117. EthBlockNum: dbTxs[i].EthBlockNum,
  118. }
  119. } else {
  120. apiTx.IsL1 = "L2"
  121. apiTx.L2Info = &l2Info{
  122. Fee: *dbTxs[i].Fee,
  123. HistoricFeeUSD: dbTxs[i].HistoricFeeUSD,
  124. Nonce: *dbTxs[i].Nonce,
  125. }
  126. }
  127. apiTxs = append(apiTxs, apiTx)
  128. }
  129. return apiTxs
  130. }
  131. // Exit
  132. type exitsAPI struct {
  133. Exits []exitAPI `json:"exits"`
  134. Pagination *db.Pagination `json:"pagination"`
  135. }
  136. func (e *exitsAPI) GetPagination() *db.Pagination {
  137. if e.Exits[0].ItemID < e.Exits[len(e.Exits)-1].ItemID {
  138. e.Pagination.FirstReturnedItem = e.Exits[0].ItemID
  139. e.Pagination.LastReturnedItem = e.Exits[len(e.Exits)-1].ItemID
  140. } else {
  141. e.Pagination.LastReturnedItem = e.Exits[0].ItemID
  142. e.Pagination.FirstReturnedItem = e.Exits[len(e.Exits)-1].ItemID
  143. }
  144. return e.Pagination
  145. }
  146. func (e *exitsAPI) Len() int { return len(e.Exits) }
  147. type exitAPI struct {
  148. ItemID int `json:"itemId"`
  149. BatchNum common.BatchNum `json:"batchNum"`
  150. AccountIdx string `json:"accountIndex"`
  151. MerkleProof *merkletree.CircomVerifierProof `json:"merkleProof"`
  152. Balance string `json:"balance"`
  153. InstantWithdrawn *int64 `json:"instantWithdrawn"`
  154. DelayedWithdrawRequest *int64 `json:"delayedWithdrawRequest"`
  155. DelayedWithdrawn *int64 `json:"delayedWithdrawn"`
  156. Token tokenAPI `json:"token"`
  157. }
  158. func historyExitsToAPI(dbExits []historydb.HistoryExit) []exitAPI {
  159. apiExits := []exitAPI{}
  160. for i := 0; i < len(dbExits); i++ {
  161. apiExits = append(apiExits, exitAPI{
  162. ItemID: dbExits[i].ItemID,
  163. BatchNum: dbExits[i].BatchNum,
  164. AccountIdx: idxToHez(dbExits[i].AccountIdx, dbExits[i].TokenSymbol),
  165. MerkleProof: dbExits[i].MerkleProof,
  166. Balance: dbExits[i].Balance.String(),
  167. InstantWithdrawn: dbExits[i].InstantWithdrawn,
  168. DelayedWithdrawRequest: dbExits[i].DelayedWithdrawRequest,
  169. DelayedWithdrawn: dbExits[i].DelayedWithdrawn,
  170. Token: tokenAPI{
  171. TokenID: dbExits[i].TokenID,
  172. EthBlockNum: dbExits[i].TokenEthBlockNum,
  173. EthAddr: dbExits[i].TokenEthAddr,
  174. Name: dbExits[i].TokenName,
  175. Symbol: dbExits[i].TokenSymbol,
  176. Decimals: dbExits[i].TokenDecimals,
  177. USD: dbExits[i].TokenUSD,
  178. USDUpdate: dbExits[i].TokenUSDUpdate,
  179. },
  180. })
  181. }
  182. return apiExits
  183. }
  184. // Tokens
  185. type tokensAPI struct {
  186. Tokens []tokenAPI `json:"tokens"`
  187. Pagination *db.Pagination `json:"pagination"`
  188. }
  189. func (t *tokensAPI) GetPagination() *db.Pagination {
  190. if t.Tokens[0].ItemID < t.Tokens[len(t.Tokens)-1].ItemID {
  191. t.Pagination.FirstReturnedItem = t.Tokens[0].ItemID
  192. t.Pagination.LastReturnedItem = t.Tokens[len(t.Tokens)-1].ItemID
  193. } else {
  194. t.Pagination.LastReturnedItem = t.Tokens[0].ItemID
  195. t.Pagination.FirstReturnedItem = t.Tokens[len(t.Tokens)-1].ItemID
  196. }
  197. return t.Pagination
  198. }
  199. func (t *tokensAPI) Len() int { return len(t.Tokens) }
  200. type tokenAPI struct {
  201. ItemID int `json:"itemId"`
  202. TokenID common.TokenID `json:"id"`
  203. EthBlockNum int64 `json:"ethereumBlockNum"` // Ethereum block number in which this token was registered
  204. EthAddr ethCommon.Address `json:"ethereumAddress"`
  205. Name string `json:"name"`
  206. Symbol string `json:"symbol"`
  207. Decimals uint64 `json:"decimals"`
  208. USD *float64 `json:"USD"`
  209. USDUpdate *time.Time `json:"fiatUpdate"`
  210. }
  211. func tokensToAPI(dbTokens []historydb.TokenRead) []tokenAPI {
  212. apiTokens := []tokenAPI{}
  213. for i := 0; i < len(dbTokens); i++ {
  214. apiTokens = append(apiTokens, tokenAPI{
  215. ItemID: dbTokens[i].ItemID,
  216. TokenID: dbTokens[i].TokenID,
  217. EthBlockNum: dbTokens[i].EthBlockNum,
  218. EthAddr: dbTokens[i].EthAddr,
  219. Name: dbTokens[i].Name,
  220. Symbol: dbTokens[i].Symbol,
  221. Decimals: dbTokens[i].Decimals,
  222. USD: dbTokens[i].USD,
  223. USDUpdate: dbTokens[i].USDUpdate,
  224. })
  225. }
  226. return apiTokens
  227. }