├── .dockerignore
├── CODEOWNERS
├── .github
├── ISSUE_TEMPLATE
│ ├── config.yml
│ ├── bug_report.yml
│ └── feature_request.yml
├── PULL_REQUEST_TEMPLATE.md
├── workflows
│ ├── release.yaml
│ ├── lint.yaml
│ └── test.yaml
└── dependabot.yml
├── internal
├── engine
│ ├── protocol
│ │ ├── near
│ │ │ ├── data_source_test.go
│ │ │ ├── state.go
│ │ │ ├── filter.go
│ │ │ └── option.go
│ │ ├── atproto
│ │ │ ├── filter.go
│ │ │ ├── state.go
│ │ │ ├── option.go
│ │ │ └── task.go
│ │ ├── activitypub
│ │ │ └── state.go
│ │ ├── arweave
│ │ │ ├── state.go
│ │ │ ├── filter.go
│ │ │ └── data_source_test.go
│ │ ├── ethereum
│ │ │ ├── state.go
│ │ │ └── filter.go
│ │ ├── farcaster
│ │ │ ├── state.go
│ │ │ ├── option.go
│ │ │ └── task.go
│ │ └── factory.go
│ ├── worker
│ │ ├── decentralized
│ │ │ ├── core
│ │ │ │ ├── near
│ │ │ │ │ └── config.go
│ │ │ │ ├── arweave
│ │ │ │ │ └── config.go
│ │ │ │ ├── ethereum
│ │ │ │ │ └── config.go
│ │ │ │ └── worker.go
│ │ │ └── contract
│ │ │ │ ├── linear
│ │ │ │ ├── config.go
│ │ │ │ └── schema.go
│ │ │ │ ├── nearsocial
│ │ │ │ ├── config.go
│ │ │ │ └── schema.go
│ │ │ │ ├── mirror
│ │ │ │ └── model
│ │ │ │ │ └── dataset_mirror_post.go
│ │ │ │ ├── lens
│ │ │ │ └── utils.go
│ │ │ │ ├── curve
│ │ │ │ └── pool
│ │ │ │ │ └── schema.go
│ │ │ │ └── crossbell
│ │ │ │ └── schema.go
│ │ ├── rss
│ │ │ └── factory.go
│ │ ├── federated
│ │ │ └── factory.go
│ │ └── ai
│ │ │ └── core
│ │ │ └── agentdata
│ │ │ └── worker.go
│ ├── data_source.go
│ ├── checkpoint.go
│ ├── worker.go
│ └── task.go
├── stream
│ ├── driver.go
│ ├── client.go
│ └── provider
│ │ └── provider.go
├── database
│ ├── driver.go
│ ├── model
│ │ ├── dataset_ens_namehash.go
│ │ ├── dataset_farcaster_profile.go
│ │ ├── dataset_bluesky_profile.go
│ │ ├── dataset_mastodon_handle.go
│ │ └── activity.go
│ └── dialer
│ │ ├── postgres
│ │ ├── migration
│ │ │ ├── 20240425043201_add_calldata.sql
│ │ │ ├── 20231228162957_add_checkpoints_index_count_column.sql
│ │ │ ├── 20241218042140_add_activities_indexes.sql
│ │ │ ├── 20240115040941_add_ens_namehash.sql
│ │ │ ├── 20240922233919_add_mastodon_handles.sql
│ │ │ └── 20241210031220_add_bluesky_profiles.sql
│ │ └── table
│ │ │ ├── dataset_ens_namehash.go
│ │ │ ├── dataset_mirror_post.go
│ │ │ ├── dataset_mastodon_update_handle.go
│ │ │ ├── dataset_farcaster_profile.go
│ │ │ ├── dataset_bluesky_profile.go
│ │ │ └── checkpoint.go
│ │ └── dialer.go
├── node
│ ├── component
│ │ ├── component.go
│ │ ├── rss
│ │ │ ├── option.go
│ │ │ └── handler.go
│ │ ├── middleware
│ │ │ └── auth.go
│ │ ├── federated
│ │ │ └── transformer_activity.go
│ │ └── ai
│ │ │ └── option.go
│ ├── middlewarex
│ │ └── middlewarex_test.go
│ └── broadcaster
│ │ └── server.go
├── constant
│ └── version.go
├── telemetry
│ ├── meter
│ │ └── meter.go
│ └── tracer
│ │ └── tracer.go
└── utils
│ └── utils.go
├── docs
├── schemas
│ ├── Cursor.yaml
│ ├── To.yaml
│ ├── NodeInfoData.yaml
│ ├── Worker.yaml
│ ├── Authentication.yaml
│ ├── Platform.yaml
│ ├── RSSAccount.yaml
│ ├── Success.yaml
│ ├── Types.yaml
│ ├── DecentralizedAccount.yaml
│ ├── Networks.yaml
│ ├── Timestamp.yaml
│ ├── FederatedAccount.yaml
│ ├── ActionPage.yaml
│ ├── Tags.yaml
│ ├── ProtocolDirection.yaml
│ ├── ProtocolTag.yaml
│ ├── MetaCursor.yaml
│ ├── RSSWorker.yaml
│ ├── MetaTotalPages.yaml
│ ├── ProtocolNetwork.yaml
│ ├── RSSPlatform.yaml
│ ├── Error.yaml
│ ├── FederatedWorker.yaml
│ ├── Limit.yaml
│ ├── ActionLimit.yaml
│ ├── NetworkConfigDetail.yaml
│ ├── Version.yaml
│ ├── FederatedPlatform.yaml
│ ├── ProtocolType.yaml
│ ├── EndpointConfig.yaml
│ ├── MinimumResource.yaml
│ ├── WorkerStatus.yaml
│ ├── tmpl
│ │ ├── RSS.yaml.tmpl
│ │ ├── Federated.yaml.tmpl
│ │ └── Decentralized.yaml.tmpl
│ ├── WorkerProgress.yaml
│ ├── ProtocolMetadata.yaml
│ ├── ConfigDetail.yaml
│ ├── Calldata.yaml
│ ├── Fee.yaml
│ ├── WorkerConfig.yaml
│ ├── Reward.yaml
│ ├── WorkerInfo.yaml
│ ├── NetworkConfig.yaml
│ ├── Parameters.yaml
│ ├── Records.yaml
│ ├── DecentralizedAction.yaml
│ ├── RSSAction.yaml
│ ├── FederatedAction.yaml
│ ├── FederatedMetadata.yaml
│ ├── DecentralizedWorker.yaml
│ ├── DecentralizedPlatform.yaml
│ ├── RSSMetadata.yaml
│ ├── RSSActivity.yaml
│ ├── FederatedActivity.yaml
│ └── ComponentInfo.yaml
├── responses
│ ├── NotFound.yaml
│ ├── NodeInfoResponse.yaml
│ ├── NetworkConfigResponse.yaml
│ ├── BadRequest.yaml
│ ├── InternalError.yaml
│ ├── AIResponse.yaml
│ ├── WorkerInfoResponse.yaml
│ ├── FederatedActivityResponse.yaml
│ ├── DecentralizedActivityResponse.yaml
│ ├── FederatedActivitiesResponse.yaml
│ └── DecentralizedActivitiesResponse.yaml
├── parameters
│ ├── path_rss.yaml
│ ├── path_ai.yaml
│ ├── path_platform_federated.yaml
│ ├── path_network.yaml
│ ├── path_platform_decentralized.yaml
│ ├── query_tag.yaml
│ ├── query_cursor.yaml
│ ├── query_type.yaml
│ ├── query_network.yaml
│ ├── query_direction.yaml
│ ├── path_activity_id.yaml
│ ├── query_success.yaml
│ ├── query_until_timestamp.yaml
│ ├── path_account_decentralized.yaml
│ ├── query_since_timestamp.yaml
│ ├── query_action_page.yaml
│ ├── query_limit.yaml
│ ├── query_platform_federated.yaml
│ ├── path_account_federated.yaml
│ ├── query_action_limit.yaml
│ └── query_platform_decentralized.yaml
├── cfg.yaml
├── path
│ ├── info.yaml
│ ├── workers_status.yaml
│ ├── networks
│ │ └── config.yaml
│ ├── ai.yaml
│ ├── version.yaml
│ ├── rss.yaml
│ ├── home.yaml
│ ├── federated
│ │ ├── tx.yaml
│ │ ├── accounts.yaml
│ │ ├── network.yaml
│ │ ├── platform.yaml
│ │ └── account.yaml
│ ├── decentralized
│ │ ├── tx.yaml
│ │ ├── accounts.yaml
│ │ ├── metadata.yaml
│ │ ├── network.yaml
│ │ ├── platform.yaml
│ │ └── account.yaml
│ └── activity_count.yaml
├── tool.go
└── requestBody
│ ├── BatchGetFederatedAccountsActivities.yaml
│ ├── BatchGetDecentralizedAccountsActivities.yaml
│ └── BatchGetDecentralizedMetadataActivities.yaml
├── .devcontainer
├── Dockerfile
└── devcontainer.json
├── config
├── flag
│ └── config.go
├── parameter
│ ├── README.md
│ └── data.go
└── validator.go
├── provider
├── arweave
│ ├── contract
│ │ ├── mirror
│ │ │ └── contract.go
│ │ ├── paragraph
│ │ │ └── contract.go
│ │ └── momoka
│ │ │ └── contract.go
│ ├── type_network.go
│ ├── bundle
│ │ ├── irys
│ │ │ ├── genqlient.yaml
│ │ │ ├── graphql.config.yaml
│ │ │ ├── constant.go
│ │ │ ├── operation_test.go
│ │ │ └── operation
│ │ │ │ └── transactions.graphql
│ │ ├── transaction.go
│ │ └── signature.go
│ ├── type_block.go
│ ├── utils.go
│ ├── type_transaction.go
│ └── gateway.go
├── near
│ ├── utils.go
│ └── client_test.go
├── ethereum
│ ├── contract
│ │ ├── erc165
│ │ │ ├── contract.go
│ │ │ └── abi
│ │ │ │ └── ERC165.abi
│ │ ├── iqwiki
│ │ │ ├── graphql.config.yaml
│ │ │ ├── genqlient.yaml
│ │ │ ├── client_test.go
│ │ │ ├── contract.go
│ │ │ ├── client.go
│ │ │ └── operation
│ │ │ │ └── activities.graphql
│ │ ├── ens
│ │ │ ├── action.go
│ │ │ ├── erc1577
│ │ │ │ └── contenthash.go
│ │ │ └── contract_test.go
│ │ ├── matters
│ │ │ └── contract.go
│ │ ├── zerion
│ │ │ └── contract.go
│ │ ├── erc20
│ │ │ └── contract.go
│ │ ├── cow
│ │ │ └── contract.go
│ │ ├── erc721
│ │ │ └── contract.go
│ │ ├── erc1155
│ │ │ └── contract.go
│ │ ├── highlight
│ │ │ └── contract.go
│ │ ├── savm
│ │ │ └── contract.go
│ │ ├── aavegotchi
│ │ │ └── contract.go
│ │ ├── kiwistand
│ │ │ └── contract.go
│ │ ├── selector_test.go
│ │ ├── weth
│ │ │ └── contract.go
│ │ ├── arbitrum
│ │ │ └── abi
│ │ │ │ └── L1ERC20Gateway.abi
│ │ ├── polymarket
│ │ │ └── contract.go
│ │ ├── rainbow
│ │ │ └── contract.go
│ │ ├── benddao
│ │ │ └── contract.go
│ │ ├── paraswap
│ │ │ └── contract.go
│ │ ├── selector.go
│ │ ├── base
│ │ │ └── contract.go
│ │ └── nouns
│ │ │ └── contract.go
│ ├── option.go
│ └── etherface
│ │ └── client_test.go
├── atproto
│ └── model.go
├── ipfs
│ ├── gateway.go
│ ├── gateway_test.go
│ └── url.go
└── redis
│ └── client.go
├── cmd
└── tools.go
├── deploy
├── README.md
└── default
│ └── config.default.yaml
├── .run
├── build.run.xml
├── image.run.xml
└── run.run.xml
├── schema
└── worker
│ ├── status.go
│ ├── rss
│ ├── platform.go
│ └── worker.go
│ ├── federated
│ ├── platform.go
│ └── worker.go
│ └── worker.go
├── .pre-commit-config.yaml
├── .gitignore
├── Dockerfile
├── .golangci.yaml
├── LICENSE
├── README.md
└── common
├── http
└── response
│ └── error.go
└── sync
└── quickgroup_test.go
/.dockerignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @polebug @pseudoyu
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 |
--------------------------------------------------------------------------------
/internal/engine/protocol/near/data_source_test.go:
--------------------------------------------------------------------------------
1 | package near_test
2 |
--------------------------------------------------------------------------------
/docs/schemas/Cursor.yaml:
--------------------------------------------------------------------------------
1 | type: string
2 | description: Specify the cursor used for pagination
--------------------------------------------------------------------------------
/docs/schemas/To.yaml:
--------------------------------------------------------------------------------
1 | description: The address to which the action is directed.
2 | type: string
3 |
--------------------------------------------------------------------------------
/docs/schemas/NodeInfoData.yaml:
--------------------------------------------------------------------------------
1 | properties:
2 | data:
3 | $ref: "./NodeInfo.yaml"
4 | type: object
5 |
--------------------------------------------------------------------------------
/docs/schemas/Worker.yaml:
--------------------------------------------------------------------------------
1 | anyOf:
2 | - $ref: "./DecentralizedWorker.yaml"
3 | - $ref: "./FederatedWorker.yaml"
4 |
--------------------------------------------------------------------------------
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM fedora:39
2 |
3 | RUN dnf update -y && \
4 | dnf install procps git make golang -y
5 |
--------------------------------------------------------------------------------
/docs/schemas/Authentication.yaml:
--------------------------------------------------------------------------------
1 | properties:
2 | access_key:
3 | $ref: "./ConfigDetail.yaml"
4 | type: object
5 |
--------------------------------------------------------------------------------
/docs/schemas/Platform.yaml:
--------------------------------------------------------------------------------
1 | allOf:
2 | - $ref: "./DecentralizedPlatform.yaml"
3 | - $ref: "./FederatedPlatform.yaml"
4 |
--------------------------------------------------------------------------------
/docs/schemas/RSSAccount.yaml:
--------------------------------------------------------------------------------
1 | description: The owner of the activity.
2 | type: string
3 | example:
4 | - "www.abc.net.au"
--------------------------------------------------------------------------------
/docs/schemas/Success.yaml:
--------------------------------------------------------------------------------
1 | type: boolean
2 | description: Retrieve activities based on success status
3 | x-go-name: Status
--------------------------------------------------------------------------------
/docs/schemas/Types.yaml:
--------------------------------------------------------------------------------
1 | items:
2 | $ref: "./ProtocolType.yaml"
3 | type: array
4 | x-go-type-skip-optional-pointer: true
--------------------------------------------------------------------------------
/docs/schemas/DecentralizedAccount.yaml:
--------------------------------------------------------------------------------
1 | description: The owner of the activity.
2 | type: string
3 | pattern: 0x[0-9a-fA-F]{40}
--------------------------------------------------------------------------------
/docs/schemas/Networks.yaml:
--------------------------------------------------------------------------------
1 | items:
2 | $ref: "./ProtocolNetwork.yaml"
3 | type: array
4 | x-go-type-skip-optional-pointer: true
--------------------------------------------------------------------------------
/docs/schemas/Timestamp.yaml:
--------------------------------------------------------------------------------
1 | description: The timestamp of when the activity occurred.
2 | type: integer
3 | x-go-type: uint64
--------------------------------------------------------------------------------
/internal/engine/protocol/atproto/filter.go:
--------------------------------------------------------------------------------
1 | package atproto
2 |
3 | type Filter struct {
4 | Type []string `json:"type"`
5 | }
6 |
--------------------------------------------------------------------------------
/docs/schemas/FederatedAccount.yaml:
--------------------------------------------------------------------------------
1 | description: The owner of the activity.
2 | type: string
3 | example: "@seachdamh@101010.pl"
4 |
5 |
--------------------------------------------------------------------------------
/config/flag/config.go:
--------------------------------------------------------------------------------
1 | package flag
2 |
3 | var (
4 | KeyConfig = "config"
5 | KeyModule = "module"
6 | KeyWorkerID = "worker.id"
7 | )
8 |
--------------------------------------------------------------------------------
/docs/schemas/ActionPage.yaml:
--------------------------------------------------------------------------------
1 | default: 1
2 | minimum: 1
3 | type: integer
4 | x-oapi-codegen-extra-tags:
5 | validate: "min=1"
6 | default: "1"
--------------------------------------------------------------------------------
/provider/arweave/contract/mirror/contract.go:
--------------------------------------------------------------------------------
1 | package mirror
2 |
3 | var (
4 | AddressMirror = "Ky1c1Kkt-jZ9sY1hvLF5nCf6WWdBhIU5Un_BMYh-t3c"
5 | )
6 |
--------------------------------------------------------------------------------
/provider/arweave/contract/paragraph/contract.go:
--------------------------------------------------------------------------------
1 | package paragraph
2 |
3 | var (
4 | AddressParagraph = "w5AtiFsNvORfcRtikbdrp2tzqixb05vdPw-ZhgVkD70"
5 | )
6 |
--------------------------------------------------------------------------------
/cmd/tools.go:
--------------------------------------------------------------------------------
1 | //go:build tools
2 | // +build tools
3 |
4 | package main
5 |
6 | import (
7 | _ "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen"
8 | )
9 |
--------------------------------------------------------------------------------
/internal/stream/driver.go:
--------------------------------------------------------------------------------
1 | package stream
2 |
3 | type Driver string
4 |
5 | const (
6 | DriverKafka Driver = "kafka"
7 | DriverPulsar Driver = "pulsar"
8 | )
9 |
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/core/near/config.go:
--------------------------------------------------------------------------------
1 | package near
2 |
3 | type Config struct {
4 | // TODO Implement support for customizable configurations.
5 | }
6 |
--------------------------------------------------------------------------------
/config/parameter/README.md:
--------------------------------------------------------------------------------
1 | ## Parameter
2 |
3 | This directory contains the parameters affecting the behavior of the Node.
4 |
5 | The parameters must NOT be changed manually.
--------------------------------------------------------------------------------
/docs/responses/NotFound.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | $ref: "../schemas/Error.yaml"
5 | description: The specified resource was not found.
6 |
--------------------------------------------------------------------------------
/docs/responses/NodeInfoResponse.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | $ref: "../schemas/NodeInfoData.yaml"
5 | description: The request was successful.
6 |
--------------------------------------------------------------------------------
/docs/schemas/Tags.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities for the specified tag(s)
2 | items:
3 | $ref: "./ProtocolTag.yaml"
4 | type: array
5 | x-go-type-skip-optional-pointer: true
--------------------------------------------------------------------------------
/internal/database/driver.go:
--------------------------------------------------------------------------------
1 | package database
2 |
3 | type Driver string
4 |
5 | const (
6 | DriverPostgreSQL Driver = "postgres"
7 | DriverMySQL Driver = "mysql"
8 | )
9 |
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/contract/linear/config.go:
--------------------------------------------------------------------------------
1 | package linear
2 |
3 | type Config struct {
4 | // TODO Implement support for customizable configurations.
5 | }
6 |
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/core/arweave/config.go:
--------------------------------------------------------------------------------
1 | package arweave
2 |
3 | type Config struct {
4 | // TODO Implement support for customizable configurations.
5 | }
6 |
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/core/ethereum/config.go:
--------------------------------------------------------------------------------
1 | package ethereum
2 |
3 | type Config struct {
4 | // TODO Implement support for customizable configurations.
5 | }
6 |
--------------------------------------------------------------------------------
/docs/parameters/path_rss.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve details for the specified RSS path
2 | example: abc
3 | in: path
4 | name: path
5 | required: true
6 | schema:
7 | type: string
8 |
--------------------------------------------------------------------------------
/docs/schemas/ProtocolDirection.yaml:
--------------------------------------------------------------------------------
1 | allOf:
2 | - $ref: "https://raw.githubusercontent.com/RSS3-Network/Protocol-Go/refs/heads/main/openapi/enum/Direction.yaml"
3 | # - x-go-type: string
--------------------------------------------------------------------------------
/docs/responses/NetworkConfigResponse.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | $ref: "../schemas/NetworkConfigData.yaml"
5 | description: The request was successful.
6 |
--------------------------------------------------------------------------------
/docs/schemas/ProtocolTag.yaml:
--------------------------------------------------------------------------------
1 | allOf:
2 | - $ref: "https://raw.githubusercontent.com/RSS3-Network/Protocol-Go/refs/heads/main/openapi/enum/Tag.yaml"
3 | x-go-type-skip-optional-pointer: true
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/contract/nearsocial/config.go:
--------------------------------------------------------------------------------
1 | package nearsocial
2 |
3 | type Config struct {
4 | // TODO Implement support for customizable configurations.
5 | }
6 |
--------------------------------------------------------------------------------
/docs/responses/BadRequest.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | $ref: '../schemas/Error.yaml'
5 | description: The request is malformed or contains invalid parameters.
6 |
--------------------------------------------------------------------------------
/provider/arweave/type_network.go:
--------------------------------------------------------------------------------
1 | package arweave
2 |
3 | // Network represents the Network information of the Arweave network.
4 | type Network struct {
5 | Blocks int64 `json:"blocks"`
6 | }
7 |
--------------------------------------------------------------------------------
/docs/parameters/path_ai.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve details for the specified AgentData path
2 | example: api/v1/ai_intel
3 | in: path
4 | name: path
5 | required: true
6 | schema:
7 | type: string
8 |
--------------------------------------------------------------------------------
/docs/responses/InternalError.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | $ref: "../schemas/Error.yaml"
5 | description: An internal server error occurred while processing the request.
6 |
--------------------------------------------------------------------------------
/docs/schemas/MetaCursor.yaml:
--------------------------------------------------------------------------------
1 | description: Metadata for paginated responses.
2 | properties:
3 | cursor:
4 | description: The cursor for the next set of results.
5 | type: string
6 | type: object
7 |
--------------------------------------------------------------------------------
/internal/engine/protocol/near/state.go:
--------------------------------------------------------------------------------
1 | package near
2 |
3 | type State struct {
4 | BlockHeight uint64 `json:"block_height,omitempty"`
5 | BlockTimestamp uint64 `json:"block_timestamp,omitempty"`
6 | }
7 |
--------------------------------------------------------------------------------
/provider/arweave/bundle/irys/genqlient.yaml:
--------------------------------------------------------------------------------
1 | schema: schema.graphql
2 | operations:
3 | - ./operation/transactions.graphql
4 | generated: operation.go
5 | bindings:
6 | BigInt:
7 | type: "*math/big.Int"
8 |
--------------------------------------------------------------------------------
/internal/engine/protocol/activitypub/state.go:
--------------------------------------------------------------------------------
1 | package activitypub
2 |
3 | // State represents the state of the ActivityPub data protocol.
4 | type State struct {
5 | LastOffset int64 `json:"last_offset"`
6 | }
7 |
--------------------------------------------------------------------------------
/docs/parameters/path_platform_federated.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities from the specified platform.
2 | in: path
3 | name: platform
4 | required: true
5 | schema:
6 | $ref: "../schemas/FederatedPlatform.yaml"
7 |
--------------------------------------------------------------------------------
/docs/schemas/RSSWorker.yaml:
--------------------------------------------------------------------------------
1 | type: string
2 | enum:
3 | - core
4 | x-go-type: rss.Worker
5 | x-go-type-skip-optional-pointer: true
6 | x-go-type-import:
7 | path: github.com/rss3-network/node/v2/schema/worker/rss
8 |
--------------------------------------------------------------------------------
/docs/parameters/path_network.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities from the specified network.
2 | example: ethereum
3 | in: path
4 | name: network
5 | required: true
6 | schema:
7 | $ref: "../schemas/ProtocolNetwork.yaml"
8 |
--------------------------------------------------------------------------------
/docs/schemas/MetaTotalPages.yaml:
--------------------------------------------------------------------------------
1 | description: Metadata indicating the total number of pages.
2 | properties:
3 | totalPages:
4 | description: The total number of pages available.
5 | type: integer
6 | type: object
7 |
--------------------------------------------------------------------------------
/docs/schemas/ProtocolNetwork.yaml:
--------------------------------------------------------------------------------
1 | allOf:
2 | - $ref: "https://raw.githubusercontent.com/RSS3-Network/Protocol-Go/refs/heads/main/openapi/enum/Network.yaml"
3 | # - x-go-type: string
4 | x-go-type-skip-optional-pointer: true
--------------------------------------------------------------------------------
/docs/parameters/path_platform_decentralized.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities from the specified platform.
2 | in: path
3 | name: platform
4 | required: true
5 | schema:
6 | $ref: "../schemas/DecentralizedPlatform.yaml"
7 |
--------------------------------------------------------------------------------
/docs/parameters/query_tag.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities for the specified tag(s).
2 | in: query
3 | name: tag
4 | required: false
5 | schema:
6 | $ref: "../schemas/Tags.yaml"
7 | x-oapi-codegen-extra-tags:
8 | query: tag
--------------------------------------------------------------------------------
/docs/parameters/query_cursor.yaml:
--------------------------------------------------------------------------------
1 | description: Specify the cursor used for pagination.
2 | in: query
3 | name: cursor
4 | required: false
5 | schema:
6 | $ref: "../schemas/Cursor.yaml"
7 | x-oapi-codegen-extra-tags:
8 | query: cursor
--------------------------------------------------------------------------------
/docs/parameters/query_type.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities for the specified type(s).
2 | in: query
3 | name: type
4 | required: false
5 | schema:
6 | $ref: "../schemas/Types.yaml"
7 | x-oapi-codegen-extra-tags:
8 | query: "-"
--------------------------------------------------------------------------------
/docs/schemas/RSSPlatform.yaml:
--------------------------------------------------------------------------------
1 | type: string
2 | enum:
3 | - Unknown
4 | - RSSHub
5 | x-go-type: rss.Platform
6 | x-go-type-skip-optional-pointer: true
7 | x-go-type-import:
8 | path: github.com/rss3-network/node/v2/schema/worker/rss
9 |
--------------------------------------------------------------------------------
/docs/responses/AIResponse.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | type: object
5 | description: Response with AI-generated content of any structure
6 | description: JSON response containing AI-generated content
7 |
--------------------------------------------------------------------------------
/docs/parameters/query_network.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities from the specified network(s).
2 | in: query
3 | name: network
4 | required: false
5 | schema:
6 | $ref: "../schemas/Networks.yaml"
7 | x-oapi-codegen-extra-tags:
8 | query: network
--------------------------------------------------------------------------------
/docs/responses/WorkerInfoResponse.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | type: object
5 | properties:
6 | data:
7 | $ref: "../schemas/ComponentInfo.yaml"
8 | description: The request was successful.
9 |
--------------------------------------------------------------------------------
/docs/schemas/Error.yaml:
--------------------------------------------------------------------------------
1 | description: An error response.
2 | properties:
3 | code:
4 | description: The error code.
5 | type: integer
6 | message:
7 | description: The error message.
8 | type: string
9 | type: object
10 |
--------------------------------------------------------------------------------
/docs/parameters/query_direction.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities based on direction.
2 | in: query
3 | name: direction
4 | required: false
5 | schema:
6 | $ref: "../schemas/ProtocolDirection.yaml"
7 | x-oapi-codegen-extra-tags:
8 | query: direction
--------------------------------------------------------------------------------
/docs/schemas/FederatedWorker.yaml:
--------------------------------------------------------------------------------
1 | type: string
2 | enum:
3 | - mastodon
4 | - bluesky
5 | x-go-type: federated.Worker
6 | x-go-type-skip-optional-pointer: true
7 | x-go-type-import:
8 | path: github.com/rss3-network/node/v2/schema/worker/federated
9 |
--------------------------------------------------------------------------------
/provider/near/utils.go:
--------------------------------------------------------------------------------
1 | package near
2 |
3 | import (
4 | "encoding/base64"
5 | )
6 |
7 | // DecodeBase64 decodes a base64 string.
8 | func DecodeBase64(data string) ([]byte, error) {
9 | return base64.StdEncoding.DecodeString(data)
10 | }
11 |
--------------------------------------------------------------------------------
/docs/parameters/path_activity_id.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve details for the specified activity ID
2 | example: '0x840e42d573ebe1ff27a9e4914573b4e0518fcd685c7f9331d319abe854f780e3'
3 | in: path
4 | name: id
5 | required: true
6 | schema:
7 | type: string
8 |
--------------------------------------------------------------------------------
/docs/schemas/Limit.yaml:
--------------------------------------------------------------------------------
1 | type: integer
2 | description: Specify the number of activities to retrieve
3 | example: 20
4 | default: 100
5 | minimum: 1
6 | maximum: 100
7 | x-oapi-codegen-extra-tags:
8 | validate: "min=1,max=100"
9 | default: "100"
10 |
--------------------------------------------------------------------------------
/docs/parameters/query_success.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities based on success status.
2 | in: query
3 | name: success
4 | required: false
5 | schema:
6 | $ref: "../schemas/Success.yaml"
7 | x-go-name: Status
8 | x-oapi-codegen-extra-tags:
9 | query: success
--------------------------------------------------------------------------------
/docs/parameters/query_until_timestamp.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities up to this timestamp.
2 | in: query
3 | name: until_timestamp
4 | required: false
5 | schema:
6 | $ref: "../schemas/Timestamp.yaml"
7 | x-oapi-codegen-extra-tags:
8 | query: until_timestamp
--------------------------------------------------------------------------------
/docs/schemas/ActionLimit.yaml:
--------------------------------------------------------------------------------
1 | type: integer
2 | description: Specify the number of actions within the activity to retrieve
3 | example: 10
4 | default: 10
5 | maximum: 20
6 | minimum: 1
7 | x-oapi-codegen-extra-tags:
8 | validate: "min=1,max=20"
9 | default: "10"
--------------------------------------------------------------------------------
/docs/schemas/NetworkConfigDetail.yaml:
--------------------------------------------------------------------------------
1 | properties:
2 | endpoint_configs:
3 | $ref: "./EndpointConfig.yaml"
4 | id:
5 | type: string
6 | worker_configs:
7 | items:
8 | $ref: "./WorkerConfig.yaml"
9 | type: array
10 | type: object
11 |
--------------------------------------------------------------------------------
/docs/schemas/Version.yaml:
--------------------------------------------------------------------------------
1 | description: The git version info of node.
2 | properties:
3 | commit:
4 | description: The git commit of node.
5 | type: string
6 | tag:
7 | description: The git tag of node.
8 | type: string
9 | type: object
10 |
--------------------------------------------------------------------------------
/internal/engine/protocol/arweave/state.go:
--------------------------------------------------------------------------------
1 | package arweave
2 |
3 | type State struct {
4 | BlockHeight uint64 `json:"block_height,omitempty"`
5 | Cursor string `json:"cursor,omitempty"`
6 | BlockTimestamp uint64 `json:"block_timestamp,omitempty"`
7 | }
8 |
--------------------------------------------------------------------------------
/docs/parameters/path_account_decentralized.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities from the specified account.
2 | in: path
3 | name: account
4 | required: true
5 | schema:
6 | $ref: "../schemas/DecentralizedAccount.yaml"
7 | example: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"
--------------------------------------------------------------------------------
/docs/parameters/query_since_timestamp.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities starting from this timestamp.
2 | in: query
3 | name: since_timestamp
4 | required: false
5 | schema:
6 | $ref: "../schemas/Timestamp.yaml"
7 | x-oapi-codegen-extra-tags:
8 | query: since_timestamp
--------------------------------------------------------------------------------
/provider/ethereum/contract/erc165/contract.go:
--------------------------------------------------------------------------------
1 | package erc165
2 |
3 | // https://eips.ethereum.org/EIPS/eip-165
4 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen@v1.13.5 --abi ./abi/ERC165.abi --pkg erc165 --type ERC165 --out contract_erc165.go
5 |
--------------------------------------------------------------------------------
/internal/database/model/dataset_ens_namehash.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import "github.com/ethereum/go-ethereum/common"
4 |
5 | type ENSNamehash struct {
6 | Hash common.Hash `json:"hash"` // Hexadecimal hash bytes
7 | Name string `json:"name"` // ENS name, *.eth
8 | }
9 |
--------------------------------------------------------------------------------
/internal/engine/protocol/ethereum/state.go:
--------------------------------------------------------------------------------
1 | package ethereum
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | )
6 |
7 | type State struct {
8 | BlockHash common.Hash `json:"block_hash"`
9 | BlockNumber uint64 `json:"block_number"`
10 | }
11 |
--------------------------------------------------------------------------------
/provider/arweave/bundle/irys/graphql.config.yaml:
--------------------------------------------------------------------------------
1 | schema: schema.graphql
2 | documents: "*.graphql"
3 | extensions:
4 | endpoints:
5 | mainnet:
6 | url: https://arweave.mainnet.irys.xyz/graphql
7 | devnet:
8 | url: https://arweave.devnet.irys.xyz/graphql
9 |
--------------------------------------------------------------------------------
/docs/schemas/FederatedPlatform.yaml:
--------------------------------------------------------------------------------
1 | type: string
2 | enum:
3 | - Unknown
4 | - Mastodon
5 | - Bluesky
6 | x-go-type: federated.Platform
7 | x-go-type-skip-optional-pointer: true
8 | x-go-type-import:
9 | path: github.com/rss3-network/node/v2/schema/worker/federated
10 |
--------------------------------------------------------------------------------
/internal/engine/protocol/near/filter.go:
--------------------------------------------------------------------------------
1 | package near
2 |
3 | import (
4 | "github.com/rss3-network/node/v2/internal/engine"
5 | )
6 |
7 | var _ engine.DataSourceFilter = (*Filter)(nil)
8 |
9 | type Filter struct {
10 | ReceiverIDs []string `yaml:"receiver_ids"`
11 | }
12 |
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/contract/mirror/model/dataset_mirror_post.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | // DatasetMirrorPost represents a mirror post for revise logic check.
4 | type DatasetMirrorPost struct {
5 | TransactionID string
6 | OriginContentDigest string
7 | }
8 |
--------------------------------------------------------------------------------
/internal/stream/client.go:
--------------------------------------------------------------------------------
1 | package stream
2 |
3 | import (
4 | "context"
5 |
6 | activityx "github.com/rss3-network/protocol-go/schema/activity"
7 | )
8 |
9 | type Client interface {
10 | PushActivities(ctx context.Context, activities []*activityx.Activity) error
11 | }
12 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/iqwiki/graphql.config.yaml:
--------------------------------------------------------------------------------
1 | schema: schema.graphql
2 | documents: "**/*.graphql"
3 | extensions:
4 | endpoints:
5 | default:
6 | url: https://graph.everipedia.org/graphql
7 | headers:
8 | user-agent: JS GraphQL
9 | introspect: false
--------------------------------------------------------------------------------
/docs/schemas/ProtocolType.yaml:
--------------------------------------------------------------------------------
1 | allOf:
2 | - $ref: "https://raw.githubusercontent.com/RSS3-Network/Protocol-Go/refs/heads/main/openapi/Type.yaml"
3 | - x-go-type: schema.Type
4 | x-go-type-import:
5 | path: github.com/rss3-network/protocol-go/schema
6 | x-go-type-skip-optional-pointer: true
--------------------------------------------------------------------------------
/internal/engine/protocol/atproto/state.go:
--------------------------------------------------------------------------------
1 | package atproto
2 |
3 | type State struct {
4 | SubscribeCursor int64 `json:"subscribe_cursor,omitempty"`
5 | SubscribeTimestamp int64 `json:"subscribe_timestamp,omitempty"`
6 | ListReposCursor string `json:"list_repos_cursor,omitempty"`
7 | }
8 |
--------------------------------------------------------------------------------
/docs/schemas/EndpointConfig.yaml:
--------------------------------------------------------------------------------
1 | description: The endpoint options and config details of the worker.
2 | properties:
3 | http2_disabled:
4 | $ref: "./ConfigDetail.yaml"
5 | http_headers:
6 | $ref: "./ConfigDetail.yaml"
7 | url:
8 | $ref: "./ConfigDetail.yaml"
9 | type: object
10 |
--------------------------------------------------------------------------------
/docs/schemas/MinimumResource.yaml:
--------------------------------------------------------------------------------
1 | properties:
2 | cpu_core:
3 | format: float
4 | type: number
5 | disk_space_in_gb:
6 | type: integer
7 | key:
8 | type: string
9 | memory_in_gb:
10 | format: float
11 | type: number
12 | title:
13 | type: string
14 | type: object
15 |
--------------------------------------------------------------------------------
/docs/parameters/query_action_page.yaml:
--------------------------------------------------------------------------------
1 | description: Specify the pagination for actions
2 | example: 1
3 | in: query
4 | name: action_page
5 | required: false
6 | schema:
7 | $ref: "../schemas/ActionPage.yaml"
8 | x-oapi-codegen-extra-tags:
9 | validate: "min=1"
10 | default: "1"
11 | query: action_page
--------------------------------------------------------------------------------
/docs/parameters/query_limit.yaml:
--------------------------------------------------------------------------------
1 | description: Specify the number of activities to retrieve.
2 | example: '20'
3 | in: query
4 | name: limit
5 | required: false
6 | schema:
7 | $ref: "../schemas/Limit.yaml"
8 | x-oapi-codegen-extra-tags:
9 | validate: "min=1,max=100"
10 | default: "100"
11 | query: limit
--------------------------------------------------------------------------------
/docs/schemas/WorkerStatus.yaml:
--------------------------------------------------------------------------------
1 | description: The worker status.
2 | type: string
3 | enum:
4 | - Unknown
5 | - Indexing
6 | - Ready
7 | - Unhealthy
8 | x-go-type: worker.Status
9 | x-go-type-skip-optional-pointer: true
10 | x-go-type-import:
11 | path: github.com/rss3-network/node/v2/schema/worker
12 |
--------------------------------------------------------------------------------
/docs/schemas/tmpl/RSS.yaml.tmpl:
--------------------------------------------------------------------------------
1 | type: string
2 | {{- with .Values }}
3 | enum:
4 | {{- range . }}
5 | - {{ .name }}
6 | {{- end }}
7 | {{- end }}
8 | x-go-type: rss.{{ .Name }}
9 | x-go-type-skip-optional-pointer: true
10 | x-go-type-import:
11 | path: github.com/rss3-network/node/v2/schema/worker/rss
12 |
--------------------------------------------------------------------------------
/deploy/README.md:
--------------------------------------------------------------------------------
1 | ## config.yaml Setup
2 |
3 | Before running the Node, you need to set up the `config.yaml` file.
4 |
5 | 1. Copy `config.example.yaml` to `config.yaml`:
6 | ```bash
7 | cp config.example.yaml config.yaml
8 | ```
9 | 1. Edit `config.yaml` and fill in all the environment variables.
10 |
--------------------------------------------------------------------------------
/docs/schemas/tmpl/Federated.yaml.tmpl:
--------------------------------------------------------------------------------
1 | type: string
2 | {{- with .Values }}
3 | enum:
4 | {{- range . }}
5 | - {{ .name }}
6 | {{- end }}
7 | {{- end }}
8 | x-go-type: federated.{{ .Name }}
9 | x-go-type-skip-optional-pointer: true
10 | x-go-type-import:
11 | path: github.com/rss3-network/node/v2/schema/worker/federated
12 |
--------------------------------------------------------------------------------
/docs/responses/FederatedActivityResponse.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | properties:
5 | data:
6 | $ref: '../schemas/FederatedActivity.yaml'
7 | meta:
8 | $ref: '../schemas/MetaTotalPages.yaml'
9 | type: object
10 | description: The request was successful.
11 |
--------------------------------------------------------------------------------
/docs/schemas/WorkerProgress.yaml:
--------------------------------------------------------------------------------
1 | type: object
2 | properties:
3 | index_count:
4 | description: The index count of worker.
5 | type: integer
6 | indexed_state:
7 | description: The indexed state of worker.
8 | type: integer
9 | remote_state:
10 | description: The remote state of worker.
11 | type: integer
--------------------------------------------------------------------------------
/docs/responses/DecentralizedActivityResponse.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | properties:
5 | data:
6 | $ref: '../schemas/DecentralizedActivity.yaml'
7 | meta:
8 | $ref: '../schemas/MetaTotalPages.yaml'
9 | type: object
10 | description: The request was successful.
11 |
--------------------------------------------------------------------------------
/docs/schemas/tmpl/Decentralized.yaml.tmpl:
--------------------------------------------------------------------------------
1 | type: string
2 | {{- with .Values }}
3 | enum:
4 | {{- range . }}
5 | - {{ .name }}
6 | {{- end }}
7 | {{- end }}
8 | x-go-type: decentralized.{{ .Name }}
9 | x-go-type-skip-optional-pointer: true
10 | x-go-type-import:
11 | path: github.com/rss3-network/node/v2/schema/worker/decentralized
12 |
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/contract/lens/utils.go:
--------------------------------------------------------------------------------
1 | package lens
2 |
3 | import (
4 | "fmt"
5 | "math/big"
6 | "strconv"
7 | "strings"
8 | )
9 |
10 | func EncodeID(id *big.Int) string {
11 | value := strconv.FormatInt(id.Int64(), 16)
12 |
13 | return fmt.Sprintf("0x%s%s", strings.Repeat("0", len(value)%2), value)
14 | }
15 |
--------------------------------------------------------------------------------
/provider/arweave/type_block.go:
--------------------------------------------------------------------------------
1 | package arweave
2 |
3 | // Block represents a block on the Arweave network.
4 | type Block struct {
5 | Nonce string `json:"nonce"`
6 | Timestamp int64 `json:"timestamp"`
7 | Height int64 `json:"height"`
8 | Hash string `json:"hash"`
9 | Txs []string `json:"txs"`
10 | }
11 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/migration/20240425043201_add_calldata.sql:
--------------------------------------------------------------------------------
1 | -- +goose Up
2 | -- +goose StatementBegin
3 | ALTER TABLE "activities"
4 | ADD "calldata" json;
5 | -- +goose StatementEnd
6 |
7 | -- +goose Down
8 | -- +goose StatementBegin
9 | ALTER TABLE "activities"
10 | DROP COLUMN "calldata";
11 | -- +goose StatementEnd
12 |
--------------------------------------------------------------------------------
/docs/parameters/query_platform_federated.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities from the specified platform(s).
2 | in: query
3 | name: platform
4 | required: false
5 | schema:
6 | items:
7 | $ref: "../schemas/FederatedPlatform.yaml"
8 | type: array
9 | x-go-type-skip-optional-pointer: true
10 | x-oapi-codegen-extra-tags:
11 | query: platform
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node",
3 | "dockerComposeFile": "docker-compose.yaml",
4 | "service": "devcontainer",
5 | "runServices": [
6 | "postgres"
7 | ],
8 | "workspaceFolder": "/workspace/${localWorkspaceFolderBasename}",
9 | "forwardPorts": [
10 | "postgres:8080",
11 | "postgres:5432"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/docs/parameters/path_account_federated.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities from the specified account.
2 | in: path
3 | name: account
4 | required: true
5 | schema:
6 | $ref: "../schemas/FederatedAccount.yaml"
7 | examples:
8 | seachdamh:
9 | value: "@seachdamh@101010.pl"
10 |
11 | LukaszHorodecki:
12 | value: "@LukaszHorodecki@pol.social"
--------------------------------------------------------------------------------
/docs/parameters/query_action_limit.yaml:
--------------------------------------------------------------------------------
1 | description: Specify the number of actions within the activity to retrieve.
2 | example: '10'
3 | in: query
4 | name: action_limit
5 | required: false
6 | schema:
7 | $ref: "../schemas/ActionLimit.yaml"
8 | x-oapi-codegen-extra-tags:
9 | validate: "min=1,max=20"
10 | default: "10"
11 | query: action_limit
12 |
--------------------------------------------------------------------------------
/docs/schemas/ProtocolMetadata.yaml:
--------------------------------------------------------------------------------
1 | description: Additional metadata related to the action.
2 | type: object
3 | allOf:
4 | - $ref: "https://raw.githubusercontent.com/RSS3-Network/Protocol-Go/refs/heads/main/openapi/Metadata.yaml"
5 | - x-go-type: metadata.Metadata
6 | x-go-type-import:
7 | path: github.com/rss3-network/protocol-go/schema/metadata
8 |
--------------------------------------------------------------------------------
/docs/cfg.yaml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/oapi-codegen/oapi-codegen/HEAD/configuration-schema.json
2 | package: docs
3 | output: ./generated.go
4 | generate:
5 | models: true
6 | echo-server: true
7 | embedded-spec: true
8 | output-options:
9 | user-templates:
10 | echo/echo-wrappers.tmpl: echo/echo-wrappers.tmpl
--------------------------------------------------------------------------------
/docs/parameters/query_platform_decentralized.yaml:
--------------------------------------------------------------------------------
1 | description: Retrieve activities from the specified platform(s).
2 | in: query
3 | name: platform
4 | required: false
5 | schema:
6 | items:
7 | $ref: "../schemas/DecentralizedPlatform.yaml"
8 | type: array
9 | x-go-type-skip-optional-pointer: true
10 | x-oapi-codegen-extra-tags:
11 | query: platform
--------------------------------------------------------------------------------
/docs/schemas/ConfigDetail.yaml:
--------------------------------------------------------------------------------
1 | properties:
2 | description:
3 | type: string
4 | is_required:
5 | type: boolean
6 | key:
7 | type: string
8 | title:
9 | type: string
10 | type:
11 | type: string
12 | value:
13 | type: string
14 | required:
15 | - is_required
16 | - type
17 | - value
18 | - description
19 | type: object
20 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/iqwiki/genqlient.yaml:
--------------------------------------------------------------------------------
1 | # Default genqlient config; for full documentation see:
2 | # https://github.com/Khan/genqlient/blob/main/docs/genqlient.yaml
3 | schema: schema.graphql
4 | operations:
5 | - ./operation/activities.graphql
6 | bindings:
7 | Any:
8 | type: any
9 | DateTime:
10 | type: time.Time
11 | generated: operation.go
--------------------------------------------------------------------------------
/.run/build.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.run/image.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/docs/schemas/Calldata.yaml:
--------------------------------------------------------------------------------
1 | description: Represents the call data associated with an activity.
2 | properties:
3 | function_hash:
4 | description: The hash of the function called.
5 | type: string
6 | parsed_function:
7 | description: The parsed function name.
8 | type: string
9 | raw:
10 | description: The raw calldata.
11 | type: string
12 | type: object
13 |
--------------------------------------------------------------------------------
/docs/schemas/Fee.yaml:
--------------------------------------------------------------------------------
1 | description: Represents fee information for an activity.
2 | properties:
3 | address:
4 | description: The address to which the fee is paid.
5 | type: string
6 | amount:
7 | description: The amount of the fee.
8 | type: string
9 | decimal:
10 | description: The decimal precision of the fee amount.
11 | type: integer
12 | type: object
13 |
--------------------------------------------------------------------------------
/docs/path/info.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetNodeInfo
3 | summary: Get Node Status
4 | description: Retrieve node status details.
5 | security: []
6 | tags:
7 | - Info
8 | responses:
9 | "200":
10 | $ref: "../responses/NodeInfoResponse.yaml"
11 | "400":
12 | $ref: "../responses/BadRequest.yaml"
13 | "500":
14 | $ref: "../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/migration/20231228162957_add_checkpoints_index_count_column.sql:
--------------------------------------------------------------------------------
1 | -- +goose Up
2 | -- +goose StatementBegin
3 | ALTER TABLE "checkpoints"
4 | ADD "index_count" bigint NOT NULL DEFAULT 0;
5 | -- +goose StatementEnd
6 |
7 | -- +goose Down
8 | -- +goose StatementBegin
9 | ALTER TABLE "checkpoints"
10 | DROP COLUMN "index_count";
11 | -- +goose StatementEnd
12 |
--------------------------------------------------------------------------------
/internal/engine/protocol/ethereum/filter.go:
--------------------------------------------------------------------------------
1 | package ethereum
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/internal/engine"
6 | )
7 |
8 | var _ engine.DataSourceFilter = (*Filter)(nil)
9 |
10 | type Filter struct {
11 | LogAddresses []common.Address `yaml:"log_addresses"`
12 | LogTopics []common.Hash `yaml:"log_topics"`
13 | }
14 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Summary
2 |
3 | ## Checklist
4 |
5 | - [ ] The commit message follows [Angular Contributing guidelines](https://github.com/angular/angular/blob/main/CONTRIBUTING.md#commit);
6 | - [ ] Tests for the changes have been added (for bug fixes / features);
7 |
8 | ## Does this PR introduce a breaking change?
9 |
10 | - [ ] Yes
11 | - [ ] No
12 |
13 | ## Other information
14 |
--------------------------------------------------------------------------------
/internal/engine/worker/rss/factory.go:
--------------------------------------------------------------------------------
1 | package worker
2 |
3 | import (
4 | "github.com/rss3-network/node/v2/config"
5 | "github.com/rss3-network/node/v2/internal/engine"
6 | )
7 |
8 | func New(_ *config.Module) (engine.Worker, error) {
9 | // Not implemented
10 | // If the rsshub worker exists, it will be started by default, and there will not be a separate worker instance
11 | return nil, nil
12 | }
13 |
--------------------------------------------------------------------------------
/internal/database/model/dataset_farcaster_profile.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | type Profile struct {
4 | Fid int64 `json:"fid"` // Farcaster ID
5 | Username string `json:"username"` // Farcaster username
6 | CustodyAddress string `json:"custody_address"` // Farcaster custody address
7 | EthAddresses []string `json:"eth_addresses"` // Farcaster account bound evm addresses
8 | }
9 |
--------------------------------------------------------------------------------
/docs/path/workers_status.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetWorkersStatus
3 | summary: Get Node Worker Status
4 | description: Retrieve node worker status details.
5 | security: []
6 | tags:
7 | - Info
8 | responses:
9 | "200":
10 | $ref: "../responses/WorkerInfoResponse.yaml"
11 | "400":
12 | $ref: "../responses/BadRequest.yaml"
13 | "500":
14 | $ref: "../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/internal/database/dialer/dialer.go:
--------------------------------------------------------------------------------
1 | package dialer
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/rss3-network/node/v2/config"
7 | "github.com/rss3-network/node/v2/internal/database"
8 | "github.com/rss3-network/node/v2/internal/database/dialer/postgres"
9 | )
10 |
11 | func Dial(ctx context.Context, config *config.Database) (database.Client, error) {
12 | return postgres.Dial(ctx, config.URI, true)
13 | }
14 |
--------------------------------------------------------------------------------
/schema/worker/status.go:
--------------------------------------------------------------------------------
1 | package worker
2 |
3 | //go:generate go run --mod=mod github.com/dmarkham/enumer@v1.5.9 --values --type=Status --linecomment --output status_string.go --json --yaml --sql
4 | type Status uint64
5 |
6 | const (
7 | StatusUnknown Status = iota // Unknown
8 | StatusIndexing // Indexing
9 | StatusReady // Ready
10 | StatusUnhealthy // Unhealthy
11 | )
12 |
--------------------------------------------------------------------------------
/docs/schemas/WorkerConfig.yaml:
--------------------------------------------------------------------------------
1 | properties:
2 | endpoint:
3 | $ref: "./ConfigDetail.yaml"
4 | id:
5 | $ref: "./ConfigDetail.yaml"
6 | ipfs_gateways:
7 | $ref: "./ConfigDetail.yaml"
8 | minimum_resource:
9 | $ref: "./MinimumResource.yaml"
10 | network:
11 | $ref: "./ConfigDetail.yaml"
12 | parameters:
13 | $ref: "./Parameters.yaml"
14 | worker:
15 | $ref: "./ConfigDetail.yaml"
16 | type: object
17 |
--------------------------------------------------------------------------------
/internal/database/model/dataset_bluesky_profile.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import "time"
4 |
5 | type BlueskyProfile struct {
6 | DID string `json:"did"`
7 | Handle string `json:"handle"`
8 | CreatedAt time.Time `json:"created_at"`
9 | UpdatedAt time.Time `json:"updated_at"`
10 | }
11 |
12 | type QueryBlueskyProfiles struct {
13 | Since *uint64
14 | Limit *int
15 | Cursor *string
16 | Handles []string
17 | }
18 |
--------------------------------------------------------------------------------
/docs/path/networks/config.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetNetworksConfig
3 | summary: Get worker config options
4 | description: Retrieve worker config options and descriptions.
5 | security: []
6 | tags:
7 | - Info
8 | responses:
9 | "200":
10 | $ref: "../../responses/NetworkConfigResponse.yaml"
11 | "400":
12 | $ref: "../../responses/BadRequest.yaml"
13 | "500":
14 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/docs/schemas/Reward.yaml:
--------------------------------------------------------------------------------
1 | description: The reward of node.
2 | properties:
3 | epoch:
4 | description: The epoch of reward.
5 | type: integer
6 | operator_rewards:
7 | description: The operator rewards of reward.
8 | type: string
9 | request_counts:
10 | description: The request counts of reward.
11 | type: string
12 | staking_rewards:
13 | description: The staking rewards of reward.
14 | type: string
15 | type: object
16 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/erc165/abi/ERC165.abi:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "constant": true,
4 | "inputs": [
5 | {
6 | "name": "interfaceID",
7 | "type": "bytes4"
8 | }
9 | ],
10 | "name": "supportsInterface",
11 | "outputs": [
12 | {
13 | "name": "",
14 | "type": "bool"
15 | }
16 | ],
17 | "payable": false,
18 | "stateMutability": "view",
19 | "type": "function"
20 | }
21 | ]
22 |
--------------------------------------------------------------------------------
/internal/stream/provider/provider.go:
--------------------------------------------------------------------------------
1 | package provider
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/rss3-network/node/v2/config"
7 | "github.com/rss3-network/node/v2/internal/stream"
8 | "github.com/rss3-network/node/v2/internal/stream/provider/kafka"
9 | )
10 |
11 | const kafkaTopic = "rss3.node.activities"
12 |
13 | func New(ctx context.Context, config *config.Stream) (stream.Client, error) {
14 | return kafka.New(ctx, config.URI, kafkaTopic)
15 | }
16 |
--------------------------------------------------------------------------------
/provider/atproto/model.go:
--------------------------------------------------------------------------------
1 | package atproto
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/bluesky-social/indigo/api/bsky"
7 | "github.com/bluesky-social/indigo/atproto/syntax"
8 | )
9 |
10 | type Message struct {
11 | URI string
12 | Did syntax.DID
13 | Handle string
14 | Collection string
15 | Rkey string
16 | CreatedAt time.Time
17 |
18 | Feed *bsky.FeedPost
19 | Profile *bsky.ActorProfile
20 | RefMessage *Message
21 | }
22 |
--------------------------------------------------------------------------------
/internal/engine/data_source.go:
--------------------------------------------------------------------------------
1 | package engine
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 |
7 | "github.com/rss3-network/protocol-go/schema/network"
8 | )
9 |
10 | // DataSource is the interface that wraps the basic methods of a data protocol.
11 | type DataSource interface {
12 | Network() network.Network
13 | State() json.RawMessage
14 | Start(ctx context.Context, tasksChan chan<- *Tasks, errorChan chan<- error)
15 | }
16 |
17 | type DataSourceFilter interface{}
18 |
--------------------------------------------------------------------------------
/internal/database/model/dataset_mastodon_handle.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import "time"
4 |
5 | type MastodonHandle struct {
6 | Handle string `json:"handle"`
7 | CreatedAt time.Time `json:"created_at"`
8 | UpdatedAt time.Time `json:"updated_at"`
9 | }
10 |
11 | type PaginatedMastodonHandles struct {
12 | Handles []string
13 | TotalCount int64
14 | NextCursor string
15 | }
16 |
17 | type QueryMastodonHandles struct {
18 | Since *uint64
19 | Limit *int
20 | Cursor *string
21 | }
22 |
--------------------------------------------------------------------------------
/internal/engine/checkpoint.go:
--------------------------------------------------------------------------------
1 | package engine
2 |
3 | import (
4 | "encoding/json"
5 | "time"
6 |
7 | "github.com/rss3-network/protocol-go/schema/network"
8 | )
9 |
10 | type Checkpoint struct {
11 | ID string `json:"id"`
12 | Network network.Network `json:"network"`
13 | Worker string `json:"worker"`
14 | State json.RawMessage `json:"state"`
15 | IndexCount int64 `json:"index_count"`
16 | UpdatedAt time.Time `json:"updated_at"`
17 | }
18 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/ens/action.go:
--------------------------------------------------------------------------------
1 | package ens
2 |
3 | import "fmt"
4 |
5 | var _ fmt.Stringer = (*UpdateAction)(nil)
6 |
7 | type UpdateAction string
8 |
9 | func (n UpdateAction) String() string {
10 | return string(n)
11 | }
12 |
13 | const (
14 | FusesSet UpdateAction = "Fuses"
15 | AddressChanged UpdateAction = "Address"
16 | ContentHashChanged UpdateAction = "ContentHash"
17 | NameChanged UpdateAction = "Name"
18 | PubkeyChanged UpdateAction = "Pubkey"
19 | )
20 |
--------------------------------------------------------------------------------
/docs/schemas/WorkerInfo.yaml:
--------------------------------------------------------------------------------
1 | description: The status of the worker.
2 | type: object
3 | allOf:
4 | - properties:
5 | worker_id:
6 | description: The worker ID.
7 | type: string
8 | worker:
9 | $ref: "./Worker.yaml"
10 | network:
11 | $ref: "./ProtocolNetwork.yaml"
12 | tags:
13 | $ref: "./Tags.yaml"
14 | platform:
15 | $ref: "./Platform.yaml"
16 | status:
17 | $ref: "./WorkerStatus.yaml"
18 | - $ref: "./WorkerProgress.yaml"
--------------------------------------------------------------------------------
/.run/run.run.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/docs/responses/FederatedActivitiesResponse.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | description: The response structure for a list of activities.
5 | properties:
6 | data:
7 | description: The list of activities.
8 | items:
9 | $ref: "../schemas/FederatedActivity.yaml"
10 | type: array
11 | meta:
12 | $ref: "../schemas/MetaCursor.yaml"
13 | type: object
14 | required:
15 | - data
16 | description: The request was successful.
17 |
--------------------------------------------------------------------------------
/docs/path/ai.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetAgentData
3 | summary: Get Agent Data by Path
4 | description: Retrieve details from the specified path.
5 | tags:
6 | - AI
7 | security:
8 | - bearerAuth: []
9 | parameters:
10 | - $ref: "../parameters/path_ai.yaml"
11 | responses:
12 | "200":
13 | $ref: "../responses/AIResponse.yaml"
14 | "400":
15 | $ref: "../responses/BadRequest.yaml"
16 | "404":
17 | $ref: "../responses/NotFound.yaml"
18 | "500":
19 | $ref: "../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/docs/path/version.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | summary: Get Node Version
3 | description: Retrieve node status details.
4 | tags:
5 | - Info
6 | responses:
7 | "200":
8 | content:
9 | application/json:
10 | schema:
11 | type: object
12 | properties:
13 | data:
14 | $ref: "../schemas/Version.yaml"
15 |
16 | description: Node status details.
17 | "400":
18 | $ref: "../responses/BadRequest.yaml"
19 | "500":
20 | $ref: "../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/docs/responses/DecentralizedActivitiesResponse.yaml:
--------------------------------------------------------------------------------
1 | content:
2 | application/json:
3 | schema:
4 | description: The response structure for a list of activities.
5 | properties:
6 | data:
7 | description: The list of activities.
8 | items:
9 | $ref: "../schemas/DecentralizedActivity.yaml"
10 | type: array
11 | meta:
12 | $ref: "../schemas/MetaCursor.yaml"
13 | type: object
14 | required:
15 | - data
16 | description: The request was successful.
17 |
--------------------------------------------------------------------------------
/docs/schemas/NetworkConfig.yaml:
--------------------------------------------------------------------------------
1 | description: The worker config details by source.
2 | properties:
3 | decentralized:
4 | items:
5 | $ref: "./NetworkConfigDetail.yaml"
6 | type: array
7 | federated:
8 | items:
9 | $ref: "./NetworkConfigDetail.yaml"
10 | type: array
11 | rss:
12 | properties:
13 | endpoint_configs:
14 | $ref: "./EndpointConfig.yaml"
15 | id:
16 | type: string
17 | worker_configs:
18 | $ref: "./WorkerConfig.yaml"
19 | type: object
20 | type: object
21 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/migration/20241218042140_add_activities_indexes.sql:
--------------------------------------------------------------------------------
1 | -- +goose Up
2 | -- +goose StatementBegin
3 | CREATE INDEX IF NOT EXISTS activities_id_platform_index ON public.activities (platform);
4 | CREATE INDEX IF NOT EXISTS activities_id_tag_and_type_index ON public.activities (tag, type);
5 | -- +goose StatementEnd
6 |
7 | -- +goose Down
8 | -- +goose StatementBegin
9 | DROP INDEX IF EXISTS public.activities_id_platform_index;
10 | DROP INDEX IF EXISTS public.activities_id_tag_and_type_index;
11 | -- +goose StatementEnd
12 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v4.5.0
4 | hooks:
5 | - id: end-of-file-fixer
6 | - id: trailing-whitespace
7 | - repo: https://github.com/golangci/golangci-lint
8 | rev: v1.55.2
9 | hooks:
10 | - id: golangci-lint
11 | - repo: https://github.com/commitizen-tools/commitizen
12 | rev: v2.42.1
13 | hooks:
14 | - id: commitizen
15 | - repo: https://github.com/gitleaks/gitleaks
16 | rev: v8.16.1
17 | hooks:
18 | - id: gitleaks
19 |
--------------------------------------------------------------------------------
/docs/path/rss.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetRSS
3 | summary: Get RSS Activity by Path
4 | description: Retrieve details from the specified RSS path.
5 | tags:
6 | - RSS
7 | security:
8 | - bearerAuth: []
9 | parameters:
10 | - $ref: "../parameters/path_rss.yaml"
11 | responses:
12 | "200":
13 | $ref: "../responses/RSSActivitiesResponse.yaml"
14 | "400":
15 | $ref: "../responses/BadRequest.yaml"
16 | "404":
17 | $ref: "../responses/NotFound.yaml"
18 | "500":
19 | $ref: "../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Visual Studio Code
2 | .vscode/*
3 |
4 |
5 | ### JetBrains
6 | .idea/*
7 |
8 | !.idea/icon.svg
9 |
10 | ### Linux
11 |
12 | ### Go template
13 | *.exe
14 | *.exe~
15 | *.dll
16 | *.so
17 | *.dylib
18 |
19 | # Test binary, built with `go test -c`
20 | *.test
21 |
22 | # Output of the go coverage tool, specifically when used with LiteIDE
23 | *.out
24 |
25 | # Go workspace file
26 | go.work
27 |
28 | ### macOS
29 | .DS_Store
30 |
31 | ### Project
32 | /build/*
33 |
34 | ### Configuration
35 | deploy/config.yaml
36 |
37 | first_start_time.txt
38 |
--------------------------------------------------------------------------------
/internal/engine/protocol/farcaster/state.go:
--------------------------------------------------------------------------------
1 | package farcaster
2 |
3 | type State struct {
4 | EventID uint64 `json:"event_id"` // Event ID that has been processed
5 | CastsFid uint64 `json:"casts_fid"` // Casts ID that has been processed in backfill casts
6 | CastsBackfill bool `json:"casts_backfill"` // Casts backfill flag
7 | ReactionsFid uint64 `json:"reactions_fid"` // Reactions ID that has been processed in backfill reactions
8 | ReactionsBackfill bool `json:"reactions_backfill"` // Reactions backfill flag
9 | }
10 |
--------------------------------------------------------------------------------
/provider/arweave/contract/momoka/contract.go:
--------------------------------------------------------------------------------
1 | package momoka
2 |
3 | var AddressesLens = []string{
4 | "llq4QhHA7fQWBKd6V8vzAhK-qy_JulpzlYUEgxAgJ4E",
5 | "6Li0nuSO_w6DLZN4OC7XclIL6uLaeSSkjVX_B2Qn6r8",
6 | }
7 |
8 | var AddressesBundlr = []string{
9 | "OXcT1sVRSA5eGwt2k6Yuz8-3e3g9WJi5uSE99CWqsBs",
10 | "ZE0N-8P9gXkhtK-07PQu9d8me5tGDxa_i4Mee5RzVYg",
11 | }
12 |
13 | // AddressesSubmitter is a list of addresses that Lens uses to submit transactions to Irys.
14 | var AddressesSubmitter = []string{
15 | "0xBe29464B9784a0d8956f29630d8bc4D7B5737435", // Lens's default submitter.
16 | }
17 |
--------------------------------------------------------------------------------
/docs/path/home.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetNodeOperatorInfo
3 | summary: Get Node Operator Info
4 | description: Retrieve node status details.
5 | security: []
6 | tags:
7 | - Info
8 | responses:
9 | "200":
10 | content:
11 | # return raw string
12 | text/plain:
13 | schema:
14 | type: string
15 | pattern: "This is an RSS3 Node operated by 0x[0-9a-fA-F]{40}."
16 | description: Node status details.
17 | "400":
18 | $ref: "../responses/BadRequest.yaml"
19 | "500":
20 | $ref: "../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/docs/schemas/Parameters.yaml:
--------------------------------------------------------------------------------
1 | properties:
2 | api_key:
3 | $ref: "./ConfigDetail.yaml"
4 | authentication:
5 | $ref: "./Authentication.yaml"
6 | block_batch_size:
7 | $ref: "./ConfigDetail.yaml"
8 | block_receipts_batch_size:
9 | $ref: "./ConfigDetail.yaml"
10 | block_start:
11 | $ref: "./ConfigDetail.yaml"
12 | block_target:
13 | $ref: "./ConfigDetail.yaml"
14 | concurrent_block_requests:
15 | $ref: "./ConfigDetail.yaml"
16 | relay_url_list:
17 | $ref: "./ConfigDetail.yaml"
18 | receipts_batch_size:
19 | $ref: "./ConfigDetail.yaml"
20 | type: object
21 |
--------------------------------------------------------------------------------
/provider/arweave/bundle/irys/constant.go:
--------------------------------------------------------------------------------
1 | package irys
2 |
3 | //go:generate go run --mod=mod github.com/Khan/genqlient@v0.7.0
4 |
5 | const (
6 | GatewayMainnet = "https://gateway.irys.xyz"
7 |
8 | EndpointMainnet = "https://arweave.mainnet.irys.xyz/graphql"
9 | EndpointDevnet = "https://arweave.devnet.irys.xyz/graphql"
10 |
11 | // DefaultLimit is the limit on the number of items when obtaining transactions, with a maximum value of 1000.
12 | DefaultLimit = 1000
13 | )
14 |
15 | // DefaultGateways is the list of default gateways.
16 | var DefaultGateways = []string{
17 | GatewayMainnet,
18 | }
19 |
--------------------------------------------------------------------------------
/.github/workflows/release.yaml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | permissions:
4 | contents: write
5 |
6 | on:
7 | push:
8 | tags:
9 | - 'v*'
10 |
11 | jobs:
12 | release:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: actions/checkout@v4
16 | with:
17 | fetch-depth: 0
18 |
19 | - name: Set node
20 | uses: actions/setup-node@v4
21 | with:
22 | registry-url: https://registry.npmjs.org/
23 | node-version: lts/*
24 |
25 | - run: npx changelogithub
26 | env:
27 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
28 |
--------------------------------------------------------------------------------
/docs/schemas/Records.yaml:
--------------------------------------------------------------------------------
1 | description: The records of node activities.
2 | properties:
3 | last_heartbeat:
4 | description: The last heartbeat of node.
5 | type: integer
6 | recent_requests:
7 | description: The recent requests of node.
8 | items:
9 | description: The request to the node api.
10 | type: string
11 | type: array
12 | recent_rewards:
13 | description: The recent rewards of node.
14 | items:
15 | $ref: "./Reward.yaml"
16 | type: array
17 | slashed_tokens:
18 | description: The slashed tokens of node.
19 | type: string
20 | type: object
21 |
--------------------------------------------------------------------------------
/internal/node/component/component.go:
--------------------------------------------------------------------------------
1 | package component
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/go-playground/validator/v10"
7 | "github.com/labstack/echo/v4"
8 | )
9 |
10 | type Component interface {
11 | Name() string
12 | InitMeter() error
13 | CollectMetric(ctx context.Context, path, value string)
14 | CollectTrace(ctx context.Context, path, value string)
15 | }
16 |
17 | var _ echo.Validator = (*Validator)(nil)
18 |
19 | type Validator struct {
20 | Validator *validator.Validate
21 | }
22 |
23 | func (v *Validator) Validate(i interface{}) error {
24 | return v.Validator.Struct(i)
25 | }
26 |
--------------------------------------------------------------------------------
/docs/schemas/DecentralizedAction.yaml:
--------------------------------------------------------------------------------
1 | description: Represents an individual action within an activity.
2 | properties:
3 | from:
4 | $ref: './DecentralizedAccount.yaml'
5 | metadata:
6 | $ref: "./ProtocolMetadata.yaml"
7 | platform:
8 | $ref: "./DecentralizedPlatform.yaml"
9 | related_urls:
10 | description: A list of URLs related to the action.
11 | items:
12 | type: string
13 | format: uri
14 | type: array
15 | tag:
16 | $ref: "./ProtocolTag.yaml"
17 | to:
18 | $ref: "./DecentralizedAccount.yaml"
19 | type:
20 | $ref: "./ProtocolType.yaml"
21 | type: object
22 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/migration/20240115040941_add_ens_namehash.sql:
--------------------------------------------------------------------------------
1 | -- +goose Up
2 | -- +goose StatementBegin
3 | CREATE TABLE IF NOT EXISTS "dataset_ens_namehashes"
4 | (
5 | "hash" bytea NOT NULL,
6 | "name" text NOT NULL,
7 |
8 | CONSTRAINT "pk_dataset_ens_namehashs" PRIMARY KEY ("hash")
9 | );
10 |
11 | CREATE INDEX IF NOT EXISTS idx_ensnamehash_name ON dataset_ens_namehashes (name);
12 | -- +goose StatementEnd
13 |
14 | -- +goose Down
15 | -- +goose StatementBegin
16 | DROP INDEX IF EXISTS idx_ensnamehash_name;
17 | DROP TABLE IF EXISTS "dataset_ens_namehashes";
18 | -- +goose StatementEnd
19 |
--------------------------------------------------------------------------------
/internal/engine/protocol/arweave/filter.go:
--------------------------------------------------------------------------------
1 | package arweave
2 |
3 | import (
4 | "github.com/rss3-network/node/v2/internal/engine"
5 | )
6 |
7 | var _ engine.DataSourceFilter = (*Filter)(nil)
8 |
9 | type Filter struct {
10 | OwnerAddresses []string `yaml:"owner_addresses"`
11 |
12 | // BundlrOnly is a tag, indicating that only transactions of Bundlr nodes are pulled.
13 | BundlrOnly bool `yaml:"bundlr_only"`
14 |
15 | // BundlrAddresses is a list of addresses that are considered Bundlr nodes.
16 | // If BundlrOnly is true, the field needs to be ignored.
17 | BundlrAddresses []string `yaml:"bundlr_addresses"`
18 | }
19 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/migration/20240922233919_add_mastodon_handles.sql:
--------------------------------------------------------------------------------
1 | -- +goose Up
2 | -- +goose StatementBegin
3 | CREATE TABLE IF NOT EXISTS dataset_mastodon_update_handles (
4 | "handle" text PRIMARY KEY,
5 | "created_at" timestamptz NOT NULL DEFAULT now(),
6 | "updated_at" timestamptz NOT NULL DEFAULT now()
7 | );
8 |
9 | CREATE INDEX idx_mastodon_update_handles_time_at ON dataset_mastodon_update_handles(updated_at DESC,created_at DESC);
10 | -- +goose StatementEnd
11 |
12 | -- +goose Down
13 | -- +goose StatementBegin
14 | DROP TABLE IF EXISTS dataset_mastodon_update_handles;
15 | -- +goose StatementEnd
16 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yaml:
--------------------------------------------------------------------------------
1 | name: Lint
2 | on:
3 | push:
4 | branches:
5 | - main
6 | - prod
7 | paths-ignore:
8 | - "deploy/**"
9 | pull_request:
10 | paths-ignore:
11 | - "deploy/**"
12 |
13 | jobs:
14 | lint:
15 | name: Lint
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Setup Go
19 | uses: actions/setup-go@v5
20 | with:
21 | go-version: "1.22.7"
22 | - name: Checkout
23 | uses: actions/checkout@v4
24 | - name: GolangCI Lint
25 | uses: golangci/golangci-lint-action@v6
26 | with:
27 | version: v1.55.2
28 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/iqwiki/client_test.go:
--------------------------------------------------------------------------------
1 | package iqwiki_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 |
7 | "github.com/rss3-network/node/v2/provider/ethereum/contract/iqwiki"
8 | "github.com/stretchr/testify/require"
9 | )
10 |
11 | func Test_Client(t *testing.T) {
12 | t.Parallel()
13 |
14 | client, err := iqwiki.NewClient(iqwiki.Endpoint)
15 |
16 | require.NoError(t, err, "build IQ.Wiki client")
17 |
18 | wikiResponse, err := iqwiki.ActivityByWikiIdAndBlock(context.Background(), client, 46938791, "buffer")
19 |
20 | require.NoError(t, err)
21 |
22 | t.Log(wikiResponse.ActivityByWikiIdAndBlock.Ipfs)
23 | }
24 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/matters/contract.go:
--------------------------------------------------------------------------------
1 | package matters
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | // Wiki
9 | // https://polygonscan.com/address/0x5edebbdae7B5C79a69AaCF7873796bb1Ec664DB8
10 | //go:generate go run -mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi abi/curation.abi --pkg matters --type Matters --out contract_curation.go
11 |
12 | var (
13 | AddressCuration = common.HexToAddress("0x5edebbdae7B5C79a69AaCF7873796bb1Ec664DB8")
14 |
15 | EventCuration = contract.EventHash("Curation(address,address,address,string,uint256)")
16 | )
17 |
--------------------------------------------------------------------------------
/internal/node/component/rss/option.go:
--------------------------------------------------------------------------------
1 | package rss
2 |
3 | import (
4 | "github.com/rss3-network/node/v2/config"
5 | )
6 |
7 | type Option struct {
8 | Authentication OptionAuthentication `json:"authentication" mapstructure:"authentication"`
9 | }
10 |
11 | type OptionAuthentication struct {
12 | AccessKey string `json:"access_key" mapstructure:"access_key"`
13 | }
14 |
15 | func NewOption(options *config.Parameters) (*Option, error) {
16 | var instance Option
17 |
18 | if options == nil {
19 | return &instance, nil
20 | }
21 |
22 | if err := options.Decode(&instance); err != nil {
23 | return nil, err
24 | }
25 |
26 | return &instance, nil
27 | }
28 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: gomod
4 | directory: /
5 | schedule:
6 | interval: weekly
7 | target-branch: main
8 | open-pull-requests-limit: 0
9 | ignore:
10 | - dependency-name: "github.com/ethereum/go-ethereum"
11 | - dependency-name: "github.com/rss3-network/protocol-go"
12 | - package-ecosystem: github-actions
13 | directory: /
14 | schedule:
15 | interval: weekly
16 | target-branch: main
17 | open-pull-requests-limit: 0
18 | - package-ecosystem: docker
19 | directory: /
20 | schedule:
21 | interval: weekly
22 | target-branch: main
23 | open-pull-requests-limit: 0
24 |
--------------------------------------------------------------------------------
/docs/schemas/RSSAction.yaml:
--------------------------------------------------------------------------------
1 | description: Represents an individual action within an activity.
2 | properties:
3 | tag:
4 | allOf:
5 | - $ref: "./ProtocolTag.yaml"
6 | - example: rss
7 | type:
8 | $ref: "https://raw.githubusercontent.com/RSS3-Network/Protocol-Go/refs/heads/main/openapi/type/RSSType.yaml"
9 | platform:
10 | $ref: "./RSSPlatform.yaml"
11 | from:
12 | $ref: "./RSSAccount.yaml"
13 | to:
14 | $ref: "./RSSAccount.yaml"
15 | metadata:
16 | $ref: "./RSSMetadata.yaml"
17 | related_urls:
18 | description: A list of URLs related to the action.
19 | items:
20 | type: string
21 | format: uri
22 | type: array
23 | type: object
24 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/iqwiki/contract.go:
--------------------------------------------------------------------------------
1 | package iqwiki
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | // Wiki
9 | // https://polygonscan.com/address/0xb8aa8cabfba7ee3ccb218a9969aef86dff3b9d2d
10 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/Wiki.abi --pkg iqwiki --type IqWiki --out contract_wiki.go
11 |
12 | var (
13 | AddressWiki = common.HexToAddress("0xb8aA8CabfBa7eE3ccb218a9969AEF86DFf3b9d2D")
14 | AddressSig = common.HexToAddress("0x191a41c307373211d08613b68df4031977589069")
15 |
16 | EventPosted = contract.EventHash("Posted(address,string)")
17 | )
18 |
--------------------------------------------------------------------------------
/docs/path/federated/tx.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetFederatedTxID
3 | summary: Get Activity by ID
4 | description: Retrieve details for the specified activity ID.
5 | tags:
6 | - Federated
7 | security:
8 | - bearerAuth: []
9 | parameters:
10 | - $ref: "../../parameters/path_activity_id.yaml"
11 | - $ref: "../../parameters/query_action_limit.yaml"
12 | - $ref: "../../parameters/query_action_page.yaml"
13 | responses:
14 | "200":
15 | $ref: "../../responses/FederatedActivityResponse.yaml"
16 | "400":
17 | $ref: "../../responses/BadRequest.yaml"
18 | "404":
19 | $ref: "../../responses/NotFound.yaml"
20 | "500":
21 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/internal/constant/version.go:
--------------------------------------------------------------------------------
1 | package constant
2 |
3 | // FIXME: should this be mvoed to config/parameter.go?
4 |
5 | import "fmt"
6 |
7 | const Name = "node"
8 |
9 | // The Go compiler will set these variables via ldflags.
10 | var (
11 | Version string
12 | Commit string
13 | )
14 |
15 | func BuildVersion() string {
16 | if Version == "" {
17 | Version = "0.0.0"
18 | }
19 |
20 | if Commit == "" {
21 | Commit = "000000"
22 | }
23 |
24 | return fmt.Sprintf("%s (%s)", Version, Commit)
25 | }
26 |
27 | func BuildVersionDetail() (string, string) {
28 | if Version == "" {
29 | Version = "0.0.0"
30 | }
31 |
32 | if Commit == "" {
33 | Commit = "000000"
34 | }
35 |
36 | return Version, Commit
37 | }
38 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/iqwiki/client.go:
--------------------------------------------------------------------------------
1 | package iqwiki
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/Khan/genqlient/graphql"
7 | )
8 |
9 | //go:generate go run --mod=mod github.com/Khan/genqlient
10 |
11 | const Endpoint = "https://graph.everipedia.org/graphql"
12 |
13 | var _ graphql.Doer = (*client)(nil)
14 |
15 | type client struct {
16 | httpClient *http.Client
17 | }
18 |
19 | func (c *client) Do(request *http.Request) (*http.Response, error) {
20 | return c.httpClient.Do(request)
21 | }
22 |
23 | func NewClient(endpoint string) (graphql.Client, error) {
24 | instance := client{
25 | httpClient: http.DefaultClient,
26 | }
27 |
28 | return graphql.NewClient(endpoint, &instance), nil
29 | }
30 |
--------------------------------------------------------------------------------
/docs/path/decentralized/tx.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetDecentralizedTxID
3 | summary: Get Activity by ID
4 | description: Retrieve details for the specified activity ID.
5 | tags: [Decentralized]
6 | security:
7 | - bearerAuth: []
8 | parameters:
9 | - $ref: "../../parameters/path_activity_id.yaml"
10 | - $ref: "../../parameters/query_action_limit.yaml"
11 | - $ref: "../../parameters/query_action_page.yaml"
12 | responses:
13 | '200':
14 | $ref: "../../responses/DecentralizedActivityResponse.yaml"
15 | '400':
16 | $ref: "../../responses/BadRequest.yaml"
17 | '404':
18 | $ref: "../../responses/NotFound.yaml"
19 | '500':
20 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/docs/schemas/FederatedAction.yaml:
--------------------------------------------------------------------------------
1 | description: Represents an individual action within an activity.
2 | properties:
3 | tag:
4 | allOf:
5 | - $ref: "./ProtocolTag.yaml"
6 | - example: social
7 | type:
8 | $ref: "https://raw.githubusercontent.com/RSS3-Network/Protocol-Go/refs/heads/main/openapi/type/Social.yaml"
9 | platform:
10 | $ref: "./FederatedPlatform.yaml"
11 | from:
12 | $ref: "./FederatedAccount.yaml"
13 | to:
14 | $ref: "./FederatedAccount.yaml"
15 | metadata:
16 | $ref: "./FederatedMetadata.yaml"
17 | related_urls:
18 | description: A list of URLs related to the action.
19 | items:
20 | type: string
21 | format: uri
22 | type: array
23 | type: object
24 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/zerion/contract.go:
--------------------------------------------------------------------------------
1 | package zerion
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./Router.abi --pkg zerion --type Router --out router.go
9 | var (
10 | AddressRouter = common.HexToAddress("0xd7F1Dd5D49206349CaE8b585fcB0Ce3D96f1696F")
11 | AddressNativeToken = common.HexToAddress("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE")
12 |
13 | EventHashExecuted = contract.EventHash("Executed(address,uint256,uint256,address,uint256,uint256,uint256,uint256,(uint8,(uint256,address),(uint256,address),address,address,bytes),address)")
14 | )
15 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/migration/20241210031220_add_bluesky_profiles.sql:
--------------------------------------------------------------------------------
1 | -- +goose Up
2 | -- +goose StatementBegin
3 | CREATE TABLE IF NOT EXISTS dataset_bluesky_profiles
4 | (
5 | "did" text PRIMARY KEY,
6 | "handle" text,
7 | "created_at" timestamptz NOT NULL DEFAULT now(),
8 | "updated_at" timestamptz NOT NULL DEFAULT now()
9 | );
10 |
11 | CREATE INDEX idx_dataset_bluesky_profiles_cursor ON dataset_bluesky_profiles (updated_at DESC, created_at DESC);
12 |
13 | CREATE INDEX idx_dataset_bluesky_profiles_handle ON dataset_bluesky_profiles (handle);
14 | -- +goose StatementEnd
15 |
16 | -- +goose Down
17 | -- +goose StatementBegin
18 | DROP TABLE IF EXISTS dataset_bluesky_profiles;
19 | -- +goose StatementEnd
20 |
--------------------------------------------------------------------------------
/docs/schemas/FederatedMetadata.yaml:
--------------------------------------------------------------------------------
1 | description: Additional metadata related to the action.
2 | type: object
3 | allOf:
4 | - $ref: "./ProtocolMetadata.yaml"
5 | example:
6 | handle: "@seachdamh@101010.pl"
7 | body: "Some text"
8 | publication_id: 113550154261051135
9 | tags: ["@LukaszHorodecki@pol.social"]
10 | author_url: https://101010.pl/users/seachdamh
11 | timestamp: 1732637851
12 | target:
13 | handle: "@LukaszHorodecki@pol.social"
14 | body: Some text
15 | publication_id: 113549630375809974
16 | tags:
17 | - "#pc"
18 | - "#obudowa"
19 | author_url: https://pol.social/users/LukaszHorodecki
20 | timestamp: 1732629858
21 | target_url: https://pol.social/users/LukaszHorodecki/statuses/113549630375809974
--------------------------------------------------------------------------------
/provider/ethereum/contract/erc20/contract.go:
--------------------------------------------------------------------------------
1 | package erc20
2 |
3 | import "github.com/rss3-network/node/v2/provider/ethereum/contract"
4 |
5 | // https://eips.ethereum.org/EIPS/eip-20
6 | //go:generate go run -mod=mod github.com/ethereum/go-ethereum/cmd/abigen@v1.13.5 --abi ./abi/ERC20.abi --pkg erc20 --type ERC20 --out contract_erc20.go
7 |
8 | var (
9 | MethodIDTransfer = contract.MethodID("transfer(address,uint256)")
10 | MethodIDTransferFrom = contract.MethodID("transferFrom(address,address,uint256)")
11 | MethodIDApprove = contract.MethodID("approve(address,uint256)")
12 |
13 | EventHashTransfer = contract.EventHash("Transfer(address,address,uint256)")
14 | EventHashApproval = contract.EventHash("Approval(address,address,uint256)")
15 | )
16 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/table/dataset_ens_namehash.go:
--------------------------------------------------------------------------------
1 | package table
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/internal/database/model"
6 | )
7 |
8 | type DatasetENSNamehash struct {
9 | Hash common.Hash `gorm:"column:hash;primary_key"`
10 | Name string `gorm:"column:name;index:idx_ensnamehash_name"`
11 | }
12 |
13 | func (d *DatasetENSNamehash) Import(ensNamehash *model.ENSNamehash) (err error) {
14 | d.Hash = ensNamehash.Hash
15 | d.Name = ensNamehash.Name
16 |
17 | return nil
18 | }
19 |
20 | func (d *DatasetENSNamehash) Export() (*model.ENSNamehash, error) {
21 | profile := model.ENSNamehash{
22 | Hash: d.Hash,
23 | Name: d.Name,
24 | }
25 |
26 | return &profile, nil
27 | }
28 |
--------------------------------------------------------------------------------
/provider/arweave/bundle/irys/operation_test.go:
--------------------------------------------------------------------------------
1 | package irys_test
2 |
3 | import (
4 | "context"
5 | "net/http"
6 | "testing"
7 |
8 | "github.com/Khan/genqlient/graphql"
9 | "github.com/rss3-network/node/v2/provider/arweave/bundle/irys"
10 | "github.com/rss3-network/node/v2/provider/arweave/contract/momoka"
11 | "github.com/stretchr/testify/require"
12 | )
13 |
14 | func TestQueryTransactions(t *testing.T) {
15 | t.Parallel()
16 |
17 | graphqlClient := graphql.NewClient(irys.EndpointMainnet, http.DefaultClient)
18 |
19 | transactions, err := irys.Transactions(context.Background(), graphqlClient, momoka.AddressesSubmitter, "", irys.DefaultLimit)
20 | require.NoError(t, err)
21 |
22 | require.Len(t, transactions.Transactions.Edges, irys.DefaultLimit)
23 | }
24 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/cow/contract.go:
--------------------------------------------------------------------------------
1 | package cow
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | // GPv2Settlement
9 | // https://etherscan.io/address/0x9008D19f58AAbD9eD0D60971565AA8510560ab41
10 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/GPv2Settlement.abi --pkg cow --type Settlement --out contract_settlement.go
11 |
12 | var (
13 | AddressSettlement = common.HexToAddress("0x9008D19f58AAbD9eD0D60971565AA8510560ab41")
14 | AddressETH = common.HexToAddress("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE")
15 |
16 | EventHashSettlementTrade = contract.EventHash("Trade(address,address,address,uint256,uint256,uint256,bytes)")
17 | )
18 |
--------------------------------------------------------------------------------
/provider/arweave/utils.go:
--------------------------------------------------------------------------------
1 | package arweave
2 |
3 | import (
4 | "crypto/sha256"
5 | "encoding/base64"
6 | )
7 |
8 | // PublicKeyToAddress returns the arweave address of the owner.
9 | func PublicKeyToAddress(publicKey string) (string, error) {
10 | by, err := Base64Decode(publicKey)
11 | if err != nil {
12 | return "", err
13 | }
14 |
15 | addr := sha256.Sum256(by)
16 |
17 | return Base64Encode(addr[:]), nil
18 | }
19 |
20 | // Base64Encode returns the base64 encoding of data.
21 | func Base64Encode(data []byte) string {
22 | return base64.RawURLEncoding.EncodeToString(data)
23 | }
24 |
25 | // Base64Decode returns the bytes represented by the base64 string.
26 | func Base64Decode(data string) ([]byte, error) {
27 | return base64.RawURLEncoding.DecodeString(data)
28 | }
29 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/iqwiki/operation/activities.graphql:
--------------------------------------------------------------------------------
1 | query ActivityByWikiIdAndBlock($block:Int!,$wikiId:String) {
2 | activityByWikiIdAndBlock(block: $block, wikiId: $wikiId) {
3 | id
4 | wikiId
5 | block
6 | type
7 | datetime
8 | ipfs
9 | user {
10 | id
11 | profile {
12 | username
13 | bio
14 | }
15 | }
16 | content {
17 | id
18 | title
19 | content
20 | summary
21 | categories {
22 | title
23 | }
24 | images {
25 | id
26 | }
27 | tags {
28 | id
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/docs/schemas/DecentralizedWorker.yaml:
--------------------------------------------------------------------------------
1 | type: string
2 | enum:
3 | - aave
4 | - aavegotchi
5 | - arbitrum
6 | - base
7 | - benddao
8 | - core
9 | - cow
10 | - crossbell
11 | - curve
12 | - ens
13 | - highlight
14 | - iqwiki
15 | - kiwistand
16 | - lens
17 | - lido
18 | - linea
19 | - linear
20 | - looksrare
21 | - matters
22 | - mirror
23 | - momoka
24 | - nearsocial
25 | - nouns
26 | - 1inch
27 | - opensea
28 | - optimism
29 | - paragraph
30 | - paraswap
31 | - polymarket
32 | - rainbow
33 | - rss3
34 | - savm
35 | - stargate
36 | - uniswap
37 | - vsl
38 | - zerion
39 | x-go-type: decentralized.Worker
40 | x-go-type-skip-optional-pointer: true
41 | x-go-type-import:
42 | path: github.com/rss3-network/node/v2/schema/worker/decentralized
43 |
--------------------------------------------------------------------------------
/docs/path/federated/accounts.yaml:
--------------------------------------------------------------------------------
1 | post:
2 | operationId: PostFederatedAccounts
3 | summary: Batch Get Accounts Activities
4 | description: Retrieve a batch of activities associated with multiple specified accounts in the federated system. You can use various query parameters to filter and paginate the results, including limits on the number of activities and actions, timestamps, success status, direction, and more.
5 | tags:
6 | - Federated
7 | security:
8 | - bearerAuth: []
9 | requestBody:
10 | $ref: "../../requestBody/BatchGetFederatedAccountsActivities.yaml"
11 | responses:
12 | "200":
13 | $ref: "../../responses/FederatedActivitiesResponse.yaml"
14 | "400":
15 | $ref: "../../responses/BadRequest.yaml"
16 | "500":
17 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/docs/schemas/DecentralizedPlatform.yaml:
--------------------------------------------------------------------------------
1 | type: string
2 | enum:
3 | - Unknown
4 | - 1inch
5 | - AAVE
6 | - Aavegotchi
7 | - Arbitrum
8 | - Base
9 | - BendDAO
10 | - Cow
11 | - Crossbell
12 | - Curve
13 | - ENS
14 | - Farcaster
15 | - Highlight
16 | - IQWiki
17 | - KiwiStand
18 | - Lens
19 | - Lido
20 | - Linea
21 | - LiNEAR
22 | - LooksRare
23 | - Matters
24 | - Mirror
25 | - NearSocial
26 | - Nouns
27 | - OpenSea
28 | - Optimism
29 | - Paragraph
30 | - Paraswap
31 | - Polymarket
32 | - RSS3
33 | - Rainbow
34 | - SAVM
35 | - Stargate
36 | - Uniswap
37 | - VSL
38 | - Zerion
39 | x-go-type: decentralized.Platform
40 | x-go-type-skip-optional-pointer: true
41 | x-go-type-import:
42 | path: github.com/rss3-network/node/v2/schema/worker/decentralized
43 |
--------------------------------------------------------------------------------
/docs/path/decentralized/accounts.yaml:
--------------------------------------------------------------------------------
1 | post:
2 | operationId: PostDecentralizedAccounts
3 | summary: Batch Get Accounts Activities
4 | description: Retrieve a batch of activities associated with multiple specified accounts in the decentralized system. You can use various query parameters to filter and paginate the results, including limits on the number of activities and actions, timestamps, success status, direction, and more.
5 | tags:
6 | - Decentralized
7 | security:
8 | - bearerAuth: []
9 | requestBody:
10 | $ref: "../../requestBody/BatchGetDecentralizedAccountsActivities.yaml"
11 | responses:
12 | '200':
13 | $ref: "../../responses/DecentralizedActivitiesResponse.yaml"
14 | '400':
15 | $ref: "../../responses/BadRequest.yaml"
16 | '500':
17 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/docs/tool.go:
--------------------------------------------------------------------------------
1 | package docs
2 |
3 | //go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen --config=cfg.yaml api.yaml
4 |
5 | import (
6 | "fmt"
7 | "reflect"
8 |
9 | "github.com/labstack/echo/v4"
10 | )
11 |
12 | func BindPath(ctx echo.Context, paramName string, dest any) error {
13 | // Everything comes in by pointer, dereference it
14 | v := reflect.Indirect(reflect.ValueOf(dest))
15 |
16 | // This is the basic type of the destination object.
17 | t := v.Type()
18 |
19 | if t.Kind() == reflect.String {
20 | return echo.PathParamsBinder(ctx).String(paramName, dest.(*string)).BindError()
21 | } else if bu, ok := dest.(echo.BindUnmarshaler); ok {
22 | return echo.PathParamsBinder(ctx).BindUnmarshaler(paramName, bu).BindError()
23 | }
24 |
25 | return fmt.Errorf("unsupported type %T", t.Kind())
26 | }
27 |
--------------------------------------------------------------------------------
/docs/path/decentralized/metadata.yaml:
--------------------------------------------------------------------------------
1 | post:
2 | operationId: PostDecentralizedMetadata
3 | summary: Batch Get Activities By Metadata
4 | description: Retrieve a batch of activities associated with multiple specified metadata in the decentralized system. You can use various query parameters to filter and paginate the results, including limits on the number of activities and actions, timestamps, success status, direction, and more.
5 | tags:
6 | - Decentralized
7 | security:
8 | - bearerAuth: [ ]
9 | requestBody:
10 | $ref: "../../requestBody/BatchGetDecentralizedMetadataActivities.yaml"
11 | responses:
12 | '200':
13 | $ref: "../../responses/DecentralizedActivitiesResponse.yaml"
14 | '400':
15 | $ref: "../../responses/BadRequest.yaml"
16 | '500':
17 | $ref: "../../responses/InternalError.yaml"
18 |
--------------------------------------------------------------------------------
/provider/arweave/type_transaction.go:
--------------------------------------------------------------------------------
1 | package arweave
2 |
3 | import (
4 | "io"
5 | )
6 |
7 | // Transaction represents a transaction on the Arweave network.
8 | type Transaction struct {
9 | Format int `json:"format"`
10 | ID string `json:"id"`
11 | Owner string `json:"owner"`
12 | Tags []Tag `json:"tags"`
13 | Target string `json:"target"`
14 | Quantity string `json:"quantity"`
15 | Data string `json:"data"`
16 | DataReader io.Reader `json:"-"`
17 | DataSize string `json:"data_size"`
18 | DataRoot string `json:"data_root"`
19 | Reward string `json:"reward"`
20 | Signature string `json:"signature"`
21 | }
22 |
23 | // Tag represents a tag on the Arweave network.
24 | type Tag struct {
25 | Name string `json:"name" avro:"name"`
26 | Value string `json:"value" avro:"value"`
27 | }
28 |
--------------------------------------------------------------------------------
/docs/path/activity_count.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetActivityCount
3 | summary: Get Node Activity Count
4 | description: Retrieve node worker status details.
5 | security: []
6 | tags:
7 | - Info
8 | responses:
9 | "200":
10 | description: Activity count retrieved successfully.
11 | content:
12 | application/json:
13 | schema:
14 | type: object
15 | properties:
16 | count:
17 | type: integer
18 | description: The number of activities.
19 | example: 1242092608
20 | last_updated:
21 | type: string
22 | format: date-time
23 | description: The last time the activity count was updated.
24 | "400":
25 | $ref: "../responses/BadRequest.yaml"
26 | "500":
27 | $ref: "../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/provider/arweave/bundle/irys/operation/transactions.graphql:
--------------------------------------------------------------------------------
1 | query Transactions($owners: [String!], $after: String, $first: Int) {
2 | transactions(owners: $owners, after: $after, first: $first, order: ASC) {
3 | edges {
4 | cursor
5 | node {
6 | id
7 | token
8 | address
9 | tags {
10 | name
11 | value
12 | }
13 | signature
14 | timestamp
15 | receipt {
16 | version
17 | signature
18 | timestamp
19 | deadlineHeight
20 | }
21 | size
22 | fee
23 | }
24 | }
25 | pageInfo {
26 | endCursor
27 | hasNextPage
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/provider/arweave/bundle/transaction.go:
--------------------------------------------------------------------------------
1 | package bundle
2 |
3 | import "io"
4 |
5 | type Transaction struct {
6 | Header Header
7 | DataItems []DataItem
8 | }
9 |
10 | type Header struct {
11 | Numbers uint32
12 | DataItemInfos []DataItemInfo
13 | }
14 |
15 | type DataItemInfo struct {
16 | Size uint32
17 | ID string
18 | }
19 |
20 | var _ io.Reader = (*DataItem)(nil)
21 |
22 | type DataItem struct {
23 | SignatureType uint16
24 | Signature string
25 | Owner string
26 | Target string
27 | Anchor string
28 | TagsNumber uint16
29 | TagsBytes uint16
30 | Tags []Tag
31 | Data []byte
32 |
33 | dataReader io.Reader
34 | }
35 |
36 | func (d *DataItem) Read(buffer []byte) (int, error) {
37 | return d.dataReader.Read(buffer)
38 | }
39 |
40 | type Tag struct {
41 | Name []byte `avro:"name"`
42 | Value []byte `avro:"value"`
43 | }
44 |
--------------------------------------------------------------------------------
/internal/node/middlewarex/middlewarex_test.go:
--------------------------------------------------------------------------------
1 | package middlewarex_test
2 |
3 | import (
4 | "net/http"
5 | "net/http/httptest"
6 | "testing"
7 |
8 | "github.com/labstack/echo/v4"
9 | "github.com/rss3-network/node/v2/internal/node/middlewarex"
10 | "github.com/stretchr/testify/assert"
11 | )
12 |
13 | func TestPathParameterDecodeMiddleware_DecodesValidPathParameters(t *testing.T) {
14 | t.Parallel()
15 |
16 | e := echo.New()
17 | req := httptest.NewRequest(http.MethodGet, "/test/36kr%2Fnewsflashes+", nil)
18 | rec := httptest.NewRecorder()
19 | c := e.NewContext(req, rec)
20 | c.SetPath("/test/:path")
21 | c.SetParamNames("path")
22 | c.SetParamValues("36kr%2Fnewsflashes+")
23 |
24 | handler := middlewarex.DecodePathParamsMiddleware(func(c echo.Context) error {
25 | assert.Equal(t, "36kr/newsflashes+", c.Param("path"))
26 | return nil
27 | })
28 |
29 | err := handler(c)
30 | assert.NoError(t, err)
31 | }
32 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/table/dataset_mirror_post.go:
--------------------------------------------------------------------------------
1 | package table
2 |
3 | import (
4 | "github.com/rss3-network/node/v2/internal/engine/worker/decentralized/contract/mirror/model"
5 | )
6 |
7 | // DatasetMirrorPost represents a mirror post for revise logic check.
8 | type DatasetMirrorPost struct {
9 | ID string `gorm:"column:id;primary_key"`
10 | OriginContentDigest string `gorm:"column:origin_content_digest;index:idx_origin_content_digest"`
11 | }
12 |
13 | func (p *DatasetMirrorPost) Import(post *model.DatasetMirrorPost) (err error) {
14 | p.ID = post.TransactionID
15 | p.OriginContentDigest = post.OriginContentDigest
16 |
17 | return nil
18 | }
19 |
20 | func (p *DatasetMirrorPost) Export() (*model.DatasetMirrorPost, error) {
21 | post := model.DatasetMirrorPost{
22 | TransactionID: p.ID,
23 | OriginContentDigest: p.OriginContentDigest,
24 | }
25 |
26 | return &post, nil
27 | }
28 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ghcr.io/rss3-network/go-image/go-builder:main-230cb74 AS base
2 |
3 | WORKDIR /root/node
4 |
5 | RUN --mount=type=cache,target=/go/pkg/mod/ \
6 | --mount=type=bind,source=go.sum,target=go.sum \
7 | --mount=type=bind,source=go.mod,target=go.mod \
8 | go mod download -x
9 |
10 | RUN wget -O etherface.tar.gz https://storage.googleapis.com/rss3-etherface/etherface.tar.gz && \
11 | tar -xzf etherface.tar.gz && \
12 | rm etherface.tar.gz
13 |
14 | COPY . .
15 |
16 | FROM base AS builder
17 |
18 | ENV CGO_ENABLED=0
19 | RUN --mount=type=cache,target=/go/pkg/mod/ \
20 | make build
21 |
22 | FROM ghcr.io/rss3-network/go-image/go-builder:main-230cb74 AS runner
23 |
24 | WORKDIR /root/node
25 |
26 | COPY --from=builder /root/node/etherface /root/node/etherface
27 |
28 | COPY --from=builder /root/node/build/node .
29 | COPY deploy/default/config.default.yaml /etc/rss3/node/config.yaml
30 |
31 | ENTRYPOINT ["./node"]
32 |
--------------------------------------------------------------------------------
/internal/engine/worker/federated/factory.go:
--------------------------------------------------------------------------------
1 | package worker
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/redis/rueidis"
7 | "github.com/rss3-network/node/v2/config"
8 | "github.com/rss3-network/node/v2/internal/database"
9 | "github.com/rss3-network/node/v2/internal/engine"
10 | "github.com/rss3-network/node/v2/internal/engine/worker/federated/bluesky"
11 | "github.com/rss3-network/node/v2/internal/engine/worker/federated/mastodon"
12 | "github.com/rss3-network/node/v2/schema/worker/federated"
13 | )
14 |
15 | func New(config *config.Module, databaseClient database.Client, redisClient rueidis.Client) (engine.Worker, error) {
16 | switch config.Worker.(federated.Worker) {
17 | case federated.Mastodon:
18 | return mastodon.NewWorker(databaseClient, redisClient)
19 | case federated.Bluesky:
20 | return bluesky.NewWorker(databaseClient)
21 | default:
22 | return nil, fmt.Errorf("[federated/factory.go] unsupported worker %s", config.Worker)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/config/validator.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/samber/lo"
7 | )
8 |
9 | // HasOneWorker Check if there is at least one worker deployed
10 | func HasOneWorker(config *File) error {
11 | if (CalculateWorkerCount(config)) == 0 {
12 | return fmt.Errorf("at least one worker must be deployed")
13 | }
14 |
15 | return nil
16 | }
17 |
18 | // IsRSSOrAIComponentOnly Check if the configuration contains an RSS or AI component only
19 | func IsRSSOrAIComponentOnly(config *File) bool {
20 | return len(config.Component.Decentralized) == 0 && len(config.Component.Federated) == 0 &&
21 | (config.Component.RSS != nil || config.Component.AI != nil)
22 | }
23 |
24 | // CalculateWorkerCount returns the number of workers deployed
25 | func CalculateWorkerCount(config *File) int {
26 | return len(config.Component.Decentralized) + lo.Ternary(config.Component.RSS != nil, 1, 0) + len(config.Component.Federated) + lo.Ternary(config.Component.AI != nil, 1, 0)
27 | }
28 |
--------------------------------------------------------------------------------
/schema/worker/rss/platform.go:
--------------------------------------------------------------------------------
1 | package rss
2 |
3 | import "github.com/labstack/echo/v4"
4 |
5 | //go:generate go run --mod=mod github.com/dmarkham/enumer@v1.5.9 --values --type=Platform --linecomment --output platform_string.go --json --yaml --sql
6 | //go:generate go run --mod=mod github.com/rss3-network/enum-schema@v0.1.6 --type=Platform --linecomment --output ../../../docs/schemas/RSSPlatform.yaml -t ../../../docs/schemas/tmpl/RSS.yaml.tmpl
7 | type Platform uint64
8 |
9 | const (
10 | PlatformUnknown Platform = iota // Unknown
11 | PlatformRSSHub // RSSHub
12 | )
13 |
14 | var _ echo.BindUnmarshaler = (*Platform)(nil)
15 |
16 | func (p *Platform) UnmarshalParam(param string) error {
17 | platform, err := PlatformString(param)
18 | if err != nil {
19 | return err
20 | }
21 |
22 | *p = platform
23 |
24 | return nil
25 | }
26 |
27 | // ToPlatformMap is a map of worker to platform
28 | var ToPlatformMap = map[Worker]Platform{
29 | Core: PlatformRSSHub,
30 | }
31 |
--------------------------------------------------------------------------------
/docs/schemas/RSSMetadata.yaml:
--------------------------------------------------------------------------------
1 | description: Additional metadata related to the action.
2 | type: object
3 | allOf:
4 | - $ref: "https://raw.githubusercontent.com/RSS3-Network/Protocol-Go/refs/heads/main/openapi/metadata/RSS.yaml"
5 | example:
6 | authors:
7 | - name: Emma Wynne
8 | description: '
In short:
Nicheliving customer Cindy Richardson
9 | says she is overwhelmed with costs, including rent, mortgage and rates
10 | due to the long delays completing her house.
She has applied to
11 | access her superannuation on hardship grounds but was rejected.
What''s
12 | next?
WA Commerce Minister Sue Ellery is in talks with the company
13 | about resolving the long completion delays many customers are facing.
14 |
15 | '
16 | pub_date: '2024-07-02T04:13:38.000Z'
17 | title: Cindy was supposed to be living in a new home by now. Instead she's
18 | facing bankruptcy
--------------------------------------------------------------------------------
/provider/ethereum/contract/ens/erc1577/contenthash.go:
--------------------------------------------------------------------------------
1 | package erc1577
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/ipfs/go-cid"
7 | "github.com/multiformats/go-multicodec"
8 | "github.com/multiformats/go-varint"
9 | )
10 |
11 | func Parse(contentHash []byte) (path string, err error) {
12 | contentCode, cursor, err := varint.FromUvarint(contentHash)
13 | if err != nil {
14 | return "", fmt.Errorf("invaild content hash: %w", err)
15 | }
16 |
17 | var protocol string
18 |
19 | switch contentCode := multicodec.Code(contentCode); contentCode {
20 | case multicodec.Ipfs:
21 | protocol = "ipfs"
22 | case multicodec.Ipns:
23 | protocol = "ipns"
24 | default:
25 | return "", fmt.Errorf("unsupported content code: %d", contentCode)
26 | }
27 |
28 | _, contentCID, err := cid.CidFromBytes(contentHash[cursor:])
29 | if err != nil {
30 | return "", fmt.Errorf("invalid content hash: %w", err)
31 | }
32 |
33 | return fmt.Sprintf("/%s/%s", protocol, contentCID.String()), nil
34 | }
35 |
--------------------------------------------------------------------------------
/.golangci.yaml:
--------------------------------------------------------------------------------
1 | run:
2 | timeout: 10m
3 |
4 | linters:
5 | enable:
6 | - asasalint
7 | - asciicheck
8 | - bodyclose
9 | - durationcheck
10 | - errcheck
11 | - errorlint
12 | - gci
13 | - gocognit
14 | - gocritic
15 | - gocyclo
16 | - gosec
17 | - govet
18 | - ineffassign
19 | - makezero
20 | - nakedret
21 | - noctx
22 | - paralleltest
23 | - prealloc
24 | - predeclared
25 | - reassign
26 | - revive
27 | - staticcheck
28 | - stylecheck
29 | - unconvert
30 | - unparam
31 | - unused
32 | - whitespace
33 | - wsl
34 |
35 | issues:
36 | max-issues-per-linter: 0 # Unlimited
37 | max-same-issues: 0 # Unlimited
38 |
39 | linters-settings:
40 | govet:
41 | enable-all: true
42 | disable:
43 | - shadow
44 | - fieldalignment
45 | gocognit:
46 | min-complexity: 30
47 | gocyclo:
48 | min-complexity: 30
49 | gocritic:
50 | disabled-tags: ["opinionated", "experimental"]
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/contract/linear/schema.go:
--------------------------------------------------------------------------------
1 | package linear
2 |
3 | type FunctionCallArgs struct {
4 | ReceiverID string `json:"receiver_id"`
5 | Amount string `json:"amount"`
6 | Msg string `json:"msg"`
7 | }
8 |
9 | type Msg struct {
10 | Force int64 `json:"force"`
11 | Actions []Action `json:"actions"`
12 | }
13 |
14 | type Action struct {
15 | PoolID int64 `json:"pool_id"`
16 | TokenIn string `json:"token_in"`
17 | TokenOut string `json:"token_out"`
18 | AmountIn string `json:"amount_in,omitempty"`
19 | MinAmountOut string `json:"min_amount_out"`
20 | }
21 |
22 | type Event struct {
23 | Standard string `json:"standard"`
24 | Version string `json:"version"`
25 | Event string `json:"event"`
26 | Data []Data `json:"data"`
27 | TokenAddress string `json:"token_address"`
28 | }
29 |
30 | type Data struct {
31 | OldOwnerID string `json:"old_owner_id"`
32 | NewOwnerID string `json:"new_owner_id"`
33 | Amount string `json:"amount"`
34 | }
35 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/table/dataset_mastodon_update_handle.go:
--------------------------------------------------------------------------------
1 | package table
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/rss3-network/node/v2/internal/database/model"
7 | )
8 |
9 | type DatasetMastodonUpdateHandle struct {
10 | Handle string `gorm:"column:handle;primaryKey"`
11 | CreatedAt time.Time `gorm:"column:created_at;autoCreateTime"`
12 | UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime"`
13 | }
14 |
15 | func (d *DatasetMastodonUpdateHandle) Import(handle *model.MastodonHandle) error {
16 | d.Handle = handle.Handle
17 | d.UpdatedAt = handle.UpdatedAt
18 | d.CreatedAt = handle.CreatedAt
19 |
20 | return nil
21 | }
22 |
23 | func (d *DatasetMastodonUpdateHandle) Export() (*model.MastodonHandle, error) {
24 | handle := model.MastodonHandle{
25 | Handle: d.Handle,
26 | UpdatedAt: d.UpdatedAt,
27 | CreatedAt: d.CreatedAt,
28 | }
29 |
30 | return &handle, nil
31 | }
32 |
33 | func (DatasetMastodonUpdateHandle) TableName() string {
34 | return "dataset_mastodon_update_handles"
35 | }
36 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/erc721/contract.go:
--------------------------------------------------------------------------------
1 | package erc721
2 |
3 | import "github.com/rss3-network/node/v2/provider/ethereum/contract"
4 |
5 | // https://eips.ethereum.org/EIPS/eip-721
6 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen@v1.13.5 --abi ./abi/ERC721.abi --pkg erc721 --type ERC721 --out contract_erc721.go
7 |
8 | var (
9 | MethodIDSafeTransferFrom = contract.MethodID("safeTransferFrom(address,address,uint256)")
10 | MethodIDSafeTransferFromAndCallReceiver = contract.MethodID("safeTransferFrom(address,address,uint256,bytes)")
11 | MethodIDApprove = contract.MethodID("approve(address,uint256)")
12 | MethodIDSetApprovalForAll = contract.MethodID("setApprovalForAll(address,bool)")
13 |
14 | EventHashTransfer = contract.EventHash("Transfer(address,address,uint256)")
15 | EventHashApproval = contract.EventHash("Approval(address,address,uint256)")
16 | EventHashApprovalForAll = contract.EventHash("ApprovalForAll(address,address,bool)")
17 | )
18 |
--------------------------------------------------------------------------------
/internal/engine/protocol/farcaster/option.go:
--------------------------------------------------------------------------------
1 | package farcaster
2 |
3 | import (
4 | "math/big"
5 |
6 | "github.com/rss3-network/node/v2/config"
7 | "github.com/rss3-network/node/v2/config/parameter"
8 | "github.com/rss3-network/protocol-go/schema/network"
9 | )
10 |
11 | type Option struct {
12 | APIKey *string `json:"api_key" mapstructure:"api_key"`
13 | // TimestampStart is the Farcaster seconds timestamp that the worker should start from.
14 | TimestampStart *big.Int `json:"timestamp_start" mapstructure:"timestamp_start"`
15 | }
16 |
17 | func NewOption(n network.Network, parameters *config.Parameters) (*Option, error) {
18 | var option Option
19 |
20 | if parameters == nil {
21 | return &Option{
22 | TimestampStart: parameter.CurrentNetworkStartBlock[n].Block,
23 | }, nil
24 | }
25 |
26 | if err := parameters.Decode(&option); err != nil {
27 | return nil, err
28 | }
29 |
30 | if option.TimestampStart == nil {
31 | option.TimestampStart = parameter.CurrentNetworkStartBlock[n].Block
32 | }
33 |
34 | return &option, nil
35 | }
36 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/table/dataset_farcaster_profile.go:
--------------------------------------------------------------------------------
1 | package table
2 |
3 | import (
4 | "github.com/lib/pq"
5 | "github.com/rss3-network/node/v2/internal/database/model"
6 | )
7 |
8 | type DatasetFarcasterProfile struct {
9 | Fid int64 `gorm:"column:fid"`
10 | Username string `gorm:"column:username"`
11 | CustodyAddress string `gorm:"column:custody_address"`
12 | EthAddresses pq.StringArray `gorm:"column:eth_addresses;type:text[]"`
13 | }
14 |
15 | func (d *DatasetFarcasterProfile) Import(profile *model.Profile) (err error) {
16 | d.Fid = profile.Fid
17 | d.Username = profile.Username
18 | d.CustodyAddress = profile.CustodyAddress
19 | d.EthAddresses = profile.EthAddresses
20 |
21 | return nil
22 | }
23 |
24 | func (d *DatasetFarcasterProfile) Export() (*model.Profile, error) {
25 | profile := model.Profile{
26 | Fid: d.Fid,
27 | Username: d.Username,
28 | CustodyAddress: d.CustodyAddress,
29 | EthAddresses: d.EthAddresses,
30 | }
31 |
32 | return &profile, nil
33 | }
34 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/erc1155/contract.go:
--------------------------------------------------------------------------------
1 | package erc1155
2 |
3 | import "github.com/rss3-network/node/v2/provider/ethereum/contract"
4 |
5 | // https://eips.ethereum.org/EIPS/eip-1155
6 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen@v1.13.5 --abi ./abi/ERC1155.abi --pkg erc1155 --type ERC1155 --out contract_erc1155.go
7 |
8 | var (
9 | MethodIDSafeTransferFrom = contract.MethodID("safeTransferFrom(address,address,uint256,uint256,bytes)")
10 | MethodIDSafeBatchTransferFrom = contract.MethodID("safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)")
11 | MethodIDSetApprovalForAll = contract.MethodID("setApprovalForAll(address,bool)")
12 |
13 | EventHashTransferSingle = contract.EventHash("TransferSingle(address,address,address,uint256,uint256)")
14 | EventHashTransferBatch = contract.EventHash("TransferBatch(address,address,address,uint256[],uint256[])")
15 | EventHashApprovalForAll = contract.EventHash("ApprovalForAll(address,address,bool)")
16 | EventHashURI = contract.EventHash("URI(string,uint256)")
17 | )
18 |
--------------------------------------------------------------------------------
/internal/node/component/middleware/auth.go:
--------------------------------------------------------------------------------
1 | package middleware
2 |
3 | import (
4 | "net/http"
5 | "strings"
6 |
7 | "github.com/labstack/echo/v4"
8 | )
9 |
10 | // BearerAuth middleware for bearer token authentication
11 | func BearerAuth(accessToken string) echo.MiddlewareFunc {
12 | return func(next echo.HandlerFunc) echo.HandlerFunc {
13 | return func(c echo.Context) error {
14 | authHeader := c.Request().Header.Get("Authorization")
15 | if authHeader == "" {
16 | return echo.NewHTTPError(http.StatusUnauthorized, "Missing Authorization header")
17 | }
18 |
19 | // Check if the header starts with "Bearer "
20 | if !strings.HasPrefix(authHeader, "Bearer ") {
21 | return echo.NewHTTPError(http.StatusUnauthorized, "Invalid Authorization header format")
22 | }
23 |
24 | // Extract the token
25 | token := strings.TrimPrefix(authHeader, "Bearer ")
26 |
27 | // Verify the token
28 | if token != accessToken {
29 | return echo.NewHTTPError(http.StatusUnauthorized, "Invalid access token")
30 | }
31 |
32 | return next(c)
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023-present, The RSS3 Community
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/schema/worker/federated/platform.go:
--------------------------------------------------------------------------------
1 | package federated
2 |
3 | import "github.com/labstack/echo/v4"
4 |
5 | //go:generate go run --mod=mod github.com/dmarkham/enumer@v1.5.9 --values --type=Platform --linecomment --output platform_string.go --json --yaml --sql
6 | //go:generate go run --mod=mod github.com/rss3-network/enum-schema@v0.1.6 --type=Platform --linecomment --output ../../../docs/schemas/FederatedPlatform.yaml -t ../../../docs/schemas/tmpl/Federated.yaml.tmpl
7 | type Platform uint64
8 |
9 | const (
10 | PlatformUnknown Platform = iota // Unknown
11 | PlatformMastodon // Mastodon
12 | PlatformBluesky // Bluesky
13 | )
14 |
15 | var _ echo.BindUnmarshaler = (*Platform)(nil)
16 |
17 | func (p *Platform) UnmarshalParam(param string) error {
18 | platform, err := PlatformString(param)
19 | if err != nil {
20 | return err
21 | }
22 |
23 | *p = platform
24 |
25 | return nil
26 | }
27 |
28 | // ToPlatformMap is a map of worker to platform
29 | var ToPlatformMap = map[Worker]Platform{
30 | Mastodon: PlatformMastodon,
31 | Bluesky: PlatformBluesky,
32 | }
33 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/table/dataset_bluesky_profile.go:
--------------------------------------------------------------------------------
1 | package table
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/rss3-network/node/v2/internal/database/model"
7 | )
8 |
9 | type DatasetBlueskyProfile struct {
10 | DID string `gorm:"column:did;primaryKey"`
11 | Handle string `gorm:"column:handle"`
12 | CreatedAt time.Time `gorm:"column:created_at;autoCreateTime"`
13 | UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime"`
14 | }
15 |
16 | func (DatasetBlueskyProfile) TableName() string {
17 | return "dataset_bluesky_profiles"
18 | }
19 |
20 | func (d *DatasetBlueskyProfile) Import(profile *model.BlueskyProfile) error {
21 | d.DID = profile.DID
22 | d.Handle = profile.Handle
23 | d.CreatedAt = profile.CreatedAt
24 | d.UpdatedAt = profile.UpdatedAt
25 |
26 | return nil
27 | }
28 |
29 | func (d *DatasetBlueskyProfile) Export() (*model.BlueskyProfile, error) {
30 | profile := model.BlueskyProfile{
31 | DID: d.DID,
32 | Handle: d.Handle,
33 | CreatedAt: d.CreatedAt,
34 | UpdatedAt: d.UpdatedAt,
35 | }
36 |
37 | return &profile, nil
38 | }
39 |
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/contract/curve/pool/schema.go:
--------------------------------------------------------------------------------
1 | package pool
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/protocol-go/schema/network"
6 | )
7 |
8 | type ContractType string
9 |
10 | // Contract types.
11 | const (
12 | ContractTypePool ContractType = "pool"
13 | ContractTypeToken ContractType = "token"
14 | ContractTypeGauge ContractType = "gauge"
15 | )
16 |
17 | // Response is a curve pool.
18 | type Response[T any] struct {
19 | Success bool `json:"success"`
20 | Data T `json:"data"`
21 | Timestamp int64 `json:"generatedTimeMs"`
22 | }
23 |
24 | type GetPoolData struct {
25 | PoolData []Pool `json:"poolData"`
26 | }
27 |
28 | // Pool is a curve pool.
29 | type Pool struct {
30 | Network network.Network `json:"-"`
31 | Name string `json:"name"`
32 | Address common.Address `json:"address"`
33 | LiquidityProviderTokenAddress common.Address `json:"lpTokenAddress"`
34 | GaugeAddress common.Address `json:"gaugeAddress"`
35 | }
36 |
--------------------------------------------------------------------------------
/provider/arweave/bundle/signature.go:
--------------------------------------------------------------------------------
1 | package bundle
2 |
3 | const (
4 | SignatureTypeArweave = 1
5 | SignatureED25519 = 2
6 | SignatureEthereum = 3
7 | SignatureSolana = 4
8 | SignatureInjectedAptos = 5
9 | SignatureMultiAptos = 6
10 | SignatureTypeTypedEthereum = 7
11 | )
12 |
13 | type SignatureType struct {
14 | SignatureLength uint16
15 | PublicKeyLength uint16
16 | }
17 |
18 | var signatureTypeMap = map[uint16]SignatureType{
19 | SignatureTypeArweave: {
20 | SignatureLength: 512,
21 | PublicKeyLength: 512,
22 | },
23 | SignatureED25519: {
24 | SignatureLength: 64,
25 | PublicKeyLength: 32,
26 | },
27 | SignatureEthereum: {
28 | SignatureLength: 64 + 1,
29 | PublicKeyLength: 65,
30 | },
31 | SignatureSolana: {
32 | SignatureLength: 64,
33 | PublicKeyLength: 32,
34 | },
35 | SignatureInjectedAptos: {
36 | SignatureLength: 64,
37 | PublicKeyLength: 32,
38 | },
39 | SignatureMultiAptos: {
40 | SignatureLength: 64*32 + 4,
41 | PublicKeyLength: 32*32 + 1,
42 | },
43 | SignatureTypeTypedEthereum: {
44 | SignatureLength: 64 + 1,
45 | PublicKeyLength: 42,
46 | },
47 | }
48 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: 🐛 Bug Report
2 | description: Submit discovered bugs
3 | labels: ['bug']
4 |
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | Please ensure you provide all the information required by this template, otherwise the issue will be closed immediately.
10 |
11 | - type: textarea
12 | id: what-expected
13 | attributes:
14 | label: What is expected?
15 | validations:
16 | required: true
17 |
18 | - type: textarea
19 | id: actual-happened
20 | attributes:
21 | label: What is actually happening?
22 | validations:
23 | required: true
24 |
25 | - type: textarea
26 | id: logs
27 | attributes:
28 | label: Additional info
29 | description: logs, errors, etc.
30 | render: shell
31 | validations:
32 | required: true
33 |
34 | - type: checkboxes
35 | id: terms
36 | attributes:
37 | label: This is not a duplicated issue
38 | options:
39 | - label: I have searched [existing issues](https://github.com/rss3-network/node/issues) to ensure this bug has not already been reported
40 | required: true
41 |
--------------------------------------------------------------------------------
/internal/engine/worker.go:
--------------------------------------------------------------------------------
1 | package engine
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/rss3-network/protocol-go/schema"
7 | activityx "github.com/rss3-network/protocol-go/schema/activity"
8 | "github.com/rss3-network/protocol-go/schema/network"
9 | "github.com/rss3-network/protocol-go/schema/tag"
10 | )
11 |
12 | type Worker interface {
13 | // Name is the name of the worker.
14 | Name() string
15 | // Platform returns the display name of the worker as the `platform` in the final Activity response.
16 | Platform() string
17 | // Network returns all networks where the worker runs on and displayed as the `network` in the final Activity response.
18 | Network() []network.Network
19 | // Tags the possible `tag` of the worker, displayed in the final Activity response.
20 | Tags() []tag.Tag
21 | // Types the possible `type` of the worker, displayed in the final Activity response.
22 | Types() []schema.Type
23 | // Filter the DataSourceFilter of the worker(network, state, start logics, etc.).
24 | Filter() DataSourceFilter
25 | // Transform the core logic of the worker and returns the Activity.
26 | Transform(ctx context.Context, task Task) (*activityx.Activity, error)
27 | }
28 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/highlight/contract.go:
--------------------------------------------------------------------------------
1 | package highlight
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | // exchange https://etherscan.io/address/0x1bf979282181f2b7a640d17ab5d2e25125f2de5e
9 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/MintManager.abi --pkg highlight --type mint_manager --out mint_manager.go
10 |
11 | var (
12 | AddressMintManagerMainnet = common.HexToAddress("0x1bf979282181f2b7a640d17ab5d2e25125f2de5e")
13 | AddressMintManagerPolygon = common.HexToAddress("0xfbb65C52f439B762F712026CF6DD7D8E82F81eb9")
14 | AddressMintManagerArbitrum = common.HexToAddress("0x41cbab1028984A34C1338F437C726de791695AE8")
15 | AddressMintManagerBase = common.HexToAddress("0x8087039152c472Fa74F47398628fF002994056EA")
16 | AddressMintManagerOptimism = common.HexToAddress("0xFafd47bb399d570b5AC95694c5D2a1fb5EA030bB")
17 |
18 | EventHashNativeGasTokenPayment = contract.EventHash("NativeGasTokenPayment(address,bytes32,uint256,uint32)")
19 | EventHashNumTokenMint = contract.EventHash("NumTokenMint(bytes32,address,bool,uint256)")
20 | )
21 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/savm/contract.go:
--------------------------------------------------------------------------------
1 | package savm
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | // SAVMBridge
9 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/SAVMBridge.abi --pkg savm --type SAVMBridge --out contract_savm_bridge.go
10 | // BTCBridge
11 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/BTCBridge.abi --pkg savm --type BTCBridge --out contract_btc_bridge.go
12 |
13 | var (
14 | AddressSAVMBridge = common.HexToAddress("0x1109F6221F684BCb9B2529b8803a7b8c3411d45f")
15 | AddressBTCBridge = common.HexToAddress("0xF70Af817B07118CBF7ACCC38767899598e045408")
16 | AddressSAVMToken = common.HexToAddress("0x0E02765992f946397E6d2e65642eABb9cc674928")
17 | AddressWBTCToken = common.HexToAddress("0x5db252ead05C54B08A83414adCAbF46Eaa9E0337")
18 |
19 | EventHashBTCBridgeDeposit = contract.EventHash("Deposit(bytes32,uint256,address)")
20 | EventHashBTCBridgeWithdraw = contract.EventHash("Withdraw(bytes32,uint256,address)")
21 | EventHashSAVMTransfer = contract.EventHash("Transfer(address,address,uint256)")
22 | )
23 |
--------------------------------------------------------------------------------
/config/parameter/data.go:
--------------------------------------------------------------------------------
1 | package parameter
2 |
3 | import (
4 | "math/big"
5 |
6 | "github.com/rss3-network/protocol-go/schema/network"
7 | )
8 |
9 | // NumberOfMonthsToCover the number of months that a Node should cover data for
10 | const NumberOfMonthsToCover = 4
11 |
12 | type StartBlock struct {
13 | Block *big.Int `json:"block"`
14 | Timestamp int64 `json:"timestamp"`
15 | }
16 |
17 | type NetworkTolerance map[network.Network]uint64
18 | type NetworkStartBlock map[network.Network]*StartBlock
19 |
20 | type NetworkCoreWorkerDiskSpacePerMonth map[network.Network]uint
21 |
22 | // CurrentNetworkTolerance should be updated each epoch from vsl
23 | var CurrentNetworkTolerance = NetworkTolerance{}
24 |
25 | // CurrentNetworkStartBlock should be updated each epoch from vsl
26 | var CurrentNetworkStartBlock = NetworkStartBlock{}
27 |
28 | // CurrentNetworkCoreWorkerDiskSpacePerMonth the disk space required for the network's core worker to store a month worth of data
29 | // The data is calculated based on the average disk space usage during 2024 Q1.
30 | // Actually usage may vary depending on the network's activity.
31 | var CurrentNetworkCoreWorkerDiskSpacePerMonth = NetworkCoreWorkerDiskSpacePerMonth{}
32 |
--------------------------------------------------------------------------------
/schema/worker/rss/worker.go:
--------------------------------------------------------------------------------
1 | package rss
2 |
3 | import (
4 | "github.com/labstack/echo/v4"
5 | "github.com/rss3-network/protocol-go/schema/tag"
6 | )
7 |
8 | //go:generate go run --mod=mod github.com/dmarkham/enumer@v1.5.9 --values --type=Worker --linecomment --output worker_string.go --json --yaml --sql
9 | //go:generate go run --mod=mod github.com/rss3-network/enum-schema@v0.1.6 --type=Worker --linecomment --output ../../../docs/schemas/RSSWorker.yaml -t ../../../docs/schemas/tmpl/RSS.yaml.tmpl
10 | type Worker int
11 |
12 | const (
13 | Core Worker = iota + 1 // core
14 | )
15 |
16 | func (w Worker) Component() string {
17 | return "rss"
18 | }
19 |
20 | func (w Worker) Name() string {
21 | return w.String()
22 | }
23 |
24 | var _ echo.BindUnmarshaler = (*Worker)(nil)
25 |
26 | func (w *Worker) UnmarshalParam(param string) error {
27 | worker, err := WorkerString(param)
28 | if err != nil {
29 | return err
30 | }
31 |
32 | *w = worker
33 |
34 | return nil
35 | }
36 |
37 | func GetValueByWorkerStr(workerStr string) Worker {
38 | return _WorkerNameToValueMap[workerStr]
39 | }
40 |
41 | // ToTagsMap is a map of worker to tags
42 | var ToTagsMap = map[Worker][]tag.Tag{
43 | Core: {tag.RSS},
44 | }
45 |
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/core/worker.go:
--------------------------------------------------------------------------------
1 | package core
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/redis/rueidis"
7 | "github.com/rss3-network/node/v2/config"
8 | "github.com/rss3-network/node/v2/internal/engine"
9 | "github.com/rss3-network/node/v2/internal/engine/worker/decentralized/core/arweave"
10 | "github.com/rss3-network/node/v2/internal/engine/worker/decentralized/core/ethereum"
11 | "github.com/rss3-network/node/v2/internal/engine/worker/decentralized/core/farcaster"
12 | "github.com/rss3-network/node/v2/internal/engine/worker/decentralized/core/near"
13 | "github.com/rss3-network/protocol-go/schema/network"
14 | )
15 |
16 | // NewWorker creates a new core worker.
17 | func NewWorker(config *config.Module, redisClient rueidis.Client) (engine.Worker, error) {
18 | switch config.Network.Protocol() {
19 | case network.EthereumProtocol:
20 | return ethereum.NewWorker(config, redisClient)
21 | case network.ArweaveProtocol:
22 | return arweave.NewWorker(config)
23 | case network.FarcasterProtocol:
24 | return farcaster.NewWorker()
25 | case network.NearProtocol:
26 | return near.NewWorker(config)
27 | default:
28 | return nil, fmt.Errorf("unsupported worker %s", config.Network)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/schema/worker/worker.go:
--------------------------------------------------------------------------------
1 | package worker
2 |
3 | import (
4 | "reflect"
5 |
6 | "github.com/mitchellh/mapstructure"
7 | "github.com/rss3-network/node/v2/schema/worker/decentralized"
8 | "github.com/rss3-network/node/v2/schema/worker/federated"
9 | "github.com/rss3-network/node/v2/schema/worker/rss"
10 | )
11 |
12 | type Worker interface {
13 | Component() string
14 | Name() string
15 | }
16 |
17 | func HookFunc() mapstructure.DecodeHookFuncType {
18 | return func(
19 | f reflect.Type,
20 | t reflect.Type,
21 | data interface{},
22 | ) (interface{}, error) {
23 | // Only process if the target type is Worker and the protocol type is string
24 | if f.Kind() == reflect.String && t.Kind() == reflect.TypeOf((*Worker)(nil)).Elem().Kind() {
25 | workerStr := data.(string)
26 |
27 | // TODO: Implement the logic to determine the worker type
28 | if value := decentralized.GetValueByWorkerStr(workerStr); value != 0 {
29 | return value, nil
30 | } else if value := federated.GetValueByWorkerStr(workerStr); value != 0 {
31 | return value, nil
32 | } else if value := rss.GetValueByWorkerStr(workerStr); value != 0 {
33 | return value, nil
34 | }
35 | }
36 | // For all other types, return data
37 | return data, nil
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/internal/node/broadcaster/server.go:
--------------------------------------------------------------------------------
1 | package broadcaster
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "net/http"
7 | "os"
8 | "os/signal"
9 | "syscall"
10 |
11 | "github.com/robfig/cron/v3"
12 | "github.com/rss3-network/node/v2/config"
13 | )
14 |
15 | type Broadcaster struct {
16 | config *config.File
17 | cron *cron.Cron
18 | httpClient *http.Client
19 | }
20 |
21 | func (b *Broadcaster) Run(ctx context.Context) error {
22 | // run register cron job
23 | if err := b.Register(ctx); err != nil {
24 | return fmt.Errorf("register: %w", err)
25 | }
26 |
27 | _, err := b.cron.AddFunc("@every 1m", func() {
28 | if err := b.Heartbeat(ctx); err != nil {
29 | return
30 | }
31 | })
32 | if err != nil {
33 | return fmt.Errorf("add heartbeat cron job: %w", err)
34 | }
35 |
36 | b.cron.Start()
37 |
38 | stopchan := make(chan os.Signal, 1)
39 |
40 | signal.Notify(stopchan, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
41 | <-stopchan
42 |
43 | return nil
44 | }
45 |
46 | func NewBroadcaster(_ context.Context, config *config.File) (*Broadcaster, error) {
47 | instance := &Broadcaster{
48 | config: config,
49 | cron: cron.New(),
50 | httpClient: http.DefaultClient,
51 | }
52 |
53 | return instance, nil
54 | }
55 |
--------------------------------------------------------------------------------
/internal/node/component/federated/transformer_activity.go:
--------------------------------------------------------------------------------
1 | package federated
2 |
3 | import (
4 | "context"
5 |
6 | activityx "github.com/rss3-network/protocol-go/schema/activity"
7 | "github.com/rss3-network/protocol-go/schema/tag"
8 | lop "github.com/samber/lo/parallel"
9 | "go.uber.org/zap"
10 | )
11 |
12 | // TransformActivity should add related URLs to the activity based on action tag, network and platform
13 | func (c *Component) TransformActivity(ctx context.Context, activity *activityx.Activity) (*activityx.Activity, error) {
14 | if activity == nil {
15 | return nil, nil
16 | }
17 |
18 | // iterate over actions and transform them based on tag, network and platform
19 | lop.ForEach(activity.Actions, func(actionPtr *activityx.Action, index int) {
20 | action := *actionPtr
21 |
22 | var err error
23 |
24 | switch action.Tag {
25 | case tag.Social:
26 | *activity.Actions[index], err = c.TransformSocialType(ctx, activity.Network, activity.Platform, *actionPtr)
27 | default:
28 | activity.Actions[index] = actionPtr
29 | }
30 |
31 | if err != nil {
32 | zap.L().Error("failed to transform federated activity action",
33 | zap.Error(err),
34 | zap.String("id", activity.ID))
35 | }
36 | })
37 |
38 | return activity, nil
39 | }
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | # RSS3 Node
16 |
17 | The RSS3 Node, an RSS3 Data Sublayer (DSL) component, is responsible for indexing, transforming, storing, and ultimately serving the Open Information to the end users.
18 |
19 | ## Deployment
20 |
21 | See for a detailed deployment guide.
22 |
23 | ## Contribution
24 |
25 | See for a detailed contribution guide.
26 |
27 | ## License
28 |
29 | [MIT](LICENSE).
30 |
--------------------------------------------------------------------------------
/docs/path/federated/network.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetFederatedNetwork
3 | summary: Get Network Activities
4 | description: Retrieve a list of activities from the specified federated network. This endpoint allows you to filter activities by various parameters such as limit, timestamp, success status, and more.
5 | tags:
6 | - Federated
7 | security:
8 | - bearerAuth: []
9 | parameters:
10 | - $ref: "../../parameters/path_network.yaml"
11 | - $ref: "../../parameters/query_limit.yaml"
12 | - $ref: "../../parameters/query_action_limit.yaml"
13 | - $ref: "../../parameters/query_cursor.yaml"
14 | - $ref: "../../parameters/query_since_timestamp.yaml"
15 | - $ref: "../../parameters/query_until_timestamp.yaml"
16 | - $ref: "../../parameters/query_success.yaml"
17 | - $ref: "../../parameters/query_direction.yaml"
18 | - $ref: "../../parameters/query_tag.yaml"
19 | - $ref: "../../parameters/query_type.yaml"
20 | - $ref: "../../parameters/query_platform_federated.yaml"
21 | responses:
22 | "200":
23 | $ref: "../../responses/FederatedActivitiesResponse.yaml"
24 | "400":
25 | $ref: "../../responses/BadRequest.yaml"
26 | "404":
27 | $ref: "../../responses/NotFound.yaml"
28 | "500":
29 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/internal/node/component/ai/option.go:
--------------------------------------------------------------------------------
1 | package ai
2 |
3 | import (
4 | "github.com/rss3-network/node/v2/config"
5 | )
6 |
7 | type Option struct {
8 | AgentdataDBURL string `json:"agentdata_db_url" mapstructure:"agentdata_db_url"`
9 | OpenAIAPIKey string `json:"openai_api_key" mapstructure:"openai_api_key"`
10 | OllamaHost string `json:"ollama_host" mapstructure:"ollama_host"`
11 | Twitter OptionTwitter `json:"twitter" mapstructure:"twitter"`
12 | KaitoAPIToken string `json:"kaito_api_token" mapstructure:"kaito_api_token"`
13 | }
14 |
15 | type OptionTwitter struct {
16 | BearerToken string `json:"bearer_token" mapstructure:"bearer_token"`
17 | APIKey string `json:"api_key" mapstructure:"api_key"`
18 | APISecret string `json:"api_secret" mapstructure:"api_secret"`
19 | AccessToken string `json:"access_token" mapstructure:"access_token"`
20 | AccessTokenSecret string `json:"access_token_secret" mapstructure:"access_token_secret"`
21 | }
22 |
23 | func NewOption(options *config.Parameters) (*Option, error) {
24 | var instance Option
25 |
26 | if options == nil {
27 | return &instance, nil
28 | }
29 |
30 | if err := options.Decode(&instance); err != nil {
31 | return nil, err
32 | }
33 |
34 | return &instance, nil
35 | }
36 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/aavegotchi/contract.go:
--------------------------------------------------------------------------------
1 | package aavegotchi
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | //go:generate go run -mod=mod github.com/ethereum/go-ethereum/cmd/abigen@v1.13.5 --abi ./abi/ERC1155MarketplaceFacet.abi --pkg aavegotchi --type ERC1155Marketplace --out ./contract_erc1155_marketplace_facet.go
9 | //go:generate go run -mod=mod github.com/ethereum/go-ethereum/cmd/abigen@v1.13.5 --abi ./abi/ERC721MarketplaceFacet.abi --pkg aavegotchi --type ERC721Marketplace --out ./contract_erc721_marketplace_facet.go
10 |
11 | var (
12 | AddressAavegotchi = common.HexToAddress("0x86935F11C86623deC8a25696E1C19a8659CbF95d")
13 |
14 | EventHashERC721ListingAdd = contract.EventHash("ERC721ListingAdd(uint256,address,address,uint256,uint256,uint256)")
15 | EventHashERC721ExecutedListing = contract.EventHash("ERC721ExecutedListing(uint256,address,address,address,uint256,uint256,uint256,uint256)")
16 | EventHashERC1155ExecutedListing = contract.EventHash("ERC1155ExecutedListing(uint256,address,address,address,uint256,uint256,uint256,uint256,uint256)")
17 | EventHashERC1155ListingAdd = contract.EventHash("ERC1155ListingAdd(uint256,address,address,uint256,uint256,uint256,uint256,uint256)")
18 | )
19 |
--------------------------------------------------------------------------------
/docs/path/federated/platform.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetFederatedPlatform
3 | summary: Get Platform Activities
4 | description: Retrieve a list of activities from the specified federated platform. This endpoint allows you to filter activities by various parameters such as limit, timestamp, success status, and more.
5 | tags:
6 | - Federated
7 | security:
8 | - bearerAuth: []
9 | parameters:
10 | - $ref: "../../parameters/path_platform_federated.yaml"
11 | - $ref: "../../parameters/query_limit.yaml"
12 | - $ref: "../../parameters/query_action_limit.yaml"
13 | - $ref: "../../parameters/query_cursor.yaml"
14 | - $ref: "../../parameters/query_since_timestamp.yaml"
15 | - $ref: "../../parameters/query_until_timestamp.yaml"
16 | - $ref: "../../parameters/query_success.yaml"
17 | - $ref: "../../parameters/query_direction.yaml"
18 | - $ref: "../../parameters/query_tag.yaml"
19 | - $ref: "../../parameters/query_type.yaml"
20 | - $ref: "../../parameters/query_network.yaml"
21 | responses:
22 | "200":
23 | $ref: "../../responses/FederatedActivitiesResponse.yaml"
24 | "400":
25 | $ref: "../../responses/BadRequest.yaml"
26 | "404":
27 | $ref: "../../responses/NotFound.yaml"
28 | "500":
29 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/internal/node/component/rss/handler.go:
--------------------------------------------------------------------------------
1 | package rss
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/labstack/echo/v4"
7 | "github.com/rss3-network/node/v2/common/http/response"
8 | activityx "github.com/rss3-network/protocol-go/schema/activity"
9 | "go.uber.org/zap"
10 | )
11 |
12 | type Response struct {
13 | Data []*activityx.Activity `json:"data"`
14 | }
15 |
16 | func (h *Component) Handler(ctx echo.Context) error {
17 | path := ctx.Param("*")
18 | zap.L().Debug("handling RSS request",
19 | zap.String("path", path),
20 | zap.String("request_uri", ctx.Request().RequestURI))
21 |
22 | go h.CollectTrace(ctx.Request().Context(), ctx.Request().RequestURI, path)
23 |
24 | go h.CollectMetric(ctx.Request().Context(), ctx.Request().RequestURI, path)
25 |
26 | addRecentRequest(ctx.Request().RequestURI)
27 |
28 | data, err := h.getActivities(ctx.Request().Context(), path, ctx.Request().URL)
29 | if err != nil {
30 | zap.L().Error("failed to get activities from RSS feed",
31 | zap.String("path", path),
32 | zap.Error(err))
33 |
34 | return response.InternalError(ctx)
35 | }
36 |
37 | zap.L().Info("successfully retrieved RSS activities",
38 | zap.String("path", path),
39 | zap.Int("activity_count", len(data)))
40 |
41 | return ctx.JSON(http.StatusOK, Response{
42 | Data: data,
43 | })
44 | }
45 |
--------------------------------------------------------------------------------
/internal/database/dialer/postgres/table/checkpoint.go:
--------------------------------------------------------------------------------
1 | package table
2 |
3 | import (
4 | "encoding/json"
5 | "time"
6 |
7 | "github.com/rss3-network/node/v2/internal/engine"
8 | "github.com/rss3-network/protocol-go/schema/network"
9 | )
10 |
11 | type Checkpoint struct {
12 | ID string `gorm:"column:id"`
13 | Network network.Network `gorm:"column:network"`
14 | Worker string `gorm:"column:worker"`
15 | State json.RawMessage `gorm:"column:state;type:jsonb"`
16 | IndexCount int64 `gorm:"column:index_count"`
17 | CreatedAt time.Time `gorm:"column:created_at;autoCreateTime"`
18 | UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime"`
19 | }
20 |
21 | func (c *Checkpoint) Import(checkpoint *engine.Checkpoint) (err error) {
22 | c.ID = checkpoint.ID
23 | c.Network = checkpoint.Network
24 | c.Worker = checkpoint.Worker
25 | c.State = checkpoint.State
26 | c.IndexCount = checkpoint.IndexCount
27 | c.UpdatedAt = checkpoint.UpdatedAt
28 |
29 | return nil
30 | }
31 |
32 | func (c *Checkpoint) Export() (*engine.Checkpoint, error) {
33 | return &engine.Checkpoint{
34 | ID: c.ID,
35 | Network: c.Network,
36 | Worker: c.Worker,
37 | State: c.State,
38 | IndexCount: c.IndexCount,
39 | UpdatedAt: c.UpdatedAt,
40 | }, nil
41 | }
42 |
--------------------------------------------------------------------------------
/schema/worker/federated/worker.go:
--------------------------------------------------------------------------------
1 | package federated
2 |
3 | import (
4 | "github.com/labstack/echo/v4"
5 | "github.com/rss3-network/protocol-go/schema/tag"
6 | )
7 |
8 | //go:generate go run --mod=mod github.com/dmarkham/enumer@v1.5.9 --values --type=Worker --linecomment --output worker_string.go --json --yaml --sql
9 | //go:generate go run --mod=mod github.com/rss3-network/enum-schema@v0.1.6 --type=Worker --linecomment --output ../../../docs/schemas/FederatedWorker.yaml -t ../../../docs/schemas/tmpl/Federated.yaml.tmpl
10 | type Worker int
11 |
12 | const (
13 | Mastodon Worker = iota + 1 // mastodon
14 | Bluesky // bluesky
15 | )
16 |
17 | func (w Worker) Component() string {
18 | return "federated"
19 | }
20 |
21 | func (w Worker) Name() string {
22 | return w.String()
23 | }
24 |
25 | var _ echo.BindUnmarshaler = (*Worker)(nil)
26 |
27 | func (w *Worker) UnmarshalParam(param string) error {
28 | worker, err := WorkerString(param)
29 | if err != nil {
30 | return err
31 | }
32 |
33 | *w = worker
34 |
35 | return nil
36 | }
37 |
38 | func GetValueByWorkerStr(workerStr string) Worker {
39 | return _WorkerNameToValueMap[workerStr]
40 | }
41 |
42 | // ToTagsMap is a map of worker to tags
43 | var ToTagsMap = map[Worker][]tag.Tag{
44 | Mastodon: {tag.Social},
45 | Bluesky: {tag.Social},
46 | }
47 |
--------------------------------------------------------------------------------
/docs/path/decentralized/network.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetDecentralizedNetwork
3 | summary: Get Network Activities
4 | description: Retrieve a list of activities from the specified decentralized network. This endpoint allows you to filter activities by various parameters such as limit, timestamp, success status, and more.
5 | tags:
6 | - Decentralized
7 | security:
8 | - bearerAuth: []
9 | parameters:
10 | - $ref: "../../parameters/path_network.yaml"
11 | - $ref: "../../parameters/query_limit.yaml"
12 | - $ref: "../../parameters/query_action_limit.yaml"
13 | - $ref: "../../parameters/query_cursor.yaml"
14 | - $ref: "../../parameters/query_since_timestamp.yaml"
15 | - $ref: "../../parameters/query_until_timestamp.yaml"
16 | - $ref: "../../parameters/query_success.yaml"
17 | - $ref: "../../parameters/query_direction.yaml"
18 | - $ref: "../../parameters/query_tag.yaml"
19 | - $ref: "../../parameters/query_type.yaml"
20 | - $ref: "../../parameters/query_platform_decentralized.yaml"
21 | responses:
22 | "200":
23 | $ref: "../../responses/DecentralizedActivitiesResponse.yaml"
24 | "400":
25 | $ref: "../../responses/BadRequest.yaml"
26 | "404":
27 | $ref: "../../responses/NotFound.yaml"
28 | "500":
29 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/docs/path/decentralized/platform.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetDecentralizedPlatform
3 | summary: Get Platform Activities
4 | description: Retrieve a list of activities from the specified decentralized platform. This endpoint allows you to filter activities by various parameters such as limit, timestamp, success status, and more.
5 | tags:
6 | - Decentralized
7 | security:
8 | - bearerAuth: []
9 | parameters:
10 | - $ref: "../../parameters/path_platform_decentralized.yaml"
11 | - $ref: "../../parameters/query_limit.yaml"
12 | - $ref: "../../parameters/query_action_limit.yaml"
13 | - $ref: "../../parameters/query_cursor.yaml"
14 | - $ref: "../../parameters/query_since_timestamp.yaml"
15 | - $ref: "../../parameters/query_until_timestamp.yaml"
16 | - $ref: "../../parameters/query_success.yaml"
17 | - $ref: "../../parameters/query_direction.yaml"
18 | - $ref: "../../parameters/query_tag.yaml"
19 | - $ref: "../../parameters/query_type.yaml"
20 | - $ref: "../../parameters/query_network.yaml"
21 | responses:
22 | "200":
23 | $ref: "../../responses/DecentralizedActivitiesResponse.yaml"
24 | "400":
25 | $ref: "../../responses/BadRequest.yaml"
26 | "404":
27 | $ref: "../../responses/NotFound.yaml"
28 | "500":
29 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/internal/engine/protocol/atproto/option.go:
--------------------------------------------------------------------------------
1 | package atproto
2 |
3 | import (
4 | "fmt"
5 | "time"
6 |
7 | "github.com/rss3-network/node/v2/config"
8 | "github.com/rss3-network/node/v2/config/parameter"
9 | "github.com/rss3-network/protocol-go/schema/network"
10 | "github.com/samber/lo"
11 | "go.uber.org/zap"
12 | )
13 |
14 | type Option struct {
15 | Username string `json:"username" mapstructure:"username"`
16 | Password string `json:"password" mapstructure:"password"`
17 |
18 | TimestampStart time.Time `json:"timestamp_start" mapstructure:"timestamp_start"`
19 | }
20 |
21 | func NewOption(parameters *config.Parameters) (*Option, error) {
22 | var option Option
23 |
24 | if parameters == nil {
25 | return &Option{}, nil
26 | }
27 |
28 | if err := parameters.Decode(&option); err != nil {
29 | zap.L().Error("decode parameters failed", zap.Error(err))
30 |
31 | return nil, fmt.Errorf("decode parameters failed: %w", err)
32 | }
33 |
34 | if lo.IsEmpty(option.TimestampStart) {
35 | if parameter.CurrentNetworkStartBlock[network.Bluesky] == nil {
36 | // Default to 90 days ago
37 | option.TimestampStart = time.Now().Add(-time.Hour * 24 * 90)
38 |
39 | return &option, nil
40 | }
41 |
42 | option.TimestampStart = time.Unix(parameter.CurrentNetworkStartBlock[network.Bluesky].Timestamp, 0)
43 | }
44 |
45 | return &option, nil
46 | }
47 |
--------------------------------------------------------------------------------
/provider/ipfs/gateway.go:
--------------------------------------------------------------------------------
1 | package ipfs
2 |
3 | import (
4 | "bufio"
5 | "context"
6 | "net/http"
7 |
8 | "github.com/samber/lo"
9 | )
10 |
11 | const (
12 | DefaultGatewayRSS3 = "https://ipfs.rss3.page/"
13 | DefaultGatewayIPFS = "https://ipfs.io/"
14 | DefaultGatewayCloudflare = "https://cloudflare-ipfs.com/"
15 | DefaultGateway4EVERLAND = "https://4everland.io/"
16 | )
17 |
18 | var DefaultGateways = []string{
19 | DefaultGatewayRSS3,
20 | DefaultGatewayIPFS,
21 | DefaultGatewayCloudflare,
22 | DefaultGateway4EVERLAND,
23 | }
24 |
25 | const (
26 | DefaultGatewayList = "https://raw.githubusercontent.com/ipfs/public-gateway-checker/master/gateways.txt"
27 | )
28 |
29 | func FetchGateways(ctx context.Context, gatewayList string) ([]string, error) {
30 | request, err := http.NewRequestWithContext(ctx, http.MethodGet, gatewayList, nil)
31 | if err != nil {
32 | return nil, err
33 | }
34 |
35 | // nolint:bodyclose // False positive.
36 | response, err := http.DefaultClient.Do(request)
37 | if err != nil {
38 | return nil, err
39 | }
40 |
41 | defer lo.Try(response.Body.Close)
42 |
43 | var (
44 | scanner = bufio.NewScanner(response.Body)
45 | gatewayURLs = make([]string, 0)
46 | )
47 |
48 | for scanner.Scan() {
49 | gatewayURLs = append(gatewayURLs, scanner.Text())
50 | }
51 |
52 | return gatewayURLs, nil
53 | }
54 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/kiwistand/contract.go:
--------------------------------------------------------------------------------
1 | package kiwistand
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | // KIWI
9 | //https://optimistic.etherscan.io/address/0x66747bdC903d17C586fA09eE5D6b54CC85bBEA45
10 | //go:generate go run -mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi abi/kiwi.abi --pkg kiwistand --type Kiwi --out contract_kiwi.go
11 | // ProtocolRewards
12 | // https://optimistic.etherscan.io/address/0x7777777f279eba3d3ad8f4e708545291a6fdba8b
13 | //go:generate go run -mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi abi/ProtocolRewards.abi --pkg kiwistand --type ProtocolRewards --out contract_protocol_rewards.go
14 |
15 | var (
16 | AddressKIWI = common.HexToAddress("0x66747bdc903d17c586fa09ee5d6b54cc85bbea45")
17 | AddressProtocolRewards = common.HexToAddress("0x7777777f279eba3d3ad8f4e708545291a6fdba8b")
18 |
19 | EventHashRewardsDeposit = contract.EventHash("RewardsDeposit(address,address,address,address,address,address,uint256,uint256,uint256,uint256,uint256)")
20 | EventHashTransfer = contract.EventHash("Transfer(address,address,uint256)")
21 | EventHashSale = contract.EventHash("Sale(address,uint256,uint256,uint256)")
22 | EventHashMintComment = contract.EventHash("MintComment(address,address,uint256,uint256,string)")
23 | )
24 |
--------------------------------------------------------------------------------
/provider/ethereum/option.go:
--------------------------------------------------------------------------------
1 | package ethereum
2 |
3 | import (
4 | "context"
5 | "crypto/tls"
6 | "net/http"
7 |
8 | "github.com/ethereum/go-ethereum/rpc"
9 | )
10 |
11 | // Option used to configure the client with additional options.
12 | type Option = func(ctx context.Context, client *client) error
13 |
14 | // WithHTTP2Disabled sets the HTTP2 client to be disabled.
15 | func WithHTTP2Disabled() Option {
16 | return func(ctx context.Context, client *client) error {
17 | tr := http.DefaultTransport.(*http.Transport).Clone()
18 | tr.ForceAttemptHTTP2 = false
19 | tr.TLSNextProto = make(map[string]func(authority string, c *tls.Conn) http.RoundTripper)
20 | tr.TLSClientConfig = new(tls.Config)
21 |
22 | httpClient := &http.Client{
23 | Transport: tr,
24 | }
25 |
26 | var err error
27 |
28 | client.rpcClient, err = rpc.DialOptions(ctx, client.endpoint, rpc.WithHTTPClient(httpClient))
29 | if err != nil {
30 | return err
31 | }
32 |
33 | return nil
34 | }
35 | }
36 |
37 | // WithHTTPHeader sets the HTTP header for the client.
38 | // The header can be used to set the authorization token and other headers.
39 | func WithHTTPHeader(httpHeader map[string]string) Option {
40 | return func(_ context.Context, client *client) error {
41 | for key, value := range httpHeader {
42 | client.rpcClient.SetHeader(key, value)
43 | }
44 |
45 | return nil
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/provider/ethereum/etherface/client_test.go:
--------------------------------------------------------------------------------
1 | package etherface_test
2 |
3 | import (
4 | "context"
5 | "sync"
6 | "testing"
7 |
8 | "github.com/rss3-network/node/v2/provider/ethereum/etherface"
9 | "github.com/stretchr/testify/require"
10 | )
11 |
12 | var (
13 | setupOnce sync.Once
14 | etherfaceClient etherface.Client
15 | )
16 |
17 | func setup(t *testing.T) {
18 | setupOnce.Do(func() {
19 | var err error
20 |
21 | etherfaceClient, err = etherface.NewMockEtherfaceClient()
22 | require.NoError(t, err)
23 | })
24 | }
25 |
26 | func TestEtherfaceClient_Lookup(t *testing.T) {
27 | t.Parallel()
28 |
29 | setup(t)
30 |
31 | type arguments struct {
32 | hash string
33 | }
34 |
35 | testcases := []struct {
36 | name string
37 | arguments arguments
38 | }{
39 | {
40 | name: "Lookup Function Signature",
41 | arguments: arguments{
42 | hash: "8f283970",
43 | },
44 | },
45 | {
46 | name: "Lookup Function Signature with 0x prefix",
47 | arguments: arguments{
48 | hash: "0x8f283970",
49 | },
50 | },
51 | }
52 |
53 | for _, testcase := range testcases {
54 | testcase := testcase
55 |
56 | t.Run(testcase.name, func(t *testing.T) {
57 | t.Parallel()
58 |
59 | functionName, err := etherfaceClient.Lookup(context.TODO(), testcase.arguments.hash)
60 | require.NoError(t, err)
61 |
62 | require.Equal(t, "changeAdmin", functionName)
63 | })
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/.github/workflows/test.yaml:
--------------------------------------------------------------------------------
1 | name: Test
2 | on:
3 | push:
4 | branches:
5 | - main
6 | - prod
7 | paths-ignore:
8 | - "deploy/**"
9 | pull_request:
10 | paths-ignore:
11 | - "deploy/**"
12 |
13 | jobs:
14 | test:
15 | name: Test
16 | runs-on: self-hosted
17 | steps:
18 | - name: Import Secrets
19 | uses: hashicorp/vault-action@v3.3.0
20 | with:
21 | url: ${{ secrets.VAULT_ADDR }}
22 | token: ${{ secrets.VAULT_TOKEN }}
23 | secrets: |
24 | kv/data/network/rss3-node ENDPOINT_ETHEREUM ;
25 | kv/data/network/rss3-node ENDPOINT_POLYGON ;
26 | kv/data/network/rss3-node ENDPOINT_ARBITRUM ;
27 | kv/data/network/rss3-node ENDPOINT_OPTIMISM ;
28 | kv/data/network/rss3-node ENDPOINT_BASE ;
29 | kv/data/network/rss3-node ENDPOINT_AVALANCHE ;
30 | kv/data/network/rss3-node ENDPOINT_SAVM ;
31 | kv/data/network/rss3-node ENDPOINT_GNOSIS ;
32 | kv/data/network/rss3-node ENDPOINT_BINANCE_SMART_CHAIN ;
33 | kv/data/network/rss3-node ENDPOINT_LINEA ;
34 | kv/data/network/rss3-node FARCASTER_URI
35 | - name: Setup Go
36 | uses: actions/setup-go@v5
37 | with:
38 | go-version: "1.22.7"
39 | - name: Checkout
40 | uses: actions/checkout@v4
41 | - name: Test
42 | run: make test
43 |
--------------------------------------------------------------------------------
/internal/engine/protocol/arweave/data_source_test.go:
--------------------------------------------------------------------------------
1 | package arweave_test
2 |
3 | // var initializeOnce sync.Once
4 | //
5 | // func initialize(t *testing.T) {
6 | // initializeOnce.Do(func() {
7 | // zap.ReplaceGlobals(zaptest.NewLogger(t))
8 | // })
9 | // }
10 |
11 | // func TestSource(t *testing.T) {
12 | // t.Parallel()
13 | //
14 | // initialize(t)
15 | //
16 | // type arguments struct {
17 | // conf *config.Module
18 | // }
19 | //
20 | // var testcases []struct {
21 | // name string
22 | // arguments arguments
23 | // want require.ValueAssertionFunc
24 | // wantError require.ErrorAssertionFunc
25 | // }
26 | //
27 | // for _, testcase := range testcases {
28 | // testcase := testcase
29 | //
30 | // t.Run(testcase.name, func(t *testing.T) {
31 | // t.Parallel()
32 | //
33 | // instance, err := arweave.NewSource(testcase.arguments.conf, nil, nil)
34 | // require.NoError(t, err, "new arweave dataSource")
35 | //
36 | // var (
37 | // tasksChan = make(chan *engine.Tasks)
38 | // errorChan = make(chan error)
39 | // )
40 | //
41 | // instance.Start(context.Background(), tasksChan, errorChan)
42 | //
43 | // for {
44 | // select {
45 | // case tasks := <-tasksChan:
46 | // for _, task := range tasks.Tasks {
47 | // t.Logf("Task %s", task.ID())
48 | // }
49 | // case err := <-errorChan:
50 | // require.NoError(t, err)
51 | //
52 | // return
53 | // }
54 | // }
55 | // })
56 | // }
57 | // }
58 |
--------------------------------------------------------------------------------
/internal/engine/protocol/atproto/task.go:
--------------------------------------------------------------------------------
1 | package atproto
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 |
7 | "github.com/rss3-network/node/v2/internal/engine"
8 | "github.com/rss3-network/node/v2/provider/atproto"
9 | activityx "github.com/rss3-network/protocol-go/schema/activity"
10 | "github.com/rss3-network/protocol-go/schema/network"
11 | "github.com/rss3-network/protocol-go/schema/typex"
12 | )
13 |
14 | var _ engine.Task = (*Task)(nil)
15 |
16 | type Task struct {
17 | Network network.Network
18 | Message atproto.Message
19 | }
20 |
21 | func (t Task) ID() string {
22 | return strings.TrimPrefix(t.Message.URI, "at://")
23 | }
24 |
25 | func (t Task) GetNetwork() network.Network {
26 | return t.Network
27 | }
28 |
29 | func (t Task) GetTimestamp() uint64 {
30 | return uint64(t.Message.CreatedAt.Unix())
31 | }
32 |
33 | func (t Task) Validate() error {
34 | return nil
35 | }
36 |
37 | func (t Task) BuildActivity(options ...activityx.Option) (*activityx.Activity, error) {
38 | activity := activityx.Activity{
39 | ID: t.ID(),
40 | Network: t.Network,
41 | Type: typex.Unknown,
42 | Status: true,
43 | Actions: make([]*activityx.Action, 0),
44 | Timestamp: t.GetTimestamp(),
45 | }
46 |
47 | // Apply activity options.
48 | for _, option := range options {
49 | if err := option(&activity); err != nil {
50 | return nil, fmt.Errorf("apply option: %w", err)
51 | }
52 | }
53 |
54 | return &activity, nil
55 | }
56 |
--------------------------------------------------------------------------------
/docs/path/federated/account.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetFederatedAccount
3 | summary: Get Account Activities
4 | description: This endpoint retrieves the activities associated with a specified account in the federated system. You can use various query parameters to filter and paginate the results, including limits on the number of activities and actions, timestamps, success status, direction, and more.
5 | tags:
6 | - Federated
7 | security:
8 | - bearerAuth: []
9 | parameters:
10 | - $ref: "../../parameters/path_account_federated.yaml"
11 | - $ref: "../../parameters/query_limit.yaml"
12 | - $ref: "../../parameters/query_action_limit.yaml"
13 | - $ref: "../../parameters/query_cursor.yaml"
14 | - $ref: "../../parameters/query_since_timestamp.yaml"
15 | - $ref: "../../parameters/query_until_timestamp.yaml"
16 | - $ref: "../../parameters/query_success.yaml"
17 | - $ref: "../../parameters/query_direction.yaml"
18 | - $ref: "../../parameters/query_network.yaml"
19 | - $ref: "../../parameters/query_tag.yaml"
20 | - $ref: "../../parameters/query_type.yaml"
21 | - $ref: "../../parameters/query_platform_federated.yaml"
22 | responses:
23 | "200":
24 | $ref: "../../responses/FederatedActivitiesResponse.yaml"
25 | "400":
26 | $ref: "../../responses/BadRequest.yaml"
27 | "404":
28 | $ref: "../../responses/NotFound.yaml"
29 | "500":
30 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/common/http/response/error.go:
--------------------------------------------------------------------------------
1 | package response
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 |
7 | "github.com/labstack/echo/v4"
8 | )
9 |
10 | //go:generate go run --mod=mod github.com/dmarkham/enumer --type=ErrorCode --transform=snake --values --trimprefix=ErrorCode --json --output error_code.go
11 | type ErrorCode int
12 |
13 | const (
14 | ErrorCodeBadRequest ErrorCode = iota + 1
15 | ErrorCodeValidationFailed
16 | ErrorCodeBadParams
17 | ErrorCodeInternalError
18 | )
19 |
20 | type ErrorResponse struct {
21 | Message string `json:"message"`
22 | Code ErrorCode `json:"code"`
23 | }
24 |
25 | func BadRequestError(c echo.Context, err error) error {
26 | return c.JSON(http.StatusBadRequest, &ErrorResponse{
27 | Code: ErrorCodeBadRequest,
28 | Message: fmt.Sprintf("Please check your request and try again, %s", err),
29 | })
30 | }
31 |
32 | func ValidationFailedError(c echo.Context, err error) error {
33 | return c.JSON(http.StatusBadRequest, &ErrorResponse{
34 | Code: ErrorCodeValidationFailed,
35 | Message: fmt.Sprintf("Please check your request validation and try again, %s", err),
36 | })
37 | }
38 |
39 | // InternalError should not return the details of the error to the client for safety reasons.
40 | func InternalError(c echo.Context) error {
41 | return c.JSON(http.StatusInternalServerError, &ErrorResponse{
42 | Code: ErrorCodeInternalError,
43 | Message: "An internal error has occurred, please try again later",
44 | })
45 | }
46 |
--------------------------------------------------------------------------------
/docs/schemas/RSSActivity.yaml:
--------------------------------------------------------------------------------
1 | properties:
2 | id:
3 | description: The unique identifier for the activity.
4 | type: string
5 | format: uri
6 | owner:
7 | $ref: "./RSSAccount.yaml"
8 | network:
9 | allOf:
10 | - $ref: "./ProtocolNetwork.yaml"
11 | - example: rsshub
12 | index:
13 | description: The index of the activity in the list.
14 | type: integer
15 | from:
16 | $ref: "./RSSAccount.yaml"
17 | to:
18 | $ref: "./RSSAccount.yaml"
19 | tag:
20 | allOf:
21 | - $ref: "./ProtocolTag.yaml"
22 | - example: rss
23 | type:
24 | $ref: "https://raw.githubusercontent.com/RSS3-Network/Protocol-Go/refs/heads/main/openapi/type/RSSType.yaml"
25 | platform:
26 | $ref: "./RSSPlatform.yaml"
27 | total_actions:
28 | description: The total number of actions within the activity.
29 | type: integer
30 | actions:
31 | description: The list of actions within the activity.
32 | items:
33 | $ref: "./RSSAction.yaml"
34 | type: array
35 | calldata:
36 | $ref: "./Calldata.yaml"
37 | fee:
38 | $ref: "./Fee.yaml"
39 | direction:
40 | $ref: "./ProtocolDirection.yaml"
41 | success:
42 | $ref: "./Success.yaml"
43 | timestamp:
44 | $ref: "./Timestamp.yaml"
45 |
46 |
47 |
48 | type: object
49 | required:
50 | - id
51 | - network
52 | - index
53 | - from
54 | - to
55 | - tag
56 | - type
57 | - total_actions
58 | - actions
59 | - success
60 | - timestamp
--------------------------------------------------------------------------------
/deploy/default/config.default.yaml:
--------------------------------------------------------------------------------
1 | # Default configuration file for the RSS3 Node.
2 | environment: production
3 |
4 | discovery:
5 | operator:
6 | evm_address: 0x...address
7 | signature: 0x...signature
8 | server:
9 | endpoint: https://your.node.com
10 | global_indexer_endpoint: https://gi.rss3.io
11 | access_token: your_access_token
12 |
13 | database:
14 | uri: postgres://postgres:password@localhost:5432/postgres
15 |
16 | redis:
17 | endpoint: localhost:6379
18 | username:
19 | password:
20 |
21 | stream:
22 | enable: false
23 | uri: localhost:9092
24 |
25 | observability:
26 | opentelemetry:
27 | metrics:
28 | enable: false
29 | endpoint: 0.0.0.0:9090
30 | traces:
31 | enable: false
32 | endpoint: localhost:4318
33 | insecure: true
34 |
35 | endpoints:
36 | vsl:
37 | url: https://rpc.rss3.io
38 |
39 | component:
40 | rss:
41 | id: rsshub-core
42 | network: rsshub
43 | worker: core
44 | endpoint: https://your.rsshub.com/
45 | parameters:
46 | authentication:
47 | access_key:
48 | ai:
49 | id: agentdata-core
50 | worker: core
51 | endpoint: https://your.agentdata.com/
52 | parameters:
53 | agentdata_db_url:
54 | openai_api_key:
55 | ollama_host:
56 | kaito_api_token:
57 | twitter:
58 | bearer_token:
59 | api_key:
60 | api_secret:
61 | access_token:
62 | access_token_secret:
63 |
--------------------------------------------------------------------------------
/internal/engine/task.go:
--------------------------------------------------------------------------------
1 | package engine
2 |
3 | import (
4 | "time"
5 |
6 | activityx "github.com/rss3-network/protocol-go/schema/activity"
7 | "github.com/rss3-network/protocol-go/schema/network"
8 | "github.com/samber/lo"
9 | "go.opentelemetry.io/otel/attribute"
10 | "go.opentelemetry.io/otel/propagation"
11 | )
12 |
13 | type Task interface {
14 | ID() string
15 | GetNetwork() network.Network
16 | GetTimestamp() uint64
17 | Validate() error
18 | BuildActivity(options ...activityx.Option) (*activityx.Activity, error)
19 | }
20 |
21 | func BuildTaskTraceAttributes(task Task) []attribute.KeyValue {
22 | return []attribute.KeyValue{
23 | attribute.String("task.id", task.ID()),
24 | attribute.Stringer("task.network", task.GetNetwork()),
25 | attribute.Stringer("task.timestamp", time.Unix(int64(task.GetTimestamp()), 0)),
26 | }
27 | }
28 |
29 | var _ propagation.TextMapCarrier = (*Tasks)(nil)
30 |
31 | type Tasks struct {
32 | Tasks []Task
33 |
34 | // metadata is used to store OpenTelemetry trace context.
35 | metadata map[string]string
36 | }
37 |
38 | func (t *Tasks) Get(key string) string {
39 | return t.metadata[key]
40 | }
41 |
42 | func (t *Tasks) Set(key string, value string) {
43 | if t.metadata == nil {
44 | t.metadata = make(map[string]string)
45 | }
46 |
47 | t.metadata[key] = value
48 | }
49 |
50 | func (t *Tasks) Keys() []string {
51 | return lo.Keys(t.metadata)
52 | }
53 |
54 | func (t *Tasks) Len() int {
55 | return len(t.Tasks)
56 | }
57 |
--------------------------------------------------------------------------------
/internal/telemetry/meter/meter.go:
--------------------------------------------------------------------------------
1 | package meter
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 | "net/http"
7 |
8 | "github.com/labstack/echo/v4"
9 | "github.com/labstack/echo/v4/middleware"
10 | "github.com/prometheus/client_golang/prometheus/promhttp"
11 | "github.com/rss3-network/node/v2/config"
12 | )
13 |
14 | var (
15 | ErrorUnsupportedDriver = errors.New("unsupported driver")
16 | )
17 |
18 | type Driver string
19 |
20 | const (
21 | DriverPrometheus Driver = "prometheus"
22 | )
23 |
24 | type Server interface {
25 | Run(config.OpenTelemetryMetricsConfig) error
26 | }
27 |
28 | var _ Server = (*server)(nil)
29 |
30 | type server struct {
31 | httpServer *echo.Echo
32 | }
33 |
34 | func (s *server) Run(config config.OpenTelemetryMetricsConfig) error {
35 | return s.httpServer.Start(config.Endpoint)
36 | }
37 |
38 | func New(driver Driver) (Server, error) {
39 | if driver != DriverPrometheus {
40 | return nil, fmt.Errorf("%w: %s", ErrorUnsupportedDriver, driver)
41 | }
42 |
43 | instance := server{
44 | httpServer: echo.New(),
45 | }
46 |
47 | instance.httpServer.HideBanner = true
48 | instance.httpServer.HidePort = true
49 |
50 | instance.httpServer.Use(middleware.CORSWithConfig(middleware.DefaultCORSConfig))
51 | instance.httpServer.GET("/metrics", echo.WrapHandler(promhttp.Handler()))
52 | instance.httpServer.GET("/healthcheck", func(c echo.Context) error {
53 | return c.String(http.StatusOK, "ok")
54 | })
55 |
56 | return &instance, nil
57 | }
58 |
--------------------------------------------------------------------------------
/docs/path/decentralized/account.yaml:
--------------------------------------------------------------------------------
1 | get:
2 | operationId: GetDecentralizedAccount
3 | summary: Get Account Activities
4 | description: This endpoint retrieves the activities associated with a specified account in the decentralized system. You can use various query parameters to filter and paginate the results, including limits on the number of activities and actions, timestamps, success status, direction, and more.
5 | tags:
6 | - Decentralized
7 | security:
8 | - bearerAuth: []
9 | parameters:
10 | - $ref: "../../parameters/path_account_decentralized.yaml"
11 | - $ref: "../../parameters/query_limit.yaml"
12 | - $ref: "../../parameters/query_action_limit.yaml"
13 | - $ref: "../../parameters/query_cursor.yaml"
14 | - $ref: "../../parameters/query_since_timestamp.yaml"
15 | - $ref: "../../parameters/query_until_timestamp.yaml"
16 | - $ref: "../../parameters/query_success.yaml"
17 | - $ref: "../../parameters/query_direction.yaml"
18 | - $ref: "../../parameters/query_network.yaml"
19 | - $ref: "../../parameters/query_tag.yaml"
20 | - $ref: "../../parameters/query_type.yaml"
21 | - $ref: "../../parameters/query_platform_decentralized.yaml"
22 | responses:
23 | '200':
24 | $ref: "../../responses/DecentralizedActivitiesResponse.yaml"
25 | '400':
26 | $ref: "../../responses/BadRequest.yaml"
27 | '404':
28 | $ref: "../../responses/NotFound.yaml"
29 | '500':
30 | $ref: "../../responses/InternalError.yaml"
--------------------------------------------------------------------------------
/docs/schemas/FederatedActivity.yaml:
--------------------------------------------------------------------------------
1 | properties:
2 | id:
3 | description: The unique identifier for the activity.
4 | type: string
5 | format: uri
6 | owner:
7 | $ref: "./FederatedAccount.yaml"
8 | network:
9 | allOf:
10 | - $ref: "./ProtocolNetwork.yaml"
11 | - example: mastodon
12 | index:
13 | description: The index of the activity in the list.
14 | type: integer
15 | from:
16 | $ref: "./FederatedAccount.yaml"
17 | to:
18 | $ref: "./FederatedAccount.yaml"
19 | tag:
20 | allOf:
21 | - $ref: "./ProtocolTag.yaml"
22 | - example: social
23 | type:
24 | $ref: "https://raw.githubusercontent.com/RSS3-Network/Protocol-Go/refs/heads/main/openapi/type/Social.yaml"
25 | platform:
26 | $ref: "./FederatedPlatform.yaml"
27 | total_actions:
28 | description: The total number of actions within the activity.
29 | type: integer
30 | actions:
31 | description: The list of actions within the activity.
32 | items:
33 | $ref: "./FederatedAction.yaml"
34 | type: array
35 | calldata:
36 | $ref: "./Calldata.yaml"
37 | fee:
38 | $ref: "./Fee.yaml"
39 | direction:
40 | $ref: "./ProtocolDirection.yaml"
41 | success:
42 | $ref: "./Success.yaml"
43 | timestamp:
44 | $ref: "./Timestamp.yaml"
45 |
46 |
47 |
48 | type: object
49 | required:
50 | - id
51 | - network
52 | - index
53 | - from
54 | - to
55 | - tag
56 | - type
57 | - total_actions
58 | - actions
59 | - success
60 | - timestamp
--------------------------------------------------------------------------------
/internal/engine/worker/ai/core/agentdata/worker.go:
--------------------------------------------------------------------------------
1 | package agentdata
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "net/http"
7 | "time"
8 |
9 | "github.com/rss3-network/node/v2/config"
10 | "github.com/rss3-network/node/v2/internal/engine"
11 | "github.com/rss3-network/protocol-go/schema"
12 | activityx "github.com/rss3-network/protocol-go/schema/activity"
13 | "github.com/rss3-network/protocol-go/schema/network"
14 | "github.com/rss3-network/protocol-go/schema/tag"
15 | )
16 |
17 | type Worker struct {
18 | config *config.File
19 | httpClient *http.Client
20 | }
21 |
22 | func (w *Worker) Name() string {
23 | return "AgentData"
24 | }
25 |
26 | func (w *Worker) Platform() string {
27 | return ""
28 | }
29 |
30 | func (w *Worker) Network() []network.Network {
31 | return nil
32 | }
33 |
34 | func (w *Worker) Tags() []tag.Tag {
35 | return nil
36 | }
37 |
38 | func (w *Worker) Types() []schema.Type {
39 | return nil
40 | }
41 |
42 | func (w *Worker) Filter() engine.DataSourceFilter {
43 | return nil
44 | }
45 |
46 | func (w *Worker) Transform(_ context.Context, _ engine.Task) (*activityx.Activity, error) {
47 | return nil, nil
48 | }
49 |
50 | func NewWorker(config *config.File) (engine.Worker, error) {
51 | w := &Worker{
52 | config: config,
53 | httpClient: &http.Client{
54 | Timeout: 30 * time.Second,
55 | },
56 | }
57 |
58 | if config.Component.AI == nil {
59 | return nil, fmt.Errorf("missing configuration for Component Agentdata")
60 | }
61 |
62 | return w, nil
63 | }
64 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/selector_test.go:
--------------------------------------------------------------------------------
1 | package contract_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/ethereum/go-ethereum/common/hexutil"
7 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
8 | "github.com/stretchr/testify/require"
9 | )
10 |
11 | func TestMethodID(t *testing.T) {
12 | t.Parallel()
13 |
14 | type arguments struct {
15 | value string
16 | }
17 |
18 | testcases := []struct {
19 | name string
20 | arguments arguments
21 | want require.ValueAssertionFunc
22 | wantError require.ErrorAssertionFunc
23 | }{
24 | {
25 | name: "implementation()",
26 | arguments: arguments{
27 | value: "implementation()",
28 | },
29 | want: func(t require.TestingT, value interface{}, _ ...interface{}) {
30 | methodID, ok := value.(string)
31 | require.True(t, ok)
32 |
33 | require.Equal(t, "0x5c60da1b", methodID)
34 | },
35 | },
36 | {
37 | name: "name()",
38 | arguments: arguments{
39 | value: "name()",
40 | },
41 | want: func(t require.TestingT, value interface{}, _ ...interface{}) {
42 | methodID, ok := value.(string)
43 | require.True(t, ok)
44 |
45 | require.Equal(t, "0x06fdde03", methodID)
46 | },
47 | },
48 | }
49 |
50 | for _, testcase := range testcases {
51 | testcase := testcase
52 |
53 | t.Run(testcase.name, func(t *testing.T) {
54 | t.Parallel()
55 |
56 | result := contract.MethodID(testcase.arguments.value)
57 | testcase.want(t, hexutil.Encode(result[:]))
58 | })
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/weth/contract.go:
--------------------------------------------------------------------------------
1 | package weth
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | "github.com/rss3-network/protocol-go/schema/network"
7 | )
8 |
9 | // WETH9 https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
10 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/WETH9.abi --pkg weth --type WETH9 --out contract_weth9.go
11 |
12 | var (
13 | AddressMainnet = common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")
14 | AddressOptimism = common.HexToAddress("0x4200000000000000000000000000000000000006")
15 | AddressGnosis = common.HexToAddress("0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1")
16 | AddressPolygon = common.HexToAddress("0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619")
17 | AddressCelo = common.HexToAddress("0x122013fd7dF1C6F636a5bb8f03108E876548b455")
18 | AddressArbitrumOne = common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1")
19 | AddressAvalanche = common.HexToAddress("0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB")
20 |
21 | EventHashDeposit = contract.EventHash("Deposit(address,uint256)")
22 | EventHashWithdrawal = contract.EventHash("Withdrawal(address,uint256)")
23 | )
24 |
25 | func IsWETH(chainID uint64, address common.Address) bool {
26 | switch chainID {
27 | case uint64(network.EthereumChainIDMainnet):
28 | return address == AddressMainnet
29 | default:
30 | return false
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/provider/ipfs/gateway_test.go:
--------------------------------------------------------------------------------
1 | package ipfs_test
2 |
3 | import (
4 | "context"
5 | "testing"
6 | "time"
7 |
8 | "github.com/rss3-network/node/v2/provider/ipfs"
9 | "github.com/stretchr/testify/require"
10 | )
11 |
12 | func TestGetGatewayURLs(t *testing.T) {
13 | t.Parallel()
14 |
15 | type arguments struct {
16 | ctx context.Context
17 | timeout time.Duration
18 | gatewayList string
19 | }
20 |
21 | testcases := []struct {
22 | name string
23 | arguments arguments
24 | want require.ValueAssertionFunc
25 | wantError require.ErrorAssertionFunc
26 | }{
27 | {
28 | name: "Default gateway list",
29 | arguments: arguments{
30 | ctx: context.Background(),
31 | timeout: ipfs.DefaultTimeout,
32 | gatewayList: ipfs.DefaultGatewayList,
33 | },
34 | want: func(t require.TestingT, value interface{}, _ ...interface{}) {
35 | gatewayURLs, ok := value.([]string)
36 | require.True(t, ok)
37 |
38 | require.Greater(t, len(gatewayURLs), 0)
39 | },
40 | wantError: require.NoError,
41 | },
42 | }
43 |
44 | for _, testcase := range testcases {
45 | testcase := testcase
46 |
47 | t.Run(testcase.name, func(t *testing.T) {
48 | t.Parallel()
49 |
50 | ctx, cancel := context.WithTimeout(testcase.arguments.ctx, testcase.arguments.timeout)
51 | defer cancel()
52 |
53 | gatewayURLs, err := ipfs.FetchGateways(ctx, testcase.arguments.gatewayList)
54 | testcase.wantError(t, err)
55 | testcase.want(t, gatewayURLs)
56 | })
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/docs/requestBody/BatchGetFederatedAccountsActivities.yaml:
--------------------------------------------------------------------------------
1 | description: Request body for batch retrieving activities for multiple accounts
2 | required: true
3 | content:
4 | application/json:
5 | schema:
6 | type: object
7 | properties:
8 | accounts:
9 | type: array
10 | items:
11 | $ref: "../schemas/FederatedAccount.yaml"
12 | x-go-type-skip-optional-pointer: true
13 | limit:
14 | $ref: "../schemas/Limit.yaml"
15 | action_limit:
16 | $ref: "../schemas/ActionLimit.yaml"
17 | cursor:
18 | $ref: "../schemas/Cursor.yaml"
19 | since_timestamp:
20 | $ref: "../schemas/Timestamp.yaml"
21 | until_timestamp:
22 | $ref: "../schemas/Timestamp.yaml"
23 | success:
24 | $ref: "../schemas/Success.yaml"
25 | direction:
26 | $ref: "../schemas/ProtocolDirection.yaml"
27 | network:
28 | $ref: "../schemas/Networks.yaml"
29 | tag:
30 | $ref: "../schemas/Tags.yaml"
31 | type:
32 | items:
33 | allOf:
34 | - $ref: "../schemas/ProtocolType.yaml"
35 | - x-go-type: string
36 | type: array
37 | x-go-type-skip-optional-pointer: true
38 | platform:
39 | type: array
40 | items:
41 | $ref: "../schemas/FederatedPlatform.yaml"
42 | description: Retrieve activities from the specified platform(s)
43 | x-go-type-skip-optional-pointer: true
--------------------------------------------------------------------------------
/docs/requestBody/BatchGetDecentralizedAccountsActivities.yaml:
--------------------------------------------------------------------------------
1 | description: Request body for batch retrieving activities for multiple accounts
2 | required: true
3 | content:
4 | application/json:
5 | schema:
6 | type: object
7 | properties:
8 | accounts:
9 | type: array
10 | items:
11 | $ref: "../schemas/DecentralizedAccount.yaml"
12 | x-go-type-skip-optional-pointer: true
13 | limit:
14 | $ref: "../schemas/Limit.yaml"
15 | action_limit:
16 | $ref: "../schemas/ActionLimit.yaml"
17 | cursor:
18 | $ref: "../schemas/Cursor.yaml"
19 | since_timestamp:
20 | $ref: "../schemas/Timestamp.yaml"
21 | until_timestamp:
22 | $ref: "../schemas/Timestamp.yaml"
23 | success:
24 | $ref: "../schemas/Success.yaml"
25 | direction:
26 | $ref: "../schemas/ProtocolDirection.yaml"
27 | network:
28 | $ref: "../schemas/Networks.yaml"
29 | tag:
30 | $ref: "../schemas/Tags.yaml"
31 | type:
32 | items:
33 | allOf:
34 | - $ref: "../schemas/ProtocolType.yaml"
35 | - x-go-type: string
36 | type: array
37 | x-go-type-skip-optional-pointer: true
38 | platform:
39 | type: array
40 | items:
41 | $ref: "../schemas/DecentralizedPlatform.yaml"
42 | description: Retrieve activities from the specified platform(s)
43 | x-go-type-skip-optional-pointer: true
--------------------------------------------------------------------------------
/internal/database/model/activity.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "github.com/rss3-network/node/v2/schema/worker/decentralized"
5 | "github.com/rss3-network/protocol-go/schema"
6 | activityx "github.com/rss3-network/protocol-go/schema/activity"
7 | "github.com/rss3-network/protocol-go/schema/metadata"
8 | "github.com/rss3-network/protocol-go/schema/network"
9 | "github.com/rss3-network/protocol-go/schema/tag"
10 | )
11 |
12 | type ActivityQuery struct {
13 | ID *string
14 | Network *network.Network
15 | Owner *string
16 | ActionLimit int
17 | ActionPage int
18 | }
19 |
20 | type ActivitiesQuery struct {
21 | Owner *string
22 | Cursor *activityx.Activity
23 | Status *bool
24 | Direction *activityx.Direction
25 | StartTimestamp *uint64
26 | EndTimestamp *uint64
27 | Platform string
28 | Owners []string
29 | Network []network.Network
30 | Tags []tag.Tag
31 | Types []schema.Type
32 | Platforms []string
33 | Distinct *bool
34 | RelatedActions *bool
35 | Limit int
36 | ActionLimit int
37 | }
38 |
39 | type ActivitiesMetadataQuery struct {
40 | Network *network.Network
41 | Platform *decentralized.Platform
42 | Tag *tag.Tag
43 | Type *schema.Type
44 | Accounts []string
45 | Cursor *activityx.Activity
46 | Status *bool
47 | StartTimestamp *uint64
48 | EndTimestamp *uint64
49 | Limit int
50 | ActionLimit int
51 | Metadata *metadata.Metadata
52 | }
53 |
--------------------------------------------------------------------------------
/provider/arweave/gateway.go:
--------------------------------------------------------------------------------
1 | package arweave
2 |
3 | //go:generate go run --mod=mod github.com/dmarkham/enumer --values --type=Gateway --linecomment --output gateway_string.go
4 | type Gateway uint
5 |
6 | const (
7 | GatewayArweave Gateway = iota // https://arweave.net/
8 | GatewayARIO // https://ar-io.dev/
9 | GatewayPermagate // https://permagate.io/
10 | GatewayLove4Src // https://love4src.com/
11 | GatewayARBR // https://arbr.pro/
12 | GatewayBobInstein // https://bobinstein.com/
13 | GatewayAleko0o // https://aleko0o.store/
14 | GatewaySulapan // https://sulapan.com/
15 | GatewayFllstck // https://arweave.fllstck.dev/
16 | GatewayBicem // https://bicem.xyz
17 | GatewayDilsinay // https://dilsinay.online/
18 | GatewayLostGame // https://lostgame.online/
19 | GatewayKhalDrogo // https://khaldrogo.site/
20 | GatewayDasamuka // https://dasamuka.cloud/
21 | GatewayArendor // http://arendor.xyz/
22 | GatewayVelaryon // https://velaryon.xyz/
23 | )
24 |
25 | var DefaultGateways = []string{
26 | GatewayArweave.String(),
27 | GatewayARIO.String(),
28 | GatewayPermagate.String(),
29 | GatewayLove4Src.String(),
30 | GatewayARBR.String(),
31 | GatewayBobInstein.String(),
32 | GatewayAleko0o.String(),
33 | GatewaySulapan.String(),
34 | GatewayFllstck.String(),
35 | GatewayBicem.String(),
36 | }
37 |
--------------------------------------------------------------------------------
/internal/engine/protocol/farcaster/task.go:
--------------------------------------------------------------------------------
1 | package farcaster
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/ethereum/go-ethereum/common"
7 | "github.com/rss3-network/node/v2/internal/engine"
8 | "github.com/rss3-network/node/v2/provider/farcaster"
9 | activityx "github.com/rss3-network/protocol-go/schema/activity"
10 | "github.com/rss3-network/protocol-go/schema/network"
11 | "github.com/rss3-network/protocol-go/schema/typex"
12 | )
13 |
14 | var _ engine.Task = (*Task)(nil)
15 |
16 | type Task struct {
17 | Network network.Network
18 | Message farcaster.Message
19 | }
20 |
21 | func (t Task) ID() string {
22 | return fmt.Sprintf("%s.%s", t.Network, t.Message.Hash)
23 | }
24 |
25 | func (t Task) GetNetwork() network.Network {
26 | return t.Network
27 | }
28 |
29 | func (t Task) GetTimestamp() uint64 {
30 | return uint64(farcaster.CovertFarcasterTimeToTimestamp(int64(t.Message.Data.Timestamp)))
31 | }
32 |
33 | func (t Task) Validate() error {
34 | return nil
35 | }
36 |
37 | func (t Task) BuildActivity(options ...activityx.Option) (*activityx.Activity, error) {
38 | activity := activityx.Activity{
39 | ID: common.HexToHash(t.Message.Hash).String(),
40 | Network: t.Network,
41 | Type: typex.Unknown,
42 | Status: true,
43 | Actions: make([]*activityx.Action, 0),
44 | Timestamp: t.GetTimestamp(),
45 | }
46 |
47 | // Apply activity options.
48 | for _, option := range options {
49 | if err := option(&activity); err != nil {
50 | return nil, fmt.Errorf("apply option: %w", err)
51 | }
52 | }
53 |
54 | return &activity, nil
55 | }
56 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/arbitrum/abi/L1ERC20Gateway.abi:
--------------------------------------------------------------------------------
1 | [{"inputs":[{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"admin_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]
2 |
--------------------------------------------------------------------------------
/internal/utils/utils.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "math/big"
7 |
8 | "github.com/rss3-network/protocol-go/schema"
9 | "github.com/rss3-network/protocol-go/schema/metadata"
10 | "github.com/rss3-network/protocol-go/schema/tag"
11 | )
12 |
13 | // GetBigInt returns the value if not nil, otherwise returns big.NewInt(0)
14 | func GetBigInt(value *big.Int) *big.Int {
15 | if value == nil {
16 | return big.NewInt(0)
17 | }
18 |
19 | return value
20 | }
21 |
22 | // ParseTypes parses the types and returns the schema types
23 | func ParseTypes(types []string, tags []tag.Tag) ([]schema.Type, error) {
24 | if len(tags) == 0 {
25 | return nil, nil
26 | }
27 |
28 | schemaTypes := make([]schema.Type, 0)
29 |
30 | for _, typex := range types {
31 | var (
32 | value schema.Type
33 | err error
34 | )
35 |
36 | for _, tagx := range tags {
37 | value, err = schema.ParseTypeFromString(tagx, typex)
38 | if err == nil {
39 | schemaTypes = append(schemaTypes, value)
40 |
41 | break
42 | }
43 | }
44 |
45 | if err != nil {
46 | return nil, fmt.Errorf("invalid type: %s", typex)
47 | }
48 | }
49 |
50 | return schemaTypes, nil
51 | }
52 |
53 | // ParseMetadata parses the metadata and returns the schema metadata
54 | func ParseMetadata(metadataJSON json.RawMessage, typex schema.Type) (metadata.Metadata, error) {
55 | if len(metadataJSON) == 0 {
56 | return nil, nil
57 | }
58 |
59 | value, err := metadata.Unmarshal(typex, metadataJSON)
60 | if err != nil {
61 | return nil, err
62 | }
63 |
64 | return value, nil
65 | }
66 |
--------------------------------------------------------------------------------
/docs/schemas/ComponentInfo.yaml:
--------------------------------------------------------------------------------
1 | example:
2 | decentralized:
3 | - index_count: 1174
4 | indexed_state: 20416808
5 | network: ethereum
6 | platform: VSL
7 | remote_state: 20416809
8 | status: Ready
9 | tags:
10 | - transaction
11 | worker: vsl
12 | worker_id: ethereum-core
13 | - index_count: 2138457
14 | indexed_state: 59974383
15 | network: polygon
16 | platform: Curve
17 | remote_state: 59974392
18 | status: Ready
19 | tags:
20 | - exchange
21 | - transaction
22 | worker: curve
23 | worker_id: polygon-curve
24 | - index_count: 697886
25 | indexed_state: 1475385
26 | network: arweave
27 | platform: Mirror
28 | remote_state: 1475386
29 | status: Ready
30 | tags:
31 | - social
32 | worker: mirror
33 | worker_id: arweave-mirror
34 | federated:
35 | - indexed_state: 0
36 | network: mastodon
37 | platform: mastodon
38 | remote_state: 0
39 | status: Ready
40 | tags:
41 | - social
42 | worker: mastodon
43 | worker_id: mastodon-core
44 | rss:
45 | indexed_state: 0
46 | network: rss
47 | platform: Unknown
48 | remote_state: 0
49 | status: Ready
50 | tags:
51 | - rss
52 | worker: rsshub
53 | properties:
54 | decentralized:
55 | description: The decentralized worker status.
56 | items:
57 | $ref: "./WorkerInfo.yaml"
58 | type: array
59 | federated:
60 | description: The federated worker status.
61 | items:
62 | $ref: "./WorkerInfo.yaml"
63 | type: array
64 | rss:
65 | $ref: "./WorkerInfo.yaml"
66 | type: object
67 |
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/contract/crossbell/schema.go:
--------------------------------------------------------------------------------
1 | package crossbell
2 |
3 | import (
4 | "encoding/json"
5 | "time"
6 | )
7 |
8 | type NoteContent struct {
9 | Type string `json:"type"`
10 | Tags []string `json:"tags"`
11 | Authors []string `json:"authors"`
12 | Title string `json:"title"`
13 | Content string `json:"content"`
14 | Attachments []NoteContentAttachment `json:"attachments"`
15 | Sources []string `json:"sources"`
16 | ExternalUrls []string `json:"external_urls"`
17 | DatePublished time.Time `json:"date_published"`
18 | }
19 |
20 | type NoteContentAttachment struct {
21 | Name string `json:"name"`
22 | Address string `json:"address"`
23 | MimeType string `json:"mime_type"`
24 | SizeInBytes int `json:"size_in_bytes"`
25 | Alt string `json:"alt"`
26 | Width int `json:"width"`
27 | }
28 |
29 | type CharacterURIContent struct {
30 | Avatars []string `json:"avatars"`
31 | Bio string `json:"bio"`
32 | ConnectedAccounts json.RawMessage `json:"connected_accounts"`
33 | Name string `json:"name"`
34 | }
35 |
36 | type ProfileURIContent struct {
37 | ConnectedAccounts json.RawMessage `json:"connected_accounts"`
38 | ConnectedAvatars []string `json:"connected_avatars"`
39 | Name string `json:"name"`
40 | Bio string `json:"bio"`
41 | Type string `json:"type"`
42 | }
43 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/polymarket/contract.go:
--------------------------------------------------------------------------------
1 | package polymarket
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | // CTF Exchange
9 | // https://polygonscan.com/address/0x4bfb41d5b3570defd03c39a9a4d8de6bd8b8982e
10 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/CTFExchange.abi --pkg polymarket --type CTFExchange --out contract_ctf_exchange.go
11 | // Neg Risk CTF Exchange
12 | // https://polygonscan.com/address/0xc5d563a36ae78145c45a50134d48a1215220f80a
13 | // go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/NegRiskCTFExchange.abi --pkg polymarket --type NegRiskCTFExchange --out contract_neg_risk_ctf_exchange.go
14 | // Condition Tokens
15 | // https://polygonscan.com/address/0x4D97DCd97eC945f40cF65F87097ACe5EA0476045
16 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/ConditionTokens.abi --pkg polymarket --type ConditionTokens --out contract_condition_tokens.go
17 |
18 | var (
19 | AddressPolyMarketCTFExchange = common.HexToAddress("0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E")
20 | AddressPolyMarketNegRiskCTFExchange = common.HexToAddress("0xC5d563A36AE78145C45a50134d48A1215220f80a")
21 | AddressPolyMarketConditionTokens = common.HexToAddress("0x4D97DCd97eC945f40cF65F87097ACe5EA0476045")
22 |
23 | // EventOrderMatched = contract.EventHash("OrdersMatched(bytes32,address,uint256,uint256,uint256,uint256)")
24 | EventOrderFinalized = contract.EventHash("OrderFilled(bytes32,address,address,uint256,uint256,uint256,uint256,uint256)")
25 | )
26 |
--------------------------------------------------------------------------------
/internal/engine/worker/decentralized/contract/nearsocial/schema.go:
--------------------------------------------------------------------------------
1 | package nearsocial
2 |
3 | type FunctionCallArgs struct {
4 | Data map[string]UserContent `json:"data"`
5 | }
6 |
7 | type UserContent struct {
8 | Index map[string]string `json:"index,omitempty"`
9 | Post map[string]string `json:"post,omitempty"`
10 | }
11 |
12 | type IndexData struct {
13 | Key IndexKey `json:"key"`
14 | Value IndexValue `json:"value"`
15 | }
16 |
17 | type RepostIndexData []struct {
18 | Key interface{} `json:"key"`
19 | Value struct {
20 | Type string `json:"type"`
21 | Item *struct {
22 | Type string `json:"type"`
23 | Path string `json:"path"`
24 | BlockHeight int64 `json:"blockHeight"`
25 | } `json:"item,omitempty"`
26 | } `json:"value"`
27 | }
28 |
29 | type IndexKey struct {
30 | Type string `json:"type"`
31 | Path string `json:"path,omitempty"`
32 | BlockHeight int64 `json:"blockHeight,omitempty"`
33 | }
34 |
35 | type IndexValue struct {
36 | Type string `json:"type"`
37 | Path string `json:"path,omitempty"`
38 | Item *Item `json:"item,omitempty"`
39 | }
40 |
41 | type Item struct {
42 | Type string `json:"type"`
43 | Path string `json:"path"`
44 | BlockHeight int64 `json:"blockHeight,omitempty"`
45 | }
46 |
47 | type PostData struct {
48 | Type string `json:"type"`
49 | Text string `json:"text,omitempty"`
50 | Item *Item `json:"item,omitempty"`
51 | }
52 |
53 | type HashtagData struct {
54 | Key string `json:"key"`
55 | Value HashtagValue `json:"value"`
56 | }
57 |
58 | type HashtagValue struct {
59 | Type string `json:"type"`
60 | Path string `json:"path"`
61 | }
62 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/rainbow/contract.go:
--------------------------------------------------------------------------------
1 | package rainbow
2 |
3 | import (
4 | "math/big"
5 |
6 | "github.com/ethereum/go-ethereum/common"
7 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
8 | )
9 |
10 | // Router https://etherscan.io/address/0x00000000009726632680fb29d3f7a9734e3010e2
11 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/Router.abi --pkg rainbow --type Router --out contract_router.go
12 |
13 | var (
14 | AddressRouter = common.HexToAddress("0x00000000009726632680FB29d3F7A9734E3010E2")
15 |
16 | MethodIDRouterFillQuoteEthToToken = contract.MethodID("fillQuoteEthToToken(address,address,bytes,uint256)")
17 | MethodIDRouterFillQuoteTokenToEth = contract.MethodID("fillQuoteTokenToEth(address,address,bytes,uint256,uint256)")
18 | MethodIDRouterFillQuoteTokenToToken = contract.MethodID("fillQuoteTokenToToken(address,address,address,bytes,uint256,uint256)")
19 | )
20 |
21 | type RouterFillQuoteEthToTokenInput struct {
22 | BuyTokenAddress common.Address
23 | Target common.Address
24 | SwapCallData []byte
25 | FeeAmount *big.Int
26 | }
27 |
28 | type RouterFillQuoteTokenToEthInput struct {
29 | SellTokenAddress common.Address
30 | Target common.Address
31 | SwapCallData []byte
32 | SellAmount *big.Int
33 | FeePercentageBasisPoints *big.Int
34 | }
35 |
36 | type RouterFillQuoteTokenToTokenInput struct {
37 | SellTokenAddress common.Address
38 | BuyTokenAddress common.Address
39 | Target common.Address
40 | SwapCallData []byte
41 | SellAmount *big.Int
42 | FeeAmount *big.Int
43 | }
44 |
--------------------------------------------------------------------------------
/internal/telemetry/tracer/tracer.go:
--------------------------------------------------------------------------------
1 | package tracer
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "os"
7 |
8 | "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
9 | "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
10 | "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
11 | "go.opentelemetry.io/otel/sdk/trace"
12 | )
13 |
14 | type Driver string
15 |
16 | const (
17 | DriverLocal Driver = "local"
18 | DriverOpenTelemetryProtocol Driver = "otlp"
19 | )
20 |
21 | func Open(driver Driver, endpoint string, insecure bool) (trace.SpanExporter, error) {
22 | switch driver {
23 | case DriverOpenTelemetryProtocol:
24 | return openOpenTelemetryProtocolExporter(endpoint, insecure)
25 | case DriverLocal:
26 | fallthrough
27 | default:
28 | return openLocalExporter(endpoint, insecure)
29 | }
30 | }
31 |
32 | func openOpenTelemetryProtocolExporter(endpoint string, insecure bool) (exporter trace.SpanExporter, err error) {
33 | options := []otlptracehttp.Option{
34 | otlptracehttp.WithEndpoint(endpoint),
35 | }
36 |
37 | if insecure {
38 | options = append(options, otlptracehttp.WithInsecure())
39 | }
40 |
41 | return otlptrace.New(context.Background(), otlptracehttp.NewClient(options...))
42 | }
43 |
44 | func openLocalExporter(path string, _ bool) (exporter trace.SpanExporter, err error) {
45 | file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, os.ModePerm)
46 | if err != nil {
47 | return nil, fmt.Errorf("open local exporter file: %w", err)
48 | }
49 |
50 | return stdouttrace.New(
51 | stdouttrace.WithWriter(file),
52 | stdouttrace.WithPrettyPrint(),
53 | stdouttrace.WithoutTimestamps(),
54 | )
55 | }
56 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/ens/contract_test.go:
--------------------------------------------------------------------------------
1 | package ens_test
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/ethereum/go-ethereum/common"
7 | "github.com/rss3-network/node/v2/provider/ethereum/contract/ens"
8 | "github.com/stretchr/testify/require"
9 | )
10 |
11 | func TestNameHash(t *testing.T) {
12 | t.Parallel()
13 |
14 | type arguments struct {
15 | name string
16 | }
17 |
18 | testcases := []struct {
19 | name string
20 | arguments arguments
21 | want common.Hash
22 | }{
23 | {
24 | name: "vitalik.eth",
25 | arguments: arguments{
26 | name: "vitalik.eth",
27 | },
28 | want: common.HexToHash("0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835"),
29 | },
30 | {
31 | name: "planetable.eth",
32 | arguments: arguments{
33 | name: "planetable.eth",
34 | },
35 | want: common.HexToHash("0x7b26d27abaced593c582148f2eb315e57ff6bf40bbf81da5326b3055c395a7bd"),
36 | },
37 | {
38 | name: "liuguo.eth",
39 | arguments: arguments{
40 | name: "liuguo.eth",
41 | },
42 | want: common.HexToHash("0xd9fe12401ccda681464d15a7094bf8f7efc16dcc56d4098c466dd7d0c84030c0"),
43 | },
44 | {
45 | name: "kallydev.eth",
46 | arguments: arguments{
47 | name: "kallydev.eth",
48 | },
49 | want: common.HexToHash("0x8236bd8890989e1af9188cbdad0776c6eb09640f5ab61a70d4171dc066e42f19"),
50 | },
51 | }
52 |
53 | for _, testcase := range testcases {
54 | testcase := testcase
55 |
56 | t.Run(testcase.name, func(t *testing.T) {
57 | t.Parallel()
58 |
59 | node := ens.NameHash(testcase.arguments.name)
60 |
61 | require.Equal(t, node, testcase.want)
62 | })
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: 🍭 Feature Request
2 | description: Submit a new feature request
3 | labels: ['enhancement']
4 |
5 | body:
6 |
7 | - type: markdown
8 | attributes:
9 | value: |
10 | Please ensure the feature requested is not listed in [issue](https://github.com/rss3-network/node/issues), and is not a [New Worker](https://github.com/rss3-network/node/issues/new?assignees=&labels=worker&projects=&template=worker_coverage.yml), and provide all the information required by this template.
11 | Otherwise the issue will be closed immediately.
12 |
13 | - type: textarea
14 | id: feature
15 | attributes:
16 | label: What feature is it?
17 | placeholder: Please describe the feature you want to see.
18 | validations:
19 | required: true
20 |
21 | - type: textarea
22 | id: problem
23 | attributes:
24 | label: What problem does this feature solve?
25 | placeholder: Please describe the problem this feature solves.
26 | validations:
27 | required: true
28 |
29 | - type: textarea
30 | id: description
31 | attributes:
32 | label: Additional description
33 | placeholder: Any additional description.
34 |
35 | - type: checkboxes
36 | id: terms
37 | attributes:
38 | label: This is not a duplicated feature request or new worker proposal
39 | options:
40 | - label: I have searched [existing issues](https://github.com/rss3-network/node/issues) to ensure this feature has not already been requested and this is not a [New Worker](https://github.com/rss3-network/node/issues/new?assignees=&labels=worker&projects=&template=worker_coverage.yml).
41 | required: true
42 |
--------------------------------------------------------------------------------
/common/sync/quickgroup_test.go:
--------------------------------------------------------------------------------
1 | package sync
2 |
3 | import (
4 | "context"
5 | "testing"
6 | "time"
7 |
8 | "github.com/samber/lo"
9 | "github.com/stretchr/testify/require"
10 | )
11 |
12 | func TestQuickGroup(t *testing.T) {
13 | t.Parallel()
14 |
15 | quickGroup := NewQuickGroup[time.Duration](context.Background())
16 |
17 | for duration := time.Second; duration > 0; duration -= 100 * time.Millisecond {
18 | duration := duration
19 |
20 | task := func(ctx context.Context) (time.Duration, error) {
21 | timer := time.NewTimer(duration)
22 | defer timer.Stop()
23 |
24 | select {
25 | case <-ctx.Done():
26 | t.Logf("Task %s: %s", duration, context.Canceled)
27 |
28 | return duration, context.Canceled
29 | case <-timer.C:
30 | t.Logf("Task %s: %s", duration, "done")
31 |
32 | return duration, nil
33 | }
34 | }
35 |
36 | quickGroup.Go(task)
37 | }
38 |
39 | result, err := quickGroup.Wait()
40 | require.NoError(t, err)
41 | require.Equal(t, result, 100*time.Millisecond)
42 | }
43 |
44 | // TestQuickGroupDataRace checks if any data race exists for QuickGroup.
45 | func TestQuickGroupDataRace(t *testing.T) {
46 | t.Parallel()
47 |
48 | quickGroup := NewQuickGroup[bool](context.Background())
49 |
50 | for range lo.Range(10000) {
51 | task := func(ctx context.Context) (bool, error) {
52 | timer := time.NewTimer(time.Second)
53 | defer timer.Stop()
54 |
55 | select {
56 | case <-ctx.Done():
57 | return false, context.Canceled
58 | case <-timer.C:
59 | return true, nil
60 | }
61 | }
62 |
63 | quickGroup.Go(task)
64 | }
65 |
66 | result, err := quickGroup.Wait()
67 | require.NoError(t, err)
68 | require.Equal(t, result, true)
69 | }
70 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/benddao/contract.go:
--------------------------------------------------------------------------------
1 | package benddao
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | //go:generate go run -mod=mod github.com/ethereum/go-ethereum/cmd/abigen@v1.13.5 --abi ./abi/BendExchange.abi --pkg benddao --type BendExchange --out ./contract_bend_exchange.go
9 | //go:generate go run -mod=mod github.com/ethereum/go-ethereum/cmd/abigen@v1.13.5 --abi ./abi/LendPool.abi --pkg benddao --type LendPool --out ./contract_lend_pool.go
10 |
11 | var (
12 | AddressBendExchange = common.HexToAddress("0x7e832eC8ad6F66E6C9ECE63acD94516Dd7fC537A")
13 | AddressLendPool = common.HexToAddress("0x70b97A0da65C15dfb0FFA02aEE6FA36e507C2762")
14 |
15 | EventTakerAsk = contract.EventHash("TakerAsk(bytes32,uint256,address,address,address,address,address,uint256,uint256,uint256)")
16 | EventTakerBid = contract.EventHash("TakerBid(bytes32,uint256,address,address,address,address,address,uint256,uint256,uint256)")
17 |
18 | EventDeposit = contract.EventHash("Deposit(address,address,uint256,address,uint16)")
19 | EventWithdraw = contract.EventHash("Withdraw(address,address,uint256,address)")
20 | EventBorrow = contract.EventHash("Borrow(address,address,uint256,address,uint256,address,uint256,uint256,uint16)")
21 | EventRepay = contract.EventHash("Repay(address,address,uint256,address,uint256,address,uint256)")
22 | EventAuction = contract.EventHash("Auction(address,address,uint256,address,uint256,address,address,uint256)")
23 | EventRedeem = contract.EventHash("Redeem(address,address,uint256,uint256,address,uint256,address,uint256)")
24 | EventLiquidate = contract.EventHash("Liquidate(address,address,uint256,uint256,address,uint256,address,uint256)")
25 | )
26 |
--------------------------------------------------------------------------------
/docs/requestBody/BatchGetDecentralizedMetadataActivities.yaml:
--------------------------------------------------------------------------------
1 | description: Request body for batch retrieving activities for specified metadata, network and tag and type is required
2 | required: true
3 | content:
4 | application/json:
5 | schema:
6 | type: object
7 | properties:
8 | accounts:
9 | type: array
10 | items:
11 | $ref: "../schemas/DecentralizedAccount.yaml"
12 | x-go-type-skip-optional-pointer: true
13 | limit:
14 | $ref: "../schemas/Limit.yaml"
15 | action_limit:
16 | $ref: "../schemas/ActionLimit.yaml"
17 | cursor:
18 | $ref: "../schemas/Cursor.yaml"
19 | since_timestamp:
20 | $ref: "../schemas/Timestamp.yaml"
21 | until_timestamp:
22 | $ref: "../schemas/Timestamp.yaml"
23 | success:
24 | $ref: "../schemas/Success.yaml"
25 | network:
26 | type: object
27 | allOf:
28 | - $ref: "../schemas/ProtocolNetwork.yaml"
29 | x-oapi-codegen-extra-tags:
30 | validate: "required"
31 | tag:
32 | type: object
33 | allOf:
34 | - $ref: "../schemas/ProtocolTag.yaml"
35 | x-oapi-codegen-extra-tags:
36 | validate: "required"
37 | type:
38 | type: string
39 | allOf:
40 | - $ref: "../schemas/ProtocolType.yaml"
41 | x-oapi-codegen-extra-tags:
42 | validate: "required"
43 | platform:
44 | $ref: "../schemas/DecentralizedPlatform.yaml"
45 | metadata:
46 | type: object
47 | allOf:
48 | - $ref: "../schemas/ProtocolMetadata.yaml"
49 | x-oapi-codegen-extra-tags:
50 | validate: "required"
51 |
--------------------------------------------------------------------------------
/internal/engine/protocol/factory.go:
--------------------------------------------------------------------------------
1 | package protocol
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/redis/rueidis"
7 | "github.com/rss3-network/node/v2/config"
8 | "github.com/rss3-network/node/v2/internal/database"
9 | "github.com/rss3-network/node/v2/internal/engine"
10 | "github.com/rss3-network/node/v2/internal/engine/protocol/activitypub"
11 | "github.com/rss3-network/node/v2/internal/engine/protocol/arweave"
12 | "github.com/rss3-network/node/v2/internal/engine/protocol/atproto"
13 | "github.com/rss3-network/node/v2/internal/engine/protocol/ethereum"
14 | "github.com/rss3-network/node/v2/internal/engine/protocol/farcaster"
15 | "github.com/rss3-network/node/v2/internal/engine/protocol/near"
16 | "github.com/rss3-network/protocol-go/schema/network"
17 | )
18 |
19 | // New creates a new protocol.
20 | func New(config *config.Module, sourceFilter engine.DataSourceFilter, checkpoint *engine.Checkpoint, databaseClient database.Client, redisClient rueidis.Client) (engine.DataSource, error) {
21 | switch config.Network.Protocol() {
22 | case network.EthereumProtocol:
23 | return ethereum.NewSource(config, sourceFilter, checkpoint, redisClient)
24 | case network.ArweaveProtocol:
25 | return arweave.NewSource(config, sourceFilter, checkpoint, redisClient)
26 | case network.FarcasterProtocol:
27 | return farcaster.NewSource(config, checkpoint, databaseClient)
28 | case network.ActivityPubProtocol:
29 | return activitypub.NewSource(config, checkpoint, databaseClient)
30 | case network.NearProtocol:
31 | return near.NewSource(config, sourceFilter, checkpoint, redisClient)
32 | case network.ATProtocol:
33 | return atproto.NewSource(config, sourceFilter, checkpoint, databaseClient)
34 | default:
35 | return nil, fmt.Errorf("unsupported network protocol %s", config.Network)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/paraswap/contract.go:
--------------------------------------------------------------------------------
1 | package paraswap
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | // Paraswap V5 https://etherscan.io/address/0xdef171fe48cf0115b1d80b88dc8eab59176fee57
9 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/V5ParaSwap.abi --pkg paraswap --type V5ParaSwap --out contract_v5_paraswap.go
10 |
11 | // https://developers.paraswap.network/smart-contracts
12 | var (
13 | AddressV5ParaSwap = common.HexToAddress("0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57")
14 | AddressV5ParaSwapArbitrum = common.HexToAddress("0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57")
15 | AddressV5ParaSwapAvalanche = common.HexToAddress("0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57")
16 | AddressV5ParaSwapBase = common.HexToAddress("0x59C7C832e96D2568bea6db468C1aAdcbbDa08A52")
17 | AddressV5ParaSwapBinanceSmartChain = common.HexToAddress("0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57")
18 | AddressV5ParaSwapOptimism = common.HexToAddress("0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57")
19 | AddressV5ParaSwapPolygon = common.HexToAddress("0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57")
20 |
21 | AddressETH = common.HexToAddress("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE")
22 |
23 | EventHashV3Swapped = contract.EventHash("SwappedV3(bytes16,address,uint256,address,address,address,address,uint256,uint256,uint256)")
24 | EventHashV3Bought = contract.EventHash("BoughtV3(bytes16,address,uint256,address,address,address,address,uint256,uint256,uint256)")
25 | EventHashSwappedDirect = contract.EventHash("SwappedDirect(bytes16,address,uint256,address,uint8,address,address,address,uint256,uint256,uint256)")
26 | )
27 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/selector.go:
--------------------------------------------------------------------------------
1 | package contract
2 |
3 | import (
4 | "bytes"
5 |
6 | "github.com/ethereum/go-ethereum/common"
7 | "github.com/ethereum/go-ethereum/crypto"
8 | )
9 |
10 | // MethodID calculates the method ID of the function selector.
11 | func MethodID(method string) [4]byte {
12 | var (
13 | methodID [4]byte
14 | hash = crypto.Keccak256Hash([]byte(method))
15 | )
16 |
17 | copy(methodID[:], hash[:4])
18 |
19 | return methodID
20 | }
21 |
22 | // EventHash calculates the event hash of the event signature.
23 | func EventHash(event string) common.Hash {
24 | return crypto.Keccak256Hash([]byte(event))
25 | }
26 |
27 | // MatchMethodIDs checks if the input matches any of the method IDs.
28 | func MatchMethodIDs(input []byte, methodIDs ...[4]byte) bool {
29 | for _, methodID := range methodIDs {
30 | if bytes.HasPrefix(input, methodID[:]) {
31 | return true
32 | }
33 | }
34 |
35 | return false
36 | }
37 |
38 | // MatchEventHashes checks if the hash matches any of the event hashes.
39 | func MatchEventHashes(hash common.Hash, eventHashes ...common.Hash) bool {
40 | for _, eventHash := range eventHashes {
41 | if hash == eventHash {
42 | return true
43 | }
44 | }
45 |
46 | return false
47 | }
48 |
49 | // MatchAddresses checks if the address matches any of the addresses.
50 | func MatchAddresses(address common.Address, addresses ...common.Address) bool {
51 | for _, addr := range addresses {
52 | if address == addr {
53 | return true
54 | }
55 | }
56 |
57 | return false
58 | }
59 |
60 | // ContainsMethodIDs checks if the code contains all the method IDs.
61 | func ContainsMethodIDs(code []byte, methodIDs ...[4]byte) bool {
62 | for _, methodID := range methodIDs {
63 | if exists := bytes.Contains(code, methodID[:]); !exists {
64 | return exists
65 | }
66 | }
67 |
68 | return true
69 | }
70 |
--------------------------------------------------------------------------------
/provider/ipfs/url.go:
--------------------------------------------------------------------------------
1 | package ipfs
2 |
3 | import (
4 | "fmt"
5 | "net/url"
6 | "strings"
7 |
8 | "github.com/ipfs/go-cid"
9 | )
10 |
11 | func ParseURL(contentURL string) (endpoint, path string, err error) {
12 | parsedURL, err := url.Parse(contentURL)
13 | if err != nil {
14 | return "", "", fmt.Errorf("parse content url: %w", err)
15 | }
16 |
17 | if parsedURL.Scheme == "ipfs" || parsedURL.Scheme == "ipns" {
18 | ipfsCid := parsedURL.Host
19 | urlPath := fmt.Sprintf("%s%s", parsedURL.Host, parsedURL.Path)
20 |
21 | if ipfsCid == "ipfs" {
22 | ipfsCid = strings.Split(parsedURL.Path, "/")[1]
23 | urlPath = parsedURL.Path[1:]
24 | }
25 |
26 | if _, err := cid.Parse(ipfsCid); err != nil {
27 | return "", "", fmt.Errorf("invalid content id %s: %w", ipfsCid, err)
28 | }
29 |
30 | return "", fmt.Sprintf("/%s/%s", parsedURL.Scheme, urlPath), nil
31 | }
32 |
33 | // Path gateway
34 | if strings.HasPrefix(parsedURL.Path, "/ipfs/") || strings.HasPrefix(parsedURL.Path, "/ipns/") {
35 | contentID := strings.TrimPrefix(strings.TrimPrefix(parsedURL.Path, "/ipfs/"), "/ipns/")
36 |
37 | if _, err := cid.Parse(contentID); err != nil {
38 | return "", "", fmt.Errorf("invalid content id %s: %w", contentID, err)
39 | }
40 |
41 | return parsedURL.Host, parsedURL.Path, nil
42 | }
43 |
44 | // Subdomain gateway
45 | if splits := strings.Split(parsedURL.Host, "."); len(splits) >= 4 && (splits[1] == "ipfs" || splits[1] == "ipns") {
46 | contentID := splits[0]
47 |
48 | if _, err := cid.Parse(contentID); err != nil {
49 | return "", "", fmt.Errorf("invalid content id %s: %w", contentID, err)
50 | }
51 |
52 | return strings.Join(splits[2:], "."), fmt.Sprintf("/%s/%s%s", splits[1], contentID, parsedURL.Path), nil
53 | }
54 |
55 | // DNSLink gateway is not supported
56 |
57 | return "", "", fmt.Errorf("invalid content url %s", contentURL)
58 | }
59 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/base/contract.go:
--------------------------------------------------------------------------------
1 | package base
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | // OptimismPortal
9 | // https://etherscan.io/address/0x49048044D57e1C92A77f79988d21Fa8fAF74E97e
10 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/OptimismPortal.abi --pkg base --type OptimismPortal --out contract_optimism_portal.go
11 |
12 | // L1StandardBridge
13 | // https://etherscan.io/address/0x3154Cf16ccdb4C6d922629664174b904d80F2C35
14 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/L1StandardBridge.abi --pkg base --type L1StandardBridge --out contract_l1_standard_bridge.go
15 |
16 | var (
17 | AddressOptimismPortal = common.HexToAddress("0x49048044D57e1C92A77f79988d21Fa8fAF74E97e")
18 | AddressL1StandardBridge = common.HexToAddress("0x3154Cf16ccdb4C6d922629664174b904d80F2C35")
19 | AddressL2CrossDomainMessenger = common.HexToAddress("0x4200000000000000000000000000000000000007")
20 |
21 | EventHashOptimismPortalTransactionDeposited = contract.EventHash("TransactionDeposited(address,address,uint256,bytes)")
22 | EventHashOptimismPortalTransactionWithdrawalFinalized = contract.EventHash("WithdrawalFinalized(bytes32,bool)")
23 |
24 | EventHashL1StandardBridgeETHDepositInitiated = contract.EventHash("ETHDepositInitiated(address,address,uint256,bytes)")
25 | EventHashL1StandardBridgeERC20DepositInitiated = contract.EventHash("ERC20DepositInitiated(address,address,address,address,uint256,bytes)")
26 | EventHashL1StandardBridgeETHWithdrawalFinalized = contract.EventHash("ETHWithdrawalFinalized(address,address,uint256,bytes)")
27 | EventHashL1StandardBridgeERC20WithdrawalFinalized = contract.EventHash("ERC20WithdrawalFinalized(address,address,address,address,uint256,bytes)")
28 | )
29 |
--------------------------------------------------------------------------------
/provider/ethereum/contract/nouns/contract.go:
--------------------------------------------------------------------------------
1 | package nouns
2 |
3 | import (
4 | "github.com/ethereum/go-ethereum/common"
5 | "github.com/rss3-network/node/v2/provider/ethereum/contract"
6 | )
7 |
8 | // NounsAuctionHouseProxy https://etherscan.io/address/0x830BD73E4184ceF73443C15111a1DF14e495C706
9 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/NounsAuctionHouse.abi --pkg nouns --type NounsAuctionHouse --out nouns_auction_house.go
10 |
11 | // NounsDAOProxy https://etherscan.io/address/0x6f3E6272A167e8AcCb32072d08E0957F9c79223d
12 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/NounsDAO.abi --pkg nouns --type NounsDAO --out nouns_dao.go
13 |
14 | // NounsToken https://etherscan.io/address/0x9C8fF314C9Bc7F6e59A9d9225Fb22946427eDC03
15 | //go:generate go run --mod=mod github.com/ethereum/go-ethereum/cmd/abigen --abi ./abi/NounsToken.abi --pkg nouns --type NounsToken --out nouns_token.go
16 |
17 | var (
18 | AddressNouns = common.HexToAddress("0x9C8fF314C9Bc7F6e59A9d9225Fb22946427eDC03")
19 | AddressNounsAuction = common.HexToAddress("0x830BD73E4184ceF73443C15111a1DF14e495C706")
20 | AddressNounsDAO = common.HexToAddress("0x6f3E6272A167e8AcCb32072d08E0957F9c79223d")
21 |
22 | EventAuctionBid = contract.EventHash("AuctionBid(uint256,address,uint256,bool)")
23 | EventAuctionSettled = contract.EventHash("AuctionSettled(uint256,address,uint256)")
24 | EventAuctionCreated = contract.EventHash("AuctionCreated(uint256,uint256,uint256)")
25 | EventNounCreated = contract.EventHash("NounCreated(uint256,(uint48,uint48,uint48,uint48,uint48))")
26 | EventNounsProposal = contract.EventHash("ProposalCreatedWithRequirements(uint256,address,address[],uint256[],string[],bytes[],uint256,uint256,uint256,uint256,string)")
27 | EventNounsVote = contract.EventHash("VoteCast(address,uint256,uint8,uint256,string)")
28 | )
29 |
--------------------------------------------------------------------------------
/provider/redis/client.go:
--------------------------------------------------------------------------------
1 | package redis
2 |
3 | import (
4 | "crypto/tls"
5 | "crypto/x509"
6 | "fmt"
7 | "os"
8 |
9 | "github.com/redis/rueidis"
10 | "github.com/rss3-network/node/v2/config"
11 | )
12 |
13 | // NewClient creates a new Redis client.
14 | func NewClient(option config.Redis) (rueidis.Client, error) {
15 | clientOption := rueidis.ClientOption{
16 | InitAddress: []string{option.Endpoint},
17 | Username: option.Username,
18 | Password: option.Password,
19 | DisableCache: true,
20 | }
21 |
22 | // Enable TLS if it is configured
23 | if option.TLS.Enabled {
24 | tlsConfig, err := buildTLSConfig(option.TLS)
25 | if err != nil {
26 | return nil, fmt.Errorf("failed to build TLS config: %w", err)
27 | }
28 |
29 | clientOption.TLSConfig = tlsConfig
30 | }
31 |
32 | return rueidis.NewClient(clientOption)
33 | }
34 |
35 | // buildTLSConfig builds a TLS configuration from the given TLS configuration.
36 | func buildTLSConfig(tlsConfig config.RedisTLS) (*tls.Config, error) {
37 | tlsConf := &tls.Config{
38 | MinVersion: tls.VersionTLS12, // Set minimum TLS version to 1.2 to address G402 warning
39 | }
40 |
41 | if tlsConfig.CAFile != "" {
42 | caCert, err := os.ReadFile(tlsConfig.CAFile)
43 | if err != nil {
44 | return nil, fmt.Errorf("failed to read CA certificate file: %w", err)
45 | }
46 |
47 | caCertPool := x509.NewCertPool()
48 | caCertPool.AppendCertsFromPEM(caCert)
49 | tlsConf.RootCAs = caCertPool
50 | }
51 |
52 | if tlsConfig.CertFile != "" && tlsConfig.KeyFile != "" {
53 | cert, err := tls.LoadX509KeyPair(tlsConfig.CertFile, tlsConfig.KeyFile)
54 | if err != nil {
55 | return nil, fmt.Errorf("failed to load client certificate and key: %w", err)
56 | }
57 |
58 | tlsConf.Certificates = []tls.Certificate{cert}
59 | }
60 |
61 | tlsConf.InsecureSkipVerify = tlsConfig.InsecureSkipVerify
62 |
63 | return tlsConf, nil
64 | }
65 |
--------------------------------------------------------------------------------
/provider/near/client_test.go:
--------------------------------------------------------------------------------
1 | package near_test
2 |
3 | // func TestNearClient(t *testing.T) {
4 | // t.Parallel()
5 | //
6 | // ctx := context.Background()
7 | // endpoint := "https://archival-rpc.mainnet.near.org"
8 | //
9 | // client, err := near.Dial(ctx, endpoint)
10 | // require.NoError(t, err)
11 | //
12 | // t.Run("GetBlockHeight", func(t *testing.T) {
13 | // t.Parallel()
14 | //
15 | // blockHeight, err := client.GetBlockHeight(ctx)
16 | //
17 | // require.NoError(t, err)
18 | // require.Greater(t, blockHeight, int64(0))
19 | // })
20 | //
21 | // t.Run("BlockByHeight", func(t *testing.T) {
22 | // t.Parallel()
23 | //
24 | // blockHeight := big.NewInt(127103648)
25 | // block, err := client.BlockByHeight(ctx, blockHeight)
26 | //
27 | // require.NoError(t, err)
28 | // require.NotNil(t, block)
29 | // require.Equal(t, 127103648, block.Header.Height)
30 | // })
31 | //
32 | // t.Run("ChunkByHash", func(t *testing.T) {
33 | // t.Parallel()
34 | //
35 | // chunkID := "GWAab7TDaf5T8dfgJ2YrHHXgdEpJUdUS1Hmie2N2aWhw"
36 | // chunk, err := client.ChunkByHash(ctx, chunkID)
37 | //
38 | // require.NoError(t, err)
39 | // require.NotNil(t, chunk)
40 | // require.Equal(t, chunkID, chunk.Header.ChunkHash)
41 | // })
42 | //
43 | // t.Run("ChunkByHeight", func(t *testing.T) {
44 | // t.Parallel()
45 | //
46 | // blockHeight := big.NewInt(127170738)
47 | // shardID := 0
48 | // chunk, err := client.ChunkByHeight(ctx, blockHeight, shardID)
49 | //
50 | // require.NoError(t, err)
51 | // require.NotNil(t, chunk)
52 | // })
53 | //
54 | // t.Run("TransactionByHash", func(t *testing.T) {
55 | // t.Parallel()
56 | //
57 | // txHash := "9JCqrdN53VXiAVo9feEHY7FigiV1QYSyYuoXeTuee4eA"
58 | // senderID := "pseudoyu.tg"
59 | // tx, err := client.TransactionByHash(ctx, txHash, senderID)
60 | //
61 | // require.NoError(t, err)
62 | // require.NotNil(t, tx)
63 | // require.Equal(t, txHash, tx.Transaction.Hash)
64 | // })
65 | //}
66 |
--------------------------------------------------------------------------------
/internal/engine/protocol/near/option.go:
--------------------------------------------------------------------------------
1 | package near
2 |
3 | import (
4 | "fmt"
5 | "math/big"
6 | "time"
7 |
8 | "github.com/rss3-network/node/v2/config"
9 | "github.com/rss3-network/node/v2/config/parameter"
10 | "github.com/rss3-network/protocol-go/schema/network"
11 | "github.com/samber/lo"
12 | )
13 |
14 | const (
15 | defaultConcurrentBlockRequests = uint64(8)
16 | defaultRetryAttempts = uint(10)
17 | defaultRetryDelay = 500 * time.Millisecond
18 | )
19 |
20 | type Option struct {
21 | // BlockStart is the block height on Arweave that the worker should start from.
22 | BlockStart *big.Int `json:"block_start" mapstructure:"block_start"`
23 | // BlockTarget is the block height on Arweave that the worker should stop at.
24 | BlockTarget *big.Int `json:"block_target" mapstructure:"block_target"`
25 | // ConcurrentBlockRequests is the number of blocks to request concurrently.
26 | ConcurrentBlockRequests *uint64 `json:"concurrent_block_requests" mapstructure:"concurrent_block_requests"`
27 | }
28 |
29 | func NewOption(n network.Network, parameters *config.Parameters) (*Option, error) {
30 | var option Option
31 |
32 | if parameters == nil {
33 | return &Option{
34 | BlockStart: parameter.CurrentNetworkStartBlock[n].Block,
35 | ConcurrentBlockRequests: lo.ToPtr(defaultConcurrentBlockRequests),
36 | }, nil
37 | }
38 |
39 | if err := parameters.Decode(&option); err != nil {
40 | return nil, err
41 | }
42 |
43 | // Set default values.
44 | if option.ConcurrentBlockRequests == nil {
45 | option.ConcurrentBlockRequests = lo.ToPtr(defaultConcurrentBlockRequests)
46 | }
47 |
48 | if *option.ConcurrentBlockRequests == 0 {
49 | return nil, fmt.Errorf("concurrent block requests must be greater than 0")
50 | }
51 |
52 | if option.BlockStart == nil {
53 | option.BlockStart = parameter.CurrentNetworkStartBlock[n].Block
54 | }
55 |
56 | return &option, nil
57 | }
58 |
--------------------------------------------------------------------------------