feat: implement TFT-to-SPORE bridge with batch_all memo extraction #1

Merged
mahmoud merged 16 commits from development into main 2026-02-26 13:13:29 +00:00
Owner

Changes

  • Extract Hero Ledger address from Utility::batch_all extrinsics by
    scanning raw SCALE-encoded bytes for System::remark containing the
    64-char hex destination address
  • Fix amount truncation: pass raw planck amounts (u64) through the
    event pipeline; handlers convert to SPORE raw units (u128, 18 decimals)
  • Auto-register recipients on SPORE contract via storage_deposit before
    transfer (works around unreliable is_registered SDK method)
  • Use HeroLedgerClient::connect_with_root with network-derived root
    account (devnet→dev.hero, testnet→test.hero, mainnet→hero)
  • Switch hero_ledger dependency from local path to git for CI/deployment
  • Document block cursor setup in README to avoid scanning from genesis
### Changes - Extract Hero Ledger address from Utility::batch_all extrinsics by scanning raw SCALE-encoded bytes for System::remark containing the 64-char hex destination address - Fix amount truncation: pass raw planck amounts (u64) through the event pipeline; handlers convert to SPORE raw units (u128, 18 decimals) - Auto-register recipients on SPORE contract via storage_deposit before transfer (works around unreliable is_registered SDK method) - Use HeroLedgerClient::connect_with_root with network-derived root account (devnet→dev.hero, testnet→test.hero, mainnet→hero) - Switch hero_ledger dependency from local path to git for CI/deployment - Document block cursor setup in README to avoid scanning from genesis
feat: implement TFT-to-SPORE bridge with batch_all memo extraction
Some checks failed
Test / test (push) Successful in 3m17s
Test / test (pull_request) Failing after 1s
cd739c4de4
- Extract Hero Ledger address from Utility::batch_all extrinsics by
  scanning raw SCALE-encoded bytes for System::remark containing the
  64-char hex destination address
- Fix amount truncation: pass raw planck amounts (u64) through the
  event pipeline; handlers convert to SPORE raw units (u128, 18 decimals)
- Auto-register recipients on SPORE contract via storage_deposit before
  transfer (works around unreliable is_registered SDK method)
- Use HeroLedgerClient::connect_with_root with network-derived root
  account (devnet→dev.hero, testnet→test.hero, mainnet→hero)
- Switch hero_ledger dependency from local path to git for CI/deployment
- Document block cursor setup in README to avoid scanning from genesis
- Fix u128→u64 silent truncation on transfer amounts by widening
  ChainEvent.amount, PendingTx.amount, and calculate_spore_amount to u128
- Fix historical block scanning by using subxt LegacyRpcMethods for
  direct chain_getBlockHash RPC, bypassing broken upstream client method
- Prevent double-spend on crash recovery by replacing is_processed() with
  get_status() in process_event — PROCESSING records are now skipped
- Upgrade stuck transaction warnings to error-level with manual SQL
  resolution instructions and CRITICAL logging on mark_confirmed failure
- Add graceful shutdown via SIGINT/SIGTERM with tokio::signal, saving
  cursor before clean exit
- Add RPC reconnection logic that recreates TFChain client after 3
  consecutive poll failures
- Add configurable max retry limit (MAX_RETRIES, default 5) to stop
  retrying permanently-failed transactions
- Add configurable minimum transfer amount (MIN_TFT_AMOUNT, default
  1 TFT) to reject dust transfers
- Improve memo extraction to handle multiple System::remark calls in
  batch_all, rejecting all-zeros addresses
- HTTP API server (/health, /status, /txs) with query filters and pagination
- CLI commands: status, retry, resolve for operator administration
- Dual hash: store both synthetic tx_hash and extrinsic_hash, lookup by either
- Remove unused retention feature (delete_older_than_days, tx_retention_days)
- Fix silent memo loss when block.extrinsics() fails (now warns)
- Fix negative limit bypass in /txs (clamp 1..500)
- Fix cmd_retry not resetting retry counter (new reset_for_retry method)
- Fix non-deterministic find_tx on hash collision (prefer tx_hash match)
- Consolidate duplicate extrinsic lookup in decode_transfer_event
- Replace serde_json unwrap with proper error handling in handlers
- Add DB indices on sender and created_at columns
- Validate API_PORT <= 65535 before u16 cast
docs: add CLI reference and fix tx_hash query parameter
Some checks failed
Test / test (pull_request) Failing after 2s
Test / test (push) Successful in 4m7s
62aad83eb2
- Add docs/cli.md with full command reference, build instructions, and examples
- Accept both ?tx= and ?tx_hash= as query parameter names for /txs endpoint
- Document that hash values must not be wrapped in quotes
- Link CLI and API docs from README

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat: add automatic TFT refund system for invalid transfers
Some checks failed
Test / test (pull_request) Failing after 1s
Test / test (push) Successful in 3m22s
367bd539ce
- Add Refunder trait and TfChainRefunder for sending TFT back on invalid memo
- Add RefundHandler as catch-all for unmatched treasury transfers
- Add REFUNDED/REFUND_FAILED statuses with V3 DB migration
- Extend config with REFUND_ENABLED, TFCHAIN_TREASURY_MNEMONIC, REFUND_FEE_PLANCK
- Add is_refundable() to BridgeError for inline refund on handler failure
- Add comprehensive unit tests for refund flows in bridge, store, config, error
fix: use GITHUB_HEAD_REF for PR checkout branch in CI
Some checks failed
Test / test (pull_request) Successful in 3m24s
Test / test (push) Has been cancelled
01a4a9600d
- GITHUB_REF_NAME resolves to the PR number on pull_request events,
  causing "Remote branch 1 not found" clone failures
style: reformat code for improved readability
Some checks failed
Test / test (push) Has been cancelled
Test / test (pull_request) Has been cancelled
5d5d964439
- Break long lines into multiple for clarity
- Adjust indentation and newline usage
- Reformat function calls and macro arguments
ci: add fmt check and make clippy a hard failure
All checks were successful
Test / test (push) Successful in 5m34s
Test / test (pull_request) Successful in 5m34s
438a8e1444
- Add cargo fmt --check step to enforce formatting
- Remove continue-on-error from clippy so lint warnings block CI
docs: add API integration guide and update config docs
All checks were successful
Test / test (pull_request) Successful in 3m26s
Test / test (push) Successful in 3m58s
171580febd
- Add API integration guide for UI clients
- Detail API endpoints, transaction lifecycle, and polling
- Expand optional configuration variables documentation
- Add refund-specific configuration variables
- Update NEAR RPC endpoint example
feat: add Docker support, configurable operational tuning, and server tests
Some checks failed
Test / test (push) Failing after 3m20s
Test / test (pull_request) Failing after 3m23s
9a7549b2c6
Add multi-stage Dockerfile with dependency caching, docker-compose with
healthcheck, and .dockerignore. Make STUCK_CHECK_INTERVAL and
RECONNECT_THRESHOLD configurable via env vars instead of hardcoded
constants. Add comprehensive API server tests using tower::oneshot.
Update Makefile with Docker and lint targets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
style: reformat code for improved readability
All checks were successful
Test / test (push) Successful in 6m27s
Test / test (pull_request) Successful in 6m28s
a85645e3af
- Apply consistent line wrapping and indentation
- Adjust function signature formatting
- Reorder some import statements
fix: bump Dockerfile Rust version to 1.92 (required by dependencies)
All checks were successful
Test / test (push) Successful in 5m31s
Test / test (pull_request) Successful in 5m32s
1171cd4742
perf: add concurrent block scanning with configurable batch size:
Some checks failed
Test / test (pull_request) Failing after 5m41s
Test / test (push) Failing after 5m43s
916e2ab0c4
- Fetch blocks concurrently via buffer_unordered (SCAN_CONCURRENCY)
- Cap scan range per poll cycle (SCAN_BATCH_SIZE) for incremental cursor advance- Add progress logging every N blocks (SCAN_PROGRESS_INTERVAL)
- Cancel in-flight polls immediately on shutdown signal
- Add futures crate dependency for stream concurrency
docs: update documentation with refund flow
Some checks failed
Test / test (pull_request) Failing after 3m23s
Test / test (push) Failing after 3m25s
adba99dff3
- Convert state, overview, and sequence diagrams to Mermaid
- Document TFT refund mechanism and new transaction statuses
- Add `refund_tx` to transaction examples and schema
- Introduce new block scanning and refund configuration
- Update quick start with Docker commands and make targets
fix: resolve mermaid syntax and clippy lint errors
All checks were successful
Test / test (pull_request) Successful in 3m28s
Test / test (push) Successful in 4m0s
d90639cf7a
- Fix stateDiagram-v2 note syntax in api-integration.md
- Replace modulo check with is_multiple_of() for Rust 1.92 clippy
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_tfspores!1
No description provided.