diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..dc4698a95 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,90 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Build & Run + +```bash +# Build the binary (requires CGO for BLS crypto) +CGO_ENABLED=1 CGO_CFLAGS="-O2 -D__BLST_PORTABLE__ -std=gnu11" GO111MODULE=on go build -o ./cmd/flow/flow ./cmd/flow + +# Or use Make +make binary + +# Run directly without building +go run cmd/flow/main.go [command] +``` + +## Testing + +```bash +# Run all tests +make test +# Equivalent: CGO_ENABLED=1 CGO_CFLAGS="-O2 -D__BLST_PORTABLE__ -std=gnu11" GO111MODULE=on go test -coverprofile=coverage.txt ./... + +# Run a single test package +CGO_ENABLED=1 CGO_CFLAGS="-O2 -D__BLST_PORTABLE__ -std=gnu11" go test ./internal/accounts/... + +# Run a specific test +CGO_ENABLED=1 CGO_CFLAGS="-O2 -D__BLST_PORTABLE__ -std=gnu11" go test ./internal/accounts/... -run TestFunctionName + +# Skip network-dependent tests (e.g. in sandboxed environments) +SKIP_NETWORK_TESTS=1 make test +``` + +## Linting + +```bash +make lint # Run golangci-lint +make fix-lint # Auto-fix lint issues +make check-headers # Verify Apache license headers on all Go files +go generate ./... # Regenerate generated code (required before lint) +``` + +## Architecture + +The CLI is a [Cobra](https://github.com/spf13/cobra)-based application with three main layers: + +### Entry Point +`cmd/flow/main.go` — wires all subcommands into the root `flow` command. + +### Command Framework (`internal/command/`) +The `command.Command` struct wraps a `cobra.Command` with two execution modes: +- `Run` — for commands that don't need a loaded `flow.json` state +- `RunS` — for commands that require an initialized project state (`*flowkit.State`) + +`Command.AddToParent()` handles all shared boilerplate: loading `flow.json`, resolving network/host, creating the gRPC gateway, initializing `flowkit.Services`, version checking, analytics, and error formatting. **All new commands should use this pattern.** + +Every command's run function returns a `command.Result` interface with three output methods: `String()` (human-readable), `Oneliner()` (grep-friendly inline), and `JSON()` (structured). The framework handles `--output`, `--filter`, and `--save` flags automatically. + +### Command Packages (`internal/`) +Each feature area is its own package with a top-level `Cmd *cobra.Command` that aggregates subcommands. Pattern: +- `accounts.Cmd` (`internal/accounts/`) — registered in `main.go` via `cmd.AddCommand(accounts.Cmd)` +- Subcommands (e.g., `get.go`, `create.go`) define a package-level `var getCommand = &command.Command{...}` and register via `init()` or the parent's `init()` + +Key packages: +- `internal/super/` — high-level "super commands": `flow init`, `flow dev`, `flow generate`, `flow flix` +- `internal/super/generator/` — code generation engine for Cadence contracts, scripts, transactions, and tests +- `internal/dependencymanager/` — `flow deps` commands for managing on-chain contract dependencies +- `internal/config/` — `flow config` subcommands for managing `flow.json` +- `internal/emulator/` — wraps the Flow emulator + +### flowkit Dependency +The CLI delegates all blockchain interactions to the `github.com/onflow/flowkit/v2` module (external). The `flowkit.Services` interface is the primary abstraction for network calls. The local `flowkit/` directory is a historical artifact (migrated to the external module) and contains only a README and schema. + +### Global Flags +Defined in `internal/command/global_flags.go`, applied to every command: `--network`, `--host`, `--log`, `--output`, `--filter`, `--save`, `--config-path`, `--yes`, `--skip-version-check`. + +### Configuration +`flow.json` is the project config file. `flowkit.Load()` reads it. The `internal/config/` commands modify it. `state.Networks()`, `state.Accounts()`, etc. provide typed access. + +## CLI Design Conventions +- Commands follow `noun verb` pattern (`flow accounts get`) +- Prefer flags over positional args; use args only for the primary required value +- `--output json` must always work for machine-readable output +- Errors go to stderr; normal output to stdout +- Progress indicators for long-running operations via `logger.StartProgress()` / `logger.StopProgress()` +- Long-running commands support `--yes` to skip confirmation prompts + +## License Headers +All Go source files must have the Apache 2.0 license header. Run `make check-headers` to verify. diff --git a/skills/query-blockchain/SKILL.md b/skills/query-blockchain/SKILL.md new file mode 100644 index 000000000..cb0374142 --- /dev/null +++ b/skills/query-blockchain/SKILL.md @@ -0,0 +1,291 @@ +--- +name: query-blockchain +description: Use when you need to read any data from the Flow blockchain — account state, blocks, events, transaction results, collections, or custom contract state via Cadence scripts. +--- + +# Querying the Flow Blockchain with flow-cli + +## Overview + +Use this skill any time you need on-chain data. Choose the right command from the decision table, then run it. + +**When the entity commands don't expose what you need, use `flow scripts execute`** — Cadence scripts can query any on-chain state and are the primary tool for anything not covered by the commands below. See [Cadence Scripts](#cadence-scripts). + +## Network + +Default: **mainnet**. Infer from conversation context: + +| Context | Flag | +|---|---| +| Default / production | `--network mainnet` | +| Testnet discussion | `--network testnet` | +| Local development / emulator | `--network emulator` | + +Access node endpoints (built-in): +- Mainnet: `access.mainnet.nodes.onflow.org:9000` +- Testnet: `access.devnet.nodes.onflow.org:9000` +- Emulator: `127.0.0.1:3569` + +Override with `--host ` to point at a custom access node. + +## Decision Table + +| What you need | Command | +|---|---| +| Account balance, keys, deployed contracts | `flow accounts get` | +| Account staking info | `flow accounts staking-info` | +| Block info | `flow blocks get` | +| Events emitted in a block range | `flow events get` | +| Regular transaction status / result | `flow transactions get` | +| System transaction for a block | `flow transactions get-system` | +| Scheduled transaction details | `flow schedule get` / `flow schedule list` | +| Collection contents | `flow collections get` | +| Network status (online/offline) | `flow status` | +| Protocol state snapshot | `flow snapshot save` | +| Anything not covered above | `flow scripts execute` | + +--- + +## Commands + +### Accounts + +```bash +flow accounts get [--include contracts] [--network mainnet] +``` + +- `--include contracts` adds deployed contract source code to the output +- Flow addresses must include the `0x` prefix (e.g. `0xf8d6e0586b0a20c7`) +- `` resolves via `flow.json` — only use names when a `flow.json` is present + +```bash +flow accounts get 0xe467b9dd11fa00df --network mainnet +flow accounts get 0xe467b9dd11fa00df --include contracts --network mainnet +flow accounts staking-info 0xe467b9dd11fa00df --network mainnet +``` + +### Blocks + +```bash +flow blocks get [--include transactions] [--events ] [--network mainnet] +``` + +```bash +flow blocks get latest --network mainnet +flow blocks get 12884163 --include transactions --network mainnet +flow blocks get latest --events A.1654653399040a61.FlowToken.TokensDeposited --network mainnet +``` + +### Events + +```bash +flow events get [ ...] [--last 10] [--start N --end M] [--network mainnet] +``` + +- Default: last 10 blocks. Use `--last N` to widen. +- `--start`/`--end` for explicit block height range. +- Multiple event types are fetched in parallel. +- Event name format: `A.
..` + +```bash +flow events get A.1654653399040a61.FlowToken.TokensDeposited --last 20 --network mainnet +flow events get A.1654653399040a61.FlowToken.TokensDeposited --start 11559500 --end 11559600 --network mainnet +flow events get A.1654653399040a61.FlowToken.TokensDeposited A.1654653399040a61.FlowToken.TokensWithdrawn --network mainnet +``` + +### Transactions + +```bash +# Regular transaction +flow transactions get [--include signatures,code,payload,fee-events] [--exclude events] [--network mainnet] + +# System transaction (by block, not tx hash) +flow transactions get-system [tx_id] [--network mainnet] + +# Scheduled transactions +flow schedule get [--network mainnet] +flow schedule list [--network mainnet] +``` + +### Collections + +```bash +flow collections get [--network mainnet] +``` + +### Network Status + +```bash +flow status --network mainnet +``` + +--- + +## Output Format + +All commands support `--output json` for machine-readable output. + +```bash +flow accounts get 0xe467b9dd11fa00df --output json --network mainnet +flow events get A.1654653399040a61.FlowToken.TokensDeposited --output json --network mainnet +``` + +Use `--filter ` to extract specific fields from results. + +--- + +## Cadence Scripts + +`flow scripts execute` is the most powerful read tool. Use it when: + +- You need data from a contract that has no dedicated CLI command +- You need to call a `view` function or read a field from a contract +- You need to combine data from multiple contracts in one query +- You need a historical snapshot at a specific block height + +```bash +flow scripts execute [args...] [--args-json '[{"type":"...","value":"..."}]'] [--block-height N] [--block-id ] [--network mainnet] +``` + +- Simple types (Address, UInt64, String, Bool) can be passed as positional args +- Use `--args-json` for complex types (UFix64, optionals, structs, arrays) +- `--block-height` / `--block-id` execute against historical state +- Write a temporary `.cdc` file, execute it, then clean up + +### Writing and Running Scripts + +Write script to a temp file, execute, clean up: + +```bash +# Write +cat > /tmp/query.cdc << 'EOF' +import FungibleToken from 0xf233dcee88fe0abe +import FlowToken from 0x1654653399040a61 + +access(all) fun main(address: Address): UFix64 { + let account = getAccount(address) + let vaultRef = account.capabilities + .borrow<&{FungibleToken.Balance}>(/public/flowTokenBalance) + ?? panic("Could not borrow FungibleToken Balance capability for account \(address) at path /public/flowTokenBalance. Make sure the account has a FlowToken Vault set up properly.") + return vaultRef.balance +} +EOF + +# Execute +flow scripts execute /tmp/query.cdc 0xe467b9dd11fa00df --network mainnet + +# Clean up +rm /tmp/query.cdc +``` + +### Passing Arguments + +```bash +# Simple types as positional args +flow scripts execute /tmp/query.cdc 0xe467b9dd11fa00df --network mainnet + +# Complex types with --args-json (JSON-Cadence encoding) +flow scripts execute /tmp/query.cdc --args-json '[{"type":"UFix64","value":"100.0"},{"type":"Address","value":"0xe467b9dd11fa00df"}]' --network mainnet + +# Historical state +flow scripts execute /tmp/query.cdc 0xe467b9dd11fa00df --block-height 12884163 --network mainnet +``` + +--- + +## Contract Addresses + +| Contract | Mainnet | Testnet | Emulator | +|---|---|---|---| +| FungibleToken | `0xf233dcee88fe0abe` | `0x9a0766d93b6608b7` | `0xee82856bf20e2aa6` | +| FungibleTokenMetadataViews | `0xf233dcee88fe0abe` | `0x9a0766d93b6608b7` | `0xf8d6e0586b0a20c7` | +| FungibleTokenSwitchboard | `0xf233dcee88fe0abe` | `0x9a0766d93b6608b7` | `0xf8d6e0586b0a20c7` | +| Burner | `0xf233dcee88fe0abe` | `0x9a0766d93b6608b7` | `0xf8d6e0586b0a20c7` | +| FlowToken | `0x1654653399040a61` | `0x7e60df042a9c0868` | `0x0ae53cb6e3f42a79` | +| NonFungibleToken | `0x1d7e57aa55817448` | `0x631e88ae7f1d7c20` | `0xf8d6e0586b0a20c7` | +| MetadataViews | `0x1d7e57aa55817448` | `0x631e88ae7f1d7c20` | `0xf8d6e0586b0a20c7` | +| ViewResolver | `0x1d7e57aa55817448` | `0x631e88ae7f1d7c20` | `0xf8d6e0586b0a20c7` | +| FlowFees | `0xf919ee77447b7497` | `0x912d5440f7e3769e` | `0xe5a8b7f23e8b548f` | +| FlowServiceAccount | `0xe467b9dd11fa00df` | `0x8c5303eaa26202d6` | `0xf8d6e0586b0a20c7` | +| FlowStorageFees | `0xe467b9dd11fa00df` | `0x8c5303eaa26202d6` | `0xf8d6e0586b0a20c7` | +| NodeVersionBeacon | `0xe467b9dd11fa00df` | `0x8c5303eaa26202d6` | `0xf8d6e0586b0a20c7` | +| RandomBeaconHistory | `0xe467b9dd11fa00df` | `0x8c5303eaa26202d6` | `0xf8d6e0586b0a20c7` | +| FlowIDTableStaking | `0x8624b52f9ddcd04a` | `0x9eca2b38b18b5dfe` | `0xf8d6e0586b0a20c7` | +| FlowEpoch | `0x8624b52f9ddcd04a` | `0x9eca2b38b18b5dfe` | `0xf8d6e0586b0a20c7` | +| FlowClusterQC | `0x8624b52f9ddcd04a` | `0x9eca2b38b18b5dfe` | `0xf8d6e0586b0a20c7` | +| FlowDKG | `0x8624b52f9ddcd04a` | `0x9eca2b38b18b5dfe` | `0xf8d6e0586b0a20c7` | +| FlowStakingCollection | `0x8d0e87b65159ae63` | `0x95e019a17d0e23d7` | `0xf8d6e0586b0a20c7` | +| LockedTokens | `0x8d0e87b65159ae63` | `0x95e019a17d0e23d7` | `0xf8d6e0586b0a20c7` | +| StakingProxy | `0x62430cf28c26d095` | `0x7aad92e5a0715d21` | `0xf8d6e0586b0a20c7` | +| EVM | `0xe467b9dd11fa00df` | `0x8c5303eaa26202d6` | `0xf8d6e0586b0a20c7` | +| FlowEVMBridge ¹ | `0x1e4aa0b87d10b141` | `0xdfc20aee650fcbdf` | `0xf8d6e0586b0a20c7` | +| NFTStorefrontV2 | `0x1d7e57aa55817448` | `0x2d55b98eb200daef` | `0xf8d6e0586b0a20c7` | +| HybridCustody | `0xd8a7e05a7ac670c0` | `0x294e44e1ec6993c6` | `0xf8d6e0586b0a20c7` | +| CapabilityFactory | `0xd8a7e05a7ac670c0` | `0x294e44e1ec6993c6` | `0xf8d6e0586b0a20c7` | +| CapabilityFilter | `0xd8a7e05a7ac670c0` | `0x294e44e1ec6993c6` | `0xf8d6e0586b0a20c7` | +| CapabilityDelegator | `0xd8a7e05a7ac670c0` | `0x294e44e1ec6993c6` | `0xf8d6e0586b0a20c7` | + +¹ The EVM bridge account hosts many contracts beyond FlowEVMBridge itself (FlowEVMBridgeConfig, FlowEVMBridgeUtils, FlowEVMBridgeNFTEscrow, FlowEVMBridgeTokenEscrow, CrossVMNFT, CrossVMToken, and more). Run `flow accounts get 0x1e4aa0b87d10b141 --network mainnet` for the current deployed contract list, or check the [flow-evm-bridge](https://github.com/onflow/flow-evm-bridge) repo for available scripts. + +--- + +## Cadence Script Recipes & Data Structures + +See [cadence-scripts.md](cadence-scripts.md) for 20+ ready-to-use Cadence scripts organized by category: +- **Token queries** — FLOW balance, total supply, generic FT balance, FT metadata +- **Account & storage** — storage capacity, available balance, account creation fee, fee parameters +- **Epoch** — counter, phase, metadata, timing config +- **Staking** — node info, staked node IDs, total staked, by role, requirements, rewards, delegator info, staking collections +- **Protocol** — node version beacon, random beacon source +- **NFT** — collection IDs, NFT metadata (Display) +- **Key data structures** — NodeInfo, DelegatorInfo, EpochMetadata, EpochPhase, Node Roles + +--- + +## Common Event Types + +| Event | Description | +|---|---| +| `A.f233dcee88fe0abe.FungibleToken.Deposited` | Any fungible token deposited | +| `A.f233dcee88fe0abe.FungibleToken.Withdrawn` | Any fungible token withdrawn | +| `A.f233dcee88fe0abe.FungibleToken.Burned` | Any fungible token burned | +| `A.1d7e57aa55817448.NonFungibleToken.Deposited` | Any NFT deposited to a collection | +| `A.1d7e57aa55817448.NonFungibleToken.Withdrawn` | Any NFT withdrawn from a collection | +| `A.8624b52f9ddcd04a.FlowEpoch.NewEpoch` | New epoch started | +| `A.8624b52f9ddcd04a.FlowEpoch.EpochSetup` | Epoch setup phase began | +| `A.8624b52f9ddcd04a.FlowEpoch.EpochCommit` | Epoch commit phase began | +| `A.8624b52f9ddcd04a.FlowIDTableStaking.NewNodeCreated` | New staking node registered | +| `A.8624b52f9ddcd04a.FlowIDTableStaking.TokensCommitted` | Tokens committed to stake | +| `A.8624b52f9ddcd04a.FlowIDTableStaking.RewardsPaid` | Staking rewards distributed | +| `A.8624b52f9ddcd04a.FlowIDTableStaking.NewDelegatorCreated` | New delegator registered | +| `A.f919ee77447b7497.FlowFees.FeesDeducted` | Transaction fees paid | +| `A.f919ee77447b7497.FlowFees.TokensDeposited` | Fees deposited to fee vault | + +--- + +## Available Script Libraries + +For more complex queries, clone these repos to `/tmp` and use their scripts directly: + +| Repo | Scripts Path | Use For | +|---|---|---| +| [flow-core-contracts](https://github.com/onflow/flow-core-contracts) | `transactions/*/scripts/` | Staking, epoch, fees, locked tokens, version beacon, random beacon | +| [flow-ft](https://github.com/onflow/flow-ft) | `transactions/scripts/`, `transactions/metadata/scripts/` | FT balances, supply, metadata, switchboard | +| [flow-nft](https://github.com/onflow/flow-nft) | `transactions/scripts/` | NFT collections, metadata views, cross-VM views | +| [flow-evm-bridge](https://github.com/onflow/flow-evm-bridge) | `cadence/scripts/` | Bridge state, onboarding checks, escrow, EVM balances, cross-VM associations | +| [nft-storefront](https://github.com/onflow/nft-storefront) | `scripts/` | Marketplace listings, ghost listings, commission receivers, storefront IDs | +| [hybrid-custody](https://github.com/onflow/hybrid-custody) | `scripts/hybrid-custody/`, `scripts/delegator/`, `scripts/factory/` | Child/parent account relationships, cross-account NFT/FT access, capability delegation | + +```bash +# Example: use an existing script from flow-core-contracts +git clone --depth 1 https://github.com/onflow/flow-core-contracts.git /tmp/flow-core-contracts +flow scripts execute /tmp/flow-core-contracts/transactions/idTableStaking/scripts/get_node_info.cdc "abc123...def456" --network mainnet +``` + +Note: Some repo scripts use `import "ContractName"` syntax (no address). These require a `flow.json` with address mappings. For ad-hoc queries, replace with explicit addresses: +```cadence +// Repo style (requires flow.json aliases): +import "FlowToken" +// Direct style (works without flow.json): +import FlowToken from 0x1654653399040a61 +``` diff --git a/skills/query-blockchain/cadence-scripts.md b/skills/query-blockchain/cadence-scripts.md new file mode 100644 index 000000000..e2ffa4169 --- /dev/null +++ b/skills/query-blockchain/cadence-scripts.md @@ -0,0 +1,341 @@ +# Cadence Script Recipes + +Reference repos for existing scripts (clone to /tmp if you need full source): +- [flow-core-contracts](https://github.com/onflow/flow-core-contracts) — staking, epoch, fees, token +- [flow-ft](https://github.com/onflow/flow-ft) — fungible token standard +- [flow-nft](https://github.com/onflow/flow-nft) — NFT standard, metadata views + +All scripts below use **mainnet** addresses. For testnet, substitute addresses from the contract address tables in SKILL.md. + +--- + +## Token Queries + +### FLOW Token Balance + +```cadence +import FungibleToken from 0xf233dcee88fe0abe +import FlowToken from 0x1654653399040a61 + +access(all) fun main(address: Address): UFix64 { + let account = getAccount(address) + let vaultRef = account.capabilities + .borrow<&{FungibleToken.Balance}>(/public/flowTokenBalance) + ?? panic("Could not borrow FungibleToken Balance capability for account \(address) at path /public/flowTokenBalance. Make sure the account has a FlowToken Vault set up properly.") + return vaultRef.balance +} +``` + +### FLOW Total Supply + +```cadence +import FlowToken from 0x1654653399040a61 + +access(all) fun main(): UFix64 { + return FlowToken.totalSupply +} +``` + +### Generic FT Balance (Any Token by Path) + +```cadence +import FungibleToken from 0xf233dcee88fe0abe + +access(all) fun main(address: Address, path: PublicPath): UFix64 { + return getAccount(address).capabilities + .borrow<&{FungibleToken.Balance}>(path)?.balance + ?? panic("Could not borrow FungibleToken Balance capability for account \(address) at path \(path). Make sure the account has a Fungible Token Vault set up at this path.") +} +``` + +### FT Metadata (Display Info) + +```cadence +import FungibleToken from 0xf233dcee88fe0abe +import FungibleTokenMetadataViews from 0xf233dcee88fe0abe + +access(all) fun main(address: Address, vaultPath: PublicPath): FungibleTokenMetadataViews.FTDisplay? { + let account = getAccount(address) + let vaultRef = account.capabilities + .borrow<&{FungibleToken.Vault}>(vaultPath) + ?? panic("Could not borrow FungibleToken Vault capability for account \(address) at path \(vaultPath). Make sure the account has a Fungible Token Vault set up at this path.") + return FungibleTokenMetadataViews.getFTDisplay(vaultRef) +} +``` + +--- + +## Account & Storage Queries + +### Account Storage Capacity + +```cadence +import FlowStorageFees from 0xe467b9dd11fa00df + +access(all) fun main(address: Address): UFix64 { + return FlowStorageFees.calculateAccountCapacity(address) +} +``` + +### Account Available Balance (After Storage Reservation) + +```cadence +import FlowStorageFees from 0xe467b9dd11fa00df + +access(all) fun main(address: Address): UFix64 { + return FlowStorageFees.defaultTokenAvailableBalance(address) +} +``` + +### Account Creation Fee + +```cadence +import FlowServiceAccount from 0xe467b9dd11fa00df + +access(all) fun main(): UFix64 { + return FlowServiceAccount.accountCreationFee +} +``` + +### Transaction Fee Parameters + +```cadence +import FlowFees from 0xf919ee77447b7497 + +access(all) fun main(): FlowFees.FeeParameters { + return FlowFees.getFeeParameters() +} +``` + +--- + +## Epoch Queries + +### Current Epoch Counter + +```cadence +import FlowEpoch from 0x8624b52f9ddcd04a + +access(all) fun main(): UInt64 { + return FlowEpoch.currentEpochCounter +} +``` + +### Current Epoch Phase + +```cadence +import FlowEpoch from 0x8624b52f9ddcd04a + +// Returns: 0=StakingAuction, 1=EpochSetup, 2=EpochCommit +access(all) fun main(): UInt8 { + return FlowEpoch.currentEpochPhase.rawValue +} +``` + +### Epoch Metadata + +```cadence +import FlowEpoch from 0x8624b52f9ddcd04a + +access(all) fun main(counter: UInt64): FlowEpoch.EpochMetadata { + return FlowEpoch.getEpochMetadata(counter)! +} +``` + +### Epoch Timing Config + +```cadence +import FlowEpoch from 0x8624b52f9ddcd04a + +access(all) fun main(): FlowEpoch.EpochTimingConfig { + return FlowEpoch.getEpochTimingConfig() +} +``` + +--- + +## Staking Queries + +### Node Info + +```cadence +import FlowIDTableStaking from 0x8624b52f9ddcd04a + +access(all) fun main(nodeID: String): FlowIDTableStaking.NodeInfo { + return FlowIDTableStaking.NodeInfo(nodeID: nodeID) +} +``` + +### All Staked Node IDs + +```cadence +import FlowIDTableStaking from 0x8624b52f9ddcd04a + +access(all) fun main(): [String] { + return FlowIDTableStaking.getStakedNodeIDs() +} +``` + +### Total FLOW Staked + +```cadence +import FlowIDTableStaking from 0x8624b52f9ddcd04a + +access(all) fun main(): UFix64 { + return FlowIDTableStaking.getTotalStaked() +} +``` + +### Total Staked by Node Role + +```cadence +import FlowIDTableStaking from 0x8624b52f9ddcd04a + +// Roles: 1=Collector, 2=Consensus, 3=Execution, 4=Verification, 5=Access +access(all) fun main(role: UInt8): UFix64 { + return FlowIDTableStaking.getTotalTokensStakedByNodeType()[role]! +} +``` + +### Stake Requirements by Node Type + +```cadence +import FlowIDTableStaking from 0x8624b52f9ddcd04a + +access(all) fun main(): {UInt8: UFix64} { + return FlowIDTableStaking.getMinimumStakeRequirements() +} +``` + +### Weekly Epoch Reward Payout + +```cadence +import FlowIDTableStaking from 0x8624b52f9ddcd04a + +access(all) fun main(): UFix64 { + return FlowIDTableStaking.getEpochTokenPayout() +} +``` + +### Delegator Reward Cut Percentage + +```cadence +import FlowIDTableStaking from 0x8624b52f9ddcd04a + +access(all) fun main(): UFix64 { + return FlowIDTableStaking.getRewardCutPercentage() +} +``` + +### Delegator Info + +```cadence +import FlowIDTableStaking from 0x8624b52f9ddcd04a + +access(all) fun main(nodeID: String, delegatorID: UInt32): FlowIDTableStaking.DelegatorInfo { + return FlowIDTableStaking.DelegatorInfo(nodeID: nodeID, delegatorID: delegatorID) +} +``` + +### Staking Collection — All Node Info for an Account + +```cadence +import FlowStakingCollection from 0x8d0e87b65159ae63 + +access(all) fun main(address: Address): [FlowStakingCollection.NodeInfo] { + return FlowStakingCollection.getAllNodeInfo(address: address) +} +``` + +### Staking Collection — All Delegator Info for an Account + +```cadence +import FlowStakingCollection from 0x8d0e87b65159ae63 + +access(all) fun main(address: Address): [FlowStakingCollection.DelegatorInfo] { + return FlowStakingCollection.getAllDelegatorInfo(address: address) +} +``` + +--- + +## Protocol Queries + +### Current Node Version + +```cadence +import NodeVersionBeacon from 0xe467b9dd11fa00df + +access(all) fun main(): NodeVersionBeacon.Semver { + return NodeVersionBeacon.getCurrentVersionBoundary().version +} +``` + +### Latest Random Beacon Source + +```cadence +import RandomBeaconHistory from 0xe467b9dd11fa00df + +access(all) fun main(): RandomBeaconHistory.RandomSourceHistoryEntry { + return RandomBeaconHistory.getLatestSourceOfRandomness() +} +``` + +--- + +## NFT Queries + +### NFT Collection IDs + +```cadence +import NonFungibleToken from 0x1d7e57aa55817448 + +access(all) fun main(address: Address, collectionPublicPath: PublicPath): [UInt64] { + let account = getAccount(address) + let collectionRef = account.capabilities + .borrow<&{NonFungibleToken.Collection}>(collectionPublicPath) + ?? panic("Could not borrow NonFungibleToken Collection capability for account \(address) at path \(collectionPublicPath). Make sure the account has an NFT Collection set up at this path.") + return collectionRef.getIDs() +} +``` + +### NFT Metadata (Display) + +```cadence +import NonFungibleToken from 0x1d7e57aa55817448 +import MetadataViews from 0x1d7e57aa55817448 + +access(all) fun main(address: Address, collectionPublicPath: PublicPath, id: UInt64): MetadataViews.Display? { + let account = getAccount(address) + let collectionRef = account.capabilities + .borrow<&{NonFungibleToken.Collection}>(collectionPublicPath) + ?? panic("Could not borrow NonFungibleToken Collection capability for account \(address) at path \(collectionPublicPath). Make sure the account has an NFT Collection set up at this path.") + let nft = collectionRef.borrowNFT(id)! + return MetadataViews.getDisplay(nft) +} +``` + +--- + +## Key Data Structures + +### FlowIDTableStaking.NodeInfo +- `id: String` (64 hex chars), `role: UInt8` (1-5) +- `networkingAddress`, `networkingKey`, `stakingKey`: String +- Token buckets: `tokensStaked`, `tokensCommitted`, `tokensUnstaking`, `tokensUnstaked`, `tokensRewarded`: UFix64 +- `delegators`, `delegatorIDCounter`, `initialWeight` + +### FlowIDTableStaking.DelegatorInfo +- `id: UInt32`, `nodeID: String` +- Token buckets: `tokensCommitted`, `tokensStaked`, `tokensUnstaking`, `tokensRewarded`, `tokensUnstaked`: UFix64 + +### FlowEpoch.EpochMetadata +- `counter: UInt64`, `seed: String`, `startView`, `endView`, `stakingEndView`: UInt64 +- `totalRewards: UFix64`, `rewardsPaid: Bool` +- `collectorClusters`, `clusterQCs`, `dkgKeys` + +### FlowEpoch.EpochPhase +- `STAKINGAUCTION (0)`, `EPOCHSETUP (1)`, `EPOCHCOMMIT (2)` + +### Node Roles +- 1=Collector, 2=Consensus, 3=Execution, 4=Verification, 5=Access