diff --git a/gno_github_agent/.dockerignore b/gno_github_agent/.dockerignore new file mode 100644 index 0000000000..7b21a66fd0 --- /dev/null +++ b/gno_github_agent/.dockerignore @@ -0,0 +1,2 @@ +.env +github.db \ No newline at end of file diff --git a/gno_github_agent/.env b/gno_github_agent/.env new file mode 100644 index 0000000000..bbf87b4010 --- /dev/null +++ b/gno_github_agent/.env @@ -0,0 +1,5 @@ +GNO_MNEMONIC= +GNO_CHAIN_ID= +GNO_RPC_ADDR= +GNO_REALM_PATH= +GNO_TX_INDEXER= \ No newline at end of file diff --git a/gno_github_agent/Dockerfile b/gno_github_agent/Dockerfile new file mode 100644 index 0000000000..9f497dd44f --- /dev/null +++ b/gno_github_agent/Dockerfile @@ -0,0 +1,14 @@ +# Start from the latest golang base image +FROM golang:1.23-bullseye + +# Set the Current Working Directory inside the container +WORKDIR /app + +# Copy everything from the current directory to the Working Directory inside the container +COPY . . + +ENV CGO_ENABLED=1 +RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go go build -o bin/main main.go + +CMD [ "/app/bin/main" ] + diff --git a/gno_github_agent/Makefile b/gno_github_agent/Makefile new file mode 100644 index 0000000000..4dfbaf37e5 --- /dev/null +++ b/gno_github_agent/Makefile @@ -0,0 +1,7 @@ +DOCKER_REGISTRY=rg.nl-ams.scw.cloud/teritori +AGENT_DOCKER_IMAGE=$(DOCKER_REGISTRY)/gno-gh-verify-agent:$(shell git rev-parse --short HEAD) + +.PHONY: publish +publish: + docker build . --platform linux/amd64 -t $(AGENT_DOCKER_IMAGE) + docker push $(AGENT_DOCKER_IMAGE) diff --git a/gno_github_agent/clientql/client.go b/gno_github_agent/clientql/client.go new file mode 100644 index 0000000000..c4521240ae --- /dev/null +++ b/gno_github_agent/clientql/client.go @@ -0,0 +1,142 @@ +package clientql + +import ( + "context" + "errors" + "fmt" + "io" + "net/http" + "strings" + "time" + + "github.com/Khan/genqlient/graphql" + "github.com/TERITORI/gh-verify-agent/db" + "github.com/TERITORI/gh-verify-agent/gnoindexerql" + "github.com/TERITORI/gh-verify-agent/signer" + "go.uber.org/zap" + "gorm.io/gorm" +) + +type IndexerQL struct { + gqlClient graphql.Client + db *gorm.DB + logger *zap.SugaredLogger + signer *signer.Signer + verifyRealmPath string +} + +func New(graphqlEndpoint string, db *gorm.DB, logger *zap.SugaredLogger, gnoSigner *signer.Signer, verifyRealmPath string) *IndexerQL { + gqlClient := graphql.NewClient(graphqlEndpoint, nil) + return &IndexerQL{gqlClient: gqlClient, db: db, logger: logger, signer: gnoSigner, verifyRealmPath: verifyRealmPath} +} + +func (client *IndexerQL) DealWithVerifications() error { + lastBlock, err := client.getLastTreatedBlock() + if err != nil { + return err + } + + validationRequests, err := gnoindexerql.GetValidationRequests(context.Background(), client.gqlClient, lastBlock, client.verifyRealmPath) + if err != nil { + return err + } + client.logger.Infof("validation requests: %d\n", len(validationRequests.Transactions)) + + for _, validationRequest := range validationRequests.Transactions { + for _, responseEvent := range validationRequest.Response.Events { + switch event := responseEvent.(type) { + case *gnoindexerql.GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent: + client.logger.Infof("args %v\n", event.Attrs) + + err := client.dealWithVerification(event, validationRequest.Block_height) + if err != nil { + client.logger.Errorf("failed to deal with verification: %s", err.Error()) + continue + } + + default: + client.logger.Errorf("unexpected event type: %T", event) + } + } + } + + return nil +} + +func (client *IndexerQL) getLastTreatedBlock() (int, error) { + var verification db.Verification + err := client.db.Model(&db.Verification{}).Where("status != ?", string(db.VerificationStatusVerified)).Order("id asc").First(&verification).Error + + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return 0, nil + } + + return 0, err + } + return verification.BlockHeight, err +} + +func (client *IndexerQL) dealWithVerification(event *gnoindexerql.GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent, blockHeight int) error { + var handle string + var callerAddress string + for _, attr := range event.Attrs { + switch attr.Key { + case "handle": + handle = attr.Value + case "from": + callerAddress = attr.Value + } + } + + var verification db.Verification + err := client.db.Model(&db.Verification{}).Where("handle = ? AND address = ?", handle, callerAddress).Find(&verification).Error + if err != nil { + return err + } + + if verification.Status == "verified" { + // Already verified. + return nil + } + + client.logger.Infof("handle: %s, callerAddress: %s\n", handle, callerAddress) + res, err := http.DefaultClient.Get(fmt.Sprintf("https://raw.githubusercontent.com/%s/.gno/main/config.yml?version=1", handle)) + if err != nil { + return err + } + + defer res.Body.Close() + if res.StatusCode != 200 { + return client.updateVerification(handle, callerAddress, db.VerificationStatusConfigNotFound, blockHeight) + } + + data, err := io.ReadAll(res.Body) + if err != nil { + client.updateVerification(handle, callerAddress, db.VerificationStatusInvalidData, blockHeight) + return err + } + + githubConfiguredAddress := strings.TrimSpace(string(data)) + if githubConfiguredAddress == callerAddress { + err = client.signer.CallVerify(githubConfiguredAddress) + if err != nil { + return err + } + + return client.updateVerification(handle, callerAddress, db.VerificationStatusVerified, blockHeight) + } + return client.updateVerification(handle, callerAddress, db.VerificationStatusCallerAddressMismatch, blockHeight) +} + +func (client *IndexerQL) updateVerification(handle, address string, status db.VerificationStatus, blockHeight int) error { + verification := db.Verification{ + Handle: handle, + Address: address, + Status: string(status), + CreatedAt: time.Now().Format("2006-01-02 15:04:05"), + BlockHeight: blockHeight, + } + + return client.db.Model(&verification).Where("handle = ? AND address = ?", handle, address).Assign(db.Verification{Status: string(status)}).FirstOrCreate(&verification).Error +} diff --git a/gno_github_agent/db/db.go b/gno_github_agent/db/db.go new file mode 100644 index 0000000000..6e2a9a51fd --- /dev/null +++ b/gno_github_agent/db/db.go @@ -0,0 +1,47 @@ +package db + +import ( + "fmt" + + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +func New() (*gorm.DB, error) { + db, err := gorm.Open(sqlite.Open("github.db"), &gorm.Config{}) + if err != nil { + return nil, fmt.Errorf("open sqlite db:%w", err) + } + + err = db.AutoMigrate(allModels...) + if err != nil { + return nil, fmt.Errorf("migrate sqlite db:%w", err) + } + + return db, nil +} + +var allModels = []interface{}{ + &Verification{}, +} + +type Verification struct { + gorm.Model + Id uint `json:"id" gorm:"unique;primaryKey;autoIncrement"` + + Handle string + Address string + Status string + CreatedAt string + BlockHeight int +} + +type VerificationStatus string + +const ( + VerificationStatusUnverified VerificationStatus = "unverified" + VerificationStatusVerified VerificationStatus = "verified" + VerificationStatusConfigNotFound VerificationStatus = "config_not_found" + VerificationStatusInvalidData VerificationStatus = "invalid_data" + VerificationStatusCallerAddressMismatch VerificationStatus = "caller_address_mismatch" +) diff --git a/gno_github_agent/gnoindexerql/genqlient.yaml b/gno_github_agent/gnoindexerql/genqlient.yaml new file mode 100644 index 0000000000..f0f23b0f6e --- /dev/null +++ b/gno_github_agent/gnoindexerql/genqlient.yaml @@ -0,0 +1,22 @@ +schema: indexer-schema.graphql +operations: +- indexer-operations.graphql +generated: gnoindexerQL.go + +package: gnoindexerql + +# We bind github's DateTime scalar type to Go's time.Time (which conveniently +# already defines MarshalJSON and UnmarshalJSON). This means genqlient will +# use time.Time when a query requests a DateTime, and is required for custom +# scalars. +bindings: + DateTime: + type: time.Time + DateTimeUtc: + type: string + I64: + type: string + PublicKey: + type: string + U64: + type: string \ No newline at end of file diff --git a/gno_github_agent/gnoindexerql/gnoindexerQL.go b/gno_github_agent/gnoindexerql/gnoindexerQL.go new file mode 100644 index 0000000000..0663e998ef --- /dev/null +++ b/gno_github_agent/gnoindexerql/gnoindexerQL.go @@ -0,0 +1,349 @@ +// Code generated by github.com/Khan/genqlient, DO NOT EDIT. + +package gnoindexerql + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/Khan/genqlient/graphql" +) + +// GetValidationRequestsResponse is returned by GetValidationRequests on success. +type GetValidationRequestsResponse struct { + // Retrieves a list of Transactions that match the given filter criteria. If the result is incomplete due to errors, both partial results and errors are returned. + Transactions []GetValidationRequestsTransactionsTransaction `json:"transactions"` +} + +// GetTransactions returns GetValidationRequestsResponse.Transactions, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsResponse) GetTransactions() []GetValidationRequestsTransactionsTransaction { + return v.Transactions +} + +// GetValidationRequestsTransactionsTransaction includes the requested fields of the GraphQL type Transaction. +// The GraphQL type's documentation follows. +// +// Defines a transaction within a block, detailing its execution specifics and content. +type GetValidationRequestsTransactionsTransaction struct { + // The success can determine whether the transaction succeeded or failed. + Success bool `json:"success"` + // The height of the Block in which this Transaction is included. Links the Transaction to its containing Block. + Block_height int `json:"block_height"` + // `response` is the processing result of the transaction. + // It has `log`, `info`, `error`, and `data`. + Response GetValidationRequestsTransactionsTransactionResponse `json:"response"` +} + +// GetSuccess returns GetValidationRequestsTransactionsTransaction.Success, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransaction) GetSuccess() bool { return v.Success } + +// GetBlock_height returns GetValidationRequestsTransactionsTransaction.Block_height, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransaction) GetBlock_height() int { return v.Block_height } + +// GetResponse returns GetValidationRequestsTransactionsTransaction.Response, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransaction) GetResponse() GetValidationRequestsTransactionsTransactionResponse { + return v.Response +} + +// GetValidationRequestsTransactionsTransactionResponse includes the requested fields of the GraphQL type TransactionResponse. +// The GraphQL type's documentation follows. +// +// `TransactionResponse` is the processing result of the transaction. +// It has `log`, `info`, `error`, and `data`. +type GetValidationRequestsTransactionsTransactionResponse struct { + // The emitted events associated with the transaction execution, if any. + Events []GetValidationRequestsTransactionsTransactionResponseEventsEvent `json:"-"` +} + +// GetEvents returns GetValidationRequestsTransactionsTransactionResponse.Events, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransactionResponse) GetEvents() []GetValidationRequestsTransactionsTransactionResponseEventsEvent { + return v.Events +} + +func (v *GetValidationRequestsTransactionsTransactionResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *GetValidationRequestsTransactionsTransactionResponse + Events []json.RawMessage `json:"events"` + graphql.NoUnmarshalJSON + } + firstPass.GetValidationRequestsTransactionsTransactionResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.Events + src := firstPass.Events + *dst = make( + []GetValidationRequestsTransactionsTransactionResponseEventsEvent, + len(src)) + for i, src := range src { + dst := &(*dst)[i] + if len(src) != 0 && string(src) != "null" { + err = __unmarshalGetValidationRequestsTransactionsTransactionResponseEventsEvent( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal GetValidationRequestsTransactionsTransactionResponse.Events: %w", err) + } + } + } + } + return nil +} + +type __premarshalGetValidationRequestsTransactionsTransactionResponse struct { + Events []json.RawMessage `json:"events"` +} + +func (v *GetValidationRequestsTransactionsTransactionResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *GetValidationRequestsTransactionsTransactionResponse) __premarshalJSON() (*__premarshalGetValidationRequestsTransactionsTransactionResponse, error) { + var retval __premarshalGetValidationRequestsTransactionsTransactionResponse + + { + + dst := &retval.Events + src := v.Events + *dst = make( + []json.RawMessage, + len(src)) + for i, src := range src { + dst := &(*dst)[i] + var err error + *dst, err = __marshalGetValidationRequestsTransactionsTransactionResponseEventsEvent( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal GetValidationRequestsTransactionsTransactionResponse.Events: %w", err) + } + } + } + return &retval, nil +} + +// GetValidationRequestsTransactionsTransactionResponseEventsEvent includes the requested fields of the GraphQL interface Event. +// +// GetValidationRequestsTransactionsTransactionResponseEventsEvent is implemented by the following types: +// GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent +// GetValidationRequestsTransactionsTransactionResponseEventsUnknownEvent +type GetValidationRequestsTransactionsTransactionResponseEventsEvent interface { + implementsGraphQLInterfaceGetValidationRequestsTransactionsTransactionResponseEventsEvent() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent) implementsGraphQLInterfaceGetValidationRequestsTransactionsTransactionResponseEventsEvent() { +} +func (v *GetValidationRequestsTransactionsTransactionResponseEventsUnknownEvent) implementsGraphQLInterfaceGetValidationRequestsTransactionsTransactionResponseEventsEvent() { +} + +func __unmarshalGetValidationRequestsTransactionsTransactionResponseEventsEvent(b []byte, v *GetValidationRequestsTransactionsTransactionResponseEventsEvent) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "GnoEvent": + *v = new(GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent) + return json.Unmarshal(b, *v) + case "UnknownEvent": + *v = new(GetValidationRequestsTransactionsTransactionResponseEventsUnknownEvent) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing Event.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for GetValidationRequestsTransactionsTransactionResponseEventsEvent: "%v"`, tn.TypeName) + } +} + +func __marshalGetValidationRequestsTransactionsTransactionResponseEventsEvent(v *GetValidationRequestsTransactionsTransactionResponseEventsEvent) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent: + typename = "GnoEvent" + + result := struct { + TypeName string `json:"__typename"` + *GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent + }{typename, v} + return json.Marshal(result) + case *GetValidationRequestsTransactionsTransactionResponseEventsUnknownEvent: + typename = "UnknownEvent" + + result := struct { + TypeName string `json:"__typename"` + *GetValidationRequestsTransactionsTransactionResponseEventsUnknownEvent + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for GetValidationRequestsTransactionsTransactionResponseEventsEvent: "%T"`, v) + } +} + +// GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent includes the requested fields of the GraphQL type GnoEvent. +// The GraphQL type's documentation follows. +// +// `GnoEvent` is the event information exported by the Gno VM. +// It has `type`, `pkg_path`, `func`, and `attrs`. +type GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent struct { + Typename string `json:"__typename"` + // `type` is the type of transaction event emitted. + Type string `json:"type"` + // `pkg_path` is the path to the package that emitted the event. + Pkg_path string `json:"pkg_path"` + // `func` is the name of the function that emitted the event. + Func string `json:"func"` + // `attrs` is the event's attribute information. + Attrs []GetValidationRequestsTransactionsTransactionResponseEventsGnoEventAttrsGnoEventAttribute `json:"attrs"` +} + +// GetTypename returns GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent.Typename, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent) GetTypename() string { + return v.Typename +} + +// GetType returns GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent.Type, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent) GetType() string { + return v.Type +} + +// GetPkg_path returns GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent.Pkg_path, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent) GetPkg_path() string { + return v.Pkg_path +} + +// GetFunc returns GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent.Func, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent) GetFunc() string { + return v.Func +} + +// GetAttrs returns GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent.Attrs, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransactionResponseEventsGnoEvent) GetAttrs() []GetValidationRequestsTransactionsTransactionResponseEventsGnoEventAttrsGnoEventAttribute { + return v.Attrs +} + +// GetValidationRequestsTransactionsTransactionResponseEventsGnoEventAttrsGnoEventAttribute includes the requested fields of the GraphQL type GnoEventAttribute. +// The GraphQL type's documentation follows. +// +// `GnoEventAttribute` is the attributes that the event has. +// It has `key` and `value`. +type GetValidationRequestsTransactionsTransactionResponseEventsGnoEventAttrsGnoEventAttribute struct { + // The key of the event attribute. + Key string `json:"key"` + // The value of the event attribute. + Value string `json:"value"` +} + +// GetKey returns GetValidationRequestsTransactionsTransactionResponseEventsGnoEventAttrsGnoEventAttribute.Key, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransactionResponseEventsGnoEventAttrsGnoEventAttribute) GetKey() string { + return v.Key +} + +// GetValue returns GetValidationRequestsTransactionsTransactionResponseEventsGnoEventAttrsGnoEventAttribute.Value, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransactionResponseEventsGnoEventAttrsGnoEventAttribute) GetValue() string { + return v.Value +} + +// GetValidationRequestsTransactionsTransactionResponseEventsUnknownEvent includes the requested fields of the GraphQL type UnknownEvent. +// The GraphQL type's documentation follows. +// +// `UnknownEvent` is an unknown event type. +// It has `value`. +type GetValidationRequestsTransactionsTransactionResponseEventsUnknownEvent struct { + Typename string `json:"__typename"` +} + +// GetTypename returns GetValidationRequestsTransactionsTransactionResponseEventsUnknownEvent.Typename, and is useful for accessing the field via an interface. +func (v *GetValidationRequestsTransactionsTransactionResponseEventsUnknownEvent) GetTypename() string { + return v.Typename +} + +// __GetValidationRequestsInput is used internally by genqlient +type __GetValidationRequestsInput struct { + StartBlock int `json:"StartBlock"` + RealmPath string `json:"realmPath"` +} + +// GetStartBlock returns __GetValidationRequestsInput.StartBlock, and is useful for accessing the field via an interface. +func (v *__GetValidationRequestsInput) GetStartBlock() int { return v.StartBlock } + +// GetRealmPath returns __GetValidationRequestsInput.RealmPath, and is useful for accessing the field via an interface. +func (v *__GetValidationRequestsInput) GetRealmPath() string { return v.RealmPath } + +func GetValidationRequests( + ctx context.Context, + client graphql.Client, + StartBlock int, + realmPath string, +) (*GetValidationRequestsResponse, error) { + req := &graphql.Request{ + OpName: "GetValidationRequests", + Query: ` +query GetValidationRequests ($StartBlock: Int!, $realmPath: String!) { + transactions(filter: {events:{type:"verification_requested",pkg_path:$realmPath},from_block_height:$StartBlock}) { + success + block_height + response { + events { + __typename + ... on GnoEvent { + type + pkg_path + func + attrs { + key + value + } + } + } + } + } +} +`, + Variables: &__GetValidationRequestsInput{ + StartBlock: StartBlock, + RealmPath: realmPath, + }, + } + var err error + + var data GetValidationRequestsResponse + resp := &graphql.Response{Data: &data} + + err = client.MakeRequest( + ctx, + req, + resp, + ) + + return &data, err +} diff --git a/gno_github_agent/gnoindexerql/indexer-operations.graphql b/gno_github_agent/gnoindexerql/indexer-operations.graphql new file mode 100644 index 0000000000..0c809b5522 --- /dev/null +++ b/gno_github_agent/gnoindexerql/indexer-operations.graphql @@ -0,0 +1,27 @@ +query GetValidationRequests( + $StartBlock: Int! + $realmPath: String! +) { +transactions( + filter: { + events: {type:"verification_requested", pkg_path: $realmPath}, + from_block_height: $StartBlock + } +){ + success + block_height + response { + events { + ... on GnoEvent { + type + pkg_path + func + attrs { + key + value + } + } + } + } + } +} diff --git a/gno_github_agent/gnoindexerql/indexer-schema.graphql b/gno_github_agent/gnoindexerql/indexer-schema.graphql new file mode 100644 index 0000000000..c4cc5e1fda --- /dev/null +++ b/gno_github_agent/gnoindexerql/indexer-schema.graphql @@ -0,0 +1,595 @@ +schema { + query: Query + subscription: Subscription +} +""" +Field representing a point on time. It is following the RFC3339Nano format ("2006-01-02T15:04:05.999999999Z07:00") +""" +scalar Time +""" +`BankMsgSend` is a message with a message router of `bank` and a message type of `send`. +`BankMsgSend` is the fund transfer tx message. +""" +type BankMsgSend { + """ + the bech32 address of the fund sender. + ex) `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` + """ + from_address: String! + """ + the bech32 address of the fund receiver. + ex) `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` + """ + to_address: String! + """ + the denomination and amount of fund sent (""). + ex) `1000000ugnot` + """ + amount: String! +} +"Represents a blockchain block with various attributes detailing its creation and content." +type Block { + """ + A unique identifier for the block, determined by the blockchain's header. + It is computed as a Merkle tree from the header. + """ + hash: String! + """ + A unique identifier for the Block determined by its position in the blockchain. + This integer is strictly increasing with each new Block. + """ + height: Int! + """ + The software version of the node that created this Block, indicating the specific + implementation and versioning of the blockchain protocol used. + """ + version: String! + """ + An identifier for the specific blockchain network this Block belongs to. Helps in + distinguishing between different networks like mainnet, testnet, etc. + """ + chain_id: String! + "The timestamp at which this Block was proposed and finalized in the blockchain. Represented in UTC." + time: Time! + "The number of transactions this Block belongs to." + num_txs: Int! + """ + The total number of transactions that have occurred up to this block. + Indicates the total number of transactions that have occurred up to this point, even if there are no transactions in this block. + """ + total_txs: Int! + "The application's version." + app_version: String! + "The last committed block hash." + last_block_hash: String! + "Commit hash from validators from the last block." + last_commit_hash: String! + "Validators for the current block." + validators_hash: String! + "Validators for the next block." + next_validators_hash: String! + "Consensus params for current block." + consensus_hash: String! + "State after txs from the previous block." + app_hash: String! + "Root hash of all results from the txs from the previous block." + last_results_hash: String! + """ + Encoded data representing the blockchain address of the proposer who submitted this Block. + It is raw and requires decoding to be human-readable. + """ + proposer_address_raw: String! + "txs contains transactions included in the block." + txs: [BlockTransaction]! +} +"Defines a transaction within a block, its execution specifics and content." +type BlockTransaction { + "Hash computes the TMHASH hash of the wire encoded transaction." + hash: String! + "Fee information for the transaction." + fee: TxFee! + """ + `memo` are string information stored within a transaction. + `memo` can be utilized to find or distinguish transactions. + For example, when trading a specific exchange, you would utilize the memo field of the transaction. + """ + memo: String! + "The payload of the Transaction in a raw format, typically containing the instructions and any data necessary for execution." + content_raw: String! +} +"Define the quantity and denomination of a coin." +type Coin { + "The amount of coins." + amount: Int! + "The denomination of the coin." + denom: String! +} +""" +`GnoEvent` is the event information exported by the Gno VM. +It has `type`, `pkg_path`, `func`, and `attrs`. +""" +type GnoEvent { + "`type` is the type of transaction event emitted." + type: String! + "`pkg_path` is the path to the package that emitted the event." + pkg_path: String! + "`func` is the name of the function that emitted the event." + func: String! + "`attrs` is the event's attribute information." + attrs: [GnoEventAttribute!] +} +""" +`GnoEventAttribute` is the attributes that the event has. +It has `key` and `value`. +""" +type GnoEventAttribute { + "The key of the event attribute." + key: String! + "The value of the event attribute." + value: String! +} +"`MemFile` is the metadata information tied to a single gno package / realm file" +type MemFile { + "the name of the source file." + name: String! + "the content of the source file." + body: String! +} +"`MemPackage` is the metadata information tied to package / realm deployment." +type MemPackage { + "the name of the package." + name: String! + "the gno path of the package." + path: String! + "the associated package gno source." + files: [MemFile!] +} +""" +`MsgAddPackage` is a message with a message router of `vm` and a message type of `add_package`. +`MsgAddPackage` is the package deployment tx message. +""" +type MsgAddPackage { + """ + the bech32 address of the package deployer. + ex) `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` + """ + creator: String! + "the package being deployed." + package: MemPackage! + """ + the amount of funds to be deposited at deployment, if any (""). + ex) `1000000ugnot` + """ + deposit: String! +} +""" +`MsgCall` is a message with a message router of `vm` and a message type of `exec`. +`MsgCall` is the method invocation tx message. +""" +type MsgCall { + """ + the bech32 address of the function caller. + ex) `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` + """ + caller: String! + """ + the amount of funds to be deposited to the package, if any (""). + ex) `1000000ugnot` + """ + send: String! + "the gno package path." + pkg_path: String! + "the function name being invoked." + func: String! + "`args` are the arguments passed to the executed function." + args: [String!] +} +""" +`MsgRun` is a message with a message router of `vm` and a message type of `run`. +`MsgRun is the execute arbitrary Gno code tx message`. +""" +type MsgRun { + """ + the bech32 address of the function caller. + ex) `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` + """ + caller: String! + """ + the amount of funds to be deposited to the package, if any (""). + ex) `1000000ugnot` + """ + send: String! + "the package being executed." + package: MemPackage! +} +"Root Query type to fetch data about Blocks and Transactions based on filters or retrieve the latest block height." +type Query { + "Retrieves a list of Transactions that match the given filter criteria. If the result is incomplete due to errors, both partial results and errors are returned." + transactions(filter: TransactionFilter!): [Transaction!] + "Fetches Blocks matching the specified filter criteria. Incomplete results due to errors return both the partial Blocks and the associated errors." + blocks(filter: BlockFilter!): [Block!] + "Returns the height of the most recently processed Block by the blockchain indexer, indicating the current length of the blockchain." + latestBlockHeight: Int! +} +""" +Subscriptions provide a way for clients to receive real-time updates about Transactions and Blocks based on specified filter criteria. +Subscribers will only receive updates for events occurring after the subscription is established. +""" +type Subscription { + """ + Subscribes to real-time updates of Transactions that match the provided filter criteria. + This subscription starts immediately and only includes Transactions added to the blockchain after the subscription is active. + + This is useful for applications needing to track Transactions in real-time, such as wallets tracking incoming transactions + or analytics platforms monitoring blockchain activity. + + Returns: + - Transaction: Each received update is a Transaction object that matches the filter criteria. + """ + transactions(filter: TransactionFilter!): Transaction! + """ + Subscribes to real-time updates of Blocks that match the provided filter criteria. Similar to the Transactions subscription, + this subscription is active immediately upon creation and only includes Blocks added after the subscription begins. + + This subscription is ideal for services that need to be notified of new Blocks for processing or analysis, such as block explorers, + data aggregators, or security monitoring tools. + + Returns: + - Block: Each update consists of a Block object that satisfies the filter criteria, allowing subscribers to process or analyze new Blocks in real time. + """ + blocks(filter: BlockFilter!): Block! +} +"Defines a transaction within a block, detailing its execution specifics and content." +type Transaction { + "A sequential index representing the order of this Transaction within its Block. Unique within the context of its Block." + index: Int! + "Hash from Transaction content in base64 encoding." + hash: String! + "The success can determine whether the transaction succeeded or failed." + success: Boolean! + "The height of the Block in which this Transaction is included. Links the Transaction to its containing Block." + block_height: Int! + "The declared amount of computational effort the sender is willing to pay for executing this Transaction." + gas_wanted: Int! + "The actual amount of computational effort consumed to execute this Transaction. It could be less or equal to `gas_wanted`." + gas_used: Int! + """ + Fee includes the amount of coins paid in fees and the maximum + gas to be used by the transaction. + """ + gas_fee: Coin + "The payload of the Transaction in a raw format, typically containing the instructions and any data necessary for execution." + content_raw: String! + """ + The payload of a message shows the contents of the messages in a transaction. + A message consists of `router`, `type`, and `value` (whose form depends on the `router` and `type`). + """ + messages: [TransactionMessage]! + """ + `memo` are string information stored within a transaction. + `memo` can be utilized to find or distinguish transactions. + For example, when trading a specific exchange, you would utilize the memo field of the transaction. + """ + memo: String! + """ + `response` is the processing result of the transaction. + It has `log`, `info`, `error`, and `data`. + """ + response: TransactionResponse! +} +type TransactionMessage { + """ + The type of transaction message. + The value of `typeUrl` can be `send`, `exec`, `add_package`, `run`. + """ + typeUrl: String! + """ + The route of transaction message. + The value of `route` can be `bank`, `vm`. + """ + route: String! + """ + MessageValue is the content of the transaction. + `value` can be of type `BankMsgSend`, `MsgCall`, `MsgAddPackage`, `MsgRun`, `UnexpectedMessage`. + """ + value: MessageValue! +} +""" +`TransactionResponse` is the processing result of the transaction. +It has `log`, `info`, `error`, and `data`. +""" +type TransactionResponse { + "The log value associated with the Transaction execution, if any." + log: String! + "The Info associated with the Transaction execution, if any." + info: String! + "The error value associated with the Transaction execution, if any." + error: String! + "The response data associated with the Transaction execution, if any." + data: String! + "The emitted events associated with the transaction execution, if any." + events: [Event] +} +"The `TxFee` has information about the fee used in the transaction and the maximum gas fee specified by the user." +type TxFee { + "gas limit" + gas_wanted: Int! + "The gas fee in the transaction." + gas_fee: Coin! +} +"`UnexpectedMessage` is an Undefined Message, which is a message that decoding failed." +type UnexpectedMessage { + raw: String! +} +""" +`UnknownEvent` is an unknown event type. +It has `value`. +""" +type UnknownEvent { + "`value` is a raw event string." + value: String! +} +union Event = GnoEvent | UnknownEvent +union MessageValue = BankMsgSend | MsgCall | MsgAddPackage | MsgRun | UnexpectedMessage +""" +`MessageRoute` is route type of the transactional message. +`MessageRoute` has the values of vm and bank. +""" +enum MessageRoute { + vm + bank +} +""" +`MessageType` is message type of the transaction. +`MessageType` has the values `send`, `exec`, `add_package`, and `run`. +""" +enum MessageType { + """ + The route value for this message type is `bank`, and the value for transactional messages is `BankMsgSend`. + This is a transaction message used when sending native tokens. + """ + send + """ + The route value for this message type is `vm`, and the value for transactional messages is `MsgCall`. + This is a transaction message that executes a function in realm or package that is deployed in the GNO chain. + """ + exec + """ + The route value for this message type is `vm`, and the value for transactional messages is `MsgAddPackage`. + This is a transactional message that adds a package to the GNO chain. + """ + add_package + """ + The route value for this message type is `vm`, and the value for transactional messages is `MsgRun`. + This is a transactional message that executes an arbitrary Gno-coded TX message. + """ + run +} +"`AmountInput` is a range of token quantities to filter by." +input AmountInput { + "The minimum quantity of tokens to check for." + from: Int + "The maximum quantity of tokens to check for." + to: Int + """ + Filter by token's denomination. + If set to an empty string, it will get an empty value. + """ + denomination: String +} +"`BankMsgSendInput` represents input parameters required when the message type is `send`." +input BankMsgSendInput { + """ + the bech32 address of the fund sender. + You can filter by the fund sender address. + ex) `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` + """ + from_address: String + """ + the bech32 address of the fund receiver. + You can filter by the fund receiver address. + ex) `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` + """ + to_address: String + """ + the denomination and amount of fund sent (""). + ex) `1000000ugnot` + """ + amount: AmountInput +} +"Filters for querying Blocks within specified criteria related to their attributes." +input BlockFilter { + "Minimum block height from which to start fetching Blocks, inclusive. If unspecified, there is no lower bound." + from_height: Int + "Maximum block height up to which Blocks should be fetched, exclusive. If unspecified, there is no upper bound." + to_height: Int + "Minimum timestamp from which to start fetching Blocks, inclusive. Blocks created at or after this time will be included." + from_time: Time + "Maximum timestamp up to which to fetch Blocks, exclusive. Only Blocks created before this time are included." + to_time: Time +} +""" +Transaction event's attribute to filter transaction. +"EventAttributeInput" can be configured as a filter with a event attribute's `key` and `value`. +""" +input EventAttributeInput { + "`key` is the key of the event attribute." + key: String + "`value` is the value of the event attribute." + value: String +} +""" +Transaction's event to filter transactions. +"EventInput" can be configured as a filter with a transaction event's `type` and `pkg_path` and `func`, and `attrs`. +""" +input EventInput { + "`type` is the type of transaction event emitted." + type: String + "`pkg_path` is the path to the package that emitted the event." + pkg_path: String + "`func` is the name of the function that emitted the event." + func: String + """ + `attrs` filters transactions whose events contain attributes. + `attrs` is entered as an array and works exclusively. + ex) `attrs[0] || attrs[1] || attrs[2]` + """ + attrs: [EventAttributeInput!] +} +"`MemFileInput` is the metadata information tied to a single gno package / realm file." +input MemFileInput { + "the name of the source file." + name: String + "the content of the source file." + body: String +} +"`MemPackageInput` represents a package stored in memory." +input MemPackageInput { + "the name of the package." + name: String + "the gno path of the package." + path: String + "the associated package gno source." + files: [MemFileInput] +} +"`MsgAddPackageInput` represents input parameters required when the message type is `add_package`." +input MsgAddPackageInput { + """ + the bech32 address of the package deployer. + You can filter by the package deployer's address. + ex) `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` + """ + creator: String + "the package being deployed." + package: MemPackageInput + """ + the amount of funds to be deposited at deployment, if any (""). + ex) `1000000ugnot` + """ + deposit: AmountInput +} +"`MsgCallInput` represents input parameters required when the message type is `exec`." +input MsgCallInput { + """ + the bech32 address of the function caller. + You can filter by the function caller's address. + ex) `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` + """ + caller: String + """ + the amount of funds to be deposited to the package, if any (""). + ex) `1000000ugnot` + """ + send: AmountInput + "the gno package path." + pkg_path: String + "the function name being invoked." + func: String + """ + `args` are the arguments passed to the executed function. + The arguments are checked in the order of the argument array and + if they are empty strings, they are excluded from the filtering criteria. + ex) `["", "", "1"]` <- Empty strings skip the condition. + """ + args: [String!] +} +"`MsgRunInput` represents input parameters required when the message type is `run`." +input MsgRunInput { + """ + the bech32 address of the function caller. + You can filter by the function caller's address. + ex) `g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5` + """ + caller: String + """ + the amount of funds to be deposited to the package, if any (""). + ex) `1000000ugnot` + """ + send: AmountInput + "the package being executed." + package: MemPackageInput +} +"`TransactionBankMessageInput` represents input parameters required when the message router is `bank`." +input TransactionBankMessageInput { + "send represents input parameters required when the message type is `send`." + send: BankMsgSendInput +} +"Filters for querying Transactions within specified criteria related to their execution and placement within Blocks." +input TransactionFilter { + "Minimum block height from which to start fetching Transactions, inclusive. Aids in scoping the search to recent Transactions." + from_block_height: Int + "Maximum block height up to which Transactions should be fetched, exclusive. Helps in limiting the search to older Transactions." + to_block_height: Int + "Minimum Transaction index from which to start fetching, inclusive. Facilitates ordering in Transaction queries." + from_index: Int + "Maximum Transaction index up to which to fetch, exclusive. Ensures a limit on the ordering range for Transaction queries." + to_index: Int + "Minimum `gas_wanted` value to filter Transactions by, inclusive. Filters Transactions based on the minimum computational effort declared." + from_gas_wanted: Int + "Maximum `gas_wanted` value for filtering Transactions, exclusive. Limits Transactions based on the declared computational effort." + to_gas_wanted: Int + "Minimum `gas_used` value to filter Transactions by, inclusive. Selects Transactions based on the minimum computational effort actually used." + from_gas_used: Int + "Maximum `gas_used` value for filtering Transactions, exclusive. Refines selection based on the computational effort actually consumed." + to_gas_used: Int + "Hash from Transaction content in base64 encoding. If this filter is used, any other filter will be ignored." + hash: String + """ + Transaction's message to filter Transactions. + `messages` can be configured as a filter with a transaction message's `router` and `type` and `parameters(bank / vm)`. + `messages` is entered as an array and works exclusively. + ex) `messages[0] || messages[1] || messages[2]` + """ + messages: [TransactionMessageInput!] + """ + `memo` are string information stored within a transaction. + `memo` can be utilized to find or distinguish transactions. + For example, when trading a specific exchange, you would utilize the memo field of the transaction. + """ + memo: String + """ + `success` is whether the transaction was successful or not. + `success` enables you to filter between successful and unsuccessful transactions. + """ + success: Boolean + """ + `events` are what the transaction has emitted. + `events` can be filtered with a specific event to query its transactions. + `events` is entered as an array and works exclusively. + ex) `events[0] || events[1] || events[2]` + """ + events: [EventInput!] +} +""" +Transaction's message to filter Transactions. +`TransactionMessageInput` can be configured as a filter with a transaction message's `router` and `type` and `parameters(bank / vm)`. +""" +input TransactionMessageInput { + """ + The type of transaction message. + The value of `typeUrl` can be `send`, `exec`, `add_package`, `run`. + """ + type_url: MessageType + """ + The route of transaction message. + The value of `route` can be `bank`, `vm`. + """ + route: MessageRoute + "`TransactionBankMessageInput` represents input parameters required when the message router is `bank`." + bank_param: TransactionBankMessageInput + "`TransactionVmMessageInput` represents input parameters required when the message router is `vm`." + vm_param: TransactionVmMessageInput +} +"`TransactionVmMessageInput` represents input parameters required when the message router is `vm`." +input TransactionVmMessageInput { + "`MsgCallInput` represents input parameters required when the message type is `exec`." + exec: MsgCallInput + "`MsgAddPackageInput` represents input parameters required when the message type is `add_package`." + add_package: MsgAddPackageInput + "`MsgRunInput` represents input parameters required when the message type is `run`." + run: MsgRunInput +} +"The @defer directive may be specified on a fragment spread to imply de-prioritization, that causes the fragment to be omitted in the initial response, and delivered as a subsequent response afterward. A query with @defer directive will cause the request to potentially return multiple responses, where non-deferred data is delivered in the initial response and data deferred delivered in a subsequent response. @include and @skip take precedence over @defer." +directive @defer(if: Boolean = true, label: String) on FRAGMENT_SPREAD | INLINE_FRAGMENT +"The @specifiedBy built-in directive is used within the type system definition language to provide a scalar specification URL for specifying the behavior of custom scalar types." +directive @specifiedBy(url: String!) on SCALAR diff --git a/gno_github_agent/go.mod b/gno_github_agent/go.mod new file mode 100644 index 0000000000..6309741814 --- /dev/null +++ b/gno_github_agent/go.mod @@ -0,0 +1,65 @@ +module github.com/TERITORI/gh-verify-agent + +go 1.23.0 + +require ( + github.com/Khan/genqlient v0.7.0 + github.com/gnolang/gno v0.2.0 + github.com/go-co-op/gocron v1.37.0 + go.uber.org/zap v1.27.0 + gorm.io/driver/sqlite v1.5.6 + gorm.io/gorm v1.25.12 +) + +require ( + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcutil v1.1.5 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cockroachdb/apd/v3 v3.2.1 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/mattn/go-sqlite3 v1.14.22 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/rs/xid v1.5.0 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/vektah/gqlparser/v2 v2.5.11 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/gno_github_agent/go.sum b/gno_github_agent/go.sum new file mode 100644 index 0000000000..2da5bce752 --- /dev/null +++ b/gno_github_agent/go.sum @@ -0,0 +1,273 @@ +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/Khan/genqlient v0.7.0 h1:GZ1meyRnzcDTK48EjqB8t3bcfYvHArCUUvgOwpz1D4w= +github.com/Khan/genqlient v0.7.0/go.mod h1:HNyy3wZvuYwmW3Y7mkoQLZsa/R5n5yIRajS1kPBvSFM= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd h1:js1gPwhcFflTZ7Nzl7WHaOTlTr5hIrR4n1NM4v9n4Kw= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= +github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gnolang/gno v0.2.0 h1:s33kyRByweDxxHMZMQKJtCDQpueTCYCFBqlLHwr6P+Y= +github.com/gnolang/gno v0.2.0/go.mod h1:dBaL1Au2MNLol+3FXdCv+IKLJnMKtTmIt778zsKjVu0= +github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= +github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= +github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= +github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= +github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= +github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/vektah/gqlparser/v2 v2.5.11 h1:JJxLtXIoN7+3x6MBdtIP59TP1RANnY7pXOaDnADQSf8= +github.com/vektah/gqlparser/v2 v2.5.11/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= +go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0/go.mod h1:yeGZANgEcpdx/WK0IvvRFC+2oLiMS2u4L/0Rj2M2Qr0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0 h1:aLmmtjRke7LPDQ3lvpFz+kNEH43faFhzW7v8BFIEydg= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.28.0/go.mod h1:TC1pyCt6G9Sjb4bQpShH+P5R53pO6ZuGnHuuln9xMeE= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= +go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.uber.org/zap/exp v0.2.0 h1:FtGenNNeCATRB3CmB/yEUnjEFeJWpB/pMcy7e2bKPYs= +go.uber.org/zap/exp v0.2.0/go.mod h1:t0gqAIdh1MfKv9EwN/dLwfZnJxe9ITAZN78HEWPFWDQ= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE= +gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= +gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= +gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= diff --git a/gno_github_agent/main.go b/gno_github_agent/main.go new file mode 100644 index 0000000000..1ebc9a7fd4 --- /dev/null +++ b/gno_github_agent/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "os" + "time" + + "github.com/TERITORI/gh-verify-agent/clientql" + "github.com/TERITORI/gh-verify-agent/db" + "github.com/TERITORI/gh-verify-agent/signer" + "github.com/go-co-op/gocron" + "go.uber.org/zap" +) + +var gnoSigner *signer.Signer + +func main() { + logger, err := zap.NewDevelopment() + if err != nil { + panic(err) + } + + db, err := db.New() + if err != nil { + panic(err) + } + mnemonic := os.Getenv("GNO_MNEMONIC") + chainID := os.Getenv("GNO_CHAIN_ID") + rpcAddr := os.Getenv("GNO_RPC_ADDR") + realmPath := os.Getenv("GNO_REALM_PATH") + txIndexerHost := os.Getenv("GNO_TX_INDEXER") + + gnoSigner = signer.New(db, logger.Sugar(), mnemonic, chainID, rpcAddr, realmPath) + + clientql := clientql.New(txIndexerHost, db, logger.Sugar(), gnoSigner, realmPath) + schedule := gocron.NewScheduler(time.UTC) + + schedule.Every(30).Seconds().Do(func() { + err = clientql.DealWithVerifications() + if err != nil { + logger.Error("failed to deal with verifications", zap.Error(err)) + panic(err) + } + }) + + schedule.StartBlocking() +} diff --git a/gno_github_agent/signer/signer.go b/gno_github_agent/signer/signer.go new file mode 100644 index 0000000000..a426c1befa --- /dev/null +++ b/gno_github_agent/signer/signer.go @@ -0,0 +1,87 @@ +package signer + +import ( + "fmt" + + "github.com/gnolang/gno/gno.land/pkg/gnoclient" + "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + rpcclient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client" + "github.com/gnolang/gno/tm2/pkg/crypto/keys" + "go.uber.org/zap" + "gorm.io/gorm" +) + +type Signer struct { + db *gorm.DB + logger *zap.SugaredLogger + keyInfo keys.Info + gnoclient *gnoclient.Client + realmPath string +} + +func New(db *gorm.DB, + logger *zap.SugaredLogger, + mnemonic, chainID, + rpcAddr, + realmPath string, +) *Signer { + signer, err := gnoclient.SignerFromBip39(mnemonic, chainID, "", 0, 0) + if err != nil { + panic(err) + } + + keyInfo, err := signer.Info() + if err != nil { + panic(err) + } + + // Initialize the RPC client + rpc, err := rpcclient.NewHTTPClient(rpcAddr) + if err != nil { + panic(err) + } + + // Initialize the gnoclient + client := gnoclient.Client{ + Signer: signer, + RPCClient: rpc, + } + + return &Signer{ + db: db, + logger: logger, + keyInfo: keyInfo, + realmPath: realmPath, + gnoclient: &client, + } +} + +func (s *Signer) CallVerify(address string) error { + acc, _, err := s.gnoclient.QueryAccount(s.keyInfo.GetAddress()) + if err != nil { + return fmt.Errorf("failed to query account: %w", err) + } + + baseCfg := gnoclient.BaseTxCfg{ + GasFee: "1000000ugnot", + GasWanted: 3000000, + AccountNumber: acc.GetAccountNumber(), + SequenceNumber: acc.GetSequence(), + Memo: "ghverify-agent", + } + + arg := "ingest," + address + ",OK" + + _, err = s.gnoclient.Call(baseCfg, vm.MsgCall{ + Caller: s.keyInfo.GetAddress(), + Send: nil, + PkgPath: s.realmPath, + Func: "GnorkleEntrypoint", + Args: []string{arg}, + }) + if err != nil { + return fmt.Errorf("failed to call gnoclient: %s", err.Error()) + } + + return nil +}