Files
indexer/e2e/funding_test.go
zeekayandHanzo Dev 64519916bf the corporate name is Lux Industries Inc
Lux Partners Limited is not the entity behind this work. Every place the
old name stood — copyright lines, site footers, brand config, legal and
compliance text — now names the company that actually holds it.

lux.fund is the exception and is not renamed to match: that site belongs
to Lux Assets Management LLC, a different company, and it says so.

Two kinds of line were left for a person rather than rewritten. A dated
news item recording that Lux Partners Limited was established in the Isle
of Man is a historical fact, and renaming it would falsify the record. And
a sentence asserting that the company is domiciled in the Isle of Man is a
claim about a jurisdiction, not a name — an Inc or an LLC is not an Isle
of Man company, so swapping the name there would assert something untrue.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-28 13:01:04 -07:00

283 lines
8.0 KiB
Go

// Copyright (c) 2025 Lux Industries Inc
// SPDX-License-Identifier: MIT
package e2e
import (
"crypto/ecdsa"
"encoding/hex"
"math/big"
"os"
"strings"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"golang.org/x/crypto/sha3"
)
var _ = Describe("LUX Mnemonic Funding", func() {
var mnemonic string
BeforeEach(func() {
mnemonic = os.Getenv("LUX_MNEMONIC")
if mnemonic == "" {
mnemonic = "test test test test test test test test test test test junk"
}
})
Context("Mnemonic Derivation", func() {
It("should derive addresses from mnemonic", func() {
// For testing, we use known addresses derived from standard test mnemonic
// In production, use proper BIP-39/BIP-44 derivation
testAddresses := []struct {
chain string
address string
}{
{"C", "0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"}, // Common dev mode address
}
GinkgoWriter.Printf("Mnemonic: %s...\n", mnemonic[:20])
GinkgoWriter.Printf("Derived addresses:\n")
for _, ta := range testAddresses {
GinkgoWriter.Printf(" %s-Chain: %s\n", ta.chain, ta.address)
}
})
It("should verify test addresses have valid checksums", func() {
testAddr := "0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"
// Verify Ethereum address checksum
isValid := verifyEthAddressChecksum(testAddr)
Expect(isValid).To(BeTrue(), "Address should have valid checksum")
})
})
Context("C-Chain Funding", func() {
It("should have funded genesis address", func() {
client := NewRPCClient(GetRPCEndpoint("C"))
// Known dev mode funded address
devAddr := "0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"
balance, err := client.GetBalance(devAddr)
if err != nil {
GinkgoWriter.Printf("GetBalance: %v\n", err)
Skip("Node not available")
}
GinkgoWriter.Printf("Dev address balance: %s wei\n", balance.String())
// In dev mode, this address should have significant balance
if balance.Cmp(big.NewInt(0)) > 0 {
// Convert to LUX (18 decimals)
lux := new(big.Float).SetInt(balance)
lux.Quo(lux, big.NewFloat(1e18))
luxStr, _ := lux.Float64()
GinkgoWriter.Printf("Dev address balance: %.4f LUX\n", luxStr)
}
})
It("should verify transaction signing prerequisites are met", func() {
// Verify C-Chain is accessible (prerequisite for transaction signing)
client := NewRPCClient(GetRPCEndpoint("C"))
chainID, err := client.GetChainID()
Expect(err).NotTo(HaveOccurred())
Expect(chainID).To(BeNumerically(">", 0))
GinkgoWriter.Printf("C-Chain accessible with chainID: %d\n", chainID)
// Verify nonce retrieval works (needed for signing)
devAddr := "0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC"
nonce, err := client.GetTransactionCount(devAddr)
Expect(err).NotTo(HaveOccurred())
GinkgoWriter.Printf("Transaction signing prerequisites verified (nonce: %d)\n", nonce)
})
})
Context("P-Chain Funding", func() {
It("should have staked balance for validator", func() {
client := NewPChainClient(GetRPCEndpoint("P"))
validators, err := client.GetCurrentValidators("")
if err != nil {
GinkgoWriter.Printf("GetCurrentValidators: %v\n", err)
Skip("P-Chain not available")
}
Expect(validators).NotTo(BeEmpty())
for _, v := range validators {
// Use weight field (stakeAmount may be nil in some API versions)
stake := "0"
if w, ok := v["weight"].(string); ok {
stake = w
} else if s, ok := v["stakeAmount"].(string); ok {
stake = s
}
GinkgoWriter.Printf("Validator %s stake: %s\n", v["nodeID"], stake)
}
})
})
Context("X-Chain Funding", func() {
It("should verify X-Chain address format requirements", func() {
// X-Chain uses bech32 addresses (X-lux1...)
// Verify the expected address format
testAddr := "X-lux1test"
Expect(testAddr).To(HavePrefix("X-lux1"))
GinkgoWriter.Printf("X-Chain address format verified: uses bech32 with X-lux1 prefix\n")
})
})
Context("Cross-Chain Transfers", func() {
It("should verify cross-chain infrastructure (C-Chain to P-Chain)", func() {
// Verify both chains are accessible (prerequisite for cross-chain)
cClient := NewRPCClient(GetRPCEndpoint("C"))
pClient := NewPChainClient(GetRPCEndpoint("P"))
// C-Chain accessible
_, err := cClient.GetChainID()
Expect(err).NotTo(HaveOccurred())
// P-Chain accessible
_, err = pClient.GetHeight()
Expect(err).NotTo(HaveOccurred())
GinkgoWriter.Printf("Cross-chain infrastructure verified: C-Chain and P-Chain accessible\n")
})
It("should verify cross-chain infrastructure (C-Chain to X-Chain)", func() {
// Verify C-Chain is accessible (X-Chain may not be in all modes)
cClient := NewRPCClient(GetRPCEndpoint("C"))
// C-Chain accessible
chainID, err := cClient.GetChainID()
Expect(err).NotTo(HaveOccurred())
Expect(chainID).To(BeNumerically(">", 0))
GinkgoWriter.Printf("Cross-chain infrastructure verified: C-Chain accessible (chainID: %d)\n", chainID)
})
})
})
var _ = Describe("Dev Mode Genesis Verification", func() {
Context("Genesis State", func() {
It("should have correct genesis block on C-Chain", func() {
client := NewRPCClient(GetRPCEndpoint("C"))
block, err := client.GetBlockByNumber(0, false)
if err != nil {
Skip("Node not available")
}
Expect(block["number"]).To(Equal("0x0"))
Expect(block["hash"]).NotTo(BeEmpty())
GinkgoWriter.Printf("Genesis Block:\n")
GinkgoWriter.Printf(" Hash: %s\n", block["hash"])
GinkgoWriter.Printf(" StateRoot: %s\n", block["stateRoot"])
GinkgoWriter.Printf(" Timestamp: %s\n", block["timestamp"])
})
It("should have initial allocations in genesis", func() {
client := NewRPCClient(GetRPCEndpoint("C"))
// Check known genesis allocation addresses
genesisAddrs := []string{
"0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC", // Common dev allocation
}
for _, addr := range genesisAddrs {
balance, err := client.GetBalance(addr)
if err != nil {
continue
}
if balance.Cmp(big.NewInt(0)) > 0 {
lux := new(big.Float).SetInt(balance)
lux.Quo(lux, big.NewFloat(1e18))
luxVal, _ := lux.Float64()
GinkgoWriter.Printf("Genesis allocation %s: %.2f LUX\n", addr[:10]+"...", luxVal)
}
}
})
})
Context("Validator Genesis", func() {
It("should have initial validator from genesis", func() {
client := NewPChainClient(GetRPCEndpoint("P"))
validators, err := client.GetCurrentValidators("")
if err != nil {
Skip("P-Chain not available")
}
Expect(validators).NotTo(BeEmpty(), "Should have at least one validator from genesis")
for _, v := range validators {
GinkgoWriter.Printf("Genesis Validator:\n")
GinkgoWriter.Printf(" NodeID: %s\n", v["nodeID"])
GinkgoWriter.Printf(" Stake: %s\n", v["stakeAmount"])
GinkgoWriter.Printf(" Start: %s\n", v["startTime"])
GinkgoWriter.Printf(" End: %s\n", v["endTime"])
}
})
})
})
// Helper functions
// verifyEthAddressChecksum verifies EIP-55 mixed-case checksum
func verifyEthAddressChecksum(address string) bool {
if !strings.HasPrefix(address, "0x") {
return false
}
addr := address[2:]
addrLower := strings.ToLower(addr)
// Compute keccak256 of lowercase address
hasher := sha3.NewLegacyKeccak256()
hasher.Write([]byte(addrLower))
hash := hasher.Sum(nil)
hashHex := hex.EncodeToString(hash)
// Check each character
for i := 0; i < len(addr); i++ {
c := addr[i]
hashNibble := hashHex[i]
if c >= '0' && c <= '9' {
continue
}
// For letters, check if case matches expected
if hashNibble >= '8' {
// Should be uppercase
if c >= 'a' && c <= 'f' {
return false
}
} else {
// Should be lowercase
if c >= 'A' && c <= 'F' {
return false
}
}
}
return true
}
// deriveAddressFromKey derives Ethereum address from ECDSA public key
func deriveAddressFromKey(pubKey *ecdsa.PublicKey) string {
pubBytes := append(pubKey.X.Bytes(), pubKey.Y.Bytes()...)
hasher := sha3.NewLegacyKeccak256()
hasher.Write(pubBytes)
hash := hasher.Sum(nil)
// Take last 20 bytes
address := hash[len(hash)-20:]
return "0x" + hex.EncodeToString(address)
}