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
14 changes: 14 additions & 0 deletions config/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,20 @@ func (c *Contracts) AddDependencyAsContract(dependency Dependency, networkName s
})
}
}
// Also add any custom network aliases from the dependency (e.g., mainnet-fork)
for _, depAlias := range dependency.Aliases {
// Skip if already added by supportedNetworks()
alreadyExists := false
for _, existing := range aliases {
if existing.Network == depAlias.Network {
alreadyExists = true
break
}
}
if !alreadyExists {
aliases = append(aliases, depAlias)
}
}
} else {
aliases = append(aliases, dependency.Aliases...)
}
Expand Down
22 changes: 14 additions & 8 deletions config/json/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,18 @@ func (j jsonNetworks) transformToConfig() (config.Networks, error) {
networks := make(config.Networks, 0)

for networkName, n := range j {
if n.Advanced.Key != "" && n.Advanced.Host != "" {
err := validateECDSAP256Pub(n.Advanced.Key)
if err != nil {
return nil, fmt.Errorf("invalid key %s for network with name %s", n.Advanced.Key, networkName)
// Advanced form: host required, key optional, fork optional
if n.Advanced.Host != "" || n.Advanced.Fork != "" {
if n.Advanced.Key != "" {
if err := validateECDSAP256Pub(n.Advanced.Key); err != nil {
return nil, fmt.Errorf("invalid key %s for network with name %s", n.Advanced.Key, networkName)
}
}

networks = append(networks, config.Network{
Name: networkName,
Host: n.Advanced.Host,
Key: n.Advanced.Key,
Fork: n.Advanced.Fork,
})
} else if n.Simple.Host != "" {
networks = append(networks, config.Network{
Expand All @@ -66,7 +68,8 @@ func transformNetworksToJSON(networks config.Networks) jsonNetworks {
jsonNetworks := jsonNetworks{}

for _, n := range networks {
if n.Key != "" {
// Use advanced when key or fork present; otherwise simple
if n.Key != "" || n.Fork != "" {
jsonNetworks[n.Name] = transformAdvancedNetworkToJSON(n)
} else {
jsonNetworks[n.Name] = transformSimpleNetworkToJSON(n)
Expand All @@ -89,6 +92,7 @@ func transformAdvancedNetworkToJSON(n config.Network) jsonNetwork {
Advanced: advancedNetwork{
Host: n.Host,
Key: n.Key,
Fork: n.Fork,
},
}
}
Expand All @@ -103,8 +107,9 @@ type simpleNetwork struct {
}

type advancedNetwork struct {
Host string `json:"host"`
Key string `json:"key"`
Host string `json:"host,omitempty"`
Key string `json:"key,omitempty"`
Fork string `json:"fork,omitempty"`
}

func (j *jsonNetwork) UnmarshalJSON(b []byte) error {
Expand All @@ -121,6 +126,7 @@ func (j *jsonNetwork) UnmarshalJSON(b []byte) error {
if err == nil {
j.Advanced.Host = advanced.Host
j.Advanced.Key = advanced.Key
j.Advanced.Fork = advanced.Fork
}

return err
Expand Down
4 changes: 2 additions & 2 deletions config/json/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,14 @@ func Test_TransformConfigAdvanced(t *testing.T) {
assert.Equal(t, "access.testnet.nodes.onflow.org:9000", testnet.Host)
assert.Equal(t, "5000676131ad3e22d853a3f75a5b5d0db4236d08dd6612e2baad771014b5266a242bccecc3522ff7207ac357dbe4f225c709d9b273ac484fed5d13976a39bdcd", testnet.Key)
})
t.Run("should return error if advanced config does not have key", func(t *testing.T) {
t.Run("should allow advanced config without key", func(t *testing.T) {
b := []byte(`{"testnet":{"host":"access.testnet.nodes.onflow.org:9000"}}`)
var jsonNetworks jsonNetworks
err := json.Unmarshal(b, &jsonNetworks)
assert.NoError(t, err)

_, err = jsonNetworks.transformToConfig()
assert.Error(t, err)
assert.NoError(t, err)
})
t.Run("should return error if advanced config does not have host", func(t *testing.T) {
b := []byte(`{"testnet":{"key": "5000676131ad3e22d853a3f75a5b5d0db4236d08dd6612e2baad771014b5266a242bccecc3522ff7207ac357dbe4f225c709d9b273ac484fed5d13976a39bdcd"}}`)
Expand Down
1 change: 1 addition & 0 deletions config/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type Network struct {
Name string
Host string
Key string
Fork string // Source network for alias resolution (e.g., "mainnet" for forked networks)
}

// ByName get network by name or return an error if not found.
Expand Down
9 changes: 4 additions & 5 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,13 @@
},
"key": {
"type": "string"
},
"fork": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"host",
"key"
]
"type": "object"
},
"contractDeployment": {
"properties": {
Expand Down
27 changes: 21 additions & 6 deletions state.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func (p *State) SetEmulatorKey(privateKey crypto.PrivateKey) {
func (p *State) DeploymentContractsByNetwork(network config.Network) ([]*project.Contract, error) {
contracts := make([]*project.Contract, 0)

// get deployments for the specified network
// get deployments for the specified network (explicit, no fallback)
for _, deploy := range p.conf.Deployments.ByNetwork(network.Name) {
account, err := p.accounts.ByName(deploy.Account)
if err != nil {
Expand Down Expand Up @@ -276,12 +276,27 @@ func (p *State) ContractAddress(contract *config.Contract, network config.Networ
func (p *State) AliasesForNetwork(network config.Network) project.LocationAliases {
aliases := make(project.LocationAliases)

// get all contracts for selected network and if any has an address as target make it an alias
// Determine fallback from network.Fork if provided (e.g., forked emulator should use mainnet aliases)
fallback := network.Fork

// get all contracts for selected network; if alias not defined, try fallback
for _, contract := range p.conf.Contracts {
if contract.IsAliased() && contract.Aliases.ByNetwork(network.Name) != nil {
alias := contract.Aliases.ByNetwork(network.Name).Address.String()
aliases[filepath.Clean(contract.Location)] = alias // alias for import by file location
aliases[contract.Name] = alias // alias for import by name
if !contract.IsAliased() {
continue
}
if a := contract.Aliases.ByNetwork(network.Name); a != nil {
addr := a.Address.String()
aliases[filepath.Clean(contract.Location)] = addr
aliases[contract.Name] = addr
continue
}
if fallback != "" {
if a := contract.Aliases.ByNetwork(fallback); a != nil {
addr := a.Address.String()
aliases[filepath.Clean(contract.Location)] = addr
aliases[contract.Name] = addr
continue
}
}
}

Expand Down
Loading