Skip to content

Commit

Permalink
feat(builds): Add regex pattern support for KDF download
Browse files Browse the repository at this point in the history
Add regex pattern support for KDF downloads to resolve the issue where some platforms have both the “mm2” and “kdf” files listed for backwards compatibility.
  • Loading branch information
CharlVS committed Jan 14, 2025
1 parent 415baea commit 6c7cb9b
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 55 deletions.
14 changes: 7 additions & 7 deletions packages/komodo_defi_framework/app_build/build_config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"api": {
"api_commit_hash": "bb749a99344fb61e92410cb64b035dba1de35779",
"branch": "main",
"api_commit_hash": "405bcb7daf316477497eb6925cba0ca9640ab383",
"branch": "dev",
"fetch_at_build_enabled": true,
"concurrent_downloads_enabled": true,
"source_urls": [
Expand All @@ -10,16 +10,16 @@
],
"platforms": {
"web": {
"matching_keyword": "wasm",
"matching_pattern": "^kdf_[a-f0-9]+-wasm\\.zip$",
"valid_zip_sha256_checksums": [
"91ac9f0e880ec49aedab21c5df130ffc9475cdbf0b6428cf6862842142176293"
"1800ab7e8682f01d9a10679475509706b0414bc178937d6db95ebf84f29df84c"
],
"path": "web/kdf/bin"
},
"macos": {
"matching_keyword": "mac-arm64",
"matching_pattern": "^kdf_[a-f0-9]+-mac-arm64\\.zip$",
"valid_zip_sha256_checksums": [
"1a06b4e7d9b3db9ba9623445274ac420f5522d4ee56a6a2f3b305e56b6ae26c8"
"37161ccc3022f07d5e1bedf2069f3fe609cf12a18f8ca5fd4bbc32e0ce734cf5"
],
"path": "macos/bin"
}
Expand All @@ -28,7 +28,7 @@
"coins": {
"fetch_at_build_enabled": true,
"update_commit_on_build": true,
"bundled_coins_repo_commit": "642abea7172b81db24b16bffc13783b9a0e400f5",
"bundled_coins_repo_commit": "eae824b3502f9da19cce891f93e8c2f98fbf534f",
"coins_repo_api_url": "https://api.github.com/repos/KomodoPlatform/coins",
"coins_repo_content_url": "https://komodoplatform.github.io/coins",
"coins_repo_branch": "master",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,14 +417,13 @@ class FetchDefiApiStep extends BuildStep {
) async {
final releases = await githubApiProvider.getReleases();
final apiVersionShortHash = apiCommitHash.substring(0, 7);
final matchingKeyword = config[platform]!.matchingKeyword;
final matchingConfig = config[platform]!.matchingConfig;

for (final release in releases) {
for (final asset in release.assets) {
final url = asset.browserDownloadUrl;

if (url.contains(matchingKeyword) &&
url.contains(apiVersionShortHash)) {
if (matchingConfig.matches(url) && url.contains(apiVersionShortHash)) {
final commitHash = await githubApiProvider.getLatestCommitHash(
branch: release.tagName,
);
Expand Down Expand Up @@ -454,14 +453,14 @@ class FetchDefiApiStep extends BuildStep {
_checkResponseSuccess(response);

final document = parser.parse(response.body);
final matchingKeyword = config[platform]!.matchingKeyword;
final matchingConfig = config[platform]!.matchingConfig;
final extensions = ['.zip'];
final apiVersionShortHash = apiCommitHash.substring(0, 7);

for (final element in document.querySelectorAll('a')) {
final href = element.attributes['href'];
if (href != null &&
href.contains(matchingKeyword) &&
matchingConfig.matches(href) &&
extensions.any(href.endsWith) &&
href.contains(apiVersionShortHash)) {
return '$sourceUrl/$apiBranch/$href';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,57 +1,88 @@
import 'package:komodo_wallet_build_transformer/src/steps/models/api/api_file_matching_config.dart';

/// Configuration for a specific platform's API build settings.
///
/// This class contains the configuration needed to download and verify API
/// binaries for a specific platform (e.g., 'web', 'macos', 'windows', etc.).
class ApiBuildPlatformConfig {
/// Creates a new [ApiBuildPlatformConfig] with required parameters.
///
/// The [matchingConfig] specifies how to identify the correct API file.
/// [validZipSha256Checksums] contains the list of valid SHA256 checksums for
/// verification.
/// [path] specifies where the API files should be stored.
ApiBuildPlatformConfig({
required this.matchingKeyword,
required this.matchingConfig,
required this.validZipSha256Checksums,
required this.path,
});
}) : assert(
validZipSha256Checksums.isNotEmpty,
'At least one valid checksum must be provided',
);

/// Creates an instance of [ApiBuildPlatformConfig] from a JSON object.
/// Creates a [ApiBuildPlatformConfig] from a JSON map.
///
/// Throws an [ArgumentError] if the object does not match the expected
/// structure.
/// The JSON must contain either 'matching_keyword' or 'matching_pattern',
/// 'valid_zip_sha256_checksums' as a non-empty list, and a 'path' string.
/// Throws a [FormatException] if the JSON is invalid.
factory ApiBuildPlatformConfig.fromJson(Map<String, dynamic> json) {
if (!json.containsKey('matching_keyword')) {
throw ArgumentError('missing matching_keyword');
}

if (!json.containsKey('valid_zip_sha256_checksums')) {
throw ArgumentError('missing valid_zip_sha256_checksums');
throw FormatException(
'Missing required field: valid_zip_sha256_checksums',
json.toString(),
);
}

if (!json.containsKey('path')) {
throw ArgumentError('missing path');
throw FormatException('Missing required field: path', json.toString());
}

if (!json.containsKey('matching_keyword') &&
!json.containsKey('matching_pattern')) {
throw FormatException(
'Either matching_keyword or matching_pattern must be provided',
json.toString(),
);
}

final checksums = json['valid_zip_sha256_checksums'];
if (checksums is! List || checksums.isEmpty) {
throw FormatException(
'valid_zip_sha256_checksums must be a non-empty list',
json.toString(),
);
}

final matchingConfig = ApiFileMatchingConfig(
matchingKeyword: json['matching_keyword'] as String?,
matchingPattern: json['matching_pattern'] as String?,
);

return ApiBuildPlatformConfig(
matchingKeyword: json['matching_keyword'] as String,
validZipSha256Checksums:
List<String>.from(json['valid_zip_sha256_checksums'] as List),
matchingConfig: matchingConfig,
validZipSha256Checksums: List<String>.from(checksums),
path: json['path'] as String,
);
}

String matchingKeyword;
List<String> validZipSha256Checksums;
String path;
/// Configuration for matching the correct API file
final ApiFileMatchingConfig matchingConfig;

Map<String, dynamic> toJson() {
return {
'matching_keyword': matchingKeyword,
'valid_zip_sha256_checksums': validZipSha256Checksums,
'path': path,
};
}
/// List of valid SHA256 checksums for the API zip file
///
/// Multiple checksums can be valid at the same time to support different
/// versions or variations of the API.
final List<String> validZipSha256Checksums;

ApiBuildPlatformConfig copyWith({
String? matchingKeyword,
List<String>? validZipSha256Checksums,
String? path,
}) {
return ApiBuildPlatformConfig(
matchingKeyword: matchingKeyword ?? this.matchingKeyword,
validZipSha256Checksums:
validZipSha256Checksums ?? this.validZipSha256Checksums,
path: path ?? this.path,
);
}
/// Path where the API files should be stored
///
/// This path is relative to the project's artifact output directory.
final String path;

/// Converts the configuration to a JSON map.
Map<String, dynamic> toJson() => {
...matchingConfig.toJson(),
'valid_zip_sha256_checksums': validZipSha256Checksums,
'path': path,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/// Configuration for matching API files using either a simple keyword or regex pattern.
class ApiFileMatchingConfig {
ApiFileMatchingConfig({
this.matchingKeyword,
this.matchingPattern,
}) : assert(
matchingKeyword != null || matchingPattern != null,
'Either matchingKeyword or matchingPattern must be provided',
);

factory ApiFileMatchingConfig.fromJson(Map<String, dynamic> json) {
return ApiFileMatchingConfig(
matchingKeyword: json['matching_keyword'] as String?,
matchingPattern: json['matching_pattern'] as String?,
);
}

/// Simple substring to match in the filename
final String? matchingKeyword;

/// Regular expression pattern to match against the filename
final String? matchingPattern;

/// Checks if the given input string matches either the keyword or pattern
bool matches(String input) {
if (matchingPattern != null) {
try {
final regex = RegExp(matchingPattern!);
return regex.hasMatch(input);
} catch (e) {
throw FormatException(
'Invalid regex pattern: $matchingPattern',
e.toString(),
);
}
}
return matchingKeyword != null && input.contains(matchingKeyword!);
}

Map<String, dynamic> toJson() => {
if (matchingKeyword != null) 'matching_keyword': matchingKeyword,
if (matchingPattern != null) 'matching_pattern': matchingPattern,
};
}
14 changes: 7 additions & 7 deletions packages/komodo_wallet_build_transformer/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77"
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
url: "https://pub.dev"
source: hosted
version: "73.0.0"
version: "76.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
version: "0.3.2"
version: "0.3.3"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a"
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
url: "https://pub.dev"
source: hosted
version: "6.8.0"
version: "6.11.0"
args:
dependency: "direct main"
description:
Expand Down Expand Up @@ -186,10 +186,10 @@ packages:
dependency: transitive
description:
name: macros
sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
url: "https://pub.dev"
source: hosted
version: "0.1.2-main.4"
version: "0.1.3-main.0"
matcher:
dependency: transitive
description:
Expand Down

0 comments on commit 6c7cb9b

Please sign in to comment.