Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions config/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,20 @@ const (
MainnetUSDCMint = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"

// Testnet constants.
TestnetLedgerPublicRPCURL = "https://doublezerolocalnet.rpcpool.com/8a4fd3f4-0977-449f-88c7-63d4b0f10f16"
TestnetServiceabilityProgramID = "DZtnuQ839pSaDMFG5q1ad2V95G82S5EC4RrB3Ndw2Heb"
TestnetTelemetryProgramID = "3KogTMmVxc5eUHtjZnwm136H5P8tvPwVu4ufbGPvM7p1"
TestnetInternetLatencyCollectorPK = "HWGQSTmXWMB85NY2vFLhM1nGpXA8f4VCARRyeGNbqDF1"
TestnetDeviceLocalASN = 65342
TestnetTwoZOracleURL = "https://sol-2z-oracle-api-v1.testnet.doublezero.xyz"
TestnetSolanaRPC = "https://api.testnet.solana.com"
TestnetTelemetryFlowIngestURL = "http://telemetry-flow-in.testnet.doublezero.xyz"
TestnetTelemetryStateIngestURL = "https://telemetry-state-in-testnet.doublezero.xyz"
TestnetGeolocationProgramID = "3AG2BCA7gAm47Q6xZzPQcUUYvnBjxAvPKnPz919cxHF4"
TestnetShredSubscriptionProgramID = "dzshrr3yL57SB13sJPYHYo3TV8Bo1i1FxkyrZr3bKNE"
TestnetUSDCMint = "uSDZq2RMuxrEf7gqgDjR8wJCtCyaDAQk2e5jLAaoeeM"
TestnetLedgerPublicRPCURL = "https://doublezerolocalnet.rpcpool.com/8a4fd3f4-0977-449f-88c7-63d4b0f10f16"
TestnetServiceabilityProgramID = "DZtnuQ839pSaDMFG5q1ad2V95G82S5EC4RrB3Ndw2Heb"
TestnetTelemetryProgramID = "3KogTMmVxc5eUHtjZnwm136H5P8tvPwVu4ufbGPvM7p1"
TestnetInternetLatencyCollectorPK = "HWGQSTmXWMB85NY2vFLhM1nGpXA8f4VCARRyeGNbqDF1"
TestnetDeviceLocalASN = 65342
TestnetTwoZOracleURL = "https://sol-2z-oracle-api-v1.testnet.doublezero.xyz"
TestnetSolanaRPC = "https://api.testnet.solana.com"
TestnetTelemetryFlowIngestURL = "http://telemetry-flow-in.testnet.doublezero.xyz"
TestnetTelemetryStateIngestURL = "https://telemetry-state-in-testnet.doublezero.xyz"
TestnetGeolocationProgramID = "3AG2BCA7gAm47Q6xZzPQcUUYvnBjxAvPKnPz919cxHF4"
TestnetShredSubscriptionProgramID = "dzshrr3yL57SB13sJPYHYo3TV8Bo1i1FxkyrZr3bKNE"
// Testnet shred-subscription runs on Solana devnet, so settlement uses the
// Solana devnet USDC mint (not the DZ ledger testnet mint).
TestnetUSDCMint = "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"
TestnetTelemetryGNMITunnelServerAddr = "gnmic-testnet.doublezero.xyz:443"

// Devnet constants.
Expand Down
12 changes: 8 additions & 4 deletions e2e/internal/qa/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ type Client struct {

// Settlement config passed to doublezero-solana shreds commands.
// SolanaRPCURL is the Solana RPC endpoint for settlement transactions (--url).
// On testnet this is the DZ ledger URL; on mainnet it's the public Solana RPC.
// On testnet this is Solana devnet (via SOLANA_RPC_URL); on mainnet the public
// Solana RPC; on devnet the DZ ledger URL.
SolanaRPCURL string
ShredSubscriptionProgramID string
DZLedgerURL string
Expand Down Expand Up @@ -155,11 +156,14 @@ func NewClient(ctx context.Context, log *slog.Logger, hostname string, port int,

serviceabilityClient := serviceability.New(rpc.New(networkConfig.LedgerPublicRPCURL), networkConfig.ServiceabilityProgramID)

// Settlement transactions on testnet/devnet use the DZ ledger RPC endpoint
// (which hosts the settlement programs). Mainnet and localnet use the
// Settlement transactions on devnet use the DZ ledger RPC endpoint (which
// hosts the settlement programs there). Testnet reads/writes the
// shred-subscription program on Solana devnet via networkConfig.SolanaRPCURL
// (the SOLANA_RPC_URL override, a Solana devnet RPC endpoint in CI;
// defaults to the public Solana endpoint). Mainnet and localnet use the
// standard Solana RPC.
solanaRPCURL := networkConfig.SolanaRPCURL
if networkConfig.Moniker == config.EnvTestnet || networkConfig.Moniker == config.EnvDevnet {
if networkConfig.Moniker == config.EnvDevnet {
solanaRPCURL = networkConfig.LedgerPublicRPCURL
}

Expand Down
13 changes: 8 additions & 5 deletions e2e/internal/qa/client_settlement.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,13 @@ func (c *Client) ClosestDevice(ctx context.Context) (*Device, error) {
return device, nil
}

// FeedSeatPrice calls the FeedSeatPrice RPC to query device seat prices.
// This is an idempotent read, so on RPC failure it fails over to the next
// endpoint and retries.
func (c *Client) FeedSeatPrice(ctx context.Context) ([]*pb.DevicePrice, error) {
c.log.Debug("Querying seat prices", "host", c.Host)
// FeedSeatPrice calls the FeedSeatPrice RPC to query seat pricing for a single
// device (by pubkey). Querying by pubkey avoids device-code resolution, which
// the CLI refuses when it can't classify the cluster (e.g. a private Solana
// devnet RPC URL). This is an idempotent read, so on RPC failure it fails over
// to the next endpoint and retries.
func (c *Client) FeedSeatPrice(ctx context.Context, devicePubkey string) ([]*pb.DevicePrice, error) {
c.log.Debug("Querying seat prices", "host", c.Host, "device", devicePubkey)
var prices []*pb.DevicePrice
err := c.withReadFailover(func(rpcURL string) error {
resp, err := c.grpcClient.FeedSeatPrice(ctx, &pb.FeedSeatPriceRequest{
Expand All @@ -119,6 +121,7 @@ func (c *Client) FeedSeatPrice(ctx context.Context) ([]*pb.DevicePrice, error) {
UsdcMint: c.USDCMint,
Keypair: c.Keypair,
ShredSubscriptionProgramId: c.ShredSubscriptionProgramID,
DevicePubkey: devicePubkey,
})
if err != nil {
return err
Expand Down
7 changes: 7 additions & 0 deletions e2e/internal/rpc/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,13 @@ func (q *QAAgent) FeedSeatPrice(ctx context.Context, req *pb.FeedSeatPriceReques
if req.GetSolanaRpcUrl() != "" {
args = append(args, "--url", req.GetSolanaRpcUrl())
}
// Query a single device by pubkey rather than listing all. The list path
// resolves device codes via serviceability, which the CLI refuses when it
// can't classify the cluster (e.g. a private Solana devnet RPC URL, seen as
// localnet); passing --device sidesteps code resolution entirely.
if req.GetDevicePubkey() != "" {
args = append(args, "--device", req.GetDevicePubkey())
}

cmdCtx, cancel := context.WithTimeout(ctx, 60*time.Second)
defer cancel()
Expand Down
1 change: 1 addition & 0 deletions e2e/proto/qa/agent.proto
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ message FeedSeatPriceRequest {
string usdc_mint = 3;
string keypair = 4;
string shred_subscription_program_id = 5;
string device_pubkey = 6;
}

message DevicePrice {
Expand Down
15 changes: 12 additions & 3 deletions e2e/proto/qa/gen/pb-go/agent.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions e2e/qa_multicast_settlement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,14 @@ func TestQA_MulticastSettlement(t *testing.T) {
}

if !t.Run("query_seat_price", func(t *testing.T) {
prices, err := client.FeedSeatPrice(ctx)
prices, err := client.FeedSeatPrice(ctx, device.PubKey)
require.NoError(t, err, "failed to get seat prices")

// Match by pubkey, not code: querying by --device skips code resolution,
// so the returned rows may not carry a device_code.
var price *pb.DevicePrice
for _, p := range prices {
if p.DeviceCode == device.Code {
if p.DevicePubkey == device.PubKey {
price = p
break
}
Expand Down
Loading