From e5e2cdf4d4741aa05a1a8c8ca06a17a932ff53c4 Mon Sep 17 00:00:00 2001 From: Artem Poltorzhitskiy <aopoltorzhicky@gmail.com> Date: Fri, 18 Oct 2024 14:07:32 +0200 Subject: [PATCH] Feature: dusk-11 (#49) * Feature: dusk-11 * Rename actions * Genesis fees * Add Deposit entity * Fix: new change fee structure * Fix: base64 decode in deposit event * Fix: genesis constants and deposit saving * Fix: deposits endpoints * Fix: deposit response --- cmd/api/docs/docs.go | 216 +++++++++- cmd/api/docs/swagger.json | 216 +++++++++- cmd/api/docs/swagger.yaml | 153 ++++++- cmd/api/handler/address.go | 67 +++ cmd/api/handler/address_test.go | 81 +++- cmd/api/handler/block_test.go | 11 +- cmd/api/handler/constant_test.go | 2 +- cmd/api/handler/responses/action.go | 2 +- cmd/api/handler/responses/block.go | 2 +- cmd/api/handler/responses/deposit.go | 47 +++ cmd/api/handler/responses/tx.go | 2 +- cmd/api/handler/rollup.go | 62 +++ cmd/api/handler/rollup_test.go | 72 +++- cmd/api/handler/tx_test.go | 18 +- cmd/api/init.go | 6 +- go.mod | 6 +- go.sum | 12 +- internal/storage/action.go | 1 + internal/storage/deposit.go | 46 ++ internal/storage/generic.go | 4 + internal/storage/mock/deposit.go | 393 ++++++++++++++++++ internal/storage/mock/generic.go | 120 ++++++ internal/storage/postgres/action_test.go | 14 +- internal/storage/postgres/core.go | 3 + internal/storage/postgres/deposit.go | 66 +++ internal/storage/postgres/deposit_test.go | 65 +++ internal/storage/postgres/index.go | 36 ++ internal/storage/postgres/transaction.go | 26 ++ internal/storage/postgres/transaction_test.go | 91 ++++ internal/storage/postgres/tx_test.go | 4 +- internal/storage/types/action_type.go | 5 +- internal/storage/types/action_type_enum.go | 15 +- internal/storage/types/action_type_mask.go | 20 +- .../storage/types/action_type_mask_test.go | 11 +- internal/test_suite/block.go | 2 +- pkg/indexer/decode/actions.go | 319 ++++++++------ pkg/indexer/decode/actions_test.go | 358 +++++++++------- pkg/indexer/decode/context.go | 6 + pkg/indexer/decode/tx.go | 15 +- pkg/indexer/genesis/constant.go | 147 ++++++- pkg/indexer/parser/parseEvents.go | 48 +++ pkg/indexer/parser/parseEvents_test.go | 53 +++ pkg/indexer/parser/parseTxs.go | 18 +- pkg/indexer/parser/parseTxs_test.go | 24 +- pkg/indexer/rollback/rollback.go | 4 + pkg/indexer/rollback/rollback_test.go | 13 +- pkg/indexer/rollback/rollup.go | 2 +- pkg/indexer/rollback/rollup_test.go | 8 +- pkg/indexer/storage/action.go | 27 ++ pkg/node/types/genesis.go | 33 +- test/data/action.yml | 2 +- test/data/address_action.yml | 2 +- test/data/deposit.yml | 10 + 53 files changed, 2538 insertions(+), 448 deletions(-) create mode 100644 cmd/api/handler/responses/deposit.go create mode 100644 internal/storage/deposit.go create mode 100644 internal/storage/mock/deposit.go create mode 100644 internal/storage/postgres/deposit.go create mode 100644 internal/storage/postgres/deposit_test.go create mode 100644 pkg/indexer/parser/parseEvents_test.go create mode 100644 test/data/deposit.yml diff --git a/cmd/api/docs/docs.go b/cmd/api/docs/docs.go index 9fd76e0..555892c 100644 --- a/cmd/api/docs/docs.go +++ b/cmd/api/docs/docs.go @@ -202,7 +202,7 @@ const docTemplate = `{ { "enum": [ "transfer", - "sequence", + "rollup_data_submission", "validator_update", "sudo_address_change", "ibc_relay", @@ -213,7 +213,8 @@ const docTemplate = `{ "bridge_lock", "bridge_unlock", "bridge_sudo_change_action", - "fee_change" + "fee_change", + "ibc_sudo_change_action" ], "type": "string", "description": "Comma-separated action types list", @@ -246,6 +247,76 @@ const docTemplate = `{ } } }, + "/v1/address/{hash}/deposits": { + "get": { + "description": "Get bridge deposits", + "produces": [ + "application/json" + ], + "tags": [ + "address" + ], + "summary": "Get bridge deposits", + "operationId": "get-address-deposits", + "parameters": [ + { + "maxLength": 48, + "minLength": 48, + "type": "string", + "description": "Hash", + "name": "hash", + "in": "path", + "required": true + }, + { + "maximum": 100, + "type": "integer", + "description": "Count of requested entities", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Offset", + "name": "offset", + "in": "query" + }, + { + "enum": [ + "asc", + "desc" + ], + "type": "string", + "description": "Sort order", + "name": "sort", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/responses.Deposit" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/handler.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/handler.Error" + } + } + } + } + }, "/v1/address/{hash}/fees": { "get": { "description": "Get address paid fees", @@ -497,7 +568,7 @@ const docTemplate = `{ { "enum": [ "transfer", - "sequence", + "rollup_data_submission", "validator_update", "sudo_address_change", "ibc_relay", @@ -508,7 +579,8 @@ const docTemplate = `{ "bridge_lock", "bridge_unlock", "bridge_sudo_change_action", - "fee_change" + "fee_change", + "ibc_sudo_change_action" ], "type": "string", "description": "Comma-separated message types list", @@ -1385,7 +1457,7 @@ const docTemplate = `{ { "enum": [ "transfer", - "sequence", + "rollup_data_submission", "validator_update", "sudo_address_change", "ibc_relay", @@ -1396,7 +1468,8 @@ const docTemplate = `{ "bridge_lock", "bridge_unlock", "bridge_sudo_change_action", - "fee_change" + "fee_change", + "ibc_sudo_change_action" ], "type": "string", "description": "Comma-separated action types list", @@ -1511,6 +1584,74 @@ const docTemplate = `{ } } }, + "/v1/rollup/{hash}/deposits": { + "get": { + "description": "Get rollup deposits", + "produces": [ + "application/json" + ], + "tags": [ + "rollup" + ], + "summary": "Get rollup deposits", + "operationId": "get-rollup-deposits", + "parameters": [ + { + "type": "string", + "description": "Base64Url encoded rollup id", + "name": "hash", + "in": "path", + "required": true + }, + { + "maximum": 100, + "type": "integer", + "description": "Count of requested entities", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Offset", + "name": "offset", + "in": "query" + }, + { + "enum": [ + "asc", + "desc" + ], + "type": "string", + "description": "Sort order", + "name": "sort", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/responses.Deposit" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/handler.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/handler.Error" + } + } + } + } + }, "/v1/search": { "get": { "produces": [ @@ -1946,7 +2087,7 @@ const docTemplate = `{ { "enum": [ "transfer", - "sequence", + "rollup_data_submission", "validator_update", "sudo_address_change", "ibc_relay", @@ -1957,7 +2098,8 @@ const docTemplate = `{ "bridge_lock", "bridge_unlock", "bridge_sudo_change_action", - "fee_change" + "fee_change", + "ibc_sudo_change_action" ], "type": "string", "description": "Comma-separated action types list", @@ -2604,7 +2746,7 @@ const docTemplate = `{ "type": { "type": "string", "format": "string", - "example": "sequence" + "example": "rollup_data_submission" } } }, @@ -2670,7 +2812,7 @@ const docTemplate = `{ "properties": { "action_types": { "type": "string", - "example": "sequence,transfer" + "example": "rollup_data_submission,transfer" }, "app_hash": { "type": "string", @@ -2814,6 +2956,56 @@ const docTemplate = `{ } } }, + "responses.Deposit": { + "type": "object", + "properties": { + "amount": { + "type": "string", + "format": "string", + "example": "1000" + }, + "asset": { + "type": "string", + "format": "string", + "example": "nria" + }, + "bridge": { + "type": "string", + "format": "string", + "example": "astria1phym4uktjn6gjle226009ge7u82w0dgtszs8x2" + }, + "destination_chain_address": { + "type": "string", + "format": "string", + "example": "0x8bAec8896775DDa83796eda3e7E67217b5E3C5dA" + }, + "height": { + "type": "integer", + "format": "int64", + "example": 100 + }, + "id": { + "type": "integer", + "format": "int64", + "example": 321 + }, + "rollup": { + "type": "string", + "format": "string", + "example": "O0Ia+lPYYMf3iFfxBaWXCSdlhphc6d4ZoBXINov6Tjc=" + }, + "time": { + "type": "string", + "format": "date-time", + "example": "2023-07-04T03:10:57+00:00" + }, + "tx_hash": { + "type": "string", + "format": "binary", + "example": "652452A670018D629CC116E510BA88C1CABE061336661B1F3D206D248BD558AF" + } + } + }, "responses.Enums": { "type": "object", "properties": { @@ -3112,7 +3304,7 @@ const docTemplate = `{ "type": { "type": "string", "format": "string", - "example": "sequence" + "example": "rollup_data_submission" } } }, @@ -3289,7 +3481,7 @@ const docTemplate = `{ "action_types": { "type": "string", "format": "string", - "example": "sequence,transfer" + "example": "rollup_data_submission,transfer" }, "actions": { "type": "array", diff --git a/cmd/api/docs/swagger.json b/cmd/api/docs/swagger.json index dae0a36..7c69b71 100644 --- a/cmd/api/docs/swagger.json +++ b/cmd/api/docs/swagger.json @@ -192,7 +192,7 @@ { "enum": [ "transfer", - "sequence", + "rollup_data_submission", "validator_update", "sudo_address_change", "ibc_relay", @@ -203,7 +203,8 @@ "bridge_lock", "bridge_unlock", "bridge_sudo_change_action", - "fee_change" + "fee_change", + "ibc_sudo_change_action" ], "type": "string", "description": "Comma-separated action types list", @@ -236,6 +237,76 @@ } } }, + "/v1/address/{hash}/deposits": { + "get": { + "description": "Get bridge deposits", + "produces": [ + "application/json" + ], + "tags": [ + "address" + ], + "summary": "Get bridge deposits", + "operationId": "get-address-deposits", + "parameters": [ + { + "maxLength": 48, + "minLength": 48, + "type": "string", + "description": "Hash", + "name": "hash", + "in": "path", + "required": true + }, + { + "maximum": 100, + "type": "integer", + "description": "Count of requested entities", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Offset", + "name": "offset", + "in": "query" + }, + { + "enum": [ + "asc", + "desc" + ], + "type": "string", + "description": "Sort order", + "name": "sort", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/responses.Deposit" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/handler.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/handler.Error" + } + } + } + } + }, "/v1/address/{hash}/fees": { "get": { "description": "Get address paid fees", @@ -487,7 +558,7 @@ { "enum": [ "transfer", - "sequence", + "rollup_data_submission", "validator_update", "sudo_address_change", "ibc_relay", @@ -498,7 +569,8 @@ "bridge_lock", "bridge_unlock", "bridge_sudo_change_action", - "fee_change" + "fee_change", + "ibc_sudo_change_action" ], "type": "string", "description": "Comma-separated message types list", @@ -1375,7 +1447,7 @@ { "enum": [ "transfer", - "sequence", + "rollup_data_submission", "validator_update", "sudo_address_change", "ibc_relay", @@ -1386,7 +1458,8 @@ "bridge_lock", "bridge_unlock", "bridge_sudo_change_action", - "fee_change" + "fee_change", + "ibc_sudo_change_action" ], "type": "string", "description": "Comma-separated action types list", @@ -1501,6 +1574,74 @@ } } }, + "/v1/rollup/{hash}/deposits": { + "get": { + "description": "Get rollup deposits", + "produces": [ + "application/json" + ], + "tags": [ + "rollup" + ], + "summary": "Get rollup deposits", + "operationId": "get-rollup-deposits", + "parameters": [ + { + "type": "string", + "description": "Base64Url encoded rollup id", + "name": "hash", + "in": "path", + "required": true + }, + { + "maximum": 100, + "type": "integer", + "description": "Count of requested entities", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Offset", + "name": "offset", + "in": "query" + }, + { + "enum": [ + "asc", + "desc" + ], + "type": "string", + "description": "Sort order", + "name": "sort", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/responses.Deposit" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/handler.Error" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/handler.Error" + } + } + } + } + }, "/v1/search": { "get": { "produces": [ @@ -1936,7 +2077,7 @@ { "enum": [ "transfer", - "sequence", + "rollup_data_submission", "validator_update", "sudo_address_change", "ibc_relay", @@ -1947,7 +2088,8 @@ "bridge_lock", "bridge_unlock", "bridge_sudo_change_action", - "fee_change" + "fee_change", + "ibc_sudo_change_action" ], "type": "string", "description": "Comma-separated action types list", @@ -2594,7 +2736,7 @@ "type": { "type": "string", "format": "string", - "example": "sequence" + "example": "rollup_data_submission" } } }, @@ -2660,7 +2802,7 @@ "properties": { "action_types": { "type": "string", - "example": "sequence,transfer" + "example": "rollup_data_submission,transfer" }, "app_hash": { "type": "string", @@ -2804,6 +2946,56 @@ } } }, + "responses.Deposit": { + "type": "object", + "properties": { + "amount": { + "type": "string", + "format": "string", + "example": "1000" + }, + "asset": { + "type": "string", + "format": "string", + "example": "nria" + }, + "bridge": { + "type": "string", + "format": "string", + "example": "astria1phym4uktjn6gjle226009ge7u82w0dgtszs8x2" + }, + "destination_chain_address": { + "type": "string", + "format": "string", + "example": "0x8bAec8896775DDa83796eda3e7E67217b5E3C5dA" + }, + "height": { + "type": "integer", + "format": "int64", + "example": 100 + }, + "id": { + "type": "integer", + "format": "int64", + "example": 321 + }, + "rollup": { + "type": "string", + "format": "string", + "example": "O0Ia+lPYYMf3iFfxBaWXCSdlhphc6d4ZoBXINov6Tjc=" + }, + "time": { + "type": "string", + "format": "date-time", + "example": "2023-07-04T03:10:57+00:00" + }, + "tx_hash": { + "type": "string", + "format": "binary", + "example": "652452A670018D629CC116E510BA88C1CABE061336661B1F3D206D248BD558AF" + } + } + }, "responses.Enums": { "type": "object", "properties": { @@ -3102,7 +3294,7 @@ "type": { "type": "string", "format": "string", - "example": "sequence" + "example": "rollup_data_submission" } } }, @@ -3279,7 +3471,7 @@ "action_types": { "type": "string", "format": "string", - "example": "sequence,transfer" + "example": "rollup_data_submission,transfer" }, "actions": { "type": "array", diff --git a/cmd/api/docs/swagger.yaml b/cmd/api/docs/swagger.yaml index 3fdaeaf..ef20c72 100644 --- a/cmd/api/docs/swagger.yaml +++ b/cmd/api/docs/swagger.yaml @@ -32,7 +32,7 @@ definitions: format: binary type: string type: - example: sequence + example: rollup_data_submission format: string type: string type: object @@ -80,7 +80,7 @@ definitions: responses.Block: properties: action_types: - example: sequence,transfer + example: rollup_data_submission,transfer type: string app_hash: example: 652452A670018D629CC116E510BA88C1CABE061336661B1F3D206D248BD558AF @@ -185,6 +185,45 @@ definitions: $ref: '#/definitions/responses.Params' type: object type: object + responses.Deposit: + properties: + amount: + example: "1000" + format: string + type: string + asset: + example: nria + format: string + type: string + bridge: + example: astria1phym4uktjn6gjle226009ge7u82w0dgtszs8x2 + format: string + type: string + destination_chain_address: + example: 0x8bAec8896775DDa83796eda3e7E67217b5E3C5dA + format: string + type: string + height: + example: 100 + format: int64 + type: integer + id: + example: 321 + format: int64 + type: integer + rollup: + example: O0Ia+lPYYMf3iFfxBaWXCSdlhphc6d4ZoBXINov6Tjc= + format: string + type: string + time: + example: "2023-07-04T03:10:57+00:00" + format: date-time + type: string + tx_hash: + example: 652452A670018D629CC116E510BA88C1CABE061336661B1F3D206D248BD558AF + format: binary + type: string + type: object responses.Enums: properties: action_type: @@ -410,7 +449,7 @@ definitions: format: binary type: string type: - example: sequence + example: rollup_data_submission format: string type: string type: object @@ -542,7 +581,7 @@ definitions: responses.Tx: properties: action_types: - example: sequence,transfer + example: rollup_data_submission,transfer format: string type: string actions: @@ -750,7 +789,7 @@ paths: - description: Comma-separated action types list enum: - transfer - - sequence + - rollup_data_submission - validator_update - sudo_address_change - ibc_relay @@ -762,6 +801,7 @@ paths: - bridge_unlock - bridge_sudo_change_action - fee_change + - ibc_sudo_change_action in: query name: action_types type: string @@ -785,6 +825,54 @@ paths: summary: Get address actions tags: - address + /v1/address/{hash}/deposits: + get: + description: Get bridge deposits + operationId: get-address-deposits + parameters: + - description: Hash + in: path + maxLength: 48 + minLength: 48 + name: hash + required: true + type: string + - description: Count of requested entities + in: query + maximum: 100 + name: limit + type: integer + - description: Offset + in: query + name: offset + type: integer + - description: Sort order + enum: + - asc + - desc + in: query + name: sort + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/responses.Deposit' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/handler.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/handler.Error' + summary: Get bridge deposits + tags: + - address /v1/address/{hash}/fees: get: description: Get address paid fees @@ -957,7 +1045,7 @@ paths: - description: Comma-separated message types list enum: - transfer - - sequence + - rollup_data_submission - validator_update - sudo_address_change - ibc_relay @@ -969,6 +1057,7 @@ paths: - bridge_unlock - bridge_sudo_change_action - fee_change + - ibc_sudo_change_action in: query name: msg_type type: string @@ -1561,7 +1650,7 @@ paths: - description: Comma-separated action types list enum: - transfer - - sequence + - rollup_data_submission - validator_update - sudo_address_change - ibc_relay @@ -1573,6 +1662,7 @@ paths: - bridge_unlock - bridge_sudo_change_action - fee_change + - ibc_sudo_change_action in: query name: action_types type: string @@ -1652,6 +1742,52 @@ paths: summary: Get rollup bridges tags: - rollup + /v1/rollup/{hash}/deposits: + get: + description: Get rollup deposits + operationId: get-rollup-deposits + parameters: + - description: Base64Url encoded rollup id + in: path + name: hash + required: true + type: string + - description: Count of requested entities + in: query + maximum: 100 + name: limit + type: integer + - description: Offset + in: query + name: offset + type: integer + - description: Sort order + enum: + - asc + - desc + in: query + name: sort + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/responses.Deposit' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/handler.Error' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/handler.Error' + summary: Get rollup deposits + tags: + - rollup /v1/rollup/count: get: description: Get count of rollups in network @@ -1967,7 +2103,7 @@ paths: - description: Comma-separated action types list enum: - transfer - - sequence + - rollup_data_submission - validator_update - sudo_address_change - ibc_relay @@ -1979,6 +2115,7 @@ paths: - bridge_unlock - bridge_sudo_change_action - fee_change + - ibc_sudo_change_action in: query name: action_types type: string diff --git a/cmd/api/handler/address.go b/cmd/api/handler/address.go index f26e6a5..8a226be 100644 --- a/cmd/api/handler/address.go +++ b/cmd/api/handler/address.go @@ -11,6 +11,7 @@ import ( "github.com/celenium-io/astria-indexer/internal/storage" storageTypes "github.com/celenium-io/astria-indexer/internal/storage/types" "github.com/labstack/echo/v4" + "github.com/pkg/errors" ) type AddressHandler struct { @@ -20,6 +21,7 @@ type AddressHandler struct { rollups storage.IRollup fees storage.IFee bridge storage.IBridge + deposits storage.IDeposit state storage.IState indexerName string } @@ -31,6 +33,7 @@ func NewAddressHandler( rollups storage.IRollup, fees storage.IFee, bridge storage.IBridge, + deposits storage.IDeposit, state storage.IState, indexerName string, ) *AddressHandler { @@ -41,6 +44,7 @@ func NewAddressHandler( rollups: rollups, fees: fees, bridge: bridge, + deposits: deposits, state: state, indexerName: indexerName, } @@ -463,3 +467,66 @@ func (handler *AddressHandler) Fees(c echo.Context) error { } return returnArray(c, response) } + +type getAddressDeposits struct { + Hash string `param:"hash" validate:"required,address"` + Limit int `query:"limit" validate:"omitempty,min=1,max=100"` + Offset int `query:"offset" validate:"omitempty,min=0"` + Sort string `query:"sort" validate:"omitempty,oneof=asc desc"` +} + +func (p *getAddressDeposits) SetDefault() { + if p.Limit == 0 { + p.Limit = 10 + } + if p.Sort == "" { + p.Sort = desc + } +} + +// Deposits godoc +// +// @Summary Get bridge deposits +// @Description Get bridge deposits +// @Tags address +// @ID get-address-deposits +// @Param hash path string true "Hash" minlength(48) maxlength(48) +// @Param limit query integer false "Count of requested entities" mininum(1) maximum(100) +// @Param offset query integer false "Offset" mininum(1) +// @Param sort query string false "Sort order" Enums(asc, desc) +// @Produce json +// @Success 200 {array} responses.Deposit +// @Failure 400 {object} Error +// @Failure 500 {object} Error +// @Router /v1/address/{hash}/deposits [get] +func (handler *AddressHandler) Deposits(c echo.Context) error { + req, err := bindAndValidate[getAddressDeposits](c) + if err != nil { + return badRequestError(c, err) + } + req.SetDefault() + + address, err := handler.address.ByHash(c.Request().Context(), req.Hash) + if err != nil { + return handleError(c, err, handler.address) + } + + if !address.IsBridge { + return handleError(c, errors.Errorf("address %s is not bridge", req.Hash), handler.address) + } + + bridge, err := handler.bridge.ByAddress(c.Request().Context(), address.Id) + if err != nil { + return handleError(c, err, handler.address) + } + + deposits, err := handler.deposits.ByBridgeId(c.Request().Context(), bridge.Id, req.Limit, req.Offset, pgSort(req.Sort)) + if err != nil { + return handleError(c, err, handler.address) + } + response := make([]responses.Deposit, len(deposits)) + for i := range deposits { + response[i] = responses.NewDeposit(deposits[i]) + } + return returnArray(c, response) +} diff --git a/cmd/api/handler/address_test.go b/cmd/api/handler/address_test.go index 4b41ed5..9e154ae 100644 --- a/cmd/api/handler/address_test.go +++ b/cmd/api/handler/address_test.go @@ -28,16 +28,17 @@ import ( // AddressTestSuite - type AddressTestSuite struct { suite.Suite - address *mock.MockIAddress - txs *mock.MockITx - actions *mock.MockIAction - rollups *mock.MockIRollup - fees *mock.MockIFee - bridge *mock.MockIBridge - state *mock.MockIState - echo *echo.Echo - handler *AddressHandler - ctrl *gomock.Controller + address *mock.MockIAddress + txs *mock.MockITx + actions *mock.MockIAction + rollups *mock.MockIRollup + fees *mock.MockIFee + bridge *mock.MockIBridge + deposits *mock.MockIDeposit + state *mock.MockIState + echo *echo.Echo + handler *AddressHandler + ctrl *gomock.Controller } // SetupSuite - @@ -51,8 +52,9 @@ func (s *AddressTestSuite) SetupSuite() { s.rollups = mock.NewMockIRollup(s.ctrl) s.fees = mock.NewMockIFee(s.ctrl) s.bridge = mock.NewMockIBridge(s.ctrl) + s.deposits = mock.NewMockIDeposit(s.ctrl) s.state = mock.NewMockIState(s.ctrl) - s.handler = NewAddressHandler(s.address, s.txs, s.actions, s.rollups, s.fees, s.bridge, s.state, testIndexerName) + s.handler = NewAddressHandler(s.address, s.txs, s.actions, s.rollups, s.fees, s.bridge, s.deposits, s.state, testIndexerName) } // TearDownSuite - @@ -249,7 +251,7 @@ func (s *AddressTestSuite) TestTransactions() { q.Set("offset", "0") q.Set("sort", "desc") q.Set("status", "success") - q.Set("action_types", "sequence") + q.Set("action_types", "rollup_data_submission") q.Set("height", "1000") req := httptest.NewRequest(http.MethodGet, "/?"+q.Encode(), nil) @@ -289,7 +291,7 @@ func (s *AddressTestSuite) TestTransactions() { s.Require().EqualValues(10, tx.GasWanted) s.Require().EqualValues(8, tx.GasUsed) s.Require().EqualValues(10, tx.Nonce) - s.Require().EqualValues([]string{types.ActionTypeSequence.String()}, tx.ActionTypes) + s.Require().EqualValues([]string{types.ActionTypeRollupDataSubmission.String()}, tx.ActionTypes) s.Require().EqualValues(1, tx.ActionsCount) s.Require().Equal("codespace", tx.Codespace) s.Require().Equal(types.StatusSuccess, tx.Status) @@ -320,7 +322,7 @@ func (s *AddressTestSuite) TestActions() { AddressId: 1, ActionId: 1, TxId: 1, - ActionType: types.ActionTypeSequence, + ActionType: types.ActionTypeRollupDataSubmission, Height: 100, Time: testTime, Address: &testAddress, @@ -345,7 +347,7 @@ func (s *AddressTestSuite) TestActions() { s.Require().EqualValues(1, action.Id) s.Require().EqualValues(100, action.Height) s.Require().EqualValues(1, action.Position) - s.Require().EqualValues(types.ActionTypeSequence, action.Type) + s.Require().EqualValues(types.ActionTypeRollupDataSubmission, action.Type) } func (s *AddressTestSuite) TestCount() { @@ -496,3 +498,52 @@ func (s *AddressTestSuite) TestFees() { s.Require().NoError(err) s.Require().Len(fees, 1) } + +func (s *AddressTestSuite) TestDeposits() { + q := make(url.Values) + q.Set("limit", "10") + q.Set("offset", "0") + + req := httptest.NewRequest(http.MethodGet, "/?"+q.Encode(), nil) + rec := httptest.NewRecorder() + c := s.echo.NewContext(req, rec) + c.SetPath("/address/:hash/deposits") + c.SetParamNames("hash") + c.SetParamValues(testAddressHash) + + s.address.EXPECT(). + ByHash(gomock.Any(), testAddress.Hash). + Return(testAddress, nil). + Times(1) + + s.bridge.EXPECT(). + ByAddress(gomock.Any(), testAddress.Id). + Return(storage.Bridge{ + Id: 1, + }, nil). + Times(1) + + s.deposits.EXPECT(). + ByBridgeId(gomock.Any(), uint64(1), 10, 0, sdk.SortOrderDesc). + Return([]storage.Deposit{ + { + TxId: testTx.Id, + Time: testTime, + Height: 1000, + ActionId: 1, + Amount: decimal.RequireFromString("1000"), + Asset: currency.DefaultCurrency, + BridgeId: 1, + Tx: &testTx, + }, + }, nil). + Times(1) + + s.Require().NoError(s.handler.Deposits(c)) + s.Require().Equal(http.StatusOK, rec.Code) + + var deposits []responses.Deposit + err := json.NewDecoder(rec.Body).Decode(&deposits) + s.Require().NoError(err) + s.Require().Len(deposits, 1) +} diff --git a/cmd/api/handler/block_test.go b/cmd/api/handler/block_test.go index 2401836..a4e6097 100644 --- a/cmd/api/handler/block_test.go +++ b/cmd/api/handler/block_test.go @@ -35,6 +35,7 @@ var ( Nonce: 10, ActionsCount: 1, SignedTxCount: 1, + IsBridge: true, Balance: []*storage.Balance{ { Currency: currency.DefaultCurrency, @@ -93,7 +94,7 @@ var ( Height: 100, Time: testTime, Position: 1, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, TxId: 1, Data: map[string]any{ "rollup_id": hex.EncodeToString(testRollup.AstriaId), @@ -120,7 +121,7 @@ var ( Signature: testsuite.RandomHash(32), Signer: &testAddress, SignerId: testAddress.Id, - ActionTypes: types.ActionTypeSequenceBits, + ActionTypes: types.ActionTypeRollupDataSubmissionBits, Actions: []storage.Action{ *testRollupAction.Action, }, @@ -371,7 +372,7 @@ func (s *BlockTestSuite) TestGetActions() { Height: 100, Time: testTime, Position: 2, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, TxId: 10, Data: map[string]any{ "test": "value", @@ -392,7 +393,7 @@ func (s *BlockTestSuite) TestGetActions() { s.Require().EqualValues(100, actions[0].Height) s.Require().EqualValues(2, actions[0].Position) s.Require().Equal(testTime, actions[0].Time) - s.Require().Equal(types.ActionTypeSequence, actions[0].Type) + s.Require().Equal(types.ActionTypeRollupDataSubmission, actions[0].Type) s.Require().Equal(hex.EncodeToString(testTx.Hash), actions[0].TxHash) } @@ -443,7 +444,7 @@ func (s *BlockTestSuite) TestGetRollupActions() { s.Require().EqualValues(100, action.Height) s.Require().EqualValues(1, action.Position) s.Require().Equal(testTime, action.Time) - s.Require().EqualValues(string(types.ActionTypeSequence), action.Type) + s.Require().EqualValues(string(types.ActionTypeRollupDataSubmission), action.Type) } func (s *BlockTestSuite) TestGetRollupActionsCount() { diff --git a/cmd/api/handler/constant_test.go b/cmd/api/handler/constant_test.go index 396f7f6..19ee263 100644 --- a/cmd/api/handler/constant_test.go +++ b/cmd/api/handler/constant_test.go @@ -58,7 +58,7 @@ func (s *ConstantTestSuite) TestEnums() { var enums responses.Enums err := json.NewDecoder(rec.Body).Decode(&enums) s.Require().NoError(err) - s.Require().Len(enums.ActionType, 13) + s.Require().Len(enums.ActionType, 14) s.Require().Len(enums.Status, 2) } diff --git a/cmd/api/handler/responses/action.go b/cmd/api/handler/responses/action.go index d27abe5..a37f82a 100644 --- a/cmd/api/handler/responses/action.go +++ b/cmd/api/handler/responses/action.go @@ -17,7 +17,7 @@ type Action struct { Height pkgTypes.Level `example:"1000" format:"int64" json:"height" swaggertype:"integer"` Time time.Time `example:"2023-07-04T03:10:57+00:00" format:"date-time" json:"time" swaggertype:"string"` Position int64 `example:"1" format:"int64" json:"position" swaggertype:"integer"` - Type types.ActionType `example:"sequence" format:"string" json:"type" swaggertype:"string"` + Type types.ActionType `example:"rollup_data_submission" format:"string" json:"type" swaggertype:"string"` TxHash string `example:"652452A670018D629CC116E510BA88C1CABE061336661B1F3D206D248BD558AF" format:"binary" json:"tx_hash,omitempty" swaggertype:"string"` Fee *Fee `json:"fee,omitempty"` diff --git a/cmd/api/handler/responses/block.go b/cmd/api/handler/responses/block.go index 7d4a41e..0cb695b 100644 --- a/cmd/api/handler/responses/block.go +++ b/cmd/api/handler/responses/block.go @@ -28,7 +28,7 @@ type Block struct { AppHash pkgTypes.Hex `example:"652452A670018D629CC116E510BA88C1CABE061336661B1F3D206D248BD558AF" json:"app_hash" swaggertype:"string"` LastResultsHash pkgTypes.Hex `example:"652452A670018D629CC116E510BA88C1CABE061336661B1F3D206D248BD558AF" json:"last_results_hash" swaggertype:"string"` EvidenceHash pkgTypes.Hex `example:"652452A670018D629CC116E510BA88C1CABE061336661B1F3D206D248BD558AF" json:"evidence_hash" swaggertype:"string"` - ActionTypes []string `example:"sequence,transfer" json:"action_types" swaggertype:"string"` + ActionTypes []string `example:"rollup_data_submission,transfer" json:"action_types" swaggertype:"string"` Proposer *ShortValidator `json:"proposer,omitempty"` Stats *BlockStats `json:"stats,omitempty"` diff --git a/cmd/api/handler/responses/deposit.go b/cmd/api/handler/responses/deposit.go new file mode 100644 index 0000000..6e9ed11 --- /dev/null +++ b/cmd/api/handler/responses/deposit.go @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2024 PK Lab AG <contact@pklab.io> +// SPDX-License-Identifier: MIT + +package responses + +import ( + "encoding/hex" + "time" + + "github.com/celenium-io/astria-indexer/internal/storage" + pkgTypes "github.com/celenium-io/astria-indexer/pkg/types" +) + +type Deposit struct { + Id uint64 `example:"321" format:"int64" json:"id" swaggertype:"integer"` + Height pkgTypes.Level `example:"100" format:"int64" json:"height" swaggertype:"integer"` + Time time.Time `example:"2023-07-04T03:10:57+00:00" format:"date-time" json:"time" swaggertype:"string"` + Amount string `example:"1000" format:"string" json:"amount" swaggertype:"string"` + Asset string `example:"nria" format:"string" json:"asset" swaggertype:"string"` + DestinationChainAddress string `example:"0x8bAec8896775DDa83796eda3e7E67217b5E3C5dA" format:"string" json:"destination_chain_address" swaggertype:"string"` + TxHash string `example:"652452A670018D629CC116E510BA88C1CABE061336661B1F3D206D248BD558AF" format:"binary" json:"tx_hash,omitempty" swaggertype:"string"` + Rollup []byte `example:"O0Ia+lPYYMf3iFfxBaWXCSdlhphc6d4ZoBXINov6Tjc=" format:"string" json:"rollup,omitempty" swaggertype:"string"` + Bridge string `example:"astria1phym4uktjn6gjle226009ge7u82w0dgtszs8x2" format:"string" json:"bridge,omitempty" swaggertype:"string"` +} + +func NewDeposit(d storage.Deposit) Deposit { + deposit := Deposit{ + Id: d.Id, + Height: d.Height, + Time: d.Time, + Amount: d.Amount.String(), + Asset: d.Asset, + DestinationChainAddress: d.DestinationChainAddress, + } + + if d.Tx != nil { + deposit.TxHash = hex.EncodeToString(d.Tx.Hash) + } + if d.Rollup != nil { + deposit.Rollup = d.Rollup.AstriaId + } + if d.Bridge != nil && d.Bridge.Address != nil { + deposit.Bridge = d.Bridge.Address.Hash + } + + return deposit +} diff --git a/cmd/api/handler/responses/tx.go b/cmd/api/handler/responses/tx.go index 5327059..00218a9 100644 --- a/cmd/api/handler/responses/tx.go +++ b/cmd/api/handler/responses/tx.go @@ -28,7 +28,7 @@ type Tx struct { Signer string `example:"115F94D8C98FFD73FE65182611140F0EDC7C3C94" format:"string" json:"signer" swaggertype:"string"` Time time.Time `example:"2023-07-04T03:10:57+00:00" format:"date-time" json:"time" swaggertype:"string"` Status types.Status `example:"success" format:"string" json:"status" swaggertype:"string"` - ActionTypes []string `example:"sequence,transfer" format:"string" json:"action_types" swaggertype:"string"` + ActionTypes []string `example:"rollup_data_submission,transfer" format:"string" json:"action_types" swaggertype:"string"` Actions []Action `json:"actions,omitempty"` } diff --git a/cmd/api/handler/rollup.go b/cmd/api/handler/rollup.go index 17ab4aa..9905787 100644 --- a/cmd/api/handler/rollup.go +++ b/cmd/api/handler/rollup.go @@ -19,6 +19,7 @@ type RollupHandler struct { rollups storage.IRollup actions storage.IAction bridge storage.IBridge + deposits storage.IDeposit state storage.IState indexerName string } @@ -27,6 +28,7 @@ func NewRollupHandler( rollups storage.IRollup, actions storage.IAction, bridge storage.IBridge, + deposits storage.IDeposit, state storage.IState, indexerName string, ) *RollupHandler { @@ -34,6 +36,7 @@ func NewRollupHandler( rollups: rollups, actions: actions, bridge: bridge, + deposits: deposits, state: state, indexerName: indexerName, } @@ -402,3 +405,62 @@ func (handler *RollupHandler) AllActions(c echo.Context) error { return returnArray(c, response) } + +type getRollupDeposits struct { + Hash string `param:"hash" validate:"required,base64url"` + Limit int `query:"limit" validate:"omitempty,min=1,max=100"` + Offset int `query:"offset" validate:"omitempty,min=0"` + Sort string `query:"sort" validate:"omitempty,oneof=asc desc"` +} + +func (p *getRollupDeposits) SetDefault() { + if p.Limit == 0 { + p.Limit = 10 + } + if p.Sort == "" { + p.Sort = desc + } +} + +// Deposits godoc +// +// @Summary Get rollup deposits +// @Description Get rollup deposits +// @Tags rollup +// @ID get-rollup-deposits +// @Param hash path string true "Base64Url encoded rollup id" +// @Param limit query integer false "Count of requested entities" mininum(1) maximum(100) +// @Param offset query integer false "Offset" mininum(1) +// @Param sort query string false "Sort order" Enums(asc, desc) +// @Produce json +// @Success 200 {array} responses.Deposit +// @Failure 400 {object} Error +// @Failure 500 {object} Error +// @Router /v1/rollup/{hash}/deposits [get] +func (handler *RollupHandler) Deposits(c echo.Context) error { + req, err := bindAndValidate[getRollupDeposits](c) + if err != nil { + return badRequestError(c, err) + } + req.SetDefault() + + hash, err := base64.URLEncoding.DecodeString(req.Hash) + if err != nil { + return badRequestError(c, err) + } + + rollup, err := handler.rollups.ByHash(c.Request().Context(), hash) + if err != nil { + return handleError(c, err, handler.rollups) + } + + deposits, err := handler.deposits.ByRollupId(c.Request().Context(), rollup.Id, req.Limit, req.Offset, pgSort(req.Sort)) + if err != nil { + return handleError(c, err, handler.rollups) + } + response := make([]responses.Deposit, len(deposits)) + for i := range deposits { + response[i] = responses.NewDeposit(deposits[i]) + } + return returnArray(c, response) +} diff --git a/cmd/api/handler/rollup_test.go b/cmd/api/handler/rollup_test.go index 9be2b10..5f77195 100644 --- a/cmd/api/handler/rollup_test.go +++ b/cmd/api/handler/rollup_test.go @@ -18,6 +18,7 @@ import ( "github.com/celenium-io/astria-indexer/internal/storage/types" sdk "github.com/dipdup-net/indexer-sdk/pkg/storage" "github.com/labstack/echo/v4" + "github.com/shopspring/decimal" "github.com/stretchr/testify/suite" "go.uber.org/mock/gomock" ) @@ -25,13 +26,14 @@ import ( // RollupTestSuite - type RollupTestSuite struct { suite.Suite - rollups *mock.MockIRollup - actions *mock.MockIAction - bridge *mock.MockIBridge - state *mock.MockIState - echo *echo.Echo - handler *RollupHandler - ctrl *gomock.Controller + rollups *mock.MockIRollup + actions *mock.MockIAction + bridge *mock.MockIBridge + deposits *mock.MockIDeposit + state *mock.MockIState + echo *echo.Echo + handler *RollupHandler + ctrl *gomock.Controller } // SetupSuite - @@ -42,8 +44,9 @@ func (s *RollupTestSuite) SetupSuite() { s.rollups = mock.NewMockIRollup(s.ctrl) s.actions = mock.NewMockIAction(s.ctrl) s.bridge = mock.NewMockIBridge(s.ctrl) + s.deposits = mock.NewMockIDeposit(s.ctrl) s.state = mock.NewMockIState(s.ctrl) - s.handler = NewRollupHandler(s.rollups, s.actions, s.bridge, s.state, testIndexerName) + s.handler = NewRollupHandler(s.rollups, s.actions, s.bridge, s.deposits, s.state, testIndexerName) } // TearDownSuite - @@ -164,7 +167,7 @@ func (s *RollupTestSuite) TestActions() { Action: &storage.Action{ Data: map[string]any{}, Position: 1, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, Id: 1, Height: 100, }, @@ -185,7 +188,7 @@ func (s *RollupTestSuite) TestActions() { s.Require().EqualValues(1, action.Id) s.Require().EqualValues(100, action.Height) s.Require().EqualValues(1, action.Position) - s.Require().EqualValues(types.ActionTypeSequence, action.Type) + s.Require().EqualValues(types.ActionTypeRollupDataSubmission, action.Type) } func (s *RollupTestSuite) TestCount() { @@ -330,7 +333,7 @@ func (s *RollupTestSuite) TestAllActions() { Action: storage.Action{ Data: map[string]any{}, Position: 1, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, Id: 1, Height: 100, }, @@ -351,5 +354,50 @@ func (s *RollupTestSuite) TestAllActions() { s.Require().EqualValues(1, action.Id) s.Require().EqualValues(100, action.Height) s.Require().EqualValues(1, action.Position) - s.Require().EqualValues(types.ActionTypeSequence, action.Type) + s.Require().EqualValues(types.ActionTypeRollupDataSubmission, action.Type) +} + +func (s *RollupTestSuite) TestDeposits() { + q := make(url.Values) + q.Set("limit", "10") + q.Set("offset", "0") + + req := httptest.NewRequest(http.MethodGet, "/?"+q.Encode(), nil) + rec := httptest.NewRecorder() + c := s.echo.NewContext(req, rec) + c.SetPath("/rollup/:hash/deposits") + c.SetParamNames("hash") + c.SetParamValues(testRollupURLHash) + + s.rollups.EXPECT(). + ByHash(gomock.Any(), testRollup.AstriaId). + Return(testRollup, nil). + Times(1) + + s.deposits.EXPECT(). + ByRollupId(gomock.Any(), uint64(1), 10, 0, sdk.SortOrderDesc). + Return([]storage.Deposit{ + { + TxId: testTx.Id, + Time: testTime, + Height: 1000, + ActionId: 1, + Amount: decimal.RequireFromString("1000"), + Asset: currency.DefaultCurrency, + BridgeId: 1, + Tx: &testTx, + Bridge: &storage.Bridge{ + Address: &testAddress, + }, + }, + }, nil). + Times(1) + + s.Require().NoError(s.handler.Deposits(c)) + s.Require().Equal(http.StatusOK, rec.Code) + + var deposits []responses.Deposit + err := json.NewDecoder(rec.Body).Decode(&deposits) + s.Require().NoError(err) + s.Require().Len(deposits, 1) } diff --git a/cmd/api/handler/tx_test.go b/cmd/api/handler/tx_test.go index 116562e..3759cb6 100644 --- a/cmd/api/handler/tx_test.go +++ b/cmd/api/handler/tx_test.go @@ -114,7 +114,7 @@ func (s *TxTestSuite) TestList() { q.Set("offset", "0") q.Set("sort", "desc") q.Set("status", "success") - q.Set("action_types", "sequence,transfer") + q.Set("action_types", "rollup_data_submission,transfer") req := httptest.NewRequest(http.MethodGet, "/?"+q.Encode(), nil) rec := httptest.NewRecorder() @@ -127,7 +127,7 @@ func (s *TxTestSuite) TestList() { Offset: 0, Sort: pgSort(desc), Status: []string{"success"}, - ActionTypes: types.NewActionTypeMask(types.ActionTypeSequence.String(), types.ActionTypeTransfer.String()), + ActionTypes: types.NewActionTypeMask(types.ActionTypeRollupDataSubmission.String(), types.ActionTypeTransfer.String()), }). Return([]storage.Tx{ testTx, @@ -163,7 +163,7 @@ func (s *TxTestSuite) TestListValidationStatusError() { q.Set("offset", "0") q.Set("sort", "desc") q.Set("status", "invalid") - q.Set("action_types", "sequence,transfer") + q.Set("action_types", "rollup_data_submission,transfer") req := httptest.NewRequest(http.MethodGet, "/?"+q.Encode(), nil) rec := httptest.NewRecorder() @@ -207,7 +207,7 @@ func (s *TxTestSuite) TestListTime() { q.Set("offset", "0") q.Set("sort", "desc") q.Set("status", "success") - q.Set("action_types", "sequence") + q.Set("action_types", "rollup_data_submission") q.Set("from", "1692880000") q.Set("to", "1692890000") @@ -222,7 +222,7 @@ func (s *TxTestSuite) TestListTime() { Offset: 0, Sort: pgSort(desc), Status: []string{"success"}, - ActionTypes: types.NewActionTypeMask(types.ActionTypeSequence.String()), + ActionTypes: types.NewActionTypeMask(types.ActionTypeRollupDataSubmission.String()), TimeFrom: time.Unix(1692880000, 0).UTC(), TimeTo: time.Unix(1692890000, 0).UTC(), }). @@ -261,7 +261,7 @@ func (s *TxTestSuite) TestListWithActions() { q.Set("sort", "desc") q.Set("status", "success") q.Set("height", "100") - q.Set("action_types", "sequence") + q.Set("action_types", "rollup_data_submission") q.Set("with_actions", "true") req := httptest.NewRequest(http.MethodGet, "/?"+q.Encode(), nil) @@ -276,7 +276,7 @@ func (s *TxTestSuite) TestListWithActions() { Sort: pgSort(desc), Status: []string{"success"}, Height: 100, - ActionTypes: types.NewActionTypeMask(types.ActionTypeSequence.String()), + ActionTypes: types.NewActionTypeMask(types.ActionTypeRollupDataSubmission.String()), WithActions: true, }). Return([]storage.Tx{ @@ -342,7 +342,7 @@ func (s *TxTestSuite) TestGetActions() { s.Require().EqualValues(100, actions[0].Height) s.Require().EqualValues(1, actions[0].Position) s.Require().Equal(testTime, actions[0].Time) - s.Require().EqualValues(string(types.ActionTypeSequence), actions[0].Type) + s.Require().EqualValues(string(types.ActionTypeRollupDataSubmission), actions[0].Type) } func (s *TxTestSuite) TestCount() { @@ -389,7 +389,7 @@ func (s *TxTestSuite) TestRollupActions() { RollupId: 1, Rollup: &testRollup, Action: &storage.Action{ - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, }, }, }, nil). diff --git a/cmd/api/init.go b/cmd/api/init.go index 2012ab7..04d751c 100644 --- a/cmd/api/init.go +++ b/cmd/api/init.go @@ -263,7 +263,7 @@ func initHandlers(ctx context.Context, e *echo.Echo, cfg Config, db postgres.Sto searchHandler := handler.NewSearchHandler(db.Search, db.Address, db.Blocks, db.Tx, db.Rollup, db.Bridges, db.Validator) v1.GET("/search", searchHandler.Search) - addressHandlers := handler.NewAddressHandler(db.Address, db.Tx, db.Action, db.Rollup, db.Fee, db.Bridges, db.State, cfg.Indexer.Name) + addressHandlers := handler.NewAddressHandler(db.Address, db.Tx, db.Action, db.Rollup, db.Fee, db.Bridges, db.Deposit, db.State, cfg.Indexer.Name) addressesGroup := v1.Group("/address") { addressesGroup.GET("", addressHandlers.List) @@ -276,6 +276,7 @@ func initHandlers(ctx context.Context, e *echo.Echo, cfg Config, db postgres.Sto addressGroup.GET("/rollups", addressHandlers.Rollups) addressGroup.GET("/roles", addressHandlers.Roles) addressGroup.GET("/fees", addressHandlers.Fees) + addressGroup.GET("/deposits", addressHandlers.Deposits) } } @@ -310,7 +311,7 @@ func initHandlers(ctx context.Context, e *echo.Echo, cfg Config, db postgres.Sto } } - rollupsHandler := handler.NewRollupHandler(db.Rollup, db.Action, db.Bridges, db.State, cfg.Indexer.Name) + rollupsHandler := handler.NewRollupHandler(db.Rollup, db.Action, db.Bridges, db.Deposit, db.State, cfg.Indexer.Name) rollupsGroup := v1.Group("/rollup") { rollupsGroup.GET("", rollupsHandler.List) @@ -323,6 +324,7 @@ func initHandlers(ctx context.Context, e *echo.Echo, cfg Config, db postgres.Sto rollupGroup.GET("/all_actions", rollupsHandler.AllActions) rollupGroup.GET("/addresses", rollupsHandler.Addresses) rollupGroup.GET("/bridges", rollupsHandler.Bridges) + rollupGroup.GET("/deposits", rollupsHandler.Deposits) } } diff --git a/go.mod b/go.mod index a99a18b..818b996 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/celenium-io/astria-indexer go 1.23 require ( - buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240626163506-691883836b9e.2 - buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240627184145-2eaea785eb7d.2 + buf.build/gen/go/astria/primitives/protocolbuffers/go v1.35.1-20240911152449-eeebd3decdce.1 + buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.35.1-20241016184443-c3b7ab6e57dc.1 github.com/cometbft/cometbft v0.38.12 github.com/dipdup-io/workerpool v0.0.4 github.com/dipdup-net/go-lib v0.3.6 @@ -34,7 +34,7 @@ require ( go.opentelemetry.io/otel/trace v1.27.0 go.uber.org/mock v0.4.0 golang.org/x/time v0.5.0 - google.golang.org/protobuf v1.34.2 + google.golang.org/protobuf v1.35.1 ) require ( diff --git a/go.sum b/go.sum index 0469ea6..66c1fb0 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ -buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240626163506-691883836b9e.2 h1:bCHvCYyvhCPWGc3tpl164ONADbH+nKPSc6KhOWb9tfk= -buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240626163506-691883836b9e.2/go.mod h1:J0Tk7JAHcrhzWNEf1lbePSfFZ1Kp78eAlnO8Cs2ELKg= -buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240627184145-2eaea785eb7d.2 h1:+ihOgxxuevFtaVi7C86TVHg8Nusp1J6ARLqR0pEnR04= -buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240627184145-2eaea785eb7d.2/go.mod h1:Ko8az8QN6eXRnIJUUTjTLJUw4htfXfhGxBONXyJPy60= +buf.build/gen/go/astria/primitives/protocolbuffers/go v1.35.1-20240911152449-eeebd3decdce.1 h1:kG4riHqlF9X6iZ1Oxs5/6ul6aue7MS+A6DK6HAchuTk= +buf.build/gen/go/astria/primitives/protocolbuffers/go v1.35.1-20240911152449-eeebd3decdce.1/go.mod h1:n9L7X3VAj4od4VHf2ScJuHARUUQTSxJqtRHZk/7Ptt0= +buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.35.1-20241016184443-c3b7ab6e57dc.1 h1:5cxV/NMoiUqyAdi0DuAHsf2feJh60QjO+w/x3KyvF7Y= +buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.35.1-20241016184443-c3b7ab6e57dc.1/go.mod h1:XtXAwi+0M8MZWFDcda/0ShK1PKcFsLmdQOA6VKZdKVg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= @@ -537,8 +537,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/storage/action.go b/internal/storage/action.go index 0194386..7ba9328 100644 --- a/internal/storage/action.go +++ b/internal/storage/action.go @@ -67,6 +67,7 @@ type Action struct { BalanceUpdates []BalanceUpdate `bun:"-"` RollupAction *RollupAction `bun:"-"` Fee *Fee `bun:"rel:has-one,join:id=action_id"` + Deposit *Deposit `bun:"rel:has-one,join:id=action_id"` } // TableName - diff --git a/internal/storage/deposit.go b/internal/storage/deposit.go new file mode 100644 index 0000000..522623a --- /dev/null +++ b/internal/storage/deposit.go @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2024 PK Lab AG <contact@pklab.io> +// SPDX-License-Identifier: MIT + +package storage + +import ( + "context" + "time" + + pkgTypes "github.com/celenium-io/astria-indexer/pkg/types" + "github.com/dipdup-net/indexer-sdk/pkg/storage" + "github.com/shopspring/decimal" + "github.com/uptrace/bun" +) + +//go:generate mockgen -source=$GOFILE -destination=mock/$GOFILE -package=mock -typed +type IDeposit interface { + storage.Table[*Deposit] + + ByBridgeId(ctx context.Context, bridgeId uint64, limit, offset int, sort storage.SortOrder) ([]Deposit, error) + ByRollupId(ctx context.Context, rollupId uint64, limit, offset int, sort storage.SortOrder) ([]Deposit, error) +} + +type Deposit struct { + bun.BaseModel `bun:"deposit" comment:"Table with deposits"` + + Id uint64 `bun:"id,pk,notnull,autoincrement" comment:"Unique internal id"` + Height pkgTypes.Level `bun:",notnull" comment:"The number (height) of this block"` + Time time.Time `bun:"time,pk,notnull" comment:"The time of block"` + BridgeId uint64 `bun:"bridge_id" comment:"Bridge id"` + RollupId uint64 `bun:"rollup_id" comment:"Rollup id"` + Asset string `bun:"asset" comment:"Deposit asset"` + Amount decimal.Decimal `bun:"amount,type:numeric" comment:"Deposit amount"` + DestinationChainAddress string `bun:"destination_chain_address" comment:"Destination chain address"` + ActionId uint64 `bun:"action_id" comment:"Internal action id"` + TxId uint64 `bun:"tx_id" comment:"Internal transaction id"` + + Bridge *Bridge `bun:"rel:belongs-to"` + Rollup *Rollup `bun:"rel:belongs-to"` + Action *Action `bun:"rel:belongs-to"` + Tx *Tx `bun:"rel:belongs-to"` +} + +func (*Deposit) TableName() string { + return "deposit" +} diff --git a/internal/storage/generic.go b/internal/storage/generic.go index 8573401..c2f748d 100644 --- a/internal/storage/generic.go +++ b/internal/storage/generic.go @@ -37,6 +37,7 @@ var Models = []any{ &Bridge{}, &Fee{}, &Transfer{}, + &Deposit{}, } //go:generate mockgen -source=$GOFILE -destination=mock/$GOFILE -package=mock -typed @@ -58,6 +59,7 @@ type Transaction interface { SaveValidators(ctx context.Context, validators ...*Validator) error SaveFees(ctx context.Context, fees ...*Fee) error SaveTransfers(ctx context.Context, transfers ...*Transfer) error + SaveDeposits(ctx context.Context, deposits ...*Deposit) error RetentionBlockSignatures(ctx context.Context, height types.Level) error RollbackActions(ctx context.Context, height types.Level) (actions []Action, err error) @@ -75,6 +77,7 @@ type Transaction interface { RollbackTxs(ctx context.Context, height types.Level) (txs []Tx, err error) RollbackValidators(ctx context.Context, height types.Level) (err error) RollbackFees(ctx context.Context, height types.Level) (err error) + RollbackDeposits(ctx context.Context, height types.Level) (err error) RollbackTransfers(ctx context.Context, height types.Level) (err error) UpdateAddresses(ctx context.Context, address ...*Address) error UpdateConstants(ctx context.Context, constants ...*Constant) error @@ -86,6 +89,7 @@ type Transaction interface { GetProposerId(ctx context.Context, address string) (uint64, error) GetRollup(ctx context.Context, rollupId []byte) (Rollup, error) Validators(ctx context.Context) ([]Validator, error) + GetBridgeIdByAddressId(ctx context.Context, id uint64) (uint64, error) } type SearchResult struct { diff --git a/internal/storage/mock/deposit.go b/internal/storage/mock/deposit.go new file mode 100644 index 0000000..08dbb8a --- /dev/null +++ b/internal/storage/mock/deposit.go @@ -0,0 +1,393 @@ +// SPDX-FileCopyrightText: 2024 PK Lab AG <contact@pklab.io> +// SPDX-License-Identifier: MIT + +// Code generated by MockGen. DO NOT EDIT. +// Source: deposit.go +// +// Generated by this command: +// +// mockgen -source=deposit.go -destination=mock/deposit.go -package=mock -typed +// + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + reflect "reflect" + + storage "github.com/celenium-io/astria-indexer/internal/storage" + storage0 "github.com/dipdup-net/indexer-sdk/pkg/storage" + gomock "go.uber.org/mock/gomock" +) + +// MockIDeposit is a mock of IDeposit interface. +type MockIDeposit struct { + ctrl *gomock.Controller + recorder *MockIDepositMockRecorder +} + +// MockIDepositMockRecorder is the mock recorder for MockIDeposit. +type MockIDepositMockRecorder struct { + mock *MockIDeposit +} + +// NewMockIDeposit creates a new mock instance. +func NewMockIDeposit(ctrl *gomock.Controller) *MockIDeposit { + mock := &MockIDeposit{ctrl: ctrl} + mock.recorder = &MockIDepositMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIDeposit) EXPECT() *MockIDepositMockRecorder { + return m.recorder +} + +// ByBridgeId mocks base method. +func (m *MockIDeposit) ByBridgeId(ctx context.Context, bridgeId uint64, limit, offset int, sort storage0.SortOrder) ([]storage.Deposit, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ByBridgeId", ctx, bridgeId, limit, offset, sort) + ret0, _ := ret[0].([]storage.Deposit) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ByBridgeId indicates an expected call of ByBridgeId. +func (mr *MockIDepositMockRecorder) ByBridgeId(ctx, bridgeId, limit, offset, sort any) *MockIDepositByBridgeIdCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ByBridgeId", reflect.TypeOf((*MockIDeposit)(nil).ByBridgeId), ctx, bridgeId, limit, offset, sort) + return &MockIDepositByBridgeIdCall{Call: call} +} + +// MockIDepositByBridgeIdCall wrap *gomock.Call +type MockIDepositByBridgeIdCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIDepositByBridgeIdCall) Return(arg0 []storage.Deposit, arg1 error) *MockIDepositByBridgeIdCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIDepositByBridgeIdCall) Do(f func(context.Context, uint64, int, int, storage0.SortOrder) ([]storage.Deposit, error)) *MockIDepositByBridgeIdCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIDepositByBridgeIdCall) DoAndReturn(f func(context.Context, uint64, int, int, storage0.SortOrder) ([]storage.Deposit, error)) *MockIDepositByBridgeIdCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// ByRollupId mocks base method. +func (m *MockIDeposit) ByRollupId(ctx context.Context, rollupId uint64, limit, offset int, sort storage0.SortOrder) ([]storage.Deposit, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ByRollupId", ctx, rollupId, limit, offset, sort) + ret0, _ := ret[0].([]storage.Deposit) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ByRollupId indicates an expected call of ByRollupId. +func (mr *MockIDepositMockRecorder) ByRollupId(ctx, rollupId, limit, offset, sort any) *MockIDepositByRollupIdCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ByRollupId", reflect.TypeOf((*MockIDeposit)(nil).ByRollupId), ctx, rollupId, limit, offset, sort) + return &MockIDepositByRollupIdCall{Call: call} +} + +// MockIDepositByRollupIdCall wrap *gomock.Call +type MockIDepositByRollupIdCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIDepositByRollupIdCall) Return(arg0 []storage.Deposit, arg1 error) *MockIDepositByRollupIdCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIDepositByRollupIdCall) Do(f func(context.Context, uint64, int, int, storage0.SortOrder) ([]storage.Deposit, error)) *MockIDepositByRollupIdCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIDepositByRollupIdCall) DoAndReturn(f func(context.Context, uint64, int, int, storage0.SortOrder) ([]storage.Deposit, error)) *MockIDepositByRollupIdCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// CursorList mocks base method. +func (m *MockIDeposit) CursorList(ctx context.Context, id, limit uint64, order storage0.SortOrder, cmp storage0.Comparator) ([]*storage.Deposit, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CursorList", ctx, id, limit, order, cmp) + ret0, _ := ret[0].([]*storage.Deposit) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CursorList indicates an expected call of CursorList. +func (mr *MockIDepositMockRecorder) CursorList(ctx, id, limit, order, cmp any) *MockIDepositCursorListCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CursorList", reflect.TypeOf((*MockIDeposit)(nil).CursorList), ctx, id, limit, order, cmp) + return &MockIDepositCursorListCall{Call: call} +} + +// MockIDepositCursorListCall wrap *gomock.Call +type MockIDepositCursorListCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIDepositCursorListCall) Return(arg0 []*storage.Deposit, arg1 error) *MockIDepositCursorListCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIDepositCursorListCall) Do(f func(context.Context, uint64, uint64, storage0.SortOrder, storage0.Comparator) ([]*storage.Deposit, error)) *MockIDepositCursorListCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIDepositCursorListCall) DoAndReturn(f func(context.Context, uint64, uint64, storage0.SortOrder, storage0.Comparator) ([]*storage.Deposit, error)) *MockIDepositCursorListCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// GetByID mocks base method. +func (m *MockIDeposit) GetByID(ctx context.Context, id uint64) (*storage.Deposit, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetByID", ctx, id) + ret0, _ := ret[0].(*storage.Deposit) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetByID indicates an expected call of GetByID. +func (mr *MockIDepositMockRecorder) GetByID(ctx, id any) *MockIDepositGetByIDCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByID", reflect.TypeOf((*MockIDeposit)(nil).GetByID), ctx, id) + return &MockIDepositGetByIDCall{Call: call} +} + +// MockIDepositGetByIDCall wrap *gomock.Call +type MockIDepositGetByIDCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIDepositGetByIDCall) Return(arg0 *storage.Deposit, arg1 error) *MockIDepositGetByIDCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIDepositGetByIDCall) Do(f func(context.Context, uint64) (*storage.Deposit, error)) *MockIDepositGetByIDCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIDepositGetByIDCall) DoAndReturn(f func(context.Context, uint64) (*storage.Deposit, error)) *MockIDepositGetByIDCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// IsNoRows mocks base method. +func (m *MockIDeposit) IsNoRows(err error) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsNoRows", err) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsNoRows indicates an expected call of IsNoRows. +func (mr *MockIDepositMockRecorder) IsNoRows(err any) *MockIDepositIsNoRowsCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsNoRows", reflect.TypeOf((*MockIDeposit)(nil).IsNoRows), err) + return &MockIDepositIsNoRowsCall{Call: call} +} + +// MockIDepositIsNoRowsCall wrap *gomock.Call +type MockIDepositIsNoRowsCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIDepositIsNoRowsCall) Return(arg0 bool) *MockIDepositIsNoRowsCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIDepositIsNoRowsCall) Do(f func(error) bool) *MockIDepositIsNoRowsCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIDepositIsNoRowsCall) DoAndReturn(f func(error) bool) *MockIDepositIsNoRowsCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// LastID mocks base method. +func (m *MockIDeposit) LastID(ctx context.Context) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LastID", ctx) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// LastID indicates an expected call of LastID. +func (mr *MockIDepositMockRecorder) LastID(ctx any) *MockIDepositLastIDCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastID", reflect.TypeOf((*MockIDeposit)(nil).LastID), ctx) + return &MockIDepositLastIDCall{Call: call} +} + +// MockIDepositLastIDCall wrap *gomock.Call +type MockIDepositLastIDCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIDepositLastIDCall) Return(arg0 uint64, arg1 error) *MockIDepositLastIDCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIDepositLastIDCall) Do(f func(context.Context) (uint64, error)) *MockIDepositLastIDCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIDepositLastIDCall) DoAndReturn(f func(context.Context) (uint64, error)) *MockIDepositLastIDCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// List mocks base method. +func (m *MockIDeposit) List(ctx context.Context, limit, offset uint64, order storage0.SortOrder) ([]*storage.Deposit, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "List", ctx, limit, offset, order) + ret0, _ := ret[0].([]*storage.Deposit) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// List indicates an expected call of List. +func (mr *MockIDepositMockRecorder) List(ctx, limit, offset, order any) *MockIDepositListCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockIDeposit)(nil).List), ctx, limit, offset, order) + return &MockIDepositListCall{Call: call} +} + +// MockIDepositListCall wrap *gomock.Call +type MockIDepositListCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIDepositListCall) Return(arg0 []*storage.Deposit, arg1 error) *MockIDepositListCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIDepositListCall) Do(f func(context.Context, uint64, uint64, storage0.SortOrder) ([]*storage.Deposit, error)) *MockIDepositListCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIDepositListCall) DoAndReturn(f func(context.Context, uint64, uint64, storage0.SortOrder) ([]*storage.Deposit, error)) *MockIDepositListCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// Save mocks base method. +func (m_2 *MockIDeposit) Save(ctx context.Context, m *storage.Deposit) error { + m_2.ctrl.T.Helper() + ret := m_2.ctrl.Call(m_2, "Save", ctx, m) + ret0, _ := ret[0].(error) + return ret0 +} + +// Save indicates an expected call of Save. +func (mr *MockIDepositMockRecorder) Save(ctx, m any) *MockIDepositSaveCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Save", reflect.TypeOf((*MockIDeposit)(nil).Save), ctx, m) + return &MockIDepositSaveCall{Call: call} +} + +// MockIDepositSaveCall wrap *gomock.Call +type MockIDepositSaveCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIDepositSaveCall) Return(arg0 error) *MockIDepositSaveCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIDepositSaveCall) Do(f func(context.Context, *storage.Deposit) error) *MockIDepositSaveCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIDepositSaveCall) DoAndReturn(f func(context.Context, *storage.Deposit) error) *MockIDepositSaveCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// Update mocks base method. +func (m_2 *MockIDeposit) Update(ctx context.Context, m *storage.Deposit) error { + m_2.ctrl.T.Helper() + ret := m_2.ctrl.Call(m_2, "Update", ctx, m) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockIDepositMockRecorder) Update(ctx, m any) *MockIDepositUpdateCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockIDeposit)(nil).Update), ctx, m) + return &MockIDepositUpdateCall{Call: call} +} + +// MockIDepositUpdateCall wrap *gomock.Call +type MockIDepositUpdateCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIDepositUpdateCall) Return(arg0 error) *MockIDepositUpdateCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIDepositUpdateCall) Do(f func(context.Context, *storage.Deposit) error) *MockIDepositUpdateCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIDepositUpdateCall) DoAndReturn(f func(context.Context, *storage.Deposit) error) *MockIDepositUpdateCall { + c.Call = c.Call.DoAndReturn(f) + return c +} diff --git a/internal/storage/mock/generic.go b/internal/storage/mock/generic.go index be68722..f5612bc 100644 --- a/internal/storage/mock/generic.go +++ b/internal/storage/mock/generic.go @@ -281,6 +281,45 @@ func (c *MockTransactionFlushCall) DoAndReturn(f func(context.Context) error) *M return c } +// GetBridgeIdByAddressId mocks base method. +func (m *MockTransaction) GetBridgeIdByAddressId(ctx context.Context, id uint64) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBridgeIdByAddressId", ctx, id) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetBridgeIdByAddressId indicates an expected call of GetBridgeIdByAddressId. +func (mr *MockTransactionMockRecorder) GetBridgeIdByAddressId(ctx, id any) *MockTransactionGetBridgeIdByAddressIdCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBridgeIdByAddressId", reflect.TypeOf((*MockTransaction)(nil).GetBridgeIdByAddressId), ctx, id) + return &MockTransactionGetBridgeIdByAddressIdCall{Call: call} +} + +// MockTransactionGetBridgeIdByAddressIdCall wrap *gomock.Call +type MockTransactionGetBridgeIdByAddressIdCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockTransactionGetBridgeIdByAddressIdCall) Return(arg0 uint64, arg1 error) *MockTransactionGetBridgeIdByAddressIdCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockTransactionGetBridgeIdByAddressIdCall) Do(f func(context.Context, uint64) (uint64, error)) *MockTransactionGetBridgeIdByAddressIdCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockTransactionGetBridgeIdByAddressIdCall) DoAndReturn(f func(context.Context, uint64) (uint64, error)) *MockTransactionGetBridgeIdByAddressIdCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + // GetProposerId mocks base method. func (m *MockTransaction) GetProposerId(ctx context.Context, address string) (uint64, error) { m.ctrl.T.Helper() @@ -899,6 +938,44 @@ func (c *MockTransactionRollbackBridgesCall) DoAndReturn(f func(context.Context, return c } +// RollbackDeposits mocks base method. +func (m *MockTransaction) RollbackDeposits(ctx context.Context, height types.Level) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RollbackDeposits", ctx, height) + ret0, _ := ret[0].(error) + return ret0 +} + +// RollbackDeposits indicates an expected call of RollbackDeposits. +func (mr *MockTransactionMockRecorder) RollbackDeposits(ctx, height any) *MockTransactionRollbackDepositsCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RollbackDeposits", reflect.TypeOf((*MockTransaction)(nil).RollbackDeposits), ctx, height) + return &MockTransactionRollbackDepositsCall{Call: call} +} + +// MockTransactionRollbackDepositsCall wrap *gomock.Call +type MockTransactionRollbackDepositsCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockTransactionRollbackDepositsCall) Return(err error) *MockTransactionRollbackDepositsCall { + c.Call = c.Call.Return(err) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockTransactionRollbackDepositsCall) Do(f func(context.Context, types.Level) error) *MockTransactionRollbackDepositsCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockTransactionRollbackDepositsCall) DoAndReturn(f func(context.Context, types.Level) error) *MockTransactionRollbackDepositsCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + // RollbackFees mocks base method. func (m *MockTransaction) RollbackFees(ctx context.Context, height types.Level) error { m.ctrl.T.Helper() @@ -1514,6 +1591,49 @@ func (c *MockTransactionSaveConstantsCall) DoAndReturn(f func(context.Context, . return c } +// SaveDeposits mocks base method. +func (m *MockTransaction) SaveDeposits(ctx context.Context, deposits ...*storage.Deposit) error { + m.ctrl.T.Helper() + varargs := []any{ctx} + for _, a := range deposits { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "SaveDeposits", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// SaveDeposits indicates an expected call of SaveDeposits. +func (mr *MockTransactionMockRecorder) SaveDeposits(ctx any, deposits ...any) *MockTransactionSaveDepositsCall { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx}, deposits...) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveDeposits", reflect.TypeOf((*MockTransaction)(nil).SaveDeposits), varargs...) + return &MockTransactionSaveDepositsCall{Call: call} +} + +// MockTransactionSaveDepositsCall wrap *gomock.Call +type MockTransactionSaveDepositsCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockTransactionSaveDepositsCall) Return(arg0 error) *MockTransactionSaveDepositsCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockTransactionSaveDepositsCall) Do(f func(context.Context, ...*storage.Deposit) error) *MockTransactionSaveDepositsCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockTransactionSaveDepositsCall) DoAndReturn(f func(context.Context, ...*storage.Deposit) error) *MockTransactionSaveDepositsCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + // SaveFees mocks base method. func (m *MockTransaction) SaveFees(ctx context.Context, fees ...*storage.Fee) error { m.ctrl.T.Helper() diff --git a/internal/storage/postgres/action_test.go b/internal/storage/postgres/action_test.go index 743bbcd..9fae97d 100644 --- a/internal/storage/postgres/action_test.go +++ b/internal/storage/postgres/action_test.go @@ -25,7 +25,7 @@ func (s *StorageTestSuite) TestActionByBlock() { s.Require().EqualValues(1, action.Id) s.Require().EqualValues(0, action.Position) s.Require().EqualValues(1, action.TxId) - s.Require().EqualValues(types.ActionTypeSequence, action.Type) + s.Require().EqualValues(types.ActionTypeRollupDataSubmission, action.Type) s.Require().NotNil(action.Data) s.Require().NotNil(action.Fee) s.Require().NotNil(action.Tx) @@ -45,7 +45,7 @@ func (s *StorageTestSuite) TestActionByTxId() { s.Require().EqualValues(1, action.Id) s.Require().EqualValues(0, action.Position) s.Require().EqualValues(1, action.TxId) - s.Require().EqualValues(types.ActionTypeSequence, action.Type) + s.Require().EqualValues(types.ActionTypeRollupDataSubmission, action.Type) s.Require().NotNil(action.Data) s.Require().NotNil(action.Fee) } @@ -57,7 +57,7 @@ func (s *StorageTestSuite) TestActionByAddress() { actions, err := s.storage.Action.ByAddress(ctx, 1, storage.AddressActionsFilter{ Sort: sdk.SortOrderAsc, Limit: 1, - ActionTypes: types.NewActionTypeMask(types.ActionTypeSequence.String()), + ActionTypes: types.NewActionTypeMask(types.ActionTypeRollupDataSubmission.String()), }) s.Require().NoError(err) s.Require().Len(actions, 1) @@ -69,7 +69,7 @@ func (s *StorageTestSuite) TestActionByAddress() { s.Require().NotNil(action.Tx) s.Require().NotNil(action.Action) s.Require().EqualValues(1, action.Action.TxId) - s.Require().EqualValues(types.ActionTypeSequence, action.Action.Type) + s.Require().EqualValues(types.ActionTypeRollupDataSubmission, action.Action.Type) s.Require().NotNil(action.Action.Data) s.Require().NotNil(action.Action.Fee) } @@ -89,7 +89,7 @@ func (s *StorageTestSuite) TestActionByRollup() { s.Require().NotNil(action.Tx) s.Require().NotNil(action.Action) s.Require().EqualValues(1, action.Action.TxId) - s.Require().EqualValues(types.ActionTypeSequence, action.Action.Type) + s.Require().EqualValues(types.ActionTypeRollupDataSubmission, action.Action.Type) s.Require().NotNil(action.Action.Data) s.Require().NotNil(action.Action.Fee) } @@ -113,7 +113,7 @@ func (s *StorageTestSuite) TestActionByRollupAndBridge() { s.Require().NotNil(action.Tx) s.Require().NotNil(action.Action) s.Require().EqualValues(1, action.Action.TxId) - s.Require().EqualValues(types.ActionTypeSequence, action.Action.Type) + s.Require().EqualValues(types.ActionTypeRollupDataSubmission, action.Action.Type) s.Require().NotNil(action.Action.Data) s.Require().NotNil(action.Action.Fee) } @@ -137,7 +137,7 @@ func (s *StorageTestSuite) TestActionByRollupAndBridgeWithoutRollupActions() { s.Require().NotNil(action.Tx) s.Require().NotNil(action.Action) s.Require().EqualValues(1, action.Action.TxId) - s.Require().EqualValues(types.ActionTypeSequence, action.Action.Type) + s.Require().EqualValues(types.ActionTypeRollupDataSubmission, action.Action.Type) s.Require().NotNil(action.Action.Data) s.Require().NotNil(action.Action.Fee) } diff --git a/internal/storage/postgres/core.go b/internal/storage/postgres/core.go index b133919..31bd0a0 100644 --- a/internal/storage/postgres/core.go +++ b/internal/storage/postgres/core.go @@ -30,6 +30,7 @@ type Storage struct { Tx models.ITx Transfers models.ITransfer Fee models.IFee + Deposit models.IDeposit Action models.IAction Address models.IAddress Rollup models.IRollup @@ -58,6 +59,7 @@ func Create(ctx context.Context, cfg config.Database, scriptsDir string) (Storag Constants: NewConstant(strg.Connection()), Action: NewAction(strg.Connection()), Fee: NewFee(strg.Connection()), + Deposit: NewDeposit(strg.Connection()), Address: NewAddress(strg.Connection()), BlockSignatures: NewBlockSignature(strg.Connection()), Rollup: NewRollup(strg.Connection()), @@ -131,6 +133,7 @@ func createHypertables(ctx context.Context, conn *database.Bun) error { &models.RollupAction{}, &models.Fee{}, &models.Transfer{}, + &models.Deposit{}, } { if _, err := tx.ExecContext(ctx, `SELECT create_hypertable(?, 'time', chunk_time_interval => INTERVAL '1 month', if_not_exists => TRUE);`, diff --git a/internal/storage/postgres/deposit.go b/internal/storage/postgres/deposit.go new file mode 100644 index 0000000..e9f8dba --- /dev/null +++ b/internal/storage/postgres/deposit.go @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: 2024 PK Lab AG <contact@pklab.io> +// SPDX-License-Identifier: MIT + +package postgres + +import ( + "context" + + "github.com/celenium-io/astria-indexer/internal/storage" + "github.com/dipdup-net/go-lib/database" + sdk "github.com/dipdup-net/indexer-sdk/pkg/storage" + "github.com/dipdup-net/indexer-sdk/pkg/storage/postgres" +) + +// Fee - +type Deposit struct { + *postgres.Table[*storage.Deposit] +} + +// NewDeposit - +func NewDeposit(db *database.Bun) *Deposit { + return &Deposit{ + Table: postgres.NewTable[*storage.Deposit](db), + } +} + +func (d *Deposit) ByBridgeId(ctx context.Context, bridgeId uint64, limit, offset int, sort sdk.SortOrder) (deposits []storage.Deposit, err error) { + query := d.DB().NewSelect(). + Model((*storage.Deposit)(nil)). + Where("bridge_id = ?", bridgeId) + + query = limitScope(query, limit) + query = offsetScope(query, offset) + query = sortScope(query, "time", sort) + + err = d.DB().NewSelect(). + TableExpr("(?) as deposit", query). + ColumnExpr("deposit.*"). + ColumnExpr("tx.hash as tx__hash"). + Join("left join tx on tx.id = tx_id"). + Scan(ctx, &deposits) + return +} + +func (d *Deposit) ByRollupId(ctx context.Context, rollupId uint64, limit, offset int, sort sdk.SortOrder) (deposits []storage.Deposit, err error) { + query := d.DB().NewSelect(). + Model((*storage.Deposit)(nil)). + Where("rollup_id = ?", rollupId) + + query = limitScope(query, limit) + query = offsetScope(query, offset) + query = sortScope(query, "time", sort) + + err = d.DB().NewSelect(). + TableExpr("(?) as deposit", query). + ColumnExpr("deposit.*"). + ColumnExpr("tx.hash as tx__hash"). + ColumnExpr("bridge.address_id as bridge__address_id"). + ColumnExpr("address.hash as bridge__address__hash"). + Join("left join tx on tx.id = tx_id"). + Join("left join bridge on bridge_id = bridge.id"). + Join("left join address on address_id = address.id"). + Scan(ctx, &deposits) + + return +} diff --git a/internal/storage/postgres/deposit_test.go b/internal/storage/postgres/deposit_test.go new file mode 100644 index 0000000..b880e4d --- /dev/null +++ b/internal/storage/postgres/deposit_test.go @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: 2024 PK Lab AG <contact@pklab.io> +// SPDX-License-Identifier: MIT + +package postgres + +import ( + "context" + "encoding/hex" + "time" + + "github.com/dipdup-net/indexer-sdk/pkg/storage" +) + +func (s *StorageTestSuite) TestDepositByBridgeId() { + ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer ctxCancel() + + deposits, err := s.storage.Deposit.ByBridgeId(ctx, 1, 10, 0, storage.SortOrderDesc) + s.Require().NoError(err) + s.Require().Len(deposits, 1) + + deposit := deposits[0] + s.Require().EqualValues(7965, deposit.Height) + s.Require().EqualValues(1, deposit.RollupId) + s.Require().EqualValues(1, deposit.BridgeId) + s.Require().EqualValues("100", deposit.Amount.String()) + s.Require().EqualValues("destination_chain_address", deposit.DestinationChainAddress) + s.Require().EqualValues("nria", deposit.Asset) + + s.Require().NotNil(deposit.Tx) + hash := hex.EncodeToString(deposit.Tx.Hash) + s.Require().Equal("a7bc8121a38725bd33e5d66b80817a2ba39e517fb6b9244a7081ad2fb210bfcc", hash) + + s.Require().Nil(deposit.Action) + s.Require().Nil(deposit.Bridge) + s.Require().Nil(deposit.Rollup) +} + +func (s *StorageTestSuite) TestDepositByRollupId() { + ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer ctxCancel() + + deposits, err := s.storage.Deposit.ByRollupId(ctx, 1, 10, 0, storage.SortOrderDesc) + s.Require().NoError(err) + s.Require().Len(deposits, 1) + + deposit := deposits[0] + s.Require().EqualValues(7965, deposit.Height) + s.Require().EqualValues(1, deposit.RollupId) + s.Require().EqualValues(1, deposit.BridgeId) + s.Require().EqualValues("100", deposit.Amount.String()) + s.Require().EqualValues("destination_chain_address", deposit.DestinationChainAddress) + s.Require().EqualValues("nria", deposit.Asset) + + s.Require().NotNil(deposit.Tx) + hash := hex.EncodeToString(deposit.Tx.Hash) + s.Require().Equal("a7bc8121a38725bd33e5d66b80817a2ba39e517fb6b9244a7081ad2fb210bfcc", hash) + + s.Require().NotNil(deposit.Bridge) + s.Require().NotNil(deposit.Bridge.Address) + s.Require().EqualValues("astria1lm45urgugesyhaymn68xww0m6g49zreqa32w7p", deposit.Bridge.Address.Hash) + + s.Require().Nil(deposit.Action) + s.Require().Nil(deposit.Rollup) +} diff --git a/internal/storage/postgres/index.go b/internal/storage/postgres/index.go index 1a5afc9..20244ec 100644 --- a/internal/storage/postgres/index.go +++ b/internal/storage/postgres/index.go @@ -335,6 +335,42 @@ func createIndices(ctx context.Context, conn *database.Bun) error { return err } + // Deposit + if _, err := tx.NewCreateIndex(). + IfNotExists(). + Model((*storage.Deposit)(nil)). + Index("deposit_height_idx"). + Column("height"). + Using("BRIN"). + Exec(ctx); err != nil { + return err + } + if _, err := tx.NewCreateIndex(). + IfNotExists(). + Model((*storage.Deposit)(nil)). + Index("deposit_action_id_idx"). + Column("action_id"). + Using("BRIN"). + Exec(ctx); err != nil { + return err + } + if _, err := tx.NewCreateIndex(). + IfNotExists(). + Model((*storage.Deposit)(nil)). + Index("deposit_rollup_id_idx"). + Column("rollup_id"). + Exec(ctx); err != nil { + return err + } + if _, err := tx.NewCreateIndex(). + IfNotExists(). + Model((*storage.Deposit)(nil)). + Index("deposit_bridge_id_idx"). + Column("bridge_id"). + Exec(ctx); err != nil { + return err + } + return nil }) } diff --git a/internal/storage/postgres/transaction.go b/internal/storage/postgres/transaction.go index ed5134f..844228a 100644 --- a/internal/storage/postgres/transaction.go +++ b/internal/storage/postgres/transaction.go @@ -111,6 +111,15 @@ func (tx Transaction) SaveFees(ctx context.Context, fees ...*models.Fee) error { return err } +func (tx Transaction) SaveDeposits(ctx context.Context, deposits ...*models.Deposit) error { + if len(deposits) == 0 { + return nil + } + + _, err := tx.Tx().NewInsert().Model(&deposits).Returning("id").Exec(ctx) + return err +} + func (tx Transaction) SaveTransfers(ctx context.Context, transfers ...*models.Transfer) error { if len(transfers) == 0 { return nil @@ -358,6 +367,14 @@ func (tx Transaction) RollbackFees(ctx context.Context, height types.Level) (err return } +func (tx Transaction) RollbackDeposits(ctx context.Context, height types.Level) (err error) { + _, err = tx.Tx().NewDelete(). + Model((*models.Deposit)(nil)). + Where("height = ?", height). + Exec(ctx) + return +} + func (tx Transaction) RollbackTransfers(ctx context.Context, height types.Level) (err error) { _, err = tx.Tx().NewDelete(). Model((*models.Transfer)(nil)). @@ -474,3 +491,12 @@ func (tx Transaction) GetRollup(ctx context.Context, rollupId []byte) (rollup mo Scan(ctx) return } + +func (tx Transaction) GetBridgeIdByAddressId(ctx context.Context, id uint64) (bridgeId uint64, err error) { + err = tx.Tx().NewSelect(). + Column("id"). + Model((*models.Bridge)(nil)). + Where("address_id = ?", id). + Scan(ctx, &bridgeId) + return +} diff --git a/internal/storage/postgres/transaction_test.go b/internal/storage/postgres/transaction_test.go index 3888864..1904cca 100644 --- a/internal/storage/postgres/transaction_test.go +++ b/internal/storage/postgres/transaction_test.go @@ -309,6 +309,54 @@ func (s *TransactionTestSuite) TestSaveRollupAddresses() { s.Require().NoError(tx.Close(ctx)) } +func (s *TransactionTestSuite) TestSaveFees() { + ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer ctxCancel() + + tx, err := BeginTransaction(ctx, s.storage.Transactable) + s.Require().NoError(err) + + fees := make([]*storage.Fee, 5) + for i := 0; i < 5; i++ { + fees[i] = &storage.Fee{ + PayerId: uint64(i + 1), + TxId: uint64(5 - i), + ActionId: uint64(5 - i), + Height: 10000, + } + } + + err = tx.SaveFees(ctx, fees...) + s.Require().NoError(err) + + s.Require().NoError(tx.Flush(ctx)) + s.Require().NoError(tx.Close(ctx)) +} + +func (s *TransactionTestSuite) TestSaveDeposits() { + ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer ctxCancel() + + tx, err := BeginTransaction(ctx, s.storage.Transactable) + s.Require().NoError(err) + + deposits := make([]*storage.Deposit, 5) + for i := 0; i < 5; i++ { + deposits[i] = &storage.Deposit{ + BridgeId: uint64(i + 1), + RollupId: uint64(5 - i), + ActionId: uint64(5 - i), + Height: 10000, + } + } + + err = tx.SaveDeposits(ctx, deposits...) + s.Require().NoError(err) + + s.Require().NoError(tx.Flush(ctx)) + s.Require().NoError(tx.Close(ctx)) +} + func (s *TransactionTestSuite) TestSaveMsgAddresses() { ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) defer ctxCancel() @@ -551,6 +599,34 @@ func (s *TransactionTestSuite) TestRollbackBridge() { s.Require().NoError(tx.Close(ctx)) } +func (s *TransactionTestSuite) TestRollbackFees() { + ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer ctxCancel() + + tx, err := BeginTransaction(ctx, s.storage.Transactable) + s.Require().NoError(err) + + err = tx.RollbackFees(ctx, 7316) + s.Require().NoError(err) + + s.Require().NoError(tx.Flush(ctx)) + s.Require().NoError(tx.Close(ctx)) +} + +func (s *TransactionTestSuite) TestRollbackDeposits() { + ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer ctxCancel() + + tx, err := BeginTransaction(ctx, s.storage.Transactable) + s.Require().NoError(err) + + err = tx.RollbackDeposits(ctx, 7965) + s.Require().NoError(err) + + s.Require().NoError(tx.Flush(ctx)) + s.Require().NoError(tx.Close(ctx)) +} + func (s *TransactionTestSuite) TestRollbackBlockStats() { ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) defer ctxCancel() @@ -854,3 +930,18 @@ func (s *TransactionTestSuite) TestUpdateConstants() { s.Require().NoError(err) s.Require().EqualValues("100", c.Value) } + +func (s *TransactionTestSuite) TestGetBridgeIdByAddressId() { + ctx, ctxCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer ctxCancel() + + tx, err := BeginTransaction(ctx, s.storage.Transactable) + s.Require().NoError(err) + + id, err := tx.GetBridgeIdByAddressId(ctx, 1) + s.Require().NoError(err) + s.Require().EqualValues(1, id) + + s.Require().NoError(tx.Flush(ctx)) + s.Require().NoError(tx.Close(ctx)) +} diff --git a/internal/storage/postgres/tx_test.go b/internal/storage/postgres/tx_test.go index aef57ec..159e95c 100644 --- a/internal/storage/postgres/tx_test.go +++ b/internal/storage/postgres/tx_test.go @@ -69,7 +69,7 @@ func (s *StorageTestSuite) TestTxFilter() { WithActions: true, TimeFrom: time.Date(2023, 11, 30, 23, 52, 23, 0, time.UTC), Sort: sdk.SortOrderAsc, - ActionTypes: types.NewActionTypeMask(types.ActionTypeSequence.String()), + ActionTypes: types.NewActionTypeMask(types.ActionTypeRollupDataSubmission.String()), }) s.Require().NoError(err) s.Require().Len(txs, 1) @@ -102,7 +102,7 @@ func (s *StorageTestSuite) TestTxByAddress() { WithActions: true, TimeFrom: time.Date(2023, 11, 30, 23, 52, 23, 0, time.UTC), Sort: sdk.SortOrderAsc, - ActionTypes: types.NewActionTypeMask(types.ActionTypeSequence.String()), + ActionTypes: types.NewActionTypeMask(types.ActionTypeRollupDataSubmission.String()), }) s.Require().NoError(err) s.Require().Len(txs, 1) diff --git a/internal/storage/types/action_type.go b/internal/storage/types/action_type.go index f93a867..22c3c0c 100644 --- a/internal/storage/types/action_type.go +++ b/internal/storage/types/action_type.go @@ -7,7 +7,7 @@ package types /* ENUM( transfer, - sequence, + rollup_data_submission, validator_update, sudo_address_change, ibc_relay, @@ -18,7 +18,8 @@ package types bridge_lock, bridge_unlock, bridge_sudo_change_action, - fee_change + fee_change, + ibc_sudo_change_action ) */ //go:generate go-enum --marshal --sql --values --names diff --git a/internal/storage/types/action_type_enum.go b/internal/storage/types/action_type_enum.go index 047d050..daa22c5 100644 --- a/internal/storage/types/action_type_enum.go +++ b/internal/storage/types/action_type_enum.go @@ -19,8 +19,8 @@ import ( const ( // ActionTypeTransfer is a ActionType of type transfer. ActionTypeTransfer ActionType = "transfer" - // ActionTypeSequence is a ActionType of type sequence. - ActionTypeSequence ActionType = "sequence" + // ActionTypeRollupDataSubmission is a ActionType of type rollup_data_submission. + ActionTypeRollupDataSubmission ActionType = "rollup_data_submission" // ActionTypeValidatorUpdate is a ActionType of type validator_update. ActionTypeValidatorUpdate ActionType = "validator_update" // ActionTypeSudoAddressChange is a ActionType of type sudo_address_change. @@ -43,13 +43,15 @@ const ( ActionTypeBridgeSudoChangeAction ActionType = "bridge_sudo_change_action" // ActionTypeFeeChange is a ActionType of type fee_change. ActionTypeFeeChange ActionType = "fee_change" + // ActionTypeIbcSudoChangeAction is a ActionType of type ibc_sudo_change_action. + ActionTypeIbcSudoChangeAction ActionType = "ibc_sudo_change_action" ) var ErrInvalidActionType = fmt.Errorf("not a valid ActionType, try [%s]", strings.Join(_ActionTypeNames, ", ")) var _ActionTypeNames = []string{ string(ActionTypeTransfer), - string(ActionTypeSequence), + string(ActionTypeRollupDataSubmission), string(ActionTypeValidatorUpdate), string(ActionTypeSudoAddressChange), string(ActionTypeIbcRelay), @@ -61,6 +63,7 @@ var _ActionTypeNames = []string{ string(ActionTypeBridgeUnlock), string(ActionTypeBridgeSudoChangeAction), string(ActionTypeFeeChange), + string(ActionTypeIbcSudoChangeAction), } // ActionTypeNames returns a list of possible string values of ActionType. @@ -74,7 +77,7 @@ func ActionTypeNames() []string { func ActionTypeValues() []ActionType { return []ActionType{ ActionTypeTransfer, - ActionTypeSequence, + ActionTypeRollupDataSubmission, ActionTypeValidatorUpdate, ActionTypeSudoAddressChange, ActionTypeIbcRelay, @@ -86,6 +89,7 @@ func ActionTypeValues() []ActionType { ActionTypeBridgeUnlock, ActionTypeBridgeSudoChangeAction, ActionTypeFeeChange, + ActionTypeIbcSudoChangeAction, } } @@ -103,7 +107,7 @@ func (x ActionType) IsValid() bool { var _ActionTypeValue = map[string]ActionType{ "transfer": ActionTypeTransfer, - "sequence": ActionTypeSequence, + "rollup_data_submission": ActionTypeRollupDataSubmission, "validator_update": ActionTypeValidatorUpdate, "sudo_address_change": ActionTypeSudoAddressChange, "ibc_relay": ActionTypeIbcRelay, @@ -115,6 +119,7 @@ var _ActionTypeValue = map[string]ActionType{ "bridge_unlock": ActionTypeBridgeUnlock, "bridge_sudo_change_action": ActionTypeBridgeSudoChangeAction, "fee_change": ActionTypeFeeChange, + "ibc_sudo_change_action": ActionTypeIbcSudoChangeAction, } // ParseActionType attempts to convert a string to a ActionType. diff --git a/internal/storage/types/action_type_mask.go b/internal/storage/types/action_type_mask.go index e5722b5..f62604b 100644 --- a/internal/storage/types/action_type_mask.go +++ b/internal/storage/types/action_type_mask.go @@ -5,7 +5,7 @@ package types const ( ActionTypeTransferBits Bits = 1 << iota - ActionTypeSequenceBits + ActionTypeRollupDataSubmissionBits ActionTypeValidatorUpdateBits ActionTypeSudoAddressChangeBits ActionTypeIbcRelayBits @@ -17,13 +17,14 @@ const ( ActionTypeBridgeUnlockBits ActionTypeBridgeSudoChangeBits ActionTypeFeeChangeBits + ActionTypeIbcSudoChangeBits ) var ( actionTypesMap = map[ActionType]Bits{ ActionTypeIbcRelay: ActionTypeIbcRelayBits, ActionTypeIcs20Withdrawal: ActionTypeIcs20WithdrawalBits, - ActionTypeSequence: ActionTypeSequenceBits, + ActionTypeRollupDataSubmission: ActionTypeRollupDataSubmissionBits, ActionTypeSudoAddressChange: ActionTypeSudoAddressChangeBits, ActionTypeTransfer: ActionTypeTransferBits, ActionTypeValidatorUpdate: ActionTypeValidatorUpdateBits, @@ -34,6 +35,7 @@ var ( ActionTypeBridgeUnlock: ActionTypeBridgeUnlockBits, ActionTypeBridgeSudoChangeAction: ActionTypeBridgeSudoChangeBits, ActionTypeFeeChange: ActionTypeFeeChangeBits, + ActionTypeIbcSudoChangeAction: ActionTypeIbcSudoChangeBits, } ) @@ -49,8 +51,8 @@ func NewActionTypeMask(vals ...string) ActionTypeMask { mask.Set(ActionTypeIbcRelayBits) case string(ActionTypeIcs20Withdrawal): mask.Set(ActionTypeIcs20WithdrawalBits) - case string(ActionTypeSequence): - mask.Set(ActionTypeSequenceBits) + case string(ActionTypeRollupDataSubmission): + mask.Set(ActionTypeRollupDataSubmissionBits) case string(ActionTypeSudoAddressChange): mask.Set(ActionTypeSudoAddressChangeBits) case string(ActionTypeTransfer): @@ -71,6 +73,8 @@ func NewActionTypeMask(vals ...string) ActionTypeMask { mask.Set(ActionTypeBridgeSudoChangeBits) case string(ActionTypeFeeChange): mask.Set(ActionTypeFeeChangeBits) + case string(ActionTypeIbcSudoChangeAction): + mask.Set(ActionTypeIbcSudoChangeBits) } } @@ -87,7 +91,7 @@ func (mask ActionTypeMask) Strings() []string { } vals := make([]string, 0) - for val := ActionTypeTransferBits; val <= ActionTypeFeeChangeBits; val <<= 1 { + for val := ActionTypeTransferBits; val <= ActionTypeIbcSudoChangeBits; val <<= 1 { if !mask.Has(val) { continue } @@ -96,8 +100,8 @@ func (mask ActionTypeMask) Strings() []string { vals = append(vals, string(ActionTypeIbcRelay)) case ActionTypeIcs20WithdrawalBits: vals = append(vals, string(ActionTypeIcs20Withdrawal)) - case ActionTypeSequenceBits: - vals = append(vals, string(ActionTypeSequence)) + case ActionTypeRollupDataSubmissionBits: + vals = append(vals, string(ActionTypeRollupDataSubmission)) case ActionTypeSudoAddressChangeBits: vals = append(vals, string(ActionTypeSudoAddressChange)) case ActionTypeTransferBits: @@ -118,6 +122,8 @@ func (mask ActionTypeMask) Strings() []string { vals = append(vals, string(ActionTypeBridgeUnlock)) case ActionTypeFeeChangeBits: vals = append(vals, string(ActionTypeFeeChange)) + case ActionTypeIbcSudoChangeBits: + vals = append(vals, string(ActionTypeIbcSudoChangeAction)) } } diff --git a/internal/storage/types/action_type_mask_test.go b/internal/storage/types/action_type_mask_test.go index 5c948f2..a5e9955 100644 --- a/internal/storage/types/action_type_mask_test.go +++ b/internal/storage/types/action_type_mask_test.go @@ -37,8 +37,8 @@ func TestActionTypeMask(t *testing.T) { require.Equal(t, arr, mask.Strings()) }) - t.Run("sequence", func(t *testing.T) { - arr := []string{string(ActionTypeSequence)} + t.Run("rollup data submission", func(t *testing.T) { + arr := []string{string(ActionTypeRollupDataSubmission)} mask := NewActionTypeMask(arr...) require.Equal(t, arr, mask.Strings()) @@ -100,6 +100,13 @@ func TestActionTypeMask(t *testing.T) { require.Equal(t, arr, mask.Strings()) }) + t.Run("ibc sudo change", func(t *testing.T) { + arr := []string{string(ActionTypeIbcSudoChangeAction)} + + mask := NewActionTypeMask(arr...) + require.Equal(t, arr, mask.Strings()) + }) + t.Run("unknown", func(t *testing.T) { arr := []string{"unknown"} diff --git a/internal/test_suite/block.go b/internal/test_suite/block.go index c0b9881..55ffc98 100644 --- a/internal/test_suite/block.go +++ b/internal/test_suite/block.go @@ -18,7 +18,7 @@ func EmptyBlock() (types.BlockData, time.Time) { var txs = []string{ "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", - "CkATSNqP3ZBN+DgYi3anxjPcVt14d55cFq5k2hD4bZ+3iblkQ9JDam0MxTFC7osXFM/WFrrVSopirkV50xYGyh8PEiBzAhb1xqe9xHmqHiernziq508EQ6u4fVdyVFwH1Ctz2RpaCjovYXN0cmlhLnByb3RvY29sLnRyYW5zYWN0aW9ucy52MWFscGhhMS5VbnNpZ25lZFRyYW5zYWN0aW9uEhwKCaoDBgoEbnJpYRIPEg1hc3RyaWEtZHVzay04", + "CkCBcBs4ojg/IV1xLhFs5RNGSMwrlPQTuNSZB2WpfR1HD8AQF72Vdr/VhCKn2ppL4KBGgiKp+FqzchZdUIqTCy8IEiD1A4vkUMma1i1j6Mq95eIjQWn290avEMhbIEaK5psMmRq7AQovL2FzdHJpYS5wcm90b2NvbC50cmFuc2FjdGlvbi52MS5UcmFuc2FjdGlvbkJvZHkShwEKEBIOYXN0cmlhLWR1c2stMTESc2JxCi8SLWFzdHJpYTF5cWRqbm5tcnA3dzV5Z3dqMGRrbGRzZ3pqaHY1dmNha3A3eWV1ORIGCICU69wDGgRucmlhIgRucmlhKioweDlkMENFQzdCRUI5NDhBYjA0NmU4YjY0RTlhYTZDYzliNzMxQTk2MTM=", } func CreateTestBlock(tx types.ResponseDeliverTx, withTxs bool) (types.BlockData, time.Time) { diff --git a/pkg/indexer/decode/actions.go b/pkg/indexer/decode/actions.go index f85480d..28d6123 100644 --- a/pkg/indexer/decode/actions.go +++ b/pkg/indexer/decode/actions.go @@ -5,10 +5,11 @@ package decode import ( "encoding/base64" - "encoding/hex" + "fmt" "time" - astria "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria/protocol/transactions/v1alpha1" + primitive "buf.build/gen/go/astria/primitives/protocolbuffers/go/astria/primitive/v1" + astria "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria/protocol/transaction/v1alpha1" "github.com/celenium-io/astria-indexer/internal/currency" "github.com/celenium-io/astria-indexer/internal/storage" storageTypes "github.com/celenium-io/astria-indexer/internal/storage/types" @@ -40,70 +41,75 @@ func parseActions(height types.Level, blockTime time.Time, from string, tx *Deco ) switch val := rawActions[i].GetValue().(type) { - case *astria.Action_IbcAction: + case *astria.Action_Ibc: tx.ActionTypes.Set(storageTypes.ActionTypeIbcRelayBits) err = parseIbcAction(val, &actions[i]) - feeType = "penumbra.core.component.ibc.v1.IbcAction" + feeType = "penumbra.core.component.ibc.v1.IbcRelay" case *astria.Action_Ics20Withdrawal: tx.ActionTypes.Set(storageTypes.ActionTypeIcs20WithdrawalBits) err = parseIcs20Withdrawal(val, from, height, ctx, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.Ics20Withdrawal" + feeType = "astria.protocol.transaction.v1alpha1.Ics20Withdrawal" - case *astria.Action_SequenceAction: - tx.ActionTypes.Set(storageTypes.ActionTypeSequenceBits) - err = parseSequenceAction(val, from, height, ctx, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.SequenceAction" + case *astria.Action_RollupDataSubmission: + tx.ActionTypes.Set(storageTypes.ActionTypeRollupDataSubmissionBits) + err = parseRollupDataSubmission(val, from, height, ctx, &actions[i]) + feeType = "astria.protocol.transaction.v1alpha1.RollupDataSubmission" - case *astria.Action_SudoAddressChangeAction: + case *astria.Action_SudoAddressChange: tx.ActionTypes.Set(storageTypes.ActionTypeSudoAddressChangeBits) - err = parseSudoAddressChangeAction(val, height, ctx, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.SudoAddressChangeAction" + err = parseSudoAddressChangeAction(val, ctx, &actions[i]) + feeType = "astria.protocol.transaction.v1alpha1.SudoAddressChange" - case *astria.Action_TransferAction: + case *astria.Action_Transfer: tx.ActionTypes.Set(storageTypes.ActionTypeTransferBits) err = parseTransferAction(val, from, height, ctx, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.TransferAction" + feeType = "astria.protocol.transaction.v1alpha1.Transfer" - case *astria.Action_ValidatorUpdateAction: + case *astria.Action_ValidatorUpdate: tx.ActionTypes.Set(storageTypes.ActionTypeValidatorUpdateBits) err = parseValidatorUpdateAction(val, height, ctx, &actions[i]) - feeType = "tendermint.abci.ValidatorUpdateAction" + feeType = "tendermint.abci.ValidatorUpdate" - case *astria.Action_BridgeLockAction: + case *astria.Action_BridgeLock: tx.ActionTypes.Set(storageTypes.ActionTypeBridgeLockBits) err = parseBridgeLock(val, from, height, ctx, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.BridgeLockAction" + feeType = "astria.protocol.transaction.v1alpha1.BridgeLock" - case *astria.Action_FeeAssetChangeAction: + case *astria.Action_FeeAssetChange: tx.ActionTypes.Set(storageTypes.ActionTypeFeeAssetChangeBits) err = parseFeeAssetChange(val, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.FeeAssetChangeAction" + feeType = "astria.protocol.transaction.v1alpha1.FeeAssetChange" - case *astria.Action_IbcRelayerChangeAction: + case *astria.Action_IbcRelayerChange: tx.ActionTypes.Set(storageTypes.ActionTypeIbcRelayerChangeBits) err = parseIbcRelayerChange(val, height, ctx, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.IbcRelayerChangeAction" + feeType = "astria.protocol.transaction.v1alpha1.IbcRelayerChange" - case *astria.Action_InitBridgeAccountAction: + case *astria.Action_InitBridgeAccount: tx.ActionTypes.Set(storageTypes.ActionTypeInitBridgeAccountBits) err = parseInitBridgeAccount(val, from, height, ctx, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.InitBridgeAccountAction" + feeType = "astria.protocol.transaction.v1alpha1.InitBridgeAccount" - case *astria.Action_BridgeSudoChangeAction: + case *astria.Action_BridgeSudoChange: tx.ActionTypes.Set(storageTypes.ActionTypeBridgeSudoChangeBits) err = parseBridgeSudoChange(val, height, ctx, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.BridgeSudoChangeAction" + feeType = "astria.protocol.transaction.v1alpha1.BridgeSudoChange" - case *astria.Action_BridgeUnlockAction: + case *astria.Action_BridgeUnlock: tx.ActionTypes.Set(storageTypes.ActionTypeBridgeUnlockBits) err = parseBridgeUnlock(val, from, height, ctx, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.BridgeUnlockAction" + feeType = "astria.protocol.transaction.v1alpha1.BridgeUnlock" - case *astria.Action_FeeChangeAction: + case *astria.Action_FeeChange: tx.ActionTypes.Set(storageTypes.ActionTypeFeeChangeBits) err = parseFeeChange(val, ctx, &actions[i]) - feeType = "astria.protocol.transactions.v1alpha1.FeeChangeAction" + feeType = "astria.protocol.transaction.v1alpha1.FeeChange" + + case *astria.Action_IbcSudoChange: + tx.ActionTypes.Set(storageTypes.ActionTypeIbcSudoChangeBits) + err = parseIbcSudoChangeAction(val, ctx, &actions[i]) + feeType = "astria.protocol.transaction.v1alpha1.IbcSudoChange" default: return nil, errors.Errorf( @@ -143,19 +149,25 @@ func parseActions(height types.Level, blockTime time.Time, from string, tx *Deco feeCounter++ } } + + if deposit, ok := ctx.Deposits[int64(i)]; ok { + deposit.Height = height + deposit.Time = blockTime + actions[i].Deposit = deposit + } } return actions, nil } -func parseIbcAction(body *astria.Action_IbcAction, action *storage.Action) error { +func parseIbcAction(body *astria.Action_Ibc, action *storage.Action) error { action.Type = storageTypes.ActionTypeIbcRelay action.Data = make(map[string]any) - if body.IbcAction != nil && body.IbcAction.GetRawAction() != nil { - data := body.IbcAction.GetRawAction().GetValue() + if body.Ibc != nil && body.Ibc.GetRawAction() != nil { + data := body.Ibc.GetRawAction().GetValue() action.Data["raw"] = base64.StdEncoding.EncodeToString(data) - action.Data["type"] = body.IbcAction.GetRawAction().GetTypeUrl() + action.Data["type"] = body.Ibc.GetRawAction().GetTypeUrl() } return nil } @@ -172,6 +184,7 @@ func parseIcs20Withdrawal(body *astria.Action_Ics20Withdrawal, from string, heig action.Data["destination_address"] = body.Ics20Withdrawal.GetDestinationChainAddress() action.Data["return_address"] = body.Ics20Withdrawal.GetReturnAddress().GetBech32M() action.Data["source_channel"] = body.Ics20Withdrawal.GetSourceChannel() + action.Data["use_compat_address"] = body.Ics20Withdrawal.GetUseCompatAddress() decAmount := decimal.RequireFromString(amount) @@ -261,15 +274,15 @@ func parseIcs20Withdrawal(body *astria.Action_Ics20Withdrawal, from string, heig return nil } -func parseSequenceAction(body *astria.Action_SequenceAction, from string, height types.Level, ctx *Context, action *storage.Action) error { - action.Type = storageTypes.ActionTypeSequence +func parseRollupDataSubmission(body *astria.Action_RollupDataSubmission, from string, height types.Level, ctx *Context, action *storage.Action) error { + action.Type = storageTypes.ActionTypeRollupDataSubmission action.Data = make(map[string]any) - if body.SequenceAction != nil { - rollupId := body.SequenceAction.GetRollupId().GetInner() + if body.RollupDataSubmission != nil { + rollupId := body.RollupDataSubmission.GetRollupId().GetInner() action.Data["rollup_id"] = rollupId - action.Data["data"] = body.SequenceAction.GetData() - action.Data["fee_asset"] = body.SequenceAction.GetFeeAsset() - dataSize := len(body.SequenceAction.GetData()) + action.Data["data"] = body.RollupDataSubmission.GetData() + action.Data["fee_asset"] = body.RollupDataSubmission.GetFeeAsset() + dataSize := len(body.RollupDataSubmission.GetData()) rollup := ctx.Rollups.Set(rollupId, height, dataSize) fromAddress := ctx.Addresses.Set(from, height, decimal.Zero, "", 1, 0) @@ -308,14 +321,14 @@ func parseSequenceAction(body *astria.Action_SequenceAction, from string, height return nil } -func parseSudoAddressChangeAction(body *astria.Action_SudoAddressChangeAction, height types.Level, ctx *Context, action *storage.Action) error { +func parseSudoAddressChangeAction(body *astria.Action_SudoAddressChange, ctx *Context, action *storage.Action) error { action.Type = storageTypes.ActionTypeSudoAddressChange action.Data = make(map[string]any) - if body.SudoAddressChangeAction != nil { - address := body.SudoAddressChangeAction.GetNewAddress().GetBech32M() + if body.SudoAddressChange != nil { + address := body.SudoAddressChange.GetNewAddress().GetBech32M() action.Data["address"] = address - addr := ctx.Addresses.Set(address, height, decimal.Zero, "", 1, 0) + addr := ctx.Addresses.Set(address, action.Height, decimal.Zero, "", 1, 0) action.Addresses = append(action.Addresses, &storage.AddressAction{ Address: addr, Action: action, @@ -323,21 +336,22 @@ func parseSudoAddressChangeAction(body *astria.Action_SudoAddressChangeAction, h Height: action.Height, ActionType: action.Type, }) + ctx.AddGenericConstant("authority_sudo_address", address) } return nil } -func parseTransferAction(body *astria.Action_TransferAction, from string, height types.Level, ctx *Context, action *storage.Action) error { +func parseTransferAction(body *astria.Action_Transfer, from string, height types.Level, ctx *Context, action *storage.Action) error { action.Type = storageTypes.ActionTypeTransfer action.Data = make(map[string]any) - if body.TransferAction != nil { - amount := uint128ToString(body.TransferAction.GetAmount()) - to := body.TransferAction.GetTo().GetBech32M() - asset := body.TransferAction.GetAsset() + if body.Transfer != nil { + amount := uint128ToString(body.Transfer.GetAmount()) + to := body.Transfer.GetTo().GetBech32M() + asset := body.Transfer.GetAsset() action.Data["amount"] = amount action.Data["asset"] = asset - action.Data["fee_asset"] = body.TransferAction.GetFeeAsset() + action.Data["fee_asset"] = body.Transfer.GetFeeAsset() action.Data["to"] = to decAmount := decimal.RequireFromString(amount) @@ -403,16 +417,16 @@ func parseTransferAction(body *astria.Action_TransferAction, from string, height return nil } -func parseValidatorUpdateAction(body *astria.Action_ValidatorUpdateAction, height types.Level, ctx *Context, action *storage.Action) error { +func parseValidatorUpdateAction(body *astria.Action_ValidatorUpdate, height types.Level, ctx *Context, action *storage.Action) error { action.Type = storageTypes.ActionTypeValidatorUpdate action.Data = make(map[string]any) - if body.ValidatorUpdateAction != nil { - power := body.ValidatorUpdateAction.GetPower() + if body.ValidatorUpdate != nil { + power := body.ValidatorUpdate.GetPower() action.Data["power"] = power - pubKey := body.ValidatorUpdateAction.GetPubKey().GetEd25519() + pubKey := body.ValidatorUpdate.GetPubKey().GetEd25519() action.Data["pubkey"] = pubKey - address, err := AddressFromPubKey(body.ValidatorUpdateAction.GetPubKey().GetEd25519()) + address, err := AddressFromPubKey(body.ValidatorUpdate.GetPubKey().GetEd25519()) if err != nil { return err } @@ -429,11 +443,11 @@ func parseValidatorUpdateAction(body *astria.Action_ValidatorUpdateAction, heigh return nil } -func parseIbcRelayerChange(body *astria.Action_IbcRelayerChangeAction, height types.Level, ctx *Context, action *storage.Action) error { +func parseIbcRelayerChange(body *astria.Action_IbcRelayerChange, height types.Level, ctx *Context, action *storage.Action) error { action.Type = storageTypes.ActionTypeIbcRelayerChange action.Data = make(map[string]any) - if body.IbcRelayerChangeAction != nil { - if addition := body.IbcRelayerChangeAction.GetAddition(); len(addition.GetBech32M()) > 0 { + if body.IbcRelayerChange != nil { + if addition := body.IbcRelayerChange.GetAddition(); len(addition.GetBech32M()) > 0 { action.Data["addition"] = addition.GetBech32M() addr := ctx.Addresses.Set(addition.GetBech32M(), height, decimal.Zero, "", 1, 0) @@ -446,7 +460,7 @@ func parseIbcRelayerChange(body *astria.Action_IbcRelayerChangeAction, height ty }) } - if removal := body.IbcRelayerChangeAction.GetRemoval(); len(removal.GetBech32M()) > 0 { + if removal := body.IbcRelayerChange.GetRemoval(); len(removal.GetBech32M()) > 0 { action.Data["removal"] = removal.GetBech32M() addr := ctx.Addresses.Set(removal.GetBech32M(), height, decimal.Zero, "", 1, 0) @@ -462,17 +476,17 @@ func parseIbcRelayerChange(body *astria.Action_IbcRelayerChangeAction, height ty return nil } -func parseInitBridgeAccount(body *astria.Action_InitBridgeAccountAction, from string, height types.Level, ctx *Context, action *storage.Action) error { +func parseInitBridgeAccount(body *astria.Action_InitBridgeAccount, from string, height types.Level, ctx *Context, action *storage.Action) error { action.Type = storageTypes.ActionTypeInitBridgeAccount action.Data = make(map[string]any) - if body.InitBridgeAccountAction != nil { - rollupId := body.InitBridgeAccountAction.GetRollupId().GetInner() + if body.InitBridgeAccount != nil { + rollupId := body.InitBridgeAccount.GetRollupId().GetInner() rollup := ctx.Rollups.Set(rollupId, height, 0) bridge := storage.Bridge{ InitHeight: height, - Asset: body.InitBridgeAccountAction.GetAsset(), - FeeAsset: body.InitBridgeAccountAction.GetFeeAsset(), + Asset: body.InitBridgeAccount.GetAsset(), + FeeAsset: body.InitBridgeAccount.GetFeeAsset(), Address: ctx.Addresses.Set(from, height, decimal.Zero, "", 0, 0), Rollup: rollup, } @@ -483,7 +497,7 @@ func parseInitBridgeAccount(body *astria.Action_InitBridgeAccountAction, from st action.Data["fee_asset"] = bridge.FeeAsset action.Data["asset"] = bridge.Asset - if sudo := body.InitBridgeAccountAction.GetSudoAddress().GetBech32M(); sudo != "" { + if sudo := body.InitBridgeAccount.GetSudoAddress().GetBech32M(); sudo != "" { action.Data["sudo"] = sudo if sudo != from { addr := ctx.Addresses.Set(sudo, height, decimal.Zero, "", 1, 0) @@ -502,7 +516,7 @@ func parseInitBridgeAccount(body *astria.Action_InitBridgeAccountAction, from st bridge.Sudo = bridge.Address } - if withdrawer := body.InitBridgeAccountAction.GetWithdrawerAddress().GetBech32M(); withdrawer != "" { + if withdrawer := body.InitBridgeAccount.GetWithdrawerAddress().GetBech32M(); withdrawer != "" { action.Data["withdrawer"] = withdrawer if withdrawer != from { addr := ctx.Addresses.Set(withdrawer, height, decimal.Zero, "", 1, 0) @@ -534,14 +548,14 @@ func parseInitBridgeAccount(body *astria.Action_InitBridgeAccountAction, from st return nil } -func parseBridgeSudoChange(body *astria.Action_BridgeSudoChangeAction, height types.Level, ctx *Context, action *storage.Action) error { +func parseBridgeSudoChange(body *astria.Action_BridgeSudoChange, height types.Level, ctx *Context, action *storage.Action) error { action.Type = storageTypes.ActionTypeBridgeSudoChangeAction action.Data = make(map[string]any) - if body.BridgeSudoChangeAction != nil { - bridgeAddress := body.BridgeSudoChangeAction.GetBridgeAddress().GetBech32M() - sudo := body.BridgeSudoChangeAction.GetNewSudoAddress().GetBech32M() - withdrawer := body.BridgeSudoChangeAction.GetNewWithdrawerAddress().GetBech32M() - feeAsset := body.BridgeSudoChangeAction.GetFeeAsset() + if body.BridgeSudoChange != nil { + bridgeAddress := body.BridgeSudoChange.GetBridgeAddress().GetBech32M() + sudo := body.BridgeSudoChange.GetNewSudoAddress().GetBech32M() + withdrawer := body.BridgeSudoChange.GetNewWithdrawerAddress().GetBech32M() + feeAsset := body.BridgeSudoChange.GetFeeAsset() action.Data["bridge"] = bridgeAddress bridgeAddr := ctx.Addresses.Set(bridgeAddress, height, decimal.Zero, "", 1, 0) @@ -607,20 +621,20 @@ func parseBridgeSudoChange(body *astria.Action_BridgeSudoChangeAction, height ty return nil } -func parseBridgeLock(body *astria.Action_BridgeLockAction, from string, height types.Level, ctx *Context, action *storage.Action) error { +func parseBridgeLock(body *astria.Action_BridgeLock, from string, height types.Level, ctx *Context, action *storage.Action) error { action.Type = storageTypes.ActionTypeBridgeLock action.Data = make(map[string]any) - if body.BridgeLockAction != nil { - amount := uint128ToString(body.BridgeLockAction.GetAmount()) - asset := body.BridgeLockAction.GetAsset() + if body.BridgeLock != nil { + amount := uint128ToString(body.BridgeLock.GetAmount()) + asset := body.BridgeLock.GetAsset() - action.Data["to"] = body.BridgeLockAction.GetTo().GetBech32M() - action.Data["destination_chain_address"] = body.BridgeLockAction.GetDestinationChainAddress() + action.Data["to"] = body.BridgeLock.GetTo().GetBech32M() + action.Data["destination_chain_address"] = body.BridgeLock.GetDestinationChainAddress() action.Data["asset"] = asset - action.Data["fee_asset"] = body.BridgeLockAction.GetFeeAsset() + action.Data["fee_asset"] = body.BridgeLock.GetFeeAsset() action.Data["amount"] = amount - toAddress := body.BridgeLockAction.GetTo().GetBech32M() + toAddress := body.BridgeLock.GetTo().GetBech32M() decAmount := decimal.RequireFromString(amount) toAddr := ctx.Addresses.Set(toAddress, height, decAmount, asset, 1, 0) @@ -673,20 +687,23 @@ func parseBridgeLock(body *astria.Action_BridgeLockAction, from string, height t return nil } -func parseBridgeUnlock(body *astria.Action_BridgeUnlockAction, from string, height types.Level, ctx *Context, action *storage.Action) error { +func parseBridgeUnlock(body *astria.Action_BridgeUnlock, from string, height types.Level, ctx *Context, action *storage.Action) error { action.Type = storageTypes.ActionTypeBridgeUnlock action.Data = make(map[string]any) - if body.BridgeUnlockAction != nil { - amount := uint128ToString(body.BridgeUnlockAction.GetAmount()) - toAddress := body.BridgeUnlockAction.GetTo().GetBech32M() - bridge := body.BridgeUnlockAction.GetBridgeAddress().GetBech32M() - feeAsset := body.BridgeUnlockAction.GetFeeAsset() + if body.BridgeUnlock != nil { + amount := uint128ToString(body.BridgeUnlock.GetAmount()) + toAddress := body.BridgeUnlock.GetTo().GetBech32M() + bridge := body.BridgeUnlock.GetBridgeAddress().GetBech32M() + feeAsset := body.BridgeUnlock.GetFeeAsset() action.Data["to"] = toAddress action.Data["fee_asset"] = feeAsset action.Data["amount"] = amount - if memo := body.BridgeUnlockAction.GetMemo(); len(memo) > 0 { - action.Data["memo"] = hex.EncodeToString(memo) + action.Data["rollup_block_number"] = body.BridgeUnlock.GetRollupBlockNumber() + action.Data["rollup_withdrawal_event_id"] = body.BridgeUnlock.GetRollupWithdrawalEventId() + + if memo := body.BridgeUnlock.GetMemo(); len(memo) > 0 { + action.Data["memo"] = memo } if bridge != "" { action.Data["bridge"] = bridge @@ -747,61 +764,103 @@ func parseBridgeUnlock(body *astria.Action_BridgeUnlockAction, from string, heig return nil } -func parseFeeAssetChange(body *astria.Action_FeeAssetChangeAction, action *storage.Action) error { +func parseFeeAssetChange(body *astria.Action_FeeAssetChange, action *storage.Action) error { action.Type = storageTypes.ActionTypeFeeAssetChange action.Data = make(map[string]any) - if body.FeeAssetChangeAction != nil { - if addition := body.FeeAssetChangeAction.GetAddition(); len(addition) > 0 { + if body.FeeAssetChange != nil { + if addition := body.FeeAssetChange.GetAddition(); len(addition) > 0 { action.Data["addition"] = addition } - if removal := body.FeeAssetChangeAction.GetRemoval(); len(removal) > 0 { + if removal := body.FeeAssetChange.GetRemoval(); len(removal) > 0 { action.Data["removal"] = removal } } return nil } -func parseFeeChange(body *astria.Action_FeeChangeAction, ctx *Context, action *storage.Action) error { +func parseFeeChange(body *astria.Action_FeeChange, ctx *Context, action *storage.Action) error { action.Type = storageTypes.ActionTypeFeeChange action.Data = make(map[string]any) - if body.FeeChangeAction != nil { - switch t := body.FeeChangeAction.GetValue().(type) { - case *astria.FeeChangeAction_BridgeLockByteCostMultiplier: - val := uint128ToString(t.BridgeLockByteCostMultiplier) - action.Data["bridge_lock_byte_cost_multiplier"] = val - ctx.AddGenericConstant("bridge_lock_byte_cost_multiplier", val) - - case *astria.FeeChangeAction_BridgeSudoChangeBaseFee: - val := uint128ToString(t.BridgeSudoChangeBaseFee) - action.Data["bridge_sudo_change_base_fee"] = val - ctx.AddGenericConstant("bridge_sudo_change_fee", val) - - case *astria.FeeChangeAction_Ics20WithdrawalBaseFee: - val := uint128ToString(t.Ics20WithdrawalBaseFee) - action.Data["ics20_withdrawal_base_fee"] = val - ctx.AddGenericConstant("ics20_withdrawal_base_fee", val) - - case *astria.FeeChangeAction_InitBridgeAccountBaseFee: - val := uint128ToString(t.InitBridgeAccountBaseFee) - action.Data["init_bridge_account_base_fee"] = val - ctx.AddGenericConstant("init_bridge_account_base_fee", val) - - case *astria.FeeChangeAction_SequenceBaseFee: - val := uint128ToString(t.SequenceBaseFee) - action.Data["sequence_base_fee"] = val - ctx.AddGenericConstant("sequence_base_fee", val) - - case *astria.FeeChangeAction_SequenceByteCostMultiplier: - val := uint128ToString(t.SequenceByteCostMultiplier) - action.Data["sequence_byte_cost_multiplier"] = val - ctx.AddGenericConstant("sequence_byte_cost_multiplier", val) - - case *astria.FeeChangeAction_TransferBaseFee: - val := uint128ToString(t.TransferBaseFee) - action.Data["transfer_base_fee"] = val - ctx.AddGenericConstant("transfer_base_fee", val) + if body.FeeChange != nil { + switch t := body.FeeChange.GetFeeComponents().(type) { + + case *astria.FeeChange_BridgeLock: + processFeeComponent("bridge_lock", t.BridgeLock.GetMultiplier(), t.BridgeLock.GetBase(), action.Data, ctx) + + case *astria.FeeChange_BridgeSudoChange: + processFeeComponent("bridge_sudo_change", t.BridgeSudoChange.GetMultiplier(), t.BridgeSudoChange.GetBase(), action.Data, ctx) + + case *astria.FeeChange_BridgeUnlock: + processFeeComponent("bridge_unlock", t.BridgeUnlock.GetMultiplier(), t.BridgeUnlock.GetBase(), action.Data, ctx) + + case *astria.FeeChange_FeeAssetChange: + processFeeComponent("fee_asset_change", t.FeeAssetChange.GetMultiplier(), t.FeeAssetChange.GetBase(), action.Data, ctx) + + case *astria.FeeChange_FeeChange: + processFeeComponent("fee_change", t.FeeChange.GetMultiplier(), t.FeeChange.GetBase(), action.Data, ctx) + + case *astria.FeeChange_IbcRelay: + processFeeComponent("ibc_relay", t.IbcRelay.GetMultiplier(), t.IbcRelay.GetBase(), action.Data, ctx) + + case *astria.FeeChange_IbcRelayerChange: + processFeeComponent("ibc_relay_change", t.IbcRelayerChange.GetMultiplier(), t.IbcRelayerChange.GetBase(), action.Data, ctx) + + case *astria.FeeChange_IbcSudoChange: + processFeeComponent("ibc_sudo_change", t.IbcSudoChange.GetMultiplier(), t.IbcSudoChange.GetBase(), action.Data, ctx) + + case *astria.FeeChange_Ics20Withdrawal: + processFeeComponent("ics20_withdrawal", t.Ics20Withdrawal.GetMultiplier(), t.Ics20Withdrawal.GetBase(), action.Data, ctx) + + case *astria.FeeChange_InitBridgeAccount: + processFeeComponent("init_bridge_account", t.InitBridgeAccount.GetMultiplier(), t.InitBridgeAccount.GetBase(), action.Data, ctx) + + case *astria.FeeChange_RollupDataSubmission: + processFeeComponent("rollup_data_submission", t.RollupDataSubmission.GetMultiplier(), t.RollupDataSubmission.GetBase(), action.Data, ctx) + + case *astria.FeeChange_SudoAddressChange: + processFeeComponent("sudo_address_change", t.SudoAddressChange.GetMultiplier(), t.SudoAddressChange.GetBase(), action.Data, ctx) + + case *astria.FeeChange_Transfer: + processFeeComponent("transfer", t.Transfer.GetMultiplier(), t.Transfer.GetBase(), action.Data, ctx) + + case *astria.FeeChange_ValidatorUpdate: + processFeeComponent("validator_update", t.ValidatorUpdate.GetMultiplier(), t.ValidatorUpdate.GetBase(), action.Data, ctx) } } return nil } + +func parseIbcSudoChangeAction(body *astria.Action_IbcSudoChange, ctx *Context, action *storage.Action) error { + action.Type = storageTypes.ActionTypeIbcSudoChangeAction + action.Data = make(map[string]any) + if body.IbcSudoChange != nil { + address := body.IbcSudoChange.GetNewAddress().GetBech32M() + action.Data["address"] = address + + addr := ctx.Addresses.Set(address, action.Height, decimal.Zero, "", 1, 0) + action.Addresses = append(action.Addresses, &storage.AddressAction{ + Address: addr, + Action: action, + Time: action.Time, + Height: action.Height, + ActionType: action.Type, + }) + + ctx.AddGenericConstant("ibc_sudo_change", address) + } + + return nil +} + +func processFeeComponent(name string, multiplier, base *primitive.Uint128, data map[string]any, ctx *Context) { + m := uint128ToString(multiplier) + mKey := fmt.Sprintf("%s_multiplier", name) + data[mKey] = m + ctx.AddGenericConstant(mKey, m) + + b := uint128ToString(base) + bKey := fmt.Sprintf("%s_base", name) + data[bKey] = b + ctx.AddGenericConstant(bKey, b) +} diff --git a/pkg/indexer/decode/actions_test.go b/pkg/indexer/decode/actions_test.go index f72b0cb..5d7dec2 100644 --- a/pkg/indexer/decode/actions_test.go +++ b/pkg/indexer/decode/actions_test.go @@ -8,7 +8,8 @@ import ( "testing" primitivev1 "buf.build/gen/go/astria/primitives/protocolbuffers/go/astria/primitive/v1" - astria "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria/protocol/transactions/v1alpha1" + feesv1alpha1 "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria/protocol/fees/v1alpha1" + astria "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria/protocol/transaction/v1alpha1" v1 "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria_vendored/penumbra/core/component/ibc/v1" abci "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria_vendored/tendermint/abci" crypto "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria_vendored/tendermint/crypto" @@ -29,8 +30,8 @@ const ( func TestDecodeActions(t *testing.T) { t.Run("ibc action", func(t *testing.T) { - message := &astria.Action_IbcAction{ - IbcAction: &v1.IbcRelay{ + message := &astria.Action_Ibc{ + Ibc: &v1.IbcRelay{ RawAction: &anypb.Any{ Value: []byte{0, 0, 0, 0}, TypeUrl: "msg_type", @@ -83,6 +84,7 @@ func TestDecodeActions(t *testing.T) { BridgeAddress: &primitivev1.Address{ Bech32M: from, }, + UseCompatAddress: true, }, } @@ -99,10 +101,11 @@ func TestDecodeActions(t *testing.T) { "revision_number": uint64(1000), "revision_height": uint64(1001), }, - "timeout_time": uint64(1000), - "fee_asset": feeAssetId, - "memo": "memo", - "bridge": from, + "timeout_time": uint64(1000), + "fee_asset": feeAssetId, + "memo": "memo", + "bridge": from, + "use_compat_address": true, }, Addresses: []*storage.AddressAction{}, BalanceUpdates: []storage.BalanceUpdate{ @@ -166,14 +169,14 @@ func TestDecodeActions(t *testing.T) { require.Equal(t, wantAction, action) }) - t.Run("sequence", func(t *testing.T) { + t.Run("rollup data submission", func(t *testing.T) { decodeContext := NewContext(map[string]string{}) from := testsuite.RandomAddress() addressModel := decodeContext.Addresses.Set(from, 1000, decimal.Zero, "", 0, 1) - message := &astria.Action_SequenceAction{ - SequenceAction: &astria.SequenceAction{ + message := &astria.Action_RollupDataSubmission{ + RollupDataSubmission: &astria.RollupDataSubmission{ RollupId: &primitivev1.RollupId{Inner: testsuite.RandomHash(10)}, Data: testsuite.RandomHash(10), FeeAsset: feeAssetId, @@ -182,10 +185,10 @@ func TestDecodeActions(t *testing.T) { wantAction := storage.Action{ Height: 1000, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, Data: map[string]any{ - "rollup_id": message.SequenceAction.GetRollupId().GetInner(), - "data": message.SequenceAction.GetData(), + "rollup_id": message.RollupDataSubmission.GetRollupId().GetInner(), + "data": message.RollupDataSubmission.GetData(), "fee_asset": feeAssetId, }, Addresses: make([]*storage.AddressAction, 0), @@ -193,19 +196,19 @@ func TestDecodeActions(t *testing.T) { Size: 10, Height: 1000, Rollup: &storage.Rollup{ - AstriaId: message.SequenceAction.GetRollupId().GetInner(), + AstriaId: message.RollupDataSubmission.GetRollupId().GetInner(), FirstHeight: 1000, ActionsCount: 1, Size: 10, }, - ActionType: types.ActionTypeSequence, + ActionType: types.ActionTypeRollupDataSubmission, }, } wantAction.RollupAction.Action = &wantAction addressAction := storage.AddressAction{ Height: 1000, Address: addressModel, - ActionType: types.ActionTypeSequence, + ActionType: types.ActionTypeRollupDataSubmission, Action: &wantAction, } wantAction.Addresses = append(wantAction.Addresses, &addressAction) @@ -213,7 +216,7 @@ func TestDecodeActions(t *testing.T) { action := storage.Action{ Height: 1000, } - err := parseSequenceAction(message, from, 1000, &decodeContext, &action) + err := parseRollupDataSubmission(message, from, 1000, &decodeContext, &action) require.NoError(t, err) require.Equal(t, wantAction, action) }) @@ -222,8 +225,8 @@ func TestDecodeActions(t *testing.T) { decodeContext := NewContext(map[string]string{}) newAddress := testsuite.RandomAddress() - message := &astria.Action_SudoAddressChangeAction{ - SudoAddressChangeAction: &astria.SudoAddressChangeAction{ + message := &astria.Action_SudoAddressChange{ + SudoAddressChange: &astria.SudoAddressChange{ NewAddress: &primitivev1.Address{Bech32M: newAddress}, }, } @@ -253,7 +256,7 @@ func TestDecodeActions(t *testing.T) { action := storage.Action{ Height: 1000, } - err := parseSudoAddressChangeAction(message, 1000, &decodeContext, &action) + err := parseSudoAddressChangeAction(message, &decodeContext, &action) require.NoError(t, err) require.Equal(t, wantAction, action) }) @@ -289,8 +292,8 @@ func TestDecodeActions(t *testing.T) { }, } - message := &astria.Action_TransferAction{ - TransferAction: &astria.TransferAction{ + message := &astria.Action_Transfer{ + Transfer: &astria.Transfer{ To: &primitivev1.Address{Bech32M: to}, Amount: &primitivev1.Uint128{ Lo: 10, @@ -306,8 +309,8 @@ func TestDecodeActions(t *testing.T) { Data: map[string]any{ "to": to, "amount": "10", - "asset": message.TransferAction.GetAsset(), - "fee_asset": message.TransferAction.GetFeeAsset(), + "asset": message.Transfer.GetAsset(), + "fee_asset": message.Transfer.GetFeeAsset(), }, Addresses: make([]*storage.AddressAction, 0), BalanceUpdates: []storage.BalanceUpdate{ @@ -362,8 +365,8 @@ func TestDecodeActions(t *testing.T) { }, } - message := &astria.Action_TransferAction{ - TransferAction: &astria.TransferAction{ + message := &astria.Action_Transfer{ + Transfer: &astria.Transfer{ To: &primitivev1.Address{Bech32M: from}, Amount: &primitivev1.Uint128{ Lo: 10, @@ -379,8 +382,8 @@ func TestDecodeActions(t *testing.T) { Data: map[string]any{ "to": from, "amount": "10", - "asset": message.TransferAction.GetAsset(), - "fee_asset": message.TransferAction.GetFeeAsset(), + "asset": message.Transfer.GetAsset(), + "fee_asset": message.Transfer.GetFeeAsset(), }, Addresses: make([]*storage.AddressAction, 0), } @@ -402,8 +405,8 @@ func TestDecodeActions(t *testing.T) { t.Run("validator update", func(t *testing.T) { decodeContext := NewContext(map[string]string{}) - message := &astria.Action_ValidatorUpdateAction{ - ValidatorUpdateAction: &abci.ValidatorUpdate{ + message := &astria.Action_ValidatorUpdate{ + ValidatorUpdate: &abci.ValidatorUpdate{ PubKey: &crypto.PublicKey{ Sum: &crypto.PublicKey_Ed25519{ Ed25519: testsuite.RandomHash(32), @@ -418,11 +421,11 @@ func TestDecodeActions(t *testing.T) { Type: types.ActionTypeValidatorUpdate, Data: map[string]any{ "power": int64(10), - "pubkey": message.ValidatorUpdateAction.GetPubKey().GetEd25519(), + "pubkey": message.ValidatorUpdate.GetPubKey().GetEd25519(), }, Addresses: make([]*storage.AddressAction, 0), } - address, err := AddressFromPubKey(message.ValidatorUpdateAction.GetPubKey().GetEd25519()) + address, err := AddressFromPubKey(message.ValidatorUpdate.GetPubKey().GetEd25519()) require.NoError(t, err) balance := storage.EmptyBalance() @@ -447,16 +450,16 @@ func TestDecodeActions(t *testing.T) { require.Equal(t, wantAction, action) require.Len(t, decodeContext.Validators, 1) - pk := hex.EncodeToString(message.ValidatorUpdateAction.GetPubKey().GetEd25519()) + pk := hex.EncodeToString(message.ValidatorUpdate.GetPubKey().GetEd25519()) v, ok := decodeContext.Validators[pk] require.True(t, ok) require.EqualValues(t, "10", v.Power.String()) }) t.Run("fee asset change: addition", func(t *testing.T) { - message := &astria.Action_FeeAssetChangeAction{ - FeeAssetChangeAction: &astria.FeeAssetChangeAction{ - Value: &astria.FeeAssetChangeAction_Addition{ + message := &astria.Action_FeeAssetChange{ + FeeAssetChange: &astria.FeeAssetChange{ + Value: &astria.FeeAssetChange_Addition{ Addition: assetId, }, }, @@ -479,9 +482,9 @@ func TestDecodeActions(t *testing.T) { }) t.Run("fee asset change: removal", func(t *testing.T) { - message := &astria.Action_FeeAssetChangeAction{ - FeeAssetChangeAction: &astria.FeeAssetChangeAction{ - Value: &astria.FeeAssetChangeAction_Removal{ + message := &astria.Action_FeeAssetChange{ + FeeAssetChange: &astria.FeeAssetChange{ + Value: &astria.FeeAssetChange_Removal{ Removal: assetId, }, }, @@ -509,8 +512,8 @@ func TestDecodeActions(t *testing.T) { to := testsuite.RandomAddress() dest := testsuite.RandomAddress() - message := &astria.Action_BridgeLockAction{ - BridgeLockAction: &astria.BridgeLockAction{ + message := &astria.Action_BridgeLock{ + BridgeLock: &astria.BridgeLock{ FeeAsset: feeAssetId, Asset: assetId, To: &primitivev1.Address{Bech32M: to}, @@ -604,8 +607,8 @@ func TestDecodeActions(t *testing.T) { to := testsuite.RandomAddress() dest := testsuite.RandomAddress() - message := &astria.Action_BridgeLockAction{ - BridgeLockAction: &astria.BridgeLockAction{ + message := &astria.Action_BridgeLock{ + BridgeLock: &astria.BridgeLock{ FeeAsset: feeAssetId, Asset: assetId, To: &primitivev1.Address{Bech32M: to}, @@ -667,16 +670,18 @@ func TestDecodeActions(t *testing.T) { to := testsuite.RandomAddress() - message := &astria.Action_BridgeUnlockAction{ - BridgeUnlockAction: &astria.BridgeUnlockAction{ + message := &astria.Action_BridgeUnlock{ + BridgeUnlock: &astria.BridgeUnlock{ FeeAsset: feeAssetId, To: &primitivev1.Address{Bech32M: to}, BridgeAddress: &primitivev1.Address{Bech32M: bridge}, - Memo: []byte("memo"), + Memo: "memo", Amount: &primitivev1.Uint128{ Lo: 10, Hi: 0, }, + RollupBlockNumber: 101, + RollupWithdrawalEventId: "event_id", }, } @@ -709,11 +714,13 @@ func TestDecodeActions(t *testing.T) { Height: 1000, Type: types.ActionTypeBridgeUnlock, Data: map[string]any{ - "fee_asset": feeAssetId, - "to": to, - "bridge": bridge, - "amount": "10", - "memo": "6d656d6f", + "fee_asset": feeAssetId, + "to": to, + "bridge": bridge, + "amount": "10", + "memo": "memo", + "rollup_block_number": uint64(101), + "rollup_withdrawal_event_id": "event_id", }, Addresses: make([]*storage.AddressAction, 0), BalanceUpdates: []storage.BalanceUpdate{ @@ -765,8 +772,8 @@ func TestDecodeActions(t *testing.T) { sudoAddr := decodeContext.Addresses.Set(sudo, 1000, decimal.Zero, "", 1, 0) wdwAddr := decodeContext.Addresses.Set(withdrawer, 1000, decimal.Zero, "", 1, 0) - message := &astria.Action_InitBridgeAccountAction{ - InitBridgeAccountAction: &astria.InitBridgeAccountAction{ + message := &astria.Action_InitBridgeAccount{ + InitBridgeAccount: &astria.InitBridgeAccount{ RollupId: &primitivev1.RollupId{Inner: rollupId}, FeeAsset: feeAssetId, Asset: assetId, @@ -788,7 +795,7 @@ func TestDecodeActions(t *testing.T) { RollupAction: &storage.RollupAction{ Height: 1000, Rollup: &storage.Rollup{ - AstriaId: message.InitBridgeAccountAction.GetRollupId().GetInner(), + AstriaId: message.InitBridgeAccount.GetRollupId().GetInner(), FirstHeight: 1000, ActionsCount: 1, BridgeCount: 1, @@ -828,8 +835,8 @@ func TestDecodeActions(t *testing.T) { rollupId := testsuite.RandomHash(10) from := testsuite.RandomAddress() - message := &astria.Action_InitBridgeAccountAction{ - InitBridgeAccountAction: &astria.InitBridgeAccountAction{ + message := &astria.Action_InitBridgeAccount{ + InitBridgeAccount: &astria.InitBridgeAccount{ RollupId: &primitivev1.RollupId{Inner: rollupId}, FeeAsset: feeAssetId, Asset: assetId, @@ -851,7 +858,7 @@ func TestDecodeActions(t *testing.T) { RollupAction: &storage.RollupAction{ Height: 1000, Rollup: &storage.Rollup{ - AstriaId: message.InitBridgeAccountAction.GetRollupId().GetInner(), + AstriaId: message.InitBridgeAccount.GetRollupId().GetInner(), FirstHeight: 1000, ActionsCount: 1, BridgeCount: 1, @@ -875,9 +882,9 @@ func TestDecodeActions(t *testing.T) { decodeContext := NewContext(map[string]string{}) address := testsuite.RandomAddress() - message := &astria.Action_IbcRelayerChangeAction{ - IbcRelayerChangeAction: &astria.IbcRelayerChangeAction{ - Value: &astria.IbcRelayerChangeAction_Addition{ + message := &astria.Action_IbcRelayerChange{ + IbcRelayerChange: &astria.IbcRelayerChange{ + Value: &astria.IbcRelayerChange_Addition{ Addition: &primitivev1.Address{Bech32M: address}, }, }, @@ -923,9 +930,9 @@ func TestDecodeActions(t *testing.T) { decodeContext := NewContext(map[string]string{}) address := testsuite.RandomAddress() - message := &astria.Action_IbcRelayerChangeAction{ - IbcRelayerChangeAction: &astria.IbcRelayerChangeAction{ - Value: &astria.IbcRelayerChangeAction_Removal{ + message := &astria.Action_IbcRelayerChange{ + IbcRelayerChange: &astria.IbcRelayerChange{ + Value: &astria.IbcRelayerChange_Removal{ Removal: &primitivev1.Address{Bech32M: address}, }, }, @@ -967,42 +974,21 @@ func TestDecodeActions(t *testing.T) { require.Equal(t, wantAction, action) }) - t.Run("fee change: sequence_base_fee", func(t *testing.T) { - decodeContext := NewContext(map[string]string{}) - - message := &astria.Action_FeeChangeAction{ - FeeChangeAction: &astria.FeeChangeAction{ - Value: &astria.FeeChangeAction_SequenceBaseFee{ - SequenceBaseFee: &primitivev1.Uint128{ - Hi: 0, - Lo: 10, - }, - }, - }, - } - - wantAction := storage.Action{ - Type: types.ActionTypeFeeChange, - Data: map[string]any{ - "sequence_base_fee": "10", - }, - } - - action := storage.Action{} - err := parseFeeChange(message, &decodeContext, &action) - require.NoError(t, err) - require.Equal(t, wantAction, action) - }) - - t.Run("fee change: bridge_lock_byte_cost_multiplier", func(t *testing.T) { + t.Run("fee change: rollup_data_submission", func(t *testing.T) { decodeContext := NewContext(map[string]string{}) - message := &astria.Action_FeeChangeAction{ - FeeChangeAction: &astria.FeeChangeAction{ - Value: &astria.FeeChangeAction_BridgeLockByteCostMultiplier{ - BridgeLockByteCostMultiplier: &primitivev1.Uint128{ - Hi: 0, - Lo: 10, + message := &astria.Action_FeeChange{ + FeeChange: &astria.FeeChange{ + FeeComponents: &astria.FeeChange_RollupDataSubmission{ + RollupDataSubmission: &feesv1alpha1.RollupDataSubmissionFeeComponents{ + Base: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, + Multiplier: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, }, }, }, @@ -1011,7 +997,8 @@ func TestDecodeActions(t *testing.T) { wantAction := storage.Action{ Type: types.ActionTypeFeeChange, Data: map[string]any{ - "bridge_lock_byte_cost_multiplier": "10", + "rollup_data_submission_base": "10", + "rollup_data_submission_multiplier": "10", }, } @@ -1021,15 +1008,21 @@ func TestDecodeActions(t *testing.T) { require.Equal(t, wantAction, action) }) - t.Run("fee change: bridge_sudo_change_base_fee", func(t *testing.T) { + t.Run("fee change: bridge_lock", func(t *testing.T) { decodeContext := NewContext(map[string]string{}) - message := &astria.Action_FeeChangeAction{ - FeeChangeAction: &astria.FeeChangeAction{ - Value: &astria.FeeChangeAction_BridgeSudoChangeBaseFee{ - BridgeSudoChangeBaseFee: &primitivev1.Uint128{ - Hi: 0, - Lo: 10, + message := &astria.Action_FeeChange{ + FeeChange: &astria.FeeChange{ + FeeComponents: &astria.FeeChange_BridgeLock{ + BridgeLock: &feesv1alpha1.BridgeLockFeeComponents{ + Base: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, + Multiplier: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, }, }, }, @@ -1038,7 +1031,8 @@ func TestDecodeActions(t *testing.T) { wantAction := storage.Action{ Type: types.ActionTypeFeeChange, Data: map[string]any{ - "bridge_sudo_change_base_fee": "10", + "bridge_lock_base": "10", + "bridge_lock_multiplier": "10", }, } @@ -1048,15 +1042,21 @@ func TestDecodeActions(t *testing.T) { require.Equal(t, wantAction, action) }) - t.Run("fee change: ics20_withdrawal_base_fee", func(t *testing.T) { + t.Run("fee change: bridge_sudo_change", func(t *testing.T) { decodeContext := NewContext(map[string]string{}) - message := &astria.Action_FeeChangeAction{ - FeeChangeAction: &astria.FeeChangeAction{ - Value: &astria.FeeChangeAction_Ics20WithdrawalBaseFee{ - Ics20WithdrawalBaseFee: &primitivev1.Uint128{ - Hi: 0, - Lo: 10, + message := &astria.Action_FeeChange{ + FeeChange: &astria.FeeChange{ + FeeComponents: &astria.FeeChange_BridgeSudoChange{ + BridgeSudoChange: &feesv1alpha1.BridgeSudoChangeFeeComponents{ + Base: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, + Multiplier: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, }, }, }, @@ -1065,7 +1065,8 @@ func TestDecodeActions(t *testing.T) { wantAction := storage.Action{ Type: types.ActionTypeFeeChange, Data: map[string]any{ - "ics20_withdrawal_base_fee": "10", + "bridge_sudo_change_base": "10", + "bridge_sudo_change_multiplier": "10", }, } @@ -1075,15 +1076,21 @@ func TestDecodeActions(t *testing.T) { require.Equal(t, wantAction, action) }) - t.Run("fee change: init_bridge_account_base_fee", func(t *testing.T) { + t.Run("fee change: ics20_withdrawal", func(t *testing.T) { decodeContext := NewContext(map[string]string{}) - message := &astria.Action_FeeChangeAction{ - FeeChangeAction: &astria.FeeChangeAction{ - Value: &astria.FeeChangeAction_InitBridgeAccountBaseFee{ - InitBridgeAccountBaseFee: &primitivev1.Uint128{ - Hi: 0, - Lo: 10, + message := &astria.Action_FeeChange{ + FeeChange: &astria.FeeChange{ + FeeComponents: &astria.FeeChange_Ics20Withdrawal{ + Ics20Withdrawal: &feesv1alpha1.Ics20WithdrawalFeeComponents{ + Base: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, + Multiplier: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, }, }, }, @@ -1092,7 +1099,8 @@ func TestDecodeActions(t *testing.T) { wantAction := storage.Action{ Type: types.ActionTypeFeeChange, Data: map[string]any{ - "init_bridge_account_base_fee": "10", + "ics20_withdrawal_base": "10", + "ics20_withdrawal_multiplier": "10", }, } @@ -1102,15 +1110,21 @@ func TestDecodeActions(t *testing.T) { require.Equal(t, wantAction, action) }) - t.Run("fee change: sequence_byte_cost_multiplier", func(t *testing.T) { + t.Run("fee change: init_bridge_account", func(t *testing.T) { decodeContext := NewContext(map[string]string{}) - message := &astria.Action_FeeChangeAction{ - FeeChangeAction: &astria.FeeChangeAction{ - Value: &astria.FeeChangeAction_SequenceByteCostMultiplier{ - SequenceByteCostMultiplier: &primitivev1.Uint128{ - Hi: 0, - Lo: 10, + message := &astria.Action_FeeChange{ + FeeChange: &astria.FeeChange{ + FeeComponents: &astria.FeeChange_InitBridgeAccount{ + InitBridgeAccount: &feesv1alpha1.InitBridgeAccountFeeComponents{ + Base: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, + Multiplier: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, }, }, }, @@ -1119,7 +1133,8 @@ func TestDecodeActions(t *testing.T) { wantAction := storage.Action{ Type: types.ActionTypeFeeChange, Data: map[string]any{ - "sequence_byte_cost_multiplier": "10", + "init_bridge_account_base": "10", + "init_bridge_account_multiplier": "10", }, } @@ -1129,15 +1144,21 @@ func TestDecodeActions(t *testing.T) { require.Equal(t, wantAction, action) }) - t.Run("fee change: transfer_base_fee", func(t *testing.T) { + t.Run("fee change: transfer", func(t *testing.T) { decodeContext := NewContext(map[string]string{}) - message := &astria.Action_FeeChangeAction{ - FeeChangeAction: &astria.FeeChangeAction{ - Value: &astria.FeeChangeAction_TransferBaseFee{ - TransferBaseFee: &primitivev1.Uint128{ - Hi: 0, - Lo: 10, + message := &astria.Action_FeeChange{ + FeeChange: &astria.FeeChange{ + FeeComponents: &astria.FeeChange_Transfer{ + Transfer: &feesv1alpha1.TransferFeeComponents{ + Base: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, + Multiplier: &primitivev1.Uint128{ + Hi: 0, + Lo: 10, + }, }, }, }, @@ -1146,7 +1167,8 @@ func TestDecodeActions(t *testing.T) { wantAction := storage.Action{ Type: types.ActionTypeFeeChange, Data: map[string]any{ - "transfer_base_fee": "10", + "transfer_base": "10", + "transfer_multiplier": "10", }, } @@ -1162,8 +1184,8 @@ func TestDecodeActions(t *testing.T) { sudo := testsuite.RandomAddress() withdrawer := testsuite.RandomAddress() - message := &astria.Action_BridgeSudoChangeAction{ - BridgeSudoChangeAction: &astria.BridgeSudoChangeAction{ + message := &astria.Action_BridgeSudoChange{ + BridgeSudoChange: &astria.BridgeSudoChange{ FeeAsset: feeAssetId, BridgeAddress: &primitivev1.Address{Bech32M: bridge}, NewWithdrawerAddress: &primitivev1.Address{Bech32M: withdrawer}, @@ -1244,8 +1266,8 @@ func TestDecodeActions(t *testing.T) { sudo := bridge withdrawer := testsuite.RandomAddress() - message := &astria.Action_BridgeSudoChangeAction{ - BridgeSudoChangeAction: &astria.BridgeSudoChangeAction{ + message := &astria.Action_BridgeSudoChange{ + BridgeSudoChange: &astria.BridgeSudoChange{ FeeAsset: feeAssetId, BridgeAddress: &primitivev1.Address{Bech32M: bridge}, NewWithdrawerAddress: &primitivev1.Address{Bech32M: withdrawer}, @@ -1311,8 +1333,8 @@ func TestDecodeActions(t *testing.T) { sudo := testsuite.RandomAddress() withdrawer := bridge - message := &astria.Action_BridgeSudoChangeAction{ - BridgeSudoChangeAction: &astria.BridgeSudoChangeAction{ + message := &astria.Action_BridgeSudoChange{ + BridgeSudoChange: &astria.BridgeSudoChange{ FeeAsset: feeAssetId, BridgeAddress: &primitivev1.Address{Bech32M: bridge}, NewWithdrawerAddress: &primitivev1.Address{Bech32M: withdrawer}, @@ -1378,8 +1400,8 @@ func TestDecodeActions(t *testing.T) { sudo := testsuite.RandomAddress() withdrawer := sudo - message := &astria.Action_BridgeSudoChangeAction{ - BridgeSudoChangeAction: &astria.BridgeSudoChangeAction{ + message := &astria.Action_BridgeSudoChange{ + BridgeSudoChange: &astria.BridgeSudoChange{ FeeAsset: feeAssetId, BridgeAddress: &primitivev1.Address{Bech32M: bridge}, NewWithdrawerAddress: &primitivev1.Address{Bech32M: withdrawer}, @@ -1445,8 +1467,8 @@ func TestDecodeActions(t *testing.T) { sudo := bridge withdrawer := bridge - message := &astria.Action_BridgeSudoChangeAction{ - BridgeSudoChangeAction: &astria.BridgeSudoChangeAction{ + message := &astria.Action_BridgeSudoChange{ + BridgeSudoChange: &astria.BridgeSudoChange{ FeeAsset: feeAssetId, BridgeAddress: &primitivev1.Address{Bech32M: bridge}, NewWithdrawerAddress: &primitivev1.Address{Bech32M: withdrawer}, @@ -1490,4 +1512,44 @@ func TestDecodeActions(t *testing.T) { require.NoError(t, err) require.Equal(t, wantAction, action) }) + + t.Run("ibc sudo change", func(t *testing.T) { + decodeContext := NewContext(map[string]string{}) + + newAddress := testsuite.RandomAddress() + message := &astria.Action_IbcSudoChange{ + IbcSudoChange: &astria.IbcSudoChange{ + NewAddress: &primitivev1.Address{Bech32M: newAddress}, + }, + } + + wantAction := storage.Action{ + Height: 1000, + Type: types.ActionTypeIbcSudoChangeAction, + Data: map[string]any{ + "address": newAddress, + }, + Addresses: make([]*storage.AddressAction, 0), + } + balance := storage.EmptyBalance() + addressAction := storage.AddressAction{ + Height: 1000, + Address: &storage.Address{ + Height: 1000, + ActionsCount: 1, + Hash: newAddress, + Balance: []*storage.Balance{&balance}, + }, + ActionType: types.ActionTypeIbcSudoChangeAction, + Action: &wantAction, + } + wantAction.Addresses = append(wantAction.Addresses, &addressAction) + + action := storage.Action{ + Height: 1000, + } + err := parseIbcSudoChangeAction(message, &decodeContext, &action) + require.NoError(t, err) + require.Equal(t, wantAction, action) + }) } diff --git a/pkg/indexer/decode/context.go b/pkg/indexer/decode/context.go index 12e8331..dbda177 100644 --- a/pkg/indexer/decode/context.go +++ b/pkg/indexer/decode/context.go @@ -27,6 +27,7 @@ type Context struct { Bridges map[string]*storage.Bridge Fees []*storage.Fee Transfers []*storage.Transfer + Deposits map[int64]*storage.Deposit Proposer string bridgeAssets map[string]string @@ -43,6 +44,7 @@ func NewContext(bridgeAssets map[string]string) Context { Bridges: make(map[string]*storage.Bridge), Fees: make([]*storage.Fee, 0), Transfers: make([]*storage.Transfer, 0), + Deposits: make(map[int64]*storage.Deposit), bridgeAssets: bridgeAssets, } @@ -88,3 +90,7 @@ func (ctx *Context) AddBridgeAsset(bridge, asset string) { func (ctx *Context) AddTransfer(transfer *storage.Transfer) { ctx.Transfers = append(ctx.Transfers, transfer) } + +func (ctx *Context) AddDeposit(idx int64, deposit *storage.Deposit) { + ctx.Deposits[idx] = deposit +} diff --git a/pkg/indexer/decode/tx.go b/pkg/indexer/decode/tx.go index 6f8e293..22577b9 100644 --- a/pkg/indexer/decode/tx.go +++ b/pkg/indexer/decode/tx.go @@ -4,7 +4,7 @@ package decode import ( - astria "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria/protocol/transactions/v1alpha1" + astria "buf.build/gen/go/astria/protocol-apis/protocolbuffers/go/astria/protocol/transaction/v1alpha1" "github.com/celenium-io/astria-indexer/internal/storage" storageTypes "github.com/celenium-io/astria-indexer/internal/storage/types" "github.com/celenium-io/astria-indexer/pkg/types" @@ -14,8 +14,8 @@ import ( ) type DecodedTx struct { - Tx *astria.SignedTransaction - UnsignedTx *astria.UnsignedTransaction + Tx *astria.Transaction + UnsignedTx *astria.TransactionBody Actions []storage.Action Signer *storage.Address ActionTypes storageTypes.Bits @@ -26,17 +26,18 @@ func Tx(b types.BlockData, index int, ctx *Context) (d DecodedTx, err error) { ctx.BytesInBlock += int64(len(raw)) - d.Tx = new(astria.SignedTransaction) + d.Tx = new(astria.Transaction) if err := proto.Unmarshal(raw, d.Tx); err != nil { return d, errors.Wrap(err, "tx decoding") } - if d.Tx.GetTransaction() == nil { + body := d.Tx.GetBody() + if body == nil { return d, errors.Wrap(err, "nil decoded tx") } - d.UnsignedTx = new(astria.UnsignedTransaction) - if err := proto.Unmarshal(d.Tx.GetTransaction().GetValue(), d.UnsignedTx); err != nil { + d.UnsignedTx = new(astria.TransactionBody) + if err := proto.Unmarshal(body.GetValue(), d.UnsignedTx); err != nil { return d, errors.Wrap(err, "tx decoding") } diff --git a/pkg/indexer/genesis/constant.go b/pkg/indexer/genesis/constant.go index 92166aa..59459eb 100644 --- a/pkg/indexer/genesis/constant.go +++ b/pkg/indexer/genesis/constant.go @@ -73,39 +73,158 @@ func (module *Module) parseConstants(appState nodeTypes.AppState, consensus pkgT Name: "ibc_sudo_address", Value: appState.IbcSudoAddress.Value, }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "bridge_lock_base", + Value: appState.Fees.BridgeLock.Base.String(), + }) + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "bridge_lock_multiplier", + Value: appState.Fees.BridgeLock.Multiplier.String(), + }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "bridge_unlock_base", + Value: appState.Fees.BridgeUnlock.Base.String(), + }) + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "bridge_unlock_multiplier", + Value: appState.Fees.BridgeUnlock.Multiplier.String(), + }) + data.constants = append(data.constants, storage.Constant{ Module: storageTypes.ModuleNameGeneric, - Name: "bridge_lock_byte_cost_multiplier", - Value: appState.Fees.BridgeLockByteCostMultiplier.String(), + Name: "transfer_base", + Value: appState.Fees.Transfer.Base.String(), }) data.constants = append(data.constants, storage.Constant{ Module: storageTypes.ModuleNameGeneric, - Name: "ics20_withdrawal_base_fee", - Value: appState.Fees.Ics20WithdrawalBaseFee.String(), + Name: "transfer_multiplier", + Value: appState.Fees.Transfer.Multiplier.String(), }) + data.constants = append(data.constants, storage.Constant{ Module: storageTypes.ModuleNameGeneric, - Name: "init_bridge_account_base_fee", - Value: appState.Fees.InitBridgeAccountBaseFee.String(), + Name: "rollup_data_submission_base", + Value: appState.Fees.Sequence.Base.String(), }) data.constants = append(data.constants, storage.Constant{ Module: storageTypes.ModuleNameGeneric, - Name: "sequence_base_fee", - Value: appState.Fees.SequenceBaseFee.String(), + Name: "rollup_data_submission_computed_multiplier", + Value: appState.Fees.Sequence.Multiplier.String(), + }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "ics20_withdrawal_base", + Value: appState.Fees.Ics20Withdrawal.Base.String(), }) data.constants = append(data.constants, storage.Constant{ Module: storageTypes.ModuleNameGeneric, - Name: "sequence_byte_cost_multiplier", - Value: appState.Fees.SequenceByteCostMultiplier.String(), + Name: "ics20_withdrawal_multiplier", + Value: appState.Fees.Ics20Withdrawal.Multiplier.String(), }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "init_bridge_account_base", + Value: appState.Fees.InitBridgeAccount.Base.String(), + }) + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "init_bridge_account_multiplier", + Value: appState.Fees.InitBridgeAccount.Multiplier.String(), + }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "bridge_sudo_change_base", + Value: appState.Fees.BridgeSudoChange.Base.String(), + }) + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "bridge_sudo_change_multiplier", + Value: appState.Fees.BridgeSudoChange.Multiplier.String(), + }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "ibc_relay_base", + Value: appState.Fees.IbcRelay.Base.String(), + }) + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "ibc_relay_multiplier", + Value: appState.Fees.IbcRelay.Multiplier.String(), + }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "validator_update_base", + Value: appState.Fees.ValidatorUpdate.Base.String(), + }) + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "validator_update_multiplier", + Value: appState.Fees.ValidatorUpdate.Multiplier.String(), + }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "fee_asset_change_base", + Value: appState.Fees.FeeAssetChange.Base.String(), + }) + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "fee_asset_change_multiplier", + Value: appState.Fees.FeeAssetChange.Multiplier.String(), + }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "fee_change_base", + Value: appState.Fees.FeeChange.Base.String(), + }) + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "fee_change_multiplier", + Value: appState.Fees.FeeChange.Multiplier.String(), + }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "ibc_relayer_change_base", + Value: appState.Fees.IbcRelayerChange.Base.String(), + }) + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "ibc_relayer_change_multiplier", + Value: appState.Fees.IbcRelayerChange.Multiplier.String(), + }) + + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "sudo_address_change_base", + Value: appState.Fees.SudoAddressChange.Base.String(), + }) + data.constants = append(data.constants, storage.Constant{ + Module: storageTypes.ModuleNameGeneric, + Name: "sudo_address_change_multiplier", + Value: appState.Fees.SudoAddressChange.Multiplier.String(), + }) + data.constants = append(data.constants, storage.Constant{ Module: storageTypes.ModuleNameGeneric, - Name: "transfer_base_fee", - Value: appState.Fees.TransferBaseFee.String(), + Name: "ibc_sudo_change_base", + Value: appState.Fees.IbcSudoChange.Base.String(), }) data.constants = append(data.constants, storage.Constant{ Module: storageTypes.ModuleNameGeneric, - Name: "bridge_sudo_change_fee", - Value: appState.Fees.BridgeSudoChangeFee.String(), + Name: "ibc_sudo_change_multiplier", + Value: appState.Fees.IbcSudoChange.Multiplier.String(), }) } diff --git a/pkg/indexer/parser/parseEvents.go b/pkg/indexer/parser/parseEvents.go index 476a89d..f9f33a4 100644 --- a/pkg/indexer/parser/parseEvents.go +++ b/pkg/indexer/parser/parseEvents.go @@ -5,6 +5,8 @@ package parser import ( "context" + "encoding/base64" + "strconv" "strings" "time" @@ -25,6 +27,8 @@ func parseEvents(ctx context.Context, events []types.Event, decodeCtx *decode.Co switch events[i].Type { case "tx.fees": err = parseTxFees(ctx, events[i].Attributes, decodeCtx, api) + case "tx.deposit": + err = parseTxDeposit(events[i].Attributes, decodeCtx) default: continue } @@ -95,3 +99,47 @@ func parseTxFees(ctx context.Context, attrs []types.EventAttribute, decodeCtx *d decodeCtx.AddFee(fee) return nil } + +func parseTxDeposit(attrs []types.EventAttribute, decodeCtx *decode.Context) error { + deposit := new(storage.Deposit) + var idx int64 + + for i := range attrs { + switch attrs[i].Key { + case "bridgeAddress": + deposit.Bridge = &storage.Bridge{ + Address: &storage.Address{ + Hash: attrs[i].Value, + }, + } + case "rollupId": + hash, err := base64.URLEncoding.DecodeString(attrs[i].Value) + if err != nil { + return err + } + deposit.Rollup = &storage.Rollup{ + AstriaId: hash, + } + case "amount": + amount, err := decimal.NewFromString(attrs[i].Value) + if err != nil { + return err + } + deposit.Amount = amount + case "asset": + deposit.Asset = attrs[i].Value + case "destinationChainAddress": + deposit.DestinationChainAddress = attrs[i].Value + case "sourceTransactionId": + case "sourceActionIndex": + actionIndex, err := strconv.ParseInt(attrs[i].Value, 10, 64) + if err != nil { + return err + } + idx = actionIndex + } + } + + decodeCtx.AddDeposit(idx, deposit) + return nil +} diff --git a/pkg/indexer/parser/parseEvents_test.go b/pkg/indexer/parser/parseEvents_test.go new file mode 100644 index 0000000..4f1f9d6 --- /dev/null +++ b/pkg/indexer/parser/parseEvents_test.go @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2024 PK Lab AG <contact@pklab.io> +// SPDX-License-Identifier: MIT + +package parser + +import ( + "testing" + + "github.com/celenium-io/astria-indexer/pkg/indexer/decode" + "github.com/celenium-io/astria-indexer/pkg/types" + "github.com/stretchr/testify/require" +) + +func Test_parseTxDeposit(t *testing.T) { + t.Run("test deposit event", func(t *testing.T) { + attrs := []types.EventAttribute{ + { + Key: "bridgeAddress", + Value: "astria1yqdjnnmrp7w5ygwj0dkldsgzjhv5vcakp7yeu9", + }, { + Key: "rollupId", + Value: "xuzPaQ1qQbu1wl5oBdEiP-Xl977xEmJOVjVpqNrktnU=", + }, { + Key: "amount", + Value: "1000000000", + }, { + Key: "asset", + Value: "nria", + }, { + Key: "destinationChainAddress", + Value: "0x9d0CEC7BEB948Ab046e8b64E9aa6Cc9b731A9613", + }, { + Key: "sourceTransactionId", + Value: "c8c58bfd5d4745c08149da81c24df6738659634507c3eb535fa803c69d6a2b46", + }, { + Key: "sourceActionIndex", + Value: "0", + }, + } + + ctx := decode.NewContext(map[string]string{}) + err := parseTxDeposit(attrs, &ctx) + require.NoError(t, err) + require.Len(t, ctx.Deposits, 1) + + deposit := ctx.Deposits[0] + require.EqualValues(t, "astria1yqdjnnmrp7w5ygwj0dkldsgzjhv5vcakp7yeu9", deposit.Bridge.Address.String()) + require.NotNil(t, deposit.Rollup.AstriaId) + require.EqualValues(t, "1000000000", deposit.Amount.String()) + require.EqualValues(t, "nria", deposit.Asset) + require.EqualValues(t, "0x9d0CEC7BEB948Ab046e8b64E9aa6Cc9b731A9613", deposit.DestinationChainAddress) + }) +} diff --git a/pkg/indexer/parser/parseTxs.go b/pkg/indexer/parser/parseTxs.go index e85a25a..ca2b53d 100644 --- a/pkg/indexer/parser/parseTxs.go +++ b/pkg/indexer/parser/parseTxs.go @@ -34,7 +34,7 @@ func parseTxs(ctx context.Context, b types.BlockData, decodeCtx *decode.Context, return nil, errors.Wrap(err, "parse events") } - t, err := parseTx(b, i, b.TxsResults[i], decodeCtx) + t, err := parseTx(b, i, decodeCtx) if err != nil { return nil, err } @@ -47,21 +47,23 @@ func parseTxs(ctx context.Context, b types.BlockData, decodeCtx *decode.Context, return txs, nil } -func parseTx(b types.BlockData, index int, txRes *types.ResponseDeliverTx, ctx *decode.Context) (storage.Tx, error) { +func parseTx(b types.BlockData, index int, ctx *decode.Context) (storage.Tx, error) { d, err := decode.Tx(b, index, ctx) if err != nil { return storage.Tx{}, errors.Wrapf(err, "while parsing Tx on index %d", index) } + result := b.TxsResults[index] + t := storage.Tx{ Height: b.Height, Time: b.Block.Time, Position: int64(index), - GasWanted: txRes.GasWanted, - GasUsed: txRes.GasUsed, + GasWanted: result.GasWanted, + GasUsed: result.GasUsed, ActionsCount: int64(len(d.Actions)), Status: storageTypes.StatusSuccess, - Codespace: txRes.Codespace, + Codespace: result.Codespace, Hash: b.Block.Txs[index].Hash(), Signature: d.Tx.GetSignature(), Nonce: d.UnsignedTx.GetParams().GetNonce(), @@ -69,12 +71,12 @@ func parseTx(b types.BlockData, index int, txRes *types.ResponseDeliverTx, ctx * ActionTypes: d.ActionTypes, Actions: d.Actions, - BytesSize: int64(len(txRes.Data)), + BytesSize: int64(len(result.Data)), } - if txRes.IsFailed() { + if result.IsFailed() { t.Status = storageTypes.StatusFailed - t.Error = txRes.Log + t.Error = result.Log } return t, nil diff --git a/pkg/indexer/parser/parseTxs_test.go b/pkg/indexer/parser/parseTxs_test.go index 6b1f45d..31de162 100644 --- a/pkg/indexer/parser/parseTxs_test.go +++ b/pkg/indexer/parser/parseTxs_test.go @@ -39,17 +39,29 @@ func TestParseTxs_SuccessTx(t *testing.T) { GasUsed: 1000, Events: []types.Event{ { - Type: "tx.fees", + Type: "tx.deposit", Attributes: []types.EventAttribute{ { + Key: "bridgeAddress", + Value: "astria1yqdjnnmrp7w5ygwj0dkldsgzjhv5vcakp7yeu9", + }, { + Key: "rollupId", + Value: "xuzPaQ1qQbu1wl5oBdEiP-Xl977xEmJOVjVpqNrktnU=", + }, { + Key: "amount", + Value: "1000000000", + }, { Key: "asset", - Value: "ibc/704031c868fd3d3c84a1cfa8cb45deba4ea746b44697f7f4a6ed1b8f6c239b82", + Value: "nria", + }, { + Key: "destinationChainAddress", + Value: "0x9d0CEC7BEB948Ab046e8b64E9aa6Cc9b731A9613", }, { - Key: "feeAmount", - Value: "153", + Key: "sourceTransactionId", + Value: "c8c58bfd5d4745c08149da81c24df6738659634507c3eb535fa803c69d6a2b46", }, { - Key: "actionType", - Value: "astria.protocol.transactions.v1alpha1.FeeAssetChangeAction", + Key: "sourceActionIndex", + Value: "0", }, }, }, diff --git a/pkg/indexer/rollback/rollback.go b/pkg/indexer/rollback/rollback.go index 9accc35..f2cde4a 100644 --- a/pkg/indexer/rollback/rollback.go +++ b/pkg/indexer/rollback/rollback.go @@ -210,6 +210,10 @@ func rollbackBlock(ctx context.Context, tx storage.Transaction, height types.Lev return err } + if err := tx.RollbackDeposits(ctx, height); err != nil { + return err + } + if err := tx.RollbackTransfers(ctx, height); err != nil { return err } diff --git a/pkg/indexer/rollback/rollback_test.go b/pkg/indexer/rollback/rollback_test.go index c098c78..a45dae0 100644 --- a/pkg/indexer/rollback/rollback_test.go +++ b/pkg/indexer/rollback/rollback_test.go @@ -77,7 +77,7 @@ func Test_rollbackBlock(t *testing.T) { Height: height, Time: blockTime, Position: 0, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, TxId: 1, Data: map[string]any{ "rollup_id": "deadbeaf", @@ -99,7 +99,7 @@ func Test_rollbackBlock(t *testing.T) { Height: height, Time: blockTime, Position: 2, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, TxId: 1, Data: map[string]any{ "data": "+G6AhDuaygeCUgiUaN0ig7sPHLWZae8gW9rtKb4FEKSIiscjBInoAACAgxvZgqDlaFLJ2rb9OUtQRsM/meiHSoW2nSkIGJiW6fhUti+v16Ani2wgQDfXhYkgZylMwLhCXtawIhnoA8eVSnnsg/7jGQ==", @@ -116,7 +116,7 @@ func Test_rollbackBlock(t *testing.T) { { Height: height, Time: blockTime, - ActionType: types.ActionTypeSequence, + ActionType: types.ActionTypeRollupDataSubmission, ActionId: 1, AddressId: 1, }, { @@ -134,7 +134,7 @@ func Test_rollbackBlock(t *testing.T) { }, { Height: height, Time: blockTime, - ActionType: types.ActionTypeSequence, + ActionType: types.ActionTypeRollupDataSubmission, ActionId: 3, AddressId: 1, }, @@ -257,6 +257,11 @@ func Test_rollbackBlock(t *testing.T) { Return(nil). Times(1) + tx.EXPECT(). + RollbackDeposits(ctx, height). + Return(nil). + Times(1) + tx.EXPECT(). RollbackTransfers(ctx, height). Return(nil). diff --git a/pkg/indexer/rollback/rollup.go b/pkg/indexer/rollback/rollup.go index f2e37ce..6169981 100644 --- a/pkg/indexer/rollback/rollup.go +++ b/pkg/indexer/rollback/rollup.go @@ -70,7 +70,7 @@ func rollbackRollups( } func updateRollups(updates map[uint64]*storage.Rollup, rollupId uint64, action storage.Action) error { - if action.Type != storageTypes.ActionTypeSequence { + if action.Type != storageTypes.ActionTypeRollupDataSubmission { return errors.Errorf("invalid action type: %s", action.Type) } size, err := getActionSize(action) diff --git a/pkg/indexer/rollback/rollup_test.go b/pkg/indexer/rollback/rollup_test.go index f94495c..f98b110 100644 --- a/pkg/indexer/rollback/rollup_test.go +++ b/pkg/indexer/rollback/rollup_test.go @@ -26,7 +26,7 @@ func Test_getActionSize(t *testing.T) { Height: 1000, Time: time.Now(), Position: 2, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, TxId: 1, Data: map[string]any{ "data": "+G6AhDuaygeCUgiUaN0ig7sPHLWZae8gW9rtKb4FEKSIiscjBInoAACAgxvZgqDlaFLJ2rb9OUtQRsM/meiHSoW2nSkIGJiW6fhUti+v16Ani2wgQDfXhYkgZylMwLhCXtawIhnoA8eVSnnsg/7jGQ==", @@ -41,7 +41,7 @@ func Test_getActionSize(t *testing.T) { Height: 1000, Time: time.Now(), Position: 2, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, TxId: 1, Data: map[string]any{ "rollup_id": "GbqKuz5LVqMJ32dWxHuX4pjjpy2IRJ02oPrbHKc2ZTk=", @@ -55,7 +55,7 @@ func Test_getActionSize(t *testing.T) { Height: 1000, Time: time.Now(), Position: 2, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, TxId: 1, Data: map[string]any{ "rollup_id": "GbqKuz5LVqMJ32dWxHuX4pjjpy2IRJ02oPrbHKc2ZTk=", @@ -70,7 +70,7 @@ func Test_getActionSize(t *testing.T) { Height: 1000, Time: time.Now(), Position: 2, - Type: types.ActionTypeSequence, + Type: types.ActionTypeRollupDataSubmission, TxId: 1, Data: map[string]any{ "rollup_id": "GbqKuz5LVqMJ32dWxHuX4pjjpy2IRJ02oPrbHKc2ZTk=", diff --git a/pkg/indexer/storage/action.go b/pkg/indexer/storage/action.go index f9317a9..a45893b 100644 --- a/pkg/indexer/storage/action.go +++ b/pkg/indexer/storage/action.go @@ -29,6 +29,7 @@ func saveAction( addrActions = make([]*storage.AddressAction, 0) balanceUpdates = make([]storage.BalanceUpdate, 0) fees = make([]*storage.Fee, 0) + deposits = make([]*storage.Deposit, 0) ) for i := range actions { if actions[i].RollupAction != nil { @@ -60,6 +61,29 @@ func saveAction( } fees = append(fees, actions[i].Fee) } + + if actions[i].Deposit != nil { + actions[i].Deposit.ActionId = actions[i].Id + actions[i].Deposit.TxId = actions[i].TxId + + if addrId, ok := addrToId[actions[i].Deposit.Bridge.Address.Hash]; ok { + bridgeId, err := tx.GetBridgeIdByAddressId(ctx, addrId) + if err != nil { + return errors.Wrap(err, "receiving deposit bridge id") + } + actions[i].Deposit.BridgeId = bridgeId + } else { + return errors.Errorf("unknown payer id") + } + + rollup, err := tx.GetRollup(ctx, actions[i].Deposit.Rollup.AstriaId) + if err != nil { + return errors.Errorf("unknown deposit rollup id: %x", actions[i].Deposit.Rollup.AstriaId) + } + actions[i].Deposit.RollupId = rollup.Id + + deposits = append(deposits, actions[i].Deposit) + } } if err := tx.SaveRollupActions(ctx, rollupActions...); err != nil { @@ -74,6 +98,9 @@ func saveAction( if err := tx.SaveFees(ctx, fees...); err != nil { return err } + if err := tx.SaveDeposits(ctx, deposits...); err != nil { + return err + } return nil } diff --git a/pkg/node/types/genesis.go b/pkg/node/types/genesis.go index ddffaa9..31bac86 100644 --- a/pkg/node/types/genesis.go +++ b/pkg/node/types/genesis.go @@ -40,7 +40,7 @@ type AppState struct { type Account struct { Address Bech32m `json:"address"` - Balance BigInt `json:"balance"` + Balance UInt128 `json:"balance"` } type Bech32m struct { @@ -52,21 +52,34 @@ type Prefixes struct { } type Fees struct { - TransferBaseFee BigInt `json:"transfer_base_fee"` - SequenceBaseFee BigInt `json:"sequence_base_fee"` - SequenceByteCostMultiplier BigInt `json:"sequence_byte_cost_multiplier"` - InitBridgeAccountBaseFee BigInt `json:"init_bridge_account_base_fee"` - BridgeLockByteCostMultiplier BigInt `json:"bridge_lock_byte_cost_multiplier"` - Ics20WithdrawalBaseFee BigInt `json:"ics20_withdrawal_base_fee"` - BridgeSudoChangeFee BigInt `json:"bridge_sudo_change_fee"` + Transfer Fee `json:"transfer"` + Sequence Fee `json:"sequence"` + Ics20Withdrawal Fee `json:"ics20_withdrawal"` + InitBridgeAccount Fee `json:"init_bridge_account"` + BridgeLock Fee `json:"bridge_lock"` + BridgeUnlock Fee `json:"bridge_unlock"` + BridgeSudoChange Fee `json:"bridge_sudo_change"` + + IbcRelay Fee `json:"ibc_relay"` + ValidatorUpdate Fee `json:"validator_update"` + FeeAssetChange Fee `json:"fee_asset_change"` + FeeChange Fee `json:"fee_change"` + IbcRelayerChange Fee `json:"ibc_relayer_change"` + SudoAddressChange Fee `json:"sudo_address_change"` + IbcSudoChange Fee `json:"ibc_sudo_change"` +} + +type Fee struct { + Base UInt128 `json:"base"` + Multiplier UInt128 `json:"multiplier"` } -type BigInt struct { +type UInt128 struct { Low uint64 `json:"lo"` High uint64 `json:"hi"` } -func (bi BigInt) String() string { +func (bi UInt128) String() string { b := new(big.Int) b = b.SetUint64(bi.High) b = b.Lsh(b, 64) diff --git a/test/data/action.yml b/test/data/action.yml index e9ae3b3..3cee398 100644 --- a/test/data/action.yml +++ b/test/data/action.yml @@ -2,7 +2,7 @@ height: 7316 time: '2023-11-30T23:52:23.265Z' position: 0 - type: sequence + type: rollup_data_submission tx_id: 1 data: data: "+G6AhDuaygeCUgiUaN0ig7sPHLWZae8gW9rtKb4FEKSIiscjBInoAACAgxvZgqDlaFLJ2rb9OUtQRsM/meiHSoW2nSkIGJiW6fhUti+v16Ani2wgQDfXhYkgZylMwLhCXtawIhnoA8eVSnnsg/7jGQ==" diff --git a/test/data/address_action.yml b/test/data/address_action.yml index 465e063..bb1816e 100644 --- a/test/data/address_action.yml +++ b/test/data/address_action.yml @@ -1,6 +1,6 @@ - address_id: 1 action_id: 1 - action_type: sequence + action_type: rollup_data_submission time: '2023-11-30T23:52:23.265Z' height: 7316 tx_id: 1 diff --git a/test/data/deposit.yml b/test/data/deposit.yml new file mode 100644 index 0000000..db7b114 --- /dev/null +++ b/test/data/deposit.yml @@ -0,0 +1,10 @@ +- id: 1 + height: 7965 + time: '2023-12-01T00:18:07.575Z' + bridge_id: 1 + rollup_id: 1 + asset: nria + amount: 100 + destination_chain_address: destination_chain_address + action_id: 2 + tx_id: 2