Skip to content

Commit 3595078

Browse files
committed
Add pins to dependency height
1 parent 8f23115 commit 3595078

5 files changed

Lines changed: 658 additions & 93 deletions

File tree

flowkit/schema.json

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "https://json-schema.org/draft/2020-12/schema",
3-
"$id": "https://github.com/onflow/flow-cli/flowkit/config/json/json-config",
3+
"$id": "https://github.com/onflow/flowkit/v2/config/json/json-config",
44
"$ref": "#/$defs/jsonConfig",
55
"$defs": {
66
"account": {
@@ -111,20 +111,15 @@
111111
}
112112
},
113113
"additionalProperties": false,
114-
"type": "object",
115-
"required": [
116-
"host"
117-
]
114+
"type": "object"
118115
},
119116
"contractDeployment": {
120117
"properties": {
121118
"name": {
122119
"type": "string"
123120
},
124121
"args": {
125-
"items": {
126-
"type": "object"
127-
},
122+
"items": true,
128123
"type": "array"
129124
}
130125
},
@@ -199,6 +194,9 @@
199194
}
200195
},
201196
"type": "object"
197+
},
198+
"canonical": {
199+
"type": "string"
202200
}
203201
},
204202
"additionalProperties": false,
@@ -242,13 +240,19 @@
242240
"hash": {
243241
"type": "string"
244242
},
243+
"block_height": {
244+
"type": "integer"
245+
},
245246
"aliases": {
246247
"patternProperties": {
247248
".*": {
248249
"type": "string"
249250
}
250251
},
251252
"type": "object"
253+
},
254+
"canonical": {
255+
"type": "string"
252256
}
253257
},
254258
"additionalProperties": false,

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@ require (
1818
github.com/onflow/cadence-tools/test v1.10.0
1919
github.com/onflow/fcl-dev-wallet v0.9.1
2020
github.com/onflow/flixkit-go/v2 v2.7.0
21+
github.com/onflow/flow-core-contracts/lib/go/contracts v1.9.2
2122
github.com/onflow/flow-core-contracts/lib/go/templates v1.9.2
2223
github.com/onflow/flow-emulator v1.15.0
2324
github.com/onflow/flow-evm-gateway v1.4.4
2425
github.com/onflow/flow-go v0.45.0-experimental-cadence-v1.8.7.0.20251219170433-76749cca9738
2526
github.com/onflow/flow-go-sdk v1.9.8
2627
github.com/onflow/flow/protobuf/go/flow v0.4.18
27-
github.com/onflow/flowkit/v2 v2.10.0
28+
github.com/onflow/flowkit/v2 v2.10.1-0.20260106074841-4cacbcfc75c5
2829
github.com/onflowser/flowser/v3 v3.2.1-0.20240131200229-7d4d22715f48
2930
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
3031
github.com/pkg/errors v0.9.1
@@ -202,7 +203,6 @@ require (
202203
github.com/onflow/atree v0.12.0 // indirect
203204
github.com/onflow/crypto v0.25.3 // indirect
204205
github.com/onflow/fixed-point v0.1.1 // indirect
205-
github.com/onflow/flow-core-contracts/lib/go/contracts v1.9.2 // indirect
206206
github.com/onflow/flow-evm-bridge v0.1.0 // indirect
207207
github.com/onflow/flow-ft/lib/go/contracts v1.0.1 // indirect
208208
github.com/onflow/flow-ft/lib/go/templates v1.0.1 // indirect

go.sum

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,6 @@ github.com/cockroachdb/pebble/v2 v2.0.6 h1:eL54kX2AKp1ePJ/8vq4IO3xIEPpvVjlSP12dl
174174
github.com/cockroachdb/pebble/v2 v2.0.6/go.mod h1:un1DXG73PKw3F7Ndd30YactyvsFviI9Fuhe0tENdnyA=
175175
github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwPJ30=
176176
github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
177-
github.com/cockroachdb/swiss v0.0.0-20250624142022-d6e517c1d961 h1:Nua446ru3juLHLZd4AwKNzClZgL1co3pUPGv3o8FlcA=
178-
github.com/cockroachdb/swiss v0.0.0-20250624142022-d6e517c1d961/go.mod h1:yBRu/cnL4ks9bgy4vAASdjIW+/xMlFwuHKqtmh3GZQg=
179177
github.com/cockroachdb/swiss v0.0.0-20251224182025-b0f6560f979b h1:VXvSNzmr8hMj8XTuY0PT9Ane9qZGul/p67vGYwl9BFI=
180178
github.com/cockroachdb/swiss v0.0.0-20251224182025-b0f6560f979b/go.mod h1:yBRu/cnL4ks9bgy4vAASdjIW+/xMlFwuHKqtmh3GZQg=
181179
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
@@ -816,8 +814,8 @@ github.com/onflow/flow-nft/lib/go/templates v1.3.0 h1:uGIBy4GEY6Z9hKP7sm5nA5kwvb
816814
github.com/onflow/flow-nft/lib/go/templates v1.3.0/go.mod h1:gVbb5fElaOwKhV5UEUjM+JQTjlsguHg2jwRupfM/nng=
817815
github.com/onflow/flow/protobuf/go/flow v0.4.18 h1:KOujA6lg9kTXCV6oK0eErD1rwRnM9taKZss3Szi+T3Q=
818816
github.com/onflow/flow/protobuf/go/flow v0.4.18/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk=
819-
github.com/onflow/flowkit/v2 v2.10.0 h1:iv1hJeKidFdCaHZ3mY4+ZP3wWoHpukmoEspvhbBTUiI=
820-
github.com/onflow/flowkit/v2 v2.10.0/go.mod h1:vazedVB8r4CGMhFosCD5XK/K8y7br6VoDROJjINoaqQ=
817+
github.com/onflow/flowkit/v2 v2.10.1-0.20260106074841-4cacbcfc75c5 h1:u2vmqzJAeMwcq163Ku9ZpaPCHbDeIngCaWNf45b+S8M=
818+
github.com/onflow/flowkit/v2 v2.10.1-0.20260106074841-4cacbcfc75c5/go.mod h1:vazedVB8r4CGMhFosCD5XK/K8y7br6VoDROJjINoaqQ=
821819
github.com/onflow/go-ethereum v1.15.10 h1:blZBeOLJDOVWqKuhkkMh6S2PKQAJvdgbvOL9ZNggFcU=
822820
github.com/onflow/go-ethereum v1.15.10/go.mod h1:t2nZJtwruVjA5u5yEK8InFzjImFLHrF7ak2bw3E4LDM=
823821
github.com/onflow/nft-storefront/lib/go/contracts v1.0.0 h1:sxyWLqGm/p4EKT6DUlQESDG1ZNMN9GjPCm1gTq7NGfc=

internal/dependencymanager/dependencyinstaller.go

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ type DependencyInstaller struct {
147147
installCount int // Track number of dependencies installed
148148
pendingPrompts []pendingPrompt // Dependencies that need prompts after tree display
149149
prompter Prompter // Optional: for testing. If nil, uses real prompts
150+
blockHeightCache map[string]uint64 // Cache of latest block heights per network for consistent pinning
150151
}
151152

152153
type Prompter interface {
@@ -204,6 +205,7 @@ func NewDependencyInstaller(logger output.Logger, state *flowkit.State, saveStat
204205
accountAliases: make(map[string]map[string]flowsdk.Address),
205206
pendingPrompts: make([]pendingPrompt, 0),
206207
prompter: prompter{},
208+
blockHeightCache: make(map[string]uint64),
207209
}, nil
208210
}
209211

@@ -459,16 +461,60 @@ func (di *DependencyInstaller) processDependency(dependency config.Dependency) e
459461
return di.processDependencies(dependency)
460462
}
461463

464+
// getLatestBlockHeight returns the current block height for a given network.
465+
// Results are cached per network to ensure all dependencies in a single install
466+
// operation get pinned to the same block height for consistency.
467+
func (di *DependencyInstaller) getLatestBlockHeight(network string) (uint64, error) {
468+
// Check cache first
469+
if height, ok := di.blockHeightCache[network]; ok {
470+
return height, nil
471+
}
472+
473+
gw, ok := di.Gateways[network]
474+
if !ok {
475+
return 0, fmt.Errorf("gateway for network %s not found", network)
476+
}
477+
478+
ctx := context.Background()
479+
latestBlock, err := gw.GetLatestBlock(ctx)
480+
if err != nil {
481+
return 0, fmt.Errorf("failed to get latest block: %w", err)
482+
}
483+
484+
// Cache the result
485+
di.blockHeightCache[network] = latestBlock.Height
486+
return latestBlock.Height, nil
487+
}
488+
462489
func (di *DependencyInstaller) getContracts(network string, address flowsdk.Address) (map[string][]byte, error) {
490+
return di.getContractsAtBlockHeight(network, address, 0)
491+
}
492+
493+
// getContractsAtBlockHeight retrieves contracts at a specific block height.
494+
// If blockHeight is 0, it fetches the latest version.
495+
// Uses GetAccountAtBlockHeight from flowkit Gateway interface for historical queries.
496+
func (di *DependencyInstaller) getContractsAtBlockHeight(network string, address flowsdk.Address, blockHeight uint64) (map[string][]byte, error) {
463497
gw, ok := di.Gateways[network]
464498
if !ok {
465499
return nil, fmt.Errorf("gateway for network %s not found", network)
466500
}
467501

468502
ctx := context.Background()
469-
acct, err := gw.GetAccount(ctx, address)
470-
if err != nil {
471-
return nil, fmt.Errorf("failed to get account at %s on %s: %w", address, network, err)
503+
var acct *flowsdk.Account
504+
var err error
505+
506+
if blockHeight > 0 {
507+
// Query at specific block height (historical)
508+
acct, err = gw.GetAccountAtBlockHeight(ctx, address, blockHeight)
509+
if err != nil {
510+
return nil, fmt.Errorf("failed to get account at block height %d on %s: %w", blockHeight, network, err)
511+
}
512+
} else {
513+
// Query latest version
514+
acct, err = gw.GetAccount(ctx, address)
515+
if err != nil {
516+
return nil, fmt.Errorf("failed to get account at %s on %s: %w", address, network, err)
517+
}
472518
}
473519

474520
if acct == nil {
@@ -533,7 +579,19 @@ func (di *DependencyInstaller) fetchDependenciesWithDepth(dependency config.Depe
533579
return fmt.Errorf("error adding dependency: %w", err)
534580
}
535581

536-
accountContracts, err := di.getContracts(networkName, address)
582+
// Determine which block height to use for querying
583+
// If the dependency already exists in flow.json with a block height, use it
584+
// This allows us to fetch historical versions when local deps are frozen
585+
var blockHeight uint64
586+
existingDep := di.State.Dependencies().ByName(dependency.Name)
587+
if existingDep != nil && existingDep.BlockHeight > 0 {
588+
blockHeight = existingDep.BlockHeight
589+
} else {
590+
// For new dependencies or those without block height, use latest (0)
591+
blockHeight = 0
592+
}
593+
594+
accountContracts, err := di.getContractsAtBlockHeight(networkName, address, blockHeight)
537595
if err != nil {
538596
return fmt.Errorf("error fetching contracts: %w", err)
539597
}
@@ -916,13 +974,20 @@ func (di *DependencyInstaller) updateDependencyAlias(contractName, aliasNetwork
916974
}
917975

918976
func (di *DependencyInstaller) updateDependencyState(originalDependency config.Dependency, contractHash string) error {
977+
// Get current block height for the source network to pin the dependency
978+
blockHeight, err := di.getLatestBlockHeight(originalDependency.Source.NetworkName)
979+
if err != nil {
980+
return fmt.Errorf("failed to get block height for pinning dependency %s: %w", originalDependency.Name, err)
981+
}
982+
919983
// Create the dependency to save, preserving aliases and canonical from the original
920984
dep := config.Dependency{
921-
Name: originalDependency.Name,
922-
Source: originalDependency.Source,
923-
Hash: contractHash,
924-
Aliases: originalDependency.Aliases,
925-
Canonical: originalDependency.Canonical,
985+
Name: originalDependency.Name,
986+
Source: originalDependency.Source,
987+
Hash: contractHash,
988+
BlockHeight: blockHeight,
989+
Aliases: originalDependency.Aliases,
990+
Canonical: originalDependency.Canonical,
926991
}
927992

928993
isNewDep := di.State.Dependencies().ByName(dep.Name) == nil

0 commit comments

Comments
 (0)