text:
import * as web3 from '../web3.js';
import { Config } from '../config.js';
import { Request } from '../request.js';
import { Address, Engine } from '@aurora-is-near/engine';
import { Logger } from 'pino';
export declare abstract class SkeletonServer implements web3.Service {
    readonly config: Config;
    readonly logger: Logger;
    readonly engine: Engine;
    constructor(config: Config, logger: Logger, engine: Engine);
    protected abstract _init(): Promise<void>;
    protected _isBannedEOA(address: Address): boolean;
    protected _isBannedCA(address: Address): boolean;
    protected _enforceBans(address: Address, method: string): void;
    protected _enforceEOABan(address: Address, method: string): void;
    protected _enforceCABan(address: Address, method: string): void;
    protected _scanForCABans(bytes: string): string | null;
    protected _banIP(ip: string, reason?: string): Promise<void>;
    web3_clientVersion(_request: Request): Promise<string>;
    web3_sha3(_request: Request, input: web3.Data): Promise<web3.Data>;
    net_listening(_request: Request): Promise<boolean>;
    net_peerCount(_request: Request): Promise<web3.Quantity>;
    net_version(_request: Request): Promise<string>;
    eth_accounts(_request: Request): Promise<web3.Data[]>;
    eth_blockNumber(_request: Request): Promise<web3.Quantity>;
    eth_call(_request: Request, _transaction: web3.TransactionForCall, _blockNumber?: web3.Quantity | web3.Tag): Promise<web3.Data>;
    eth_chainId(_request: Request): Promise<web3.Quantity>;
    eth_coinbase(_request: Request): Promise<web3.Data>;
    eth_compileLLL(_request: Request, _code: string): Promise<web3.Data>;
    eth_compileSerpent(_request: Request, _code: string): Promise<web3.Data>;
    eth_compileSolidity(_request: Request, _code: string): Promise<web3.Data>;
    eth_estimateGas(_request: Request, _transaction: web3.TransactionForCall, _blockNumber?: web3.Quantity | web3.Tag): Promise<web3.Quantity>;
    eth_gasPrice(_request: Request): Promise<web3.Quantity>;
    eth_getBalance(_request: Request, _address: web3.Data, _blockNumber?: web3.Quantity | web3.Tag): Promise<web3.Quantity>;
    eth_getBlockByHash(_request: Request, _blockHash: web3.Data, _fullObject?: boolean): Promise<web3.BlockResult | null>;
    eth_getBlockByNumber(_request: Request, _blockNumber: web3.Quantity | web3.Tag, _fullObject?: boolean): Promise<web3.BlockResult | null>;
    eth_getBlockTransactionCountByHash(_request: Request, _blockHash: web3.Data): Promise<web3.Quantity | null>;
    eth_getBlockTransactionCountByNumber(_request: Request, _blockNumber: web3.Quantity | web3.Tag): Promise<web3.Quantity | null>;
    eth_getCode(_request: Request, _address: web3.Data, _blockNumber: web3.Quantity | web3.Tag): Promise<web3.Data>;
    eth_getCompilers(_request: Request): Promise<string[]>;
    eth_getFilterChanges(_request: Request, _filterID: web3.Quantity): Promise<web3.LogObject[]>;
    eth_getFilterLogs(_request: Request, _filterID: web3.Quantity): Promise<web3.LogObject[]>;
    eth_getLogs(_request: Request, _filter: web3.FilterOptions): Promise<web3.LogObject[]>;
    eth_getProof(_request: Request, _address: web3.Data, _keys: web3.Data[], _blockNumber: web3.Quantity | web3.Tag): Promise<web3.ProofResult>;
    eth_getStorageAt(_request: Request, _address: web3.Data, _key: web3.Quantity, _blockNumber: web3.Quantity | web3.Tag): Promise<web3.Data>;
    eth_getTransactionByBlockHashAndIndex(_request: Request, _blockHash: web3.Data, _transactionIndex: web3.Quantity): Promise<web3.TransactionResult | null>;
    eth_getTransactionByBlockNumberAndIndex(_request: Request, _blockNumber: web3.Quantity | web3.Tag, _transactionIndex: web3.Quantity): Promise<web3.TransactionResult | null>;
    eth_getTransactionByHash(_request: Request, _transactionHash: web3.Data): Promise<web3.TransactionResult | null>;
    eth_getTransactionCount(_request: Request, _address: web3.Data, _blockNumber: web3.Quantity | web3.Tag): Promise<web3.Quantity>;
    eth_getTransactionReceipt(_request: Request, _transactionHash: string): Promise<web3.TransactionReceipt | null>;
    eth_getUncleByBlockHashAndIndex(_request: Request, _blockHash: web3.Data, _uncleIndex: web3.Quantity): Promise<web3.BlockResult | null>;
    eth_getUncleByBlockNumberAndIndex(_request: Request, _blockNumber: web3.Quantity | web3.Tag, _uncleIndex: web3.Quantity): Promise<web3.BlockResult | null>;
    eth_getUncleCountByBlockHash(_request: Request, _blockHash: web3.Data): Promise<web3.Quantity | null>;
    eth_getUncleCountByBlockNumber(_request: Request, _blockNumber: web3.Quantity | web3.Tag): Promise<web3.Quantity | null>;
    eth_getWork(_request: Request): Promise<web3.Data[]>;
    eth_hashrate(_request: Request): Promise<web3.Quantity>;
    eth_mining(_request: Request): Promise<false>;
    eth_newBlockFilter(_request: Request): Promise<web3.Quantity>;
    eth_newFilter(_request: Request, _filter: web3.FilterOptions): Promise<web3.Quantity>;
    eth_newPendingTransactionFilter(_request: Request): Promise<web3.Quantity>;
    eth_pendingTransactions(_request: Request): Promise<Record<string, string | number | null>[]>;
    eth_protocolVersion(_request: Request): Promise<string>;
    eth_sendRawTransaction(_request: Request, _transaction: web3.Data): Promise<web3.Data>;
    eth_sendTransaction(_request: Request, _transaction: web3.TransactionForSend): Promise<web3.Data>;
    eth_sign(_request: Request, _account: web3.Data, _message: web3.Data): Promise<web3.Data>;
    eth_signTransaction(_request: Request, _transaction: web3.TransactionForSend): Promise<web3.Data>;
    eth_signTypedData(_request: Request, _address: web3.Data, _data: web3.TypedData): Promise<web3.Data>;
    eth_submitHashrate(_request: Request, _hashrate: web3.Quantity, _clientID: web3.Quantity): Promise<false>;
    eth_submitWork(_request: Request, _nonce: web3.Data, _powHash: web3.Data, _mixDigest: web3.Data): Promise<false>;
    eth_subscribe(_request: Request, _subsciptionType: web3.Data, _filter: any): Promise<web3.Data>;
    eth_syncing(_request: Request): Promise<false>;
    eth_uninstallFilter(_request: Request, _filterID: web3.Quantity): Promise<boolean>;
    eth_unsubscribe(_request: Request, _subsciptionId: web3.Data): Promise<boolean>;
    txpool_content(_request: Request): Promise<Record<string, any>>;
    txpool_inspect(_request: Request): Promise<Record<string, any>>;
    txpool_status(_request: Request): Promise<Record<string, number>>;
    parity_pendingTransactions(_request: Request, _limit?: number | null, _filter?: Record<string, any>): Promise<any[]>;
}


text:
module util

go 1.17

require (
	github.com/cloudflare/cloudflare-go v0.26.0
	inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6
)

require (
	github.com/pkg/errors v0.9.1 // indirect
	go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect
	go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37 // indirect
	golang.org/x/net v0.0.0-20210510120150-4163338589ed // indirect
	golang.org/x/text v0.3.6 // indirect
	golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
)

repo_name: aurora-is-near/aurora-relayer

repo_language: TypeScript

mime_type: text/plain


text:
// This is free and unencumbered software released into the public domain.

package main

import (
	"context"
	"fmt"
	"os"
	"strings"

	"github.com/cloudflare/cloudflare-go"
	"inet.af/netaddr"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Fprintf(os.Stderr, "usage: ban IPADDR [LABEL]\n")
		os.Exit(64) // EX_USAGE
	}

	cfAPIToken := os.Getenv("CF_API_TOKEN")
	if cfAPIToken == "" {
		fmt.Fprintf(os.Stderr, "missing %s environment variable\n", "CF_API_TOKEN")
		os.Exit(78) // EX_CONFIG
	}

	cfAccountID := os.Getenv("CF_ACCOUNT_ID")
	if cfAccountID == "" {
		fmt.Fprintf(os.Stderr, "missing %s environment variable\n", "CF_ACCOUNT_ID")
		os.Exit(78) // EX_CONFIG
	}

	cfListID := os.Getenv("CF_LIST_ID")
	if cfListID == "" {
		fmt.Fprintf(os.Stderr, "missing %s environment variable\n", "CF_LIST_ID")
		os.Exit(78) // EX_CONFIG
	}

	ipAddress, err := netaddr.ParseIP(os.Args[1])
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err)
		os.Exit(65) // EX_DATAERR
	}

	ipLabel := ""
	if len(os.Args) > 2 {
		ipLabel = os.Args[2]
	}

	api, err := cloudflare.NewWithAPIToken(cfAPIToken, cloudflare.UsingAccount(cfAccountID))
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err)
		os.Exit(77) // EX_NOPERM
	}

	ctx := context.Background()
	_, err = api.CreateIPListItem(ctx, cfListID, ipToString(ipAddress), ipLabel)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err)
		os.Exit(69) // EX_UNAVAILABLE
	}
}

func ipToString(ip netaddr.IP) string {
	if ip.Is4() {
		return ip.String()
	}
	return strings.Join(strings.Split(ip.StringExpanded(), ":")[0:4], ":") + "::/64"
}


text:
GO = go
GOFLAGS = -ldflags="-s -w"
UPX = upx
UPXFLAGS = --quiet --best --lzma

# The default target:

all: ban

.PHONY: all

# Output executables:

ban: main.go
	GOOS=linux GOARCH=amd64 CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o $@ $^ && $(UPX) $(UPXFLAGS) $@

# Rules for development:

clean:
	@rm -Rf ban *~

distclean: clean

mostlyclean: clean

maintainer-clean: clean

.PHONY: clean distclean mostlyclean maintainer-clean

.SECONDARY:
.SUFFIXES:


text:
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cloudflare/cloudflare-go v0.26.0 h1:u69Gye0WKOKQPOfib2yxWUl0u78k2VP05BeMJctFGRM=
github.com/cloudflare/cloudflare-go v0.26.0/go.mod h1:sPWL/lIC6biLEdyGZwBQ1rGQKF1FhM7N60fuNiFdYTI=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
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/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
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/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
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/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE=
go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37 h1:Tx9kY6yUkLge/pFG7IEMwDZy6CS2ajFc9TvQdPCW0uA=
go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 h1:acCzuUSQ79tGsM/O50VRFySfMm19IoMKL+sZztZkCxw=
inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6/go.mod h1:y3MGhcFMlh0KZPMuXXow8mpjxxAk3yoDNsp4cQz54i8=


text:
module indexer

go 1.17

require (
	github.com/aurora-is-near/go-jsonrpc/v3 v3.1.1 // indirect
	github.com/aurora-is-near/near-api-go v0.0.11 // indirect
	github.com/btcsuite/btcutil v1.0.2 // indirect
	github.com/fsnotify/fsnotify v1.5.1 // indirect
	github.com/hashicorp/hcl v1.0.0 // indirect
	github.com/inconshreveable/mousetrap v1.0.0 // indirect
	github.com/jackc/chunkreader/v2 v2.0.1 // indirect
	github.com/jackc/pgconn v1.10.0 // indirect
	github.com/jackc/pgio v1.0.0 // indirect
	github.com/jackc/pgpassfile v1.0.0 // indirect
	github.com/jackc/pgproto3/v2 v2.1.1 // indirect
	github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
	github.com/jackc/pgtype v1.8.1 // indirect
	github.com/jackc/pgx v3.6.2+incompatible // indirect
	github.com/jackc/pgx/v4 v4.13.0 // indirect
	github.com/jackc/puddle v1.1.3 // indirect
	github.com/magiconair/properties v1.8.5 // indirect
	github.com/mitchellh/mapstructure v1.4.2 // indirect
	github.com/near/borsh-go v0.3.0 // indirect
	github.com/pelletier/go-toml v1.9.4 // indirect
	github.com/pkg/errors v0.8.1 // indirect
	github.com/spf13/afero v1.6.0 // indirect
	github.com/spf13/cast v1.4.1 // indirect
	github.com/spf13/cobra v1.2.1 // indirect
	github.com/spf13/jwalterweatherman v1.1.0 // indirect
	github.com/spf13/pflag v1.0.5 // indirect
	github.com/spf13/viper v1.9.0 // indirect
	github.com/subosito/gotenv v1.2.0 // indirect
	golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
	golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf // indirect
	golang.org/x/text v0.3.6 // indirect
	gopkg.in/ini.v1 v1.63.2 // indirect
	gopkg.in/yaml.v2 v2.4.0 // indirect
)


text:
// This is free and unencumbered software released into the public domain.

package main

import (
	"container/heap"
	"sync"
)

type QueueBlock struct {
	IsHead   bool  `json:"is_head"`
	Id       int64 `json:"id"`
}

type Queue struct {
	items []QueueBlock
	mutex sync.RWMutex
}

func CreateQueue() *Queue {
	queue := &Queue{}
	heap.Init(queue)
	return queue
}

func (queue *Queue) Enqueue(x QueueBlock) {
	queue.mutex.Lock()
	defer queue.mutex.Unlock()
	heap.Push(queue, x)
}

func (queue *Queue) Dequeue() QueueBlock {
	queue.mutex.Lock()
	defer queue.mutex.Unlock()
	if queue.Len() == 0 {
		return QueueBlock{true, -1}
	}
	return heap.Pop(queue).(QueueBlock)
}

func (queue *Queue) LenSafe() int {
	queue.mutex.Lock()
	defer queue.mutex.Unlock()
	return len(queue.items)
}

func (queue *Queue) Len() int {
	return len(queue.items)
}

func (queue *Queue) Less(i, j int) bool {
	return queue.items[i].Id > queue.items[j].Id
}

func (queue *Queue) Swap(i, j int) {
	queue.items[i], queue.items[j] = queue.items[j], queue.items[i]
}

func (queue *Queue) Push(x interface{}) {
	queue.items = append(queue.items, x.(QueueBlock))
}

func (queue *Queue) Pop() interface{} {
	old := queue.items
	n := len(old)
	if n == 0 {
		return nil
	}
	x := old[n-1]
	queue.items = old[0 : n-1]
	return x
}


text:
// This is free and unencumbered software released into the public domain.

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"time"

	"github.com/aurora-is-near/near-api-go"
	"github.com/jackc/pgx/v4/pgxpool"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

const version = "0.0.0"
const timeFormat = "2006-01-02T15:04:05Z"

var configFile string
var verbose, debug bool
var databaseURL, endpointURL string
var queue = CreateQueue()

func main() {
	cobra.OnInitialize(initConfig)
	rootCmd.PersistentFlags().StringVar(&configFile, "config", "", "config file (default is config/local.yaml)")
	rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Be verbose.")
	rootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "Enable debugging.")
	cobra.CheckErr(rootCmd.Execute())
}

func initConfig() {
	if configFile != "" {
		viper.SetConfigFile(configFile)
	} else {
		if env, ok := os.LookupEnv("NEAR_ENV"); ok && env != "" {
			viper.SetConfigName(env)
		} else {
			viper.SetConfigName("local")
		}
		viper.SetConfigType("yaml")
		viper.AddConfigPath("config")
		viper.AddConfigPath("../../config")
	}

	viper.AutomaticEnv() // read in environment variables that match

	if err := viper.ReadInConfig(); err == nil {
		fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
	}
}

var rootCmd = &cobra.Command{
	Use:     "indexer",
	Short:   "Produces block numbers to be indexed, prioritized by freshness",
	Long:    `Produces block numbers to be indexed, prioritized by freshness.`,
	Version: version,
	Run: func(cmd *cobra.Command, args []string) {
		databaseURL = viper.GetString("database")
		endpointURL = viper.GetString("endpoint")

		database, err := pgxpool.Connect(context.Background(), databaseURL)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Unable to connect to database %s: %v\n", databaseURL, err)
			os.Exit(1)
		}
		defer database.Close()

		endpoint := near.NewConnection(endpointURL)

		indexedBlockID, err := getIndexedBlockHeight(database)
		if err != nil {
			indexedBlockID = 0
		}

		currentBlockID, err := getCurrentBlockHeight(endpoint)
		if err != nil {
			panic(err)
		}

		fmt.Fprintf(os.Stderr, "Indexing blocks #%d..#%d and #%d+...\n", currentBlockID, indexedBlockID, currentBlockID+1)

		go followChainHead(currentBlockID)
		go scanForIndexGaps(currentBlockID)
		for {
			queueBlock := queue.Dequeue()
			if queueBlock.Id == -1 {
				time.Sleep(100 * time.Millisecond)
				continue
			}
			data, _ := json.Marshal(queueBlock)
			fmt.Println(string(data))
		}
	},
}

func followChainHead(previousBlockID int64) {
	endpoint := near.NewConnection(endpointURL)
	for {
		currentBlockID, err := getCurrentBlockHeight(endpoint)
		if err != nil {
			panic(err)
		}
		if currentBlockID > previousBlockID { // forward only
			for blockID := previousBlockID + 1; blockID <= currentBlockID; blockID++ {
				if verbose || debug {
					if blockID < currentBlockID {
						fmt.Fprintf(os.Stderr, "Enqueued skipped block #%d.\n", blockID)
					} else {
						fmt.Fprintf(os.Stderr, "Enqueued current block #%d.\n", blockID)
					}
				}
				queue.Enqueue(QueueBlock{true, blockID})
			}
			previousBlockID = currentBlockID
		}
		time.Sleep(100 * time.Millisecond)
	}
}

func scanForIndexGaps(tipBlockID int64) {
	windowSize := int64(1000) // TODO: make this configurable
	database, err := pgxpool.Connect(context.Background(), databaseURL)
	if err != nil {
		panic(err)
	}
	defer database.Close()
	for i := int64(0); i < 100000; i++ {
		maxBlockID := tipBlockID - i*windowSize
		minBlockID := maxBlockID - windowSize + 1
		if minBlockID < 0 {
			break
		}
		if debug {
			fmt.Fprintf(os.Stderr, "Scanning blocks #%d..#%d for gaps...\n", minBlockID, maxBlockID)
		}
		query := fmt.Sprintf(`SELECT array_agg(ids) AS "id"
			FROM generate_series(%d, %d, 1) ids
			LEFT JOIN block ON ids = block.id
			WHERE block.id IS NULL
			LIMIT %d`, minBlockID, maxBlockID, windowSize)
		blockIDs := make([]int64, 0)
		err := database.QueryRow(context.Background(), query).Scan(&blockIDs)
		if err != nil {
			panic(err)
		}

		for _, blockID := range blockIDs {
			queue.Enqueue(QueueBlock{false, blockID})
			time.Sleep(time.Duration(200*queue.LenSafe()) * time.Millisecond)
		}
	}
}

func getIndexedBlockHeight(database *pgxpool.Pool) (int64, error) {
	var blockID int64
	err := database.QueryRow(context.Background(),
		"SELECT MAX(id) FROM block").Scan(&blockID)
	if err != nil {
		return -1, err
	}
	return blockID, nil
}

func getCurrentBlockHeight(endpoint *near.Connection) (int64, error) {
	nodeStatus, err := endpoint.GetNodeStatus()
	if err != nil {
		return -1, err
	}
	syncInfo := nodeStatus["sync_info"].(map[string]interface{})
	blockID, err := syncInfo["latest_block_height"].(json.Number).Int64()
	if err != nil {
		return -1, err
	}
	return blockID, nil
}


text:
GO = go
GOFLAGS = -ldflags="-s -w"
UPX = upx
UPXFLAGS = --quiet --best --lzma

# The default target:

all: indexer

.PHONY: all

# Output executables:

indexer: main.go queue.go
	GOOS=linux GOARCH=amd64 CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o $@ $^ && $(UPX) $(UPXFLAGS) $@

# Rules for development:

clean:
	@rm -Rf indexer *~

distclean: clean

mostlyclean: clean

maintainer-clean: clean

.PHONY: clean distclean mostlyclean maintainer-clean

.SECONDARY:
.SUFFIXES: