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.

278 lines
9.6 KiB

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