From 36b490775ad8ef7961f886bead197d7157b1b047 Mon Sep 17 00:00:00 2001 From: peachbits Date: Wed, 15 Jul 2026 11:50:27 -0700 Subject: [PATCH 1/2] Vendor the SDK's SwiftPM-only deps as a pre-built static binary The modern ZcashLightClientKit SDK pulls grpc-swift (1.24+), SwiftNIO, SwiftProtobuf and SQLite.swift via SwiftPM only -- grpc-swift's CocoaPods releases stopped at 1.8.0, so it can no longer be a CocoaPods dependency. Consuming the SDK via spm_dependency would force the entire host app onto dynamic frameworks. Instead, scripts/buildVendoredDeps.ts pre-builds those leaf dependencies in Release per platform (device arm64; simulator arm64+x86_64, matching the libzcashlc baseline), packages them as ios/vendored/libZcashDeps.xcframework, and harvests their Swift/C modules -- generated by 'npm run update-sources' and shipped in the npm tarball. Dependency versions are pinned to the SDK's Package.resolved (-disableAutomaticPackageResolution), and DerivedData is cleaned per run (stale precompiled modules of the libzcashlc header poison SDK bumps). The ZcashLightClientKit source keeps compiling in-pod exactly as before, and the host app stays on static frameworks. The archive ships as an XCFramework consumed via vendored_frameworks because that is a real link input: CocoaPods places it on the app link line, where the linker pulls members on demand to satisfy the in-pod SDK source's references. (pod_target_xcconfig OTHER_LDFLAGS is NOT viable for this: a static-framework pod's Libtool step ignores OTHER_LDFLAGS, and pod-target settings never propagate to the app link -- flags there are silently dead.) The binary .swiftmodule format only loads under the exact Swift compiler that produced it (library-evolution .swiftinterface is unavailable: swift-nio doesn't compile under evolution), so the build stamps ios/vendored/swift-version.txt and the podspec fails fast with rebuild instructions when the consuming Xcode doesn't match. Note: sqlite3 is not part of this binary -- SQLite.swift on Apple platforms links the system sqlite3 module, so there is nothing to exclude. Edge's pre-existing duplicate-sqlite3 ld warnings come from libzcashlc vs libpiratelc (both Rust cores embed sqlite3) and are unrelated to this change. Co-Authored-By: Claude Opus 4.8 --- .gitignore | 1 + react-native-zcash.podspec | 74 +++++++- scripts/buildVendoredDeps.ts | 348 +++++++++++++++++++++++++++++++++++ scripts/updateSources.ts | 6 + 4 files changed, 426 insertions(+), 3 deletions(-) create mode 100644 scripts/buildVendoredDeps.ts diff --git a/.gitignore b/.gitignore index a74c692c..8e4f4d2c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /android/build/ /ios/libzcashlc.xcframework/ /ios/ZCashLightClientKit/ +/ios/vendored/ /ios/zcashlc.h /lib/ /tmp/ diff --git a/react-native-zcash.podspec b/react-native-zcash.podspec index 1084086f..caed2864 100644 --- a/react-native-zcash.podspec +++ b/react-native-zcash.podspec @@ -2,6 +2,40 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +# Each bundled C dep module (ios/vendored/cmodules// — headers + +# module.modulemap) becomes one relative clang include path, so the in-pod +# ZcashLightClientKit source can resolve the C modules that the pre-built Swift +# dependency modules (SwiftNIO / GRPC) import. +cmodule_flags = Dir.glob(File.join(__dir__, "ios/vendored/cmodules/*")) + .select { |p| File.directory?(p) } + .map { |p| "-Xcc -I\"$(PODS_TARGET_SRCROOT)/ios/vendored/cmodules/#{File.basename(p)}\"" } + .join(" ") + +# The pre-built Swift modules under ios/vendored/ are only readable by the +# EXACT Swift compiler that produced them (the binary .swiftmodule format is +# not stable across compilers, and the stable alternative — library-evolution +# .swiftinterface — is unavailable because swift-nio rejects evolution builds +# by upstream policy; see apple/swift-nio#2470/#2897, closed "not planned"). +# Fail fast with instructions instead of letting the build die later on a +# cryptic "module compiled with Swift X cannot be imported by Swift Y" error. +stamp_path = File.join(__dir__, "ios/vendored/swift-version.txt") +if File.exist?(stamp_path) + built_with = File.read(stamp_path).strip + local_swift = `xcrun swift --version 2>/dev/null`[/swiftlang-[0-9.]+/] + if !built_with.empty? && !local_swift.nil? && built_with != local_swift + raise <<~MSG + react-native-zcash: the prebuilt Swift dependency modules in ios/vendored/ + were built with #{built_with}, but this machine's Swift compiler is + #{local_swift}. Binary .swiftmodule files only load under the exact + compiler that produced them. + + Fix: rebuild the vendored dependencies with your toolchain: + cd node_modules/react-native-zcash && npm run update-sources + (or switch to the Xcode whose Swift is #{built_with}) + MSG + end +end + Pod::Spec.new do |s| s.name = package['name'] s.version = package['version'] @@ -15,6 +49,10 @@ Pod::Spec.new do |s| :git => "https://github.com/EdgeApp/react-native-zcash.git", :tag => "v#{s.version}" } + + # The bridge + the vendored ZcashLightClientKit Swift source, compiled in-pod + # as ONE module (so the bridge uses SDK types directly — see copySwift in + # scripts/updateSources.ts). s.source_files = "ios/react-native-zcash-Bridging-Header.h", "ios/RNZcash.m", @@ -25,10 +63,40 @@ Pod::Spec.new do |s| "zcash-mainnet" => "ios/ZCashLightClientKit/Resources/checkpoints/mainnet/*.json", "zcash-testnet" => "ios/ZCashLightClientKit/Resources/checkpoints/testnet/*.json" } - s.vendored_frameworks = "ios/libzcashlc.xcframework" s.dependency "MnemonicSwift", "~> 2.2" - s.dependency "gRPC-Swift", "~> 1.8" - s.dependency "SQLite.swift/standalone", "~> 0.14" s.dependency "React-Core" + + # The Rust core (a binaryTarget on the SDK's GitHub release) plus the + # pre-built SwiftPM deps (see below). Vendored frameworks are real link + # inputs: CocoaPods adds them to the app link, where the linker pulls + # members on demand to satisfy the in-pod SDK source's references. + s.vendored_frameworks = + "ios/libzcashlc.xcframework", + "ios/vendored/libZcashDeps.xcframework" + + # --------------------------------------------------------------------------- + # The SDK's SwiftPM-only dependencies (grpc-swift, SwiftNIO, SwiftProtobuf, + # SQLite.swift) pre-built into one static lib per platform, plus their Swift + # and C modules. grpc-swift 1.24+ ships SwiftPM-only with no podspec, so these + # can no longer be CocoaPods `dependency`s; vendoring them as a static binary + # keeps the host app on STATIC frameworks (consuming the SDK via + # spm_dependency would force the whole app onto dynamic frameworks). + # + # sqlite3 is not in this binary: on Apple platforms SQLite.swift has no C-shim + # target — it imports the system `sqlite3` clang module — so its sqlite3_* + # references resolve at app link time from whatever the host links (in Edge, + # its own sqlite pod and/or the sqlite embedded in libzcashlc). Note: Edge's + # pre-existing duplicate-sqlite3 ld warnings come from libzcashlc vs + # react-native-piratechain's libpiratelc (both Rust cores embed sqlite3) and + # are unrelated to this package's deps binary. + # + # Regenerate ios/vendored/ with `npm run update-sources` + # (scripts/buildVendoredDeps.ts). + # --------------------------------------------------------------------------- + s.preserve_paths = "ios/vendored/**/*" + s.pod_target_xcconfig = { + "SWIFT_INCLUDE_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ios/vendored/modules\"", + "OTHER_SWIFT_FLAGS" => cmodule_flags + } end diff --git a/scripts/buildVendoredDeps.ts b/scripts/buildVendoredDeps.ts new file mode 100644 index 00000000..11995da2 --- /dev/null +++ b/scripts/buildVendoredDeps.ts @@ -0,0 +1,348 @@ +// Builds the SwiftPM dependency graph that the vendored ZcashLightClientKit +// source links against — grpc-swift, SwiftNIO, SwiftProtobuf, SQLite.swift and +// their C shims — into ONE static library per platform, plus the Swift +// `.swiftmodule`s and C `module.modulemap`s the in-pod SDK source needs to +// `import` them. +// +// Why this exists: as of the modern SDK, grpc-swift (1.24+) ships SwiftPM-only +// with no podspec, so it can no longer be a CocoaPods `dependency`. Instead of +// forcing the whole host app onto dynamic frameworks (the only way to consume +// the SDK via `spm_dependency`), we pre-build just these leaf dependencies into +// a static binary. The host app stays on static frameworks; the SDK *source* +// keeps compiling in-pod exactly as before (see copySwift in updateSources.ts). +// +// Output (all under ios/vendored/, gitignored, shipped in the npm tarball): +// libZcashDeps.xcframework - merged static lib (device arm64; sim arm64+x86_64) +// modules/.swiftmodule - Swift dep modules (all arch slices) +// cmodules// - C dep modules (headers + module.modulemap) +// swift-version.txt - the Swift compiler that produced the modules +// +// The per-platform archives are packaged as ONE xcframework because +// vendored_frameworks is a real link input: CocoaPods places it on the app +// link line, where the linker pulls members on demand. (pod_target_xcconfig +// OTHER_LDFLAGS cannot do this job: a static-framework pod's Libtool step +// ignores it, and pod-target settings never propagate to the app link.) +// +// Compiler coupling: the binary .swiftmodule format is only readable by the +// exact Swift compiler that wrote it. The stable alternative (library-evolution +// .swiftinterface) is off the table BY UPSTREAM POLICY, not by accident: +// swift-nio's @inlinable-heavy style is incompatible with evolution mode, and +// the maintainers have closed every request as "not planned" (apple/swift-nio +// #2467, #2470, #2897). Don't burn time re-testing evolution on toolchain +// bumps; this only changes if NIO reverses that policy or leaves the SDK's +// dependency graph. swift-version.txt records the producing compiler so the +// podspec can fail fast with instructions when the consuming Xcode doesn't match. + +import { execFileSync } from 'child_process' +import { existsSync, mkdirSync, readdirSync, statSync, writeFileSync } from 'fs' +import { join } from 'path' + +// This repo's @types/node predates fs.cpSync/rmSync, and the sibling scripts +// already shell out for file ops, so do the same here. +function rm(path: string): void { + execFileSync('rm', ['-rf', path]) +} +function cp(src: string, dest: string): void { + execFileSync('cp', ['-R', src, dest]) +} + +const root = join(__dirname, '..') +const tmp = join(root, 'tmp') +const sdkClone = join(tmp, 'ZCashLightClientKit') +const wrapper = join(tmp, 'deps-wrapper') +const vendored = join(root, 'ios/vendored') + +// Targets that must NOT go into the deps binary: +// - ZcashLightClientKit: compiled in-pod from source, not vendored as a binary +// - ZcashDepsWrapper: our throwaway entry-point target +// (sqlite3 needs no exclusion: on Apple platforms SQLite.swift has no C-shim +// target — it imports the system `sqlite3` clang module, so its sqlite3_* +// references resolve at app link time from whatever the host app links.) +const EXCLUDED_TARGETS = ['ZcashLightClientKit', 'ZcashDepsWrapper'] + +interface Platform { + archs: string[] + destination: string + dir: string +} + +// Arch baseline matches the libzcashlc.xcframework the SDK ships: arm64 +// devices, arm64 + x86_64 simulators (so Intel Macs can still build). +const PLATFORMS: Platform[] = [ + { + archs: ['arm64'], + destination: 'generic/platform=iOS', + dir: 'ios-arm64' + }, + { + archs: ['arm64', 'x86_64'], + destination: 'generic/platform=iOS Simulator', + dir: 'ios-arm64-simulator' + } +] + +export function buildVendoredDeps(): void { + console.log('Building vendored SwiftPM dependency binary...') + rm(vendored) + mkdirSync(join(vendored, 'modules'), { recursive: true }) + mkdirSync(join(vendored, 'cmodules'), { recursive: true }) + + writeWrapperPackage() + + for (const platform of PLATFORMS) { + console.log(` Compiling deps for ${platform.dir}...`) + const dd = join(tmp, `deps-dd-${platform.dir}`) + // Always start from clean DerivedData: reusing it across SDK version bumps + // poisons the build with stale precompiled modules of the libzcashlc + // binary-target header ("zcashlc.h has been modified since the module file + // was built"), surfacing as bogus cannot-find-FFI-symbol errors. + rm(dd) + loud(wrapper, [ + 'xcodebuild', + '-scheme', + 'ZcashDepsWrapper', + '-configuration', + 'Release', + '-destination', + platform.destination, + '-derivedDataPath', + dd, + // Honor the Package.resolved copied from the SDK checkout; hard-fail on + // any version drift instead of silently re-resolving: + '-disableAutomaticPackageResolution', + `ARCHS=${platform.archs.join(' ')}`, + 'ONLY_ACTIVE_ARCH=NO', + 'BUILD_LIBRARY_FOR_DISTRIBUTION=NO', + 'SKIP_INSTALL=NO', + 'build' + ]) + + mergeDeps(dd, platform) + harvestModules(dd) + } + + // Package the per-platform archives as ONE xcframework: vendored_frameworks + // is a real link input (CocoaPods puts it on the app link line, unlike + // pod_target_xcconfig OTHER_LDFLAGS, which a static-framework pod's Libtool + // step silently ignores). + console.log(' Creating libZcashDeps.xcframework...') + const xcframework = join(vendored, 'libZcashDeps.xcframework') + rm(xcframework) + const libArgs: string[] = [] + for (const platform of PLATFORMS) { + // CocoaPods requires a UNIFORM library basename across xcframework slices + // (mirroring libzcashlc.xcframework); stage each platform's lib under the + // same name in its own directory: + const stage = join(tmp, `xcfw-${platform.dir}`) + rm(stage) + mkdirSync(stage, { recursive: true }) + cp( + join(vendored, `libZcashDeps-${platform.dir}.a`), + join(stage, 'libZcashDeps.a') + ) + libArgs.push('-library', join(stage, 'libZcashDeps.a')) + } + loud(tmp, [ + 'xcodebuild', + '-create-xcframework', + ...libArgs, + '-output', + xcframework + ]) + for (const platform of PLATFORMS) { + rm(join(vendored, `libZcashDeps-${platform.dir}.a`)) + } + + writeCompilerStamp() + assertHarvestComplete() + console.log('Vendored deps built.') +} + +// A throwaway SwiftPM package that depends on the SDK so SwiftPM builds the +// SDK's dependency graph; we then harvest those compiled deps. The SDK +// checkout's Package.resolved is copied in so the graph resolves to the EXACT +// versions the SDK release pinned, not just whatever satisfies its ranges. +function writeWrapperPackage(): void { + rm(wrapper) + mkdirSync(join(wrapper, 'Sources/ZcashDepsWrapper'), { recursive: true }) + writeFileSync( + join(wrapper, 'Package.swift'), + `// swift-tools-version:5.9 +import PackageDescription +let package = Package( + name: "ZcashDepsWrapper", + // Match the SDK's own floor (iOS 13) so the prebuilt deps import cleanly + // from any host at or above it (Edge develop pins 15.6): + platforms: [.iOS(.v13)], + products: [.library(name: "ZcashDepsWrapper", type: .static, targets: ["ZcashDepsWrapper"])], + dependencies: [.package(path: ${JSON.stringify(sdkClone)})], + targets: [.target(name: "ZcashDepsWrapper", dependencies: [ + .product(name: "ZcashLightClientKit", package: "ZCashLightClientKit") + ])] +) +` + ) + writeFileSync( + join(wrapper, 'Sources/ZcashDepsWrapper/Empty.swift'), + '@_exported import ZcashLightClientKit\n' + ) + const sdkPins = join(sdkClone, 'Package.resolved') + if (!existsSync(sdkPins)) { + throw new Error(`SDK checkout has no Package.resolved at ${sdkPins}`) + } + cp(sdkPins, join(wrapper, 'Package.resolved')) +} + +// Merge every dependency target's compiled objects into one static lib per +// arch, then lipo the arches into the platform lib. Merging raw per-target +// objects (not the prelinked master objects) keeps every public symbol. +function mergeDeps(dd: string, platform: Platform): void { + const objectsRoot = join(dd, 'Build/Intermediates.noindex') + const archLibs: string[] = [] + + for (const arch of platform.archs) { + const objects = findObjects(objectsRoot, arch).filter(path => { + if (/IntegrationTests|Benchmarks|Tests\.build|Example/.test(path)) { + return false + } + return !EXCLUDED_TARGETS.some(target => + path.includes(`/${target}.build/`) + ) + }) + if (objects.length === 0) { + throw new Error( + `No ${arch} dependency objects found under ${objectsRoot}` + ) + } + const listFile = join(tmp, `deps-objects-${platform.dir}-${arch}.txt`) + writeFileSync(listFile, objects.join('\n')) + const archLib = join(tmp, `libZcashDeps-${platform.dir}-${arch}.a`) + rm(archLib) + loud(tmp, ['libtool', '-static', '-o', archLib, '-filelist', listFile]) + archLibs.push(archLib) + } + + const out = join(vendored, `libZcashDeps-${platform.dir}.a`) + rm(out) + if (archLibs.length === 1) { + cp(archLibs[0], out) + } else { + loud(tmp, ['lipo', '-create', ...archLibs, '-output', out]) + } +} + +function findObjects(base: string, arch: string): string[] { + const out: string[] = [] + const walk = (dir: string): void => { + for (const entry of readdirSync(dir, { withFileTypes: true })) { + const full = join(dir, entry.name) + if (entry.isDirectory()) walk(full) + else if ( + entry.name.endsWith('.o') && + dir.endsWith(`Objects-normal/${arch}`) + ) { + out.push(full) + } + } + } + walk(base) + return out +} + +// Copy the dep Swift `.swiftmodule`s (unioning arch slices across the +// per-platform builds) and the C modules (headers + module.modulemap) the SDK +// source imports. +function harvestModules(dd: string): void { + const products = findProductsDir(dd) + for (const entry of readdirSync(products)) { + if (!entry.endsWith('.swiftmodule')) continue + const name = entry.replace('.swiftmodule', '') + if (EXCLUDED_TARGETS.includes(name)) continue + const src = join(products, entry) + const dest = join(vendored, 'modules', entry) + if (statSync(src).isDirectory()) { + // Union the per-platform arch slices into one .swiftmodule bundle. + mkdirSync(dest, { recursive: true }) + cp(`${src}/.`, dest) + } else if (!existsSync(dest)) { + cp(src, dest) + } + } + // C modules: each compiled C target maps to a checkout include/ dir with a + // module.modulemap (synthesize a simple umbrella one if SwiftPM generated it). + const checkouts = join(dd, 'SourcePackages/checkouts') + if (!existsSync(checkouts)) return + for (const obj of readdirSync(products)) { + if (!obj.endsWith('.o')) continue + const mod = obj.replace('.o', '') + if (existsSync(join(vendored, 'cmodules', mod))) continue + const inc = findInclude(checkouts, mod) + if (inc == null) continue + const dest = join(vendored, 'cmodules', mod) + cp(inc, dest) + if (!existsSync(join(dest, 'module.modulemap'))) { + writeFileSync( + join(dest, 'module.modulemap'), + `module ${mod} {\n umbrella "."\n export *\n}\n` + ) + } + } +} + +function findProductsDir(dd: string): string { + const base = join(dd, 'Build/Products') + const entry = readdirSync(base).find(name => name.startsWith('Release-')) + if (entry == null) throw new Error(`No Products dir under ${base}`) + return join(base, entry) +} + +function findInclude(checkouts: string, mod: string): string | undefined { + for (const pkg of readdirSync(checkouts)) { + const inc = join(checkouts, pkg, 'Sources', mod, 'include') + if (existsSync(inc) && readdirSync(inc).some(f => f.endsWith('.h'))) { + return inc + } + } + return undefined +} + +// Record which Swift compiler produced the .swiftmodules (see the compiler +// coupling note in the file header). The podspec checks this at install time. +function writeCompilerStamp(): void { + const versionOutput = execFileSync('xcrun', ['swift', '--version'], { + encoding: 'utf8' + }) + const match = versionOutput.match(/swiftlang-[0-9.]+/) + if (match == null) { + throw new Error( + `Cannot parse Swift compiler version from: ${versionOutput}` + ) + } + writeFileSync(join(vendored, 'swift-version.txt'), `${match[0]}\n`) +} + +// Guard against a layout change in xcodebuild/SwiftPM silently producing an +// empty harvest (the build would only fail much later, in a consuming app). +function assertHarvestComplete(): void { + const moduleCount = readdirSync(join(vendored, 'modules')).filter(name => + name.endsWith('.swiftmodule') + ).length + const cmoduleCount = readdirSync(join(vendored, 'cmodules')).length + const xcframework = join(vendored, 'libZcashDeps.xcframework') + if (!existsSync(join(xcframework, 'Info.plist'))) { + throw new Error(`Missing or incomplete ${xcframework}`) + } + if (moduleCount < 10 || cmoduleCount < 5) { + throw new Error( + `Vendored module harvest looks incomplete: ${moduleCount} swiftmodules, ${cmoduleCount} cmodules` + ) + } +} + +function loud(cwd: string, argv: string[]): void { + execFileSync(argv[0], argv.slice(1), { + cwd, + stdio: 'inherit', + encoding: 'utf8' + }) +} diff --git a/scripts/updateSources.ts b/scripts/updateSources.ts index 92249df3..b42ea570 100644 --- a/scripts/updateSources.ts +++ b/scripts/updateSources.ts @@ -9,6 +9,7 @@ import { deepList, justFiles, makeNodeDisklet, navigateDisklet } from 'disklet' import { existsSync, mkdirSync, readFileSync } from 'fs' import { join } from 'path' +import { buildVendoredDeps } from './buildVendoredDeps' import { copyCheckpoints } from './copyCheckpoints' const disklet = makeNodeDisklet(join(__dirname, '../')) @@ -20,6 +21,10 @@ async function main(): Promise { await rebuildXcframework() await copySwift() await copyCheckpoints(disklet) + // grpc-swift (1.24+) and SwiftNIO are SwiftPM-only with no podspec, so the + // deps the vendored SDK source links against are pre-built into a static + // binary instead of being CocoaPods dependencies. + buildVendoredDeps() } // The Swift SDK version to vendor. The matching libzcashlc.xcframework is @@ -31,6 +36,7 @@ const ZCASH_SWIFT_SDK_VERSION = '2.5.2' // tampered or swapped upstream asset fails the build instead of injecting // attacker-controlled native code. Update this whenever the SDK version bumps: // curl -fL https://github.com/zcash/zcash-swift-wallet-sdk/releases/download//libzcashlc.xcframework.zip | shasum -a 256 +// (matches the `checksum:` in the SDK tag's own Package.swift binaryTarget) const LIBZCASHLC_XCFRAMEWORK_SHA256 = '27089796e15eacd0e5a90e7ea01884ea5c40806cf25a6fa9a6aca933dad65813' From d237b0055a67b973c471d982b8e071c7ca147cb8 Mon Sep 17 00:00:00 2001 From: peachbits Date: Wed, 15 Jul 2026 11:50:27 -0700 Subject: [PATCH 2/2] Bump SDK to 2.6.0-alpha.6 First hardfork-era prerelease: new Voting/PIR module, expanded libzcashlc FFI, updated checkpoints. Pin changes only -- the bridge needs no changes (the SDK's bridge-facing API surface is source-compatible with 2.5.2) and the dependency graph pins are identical, so the vendored deps binary is unchanged. Co-Authored-By: Claude Opus 4.8 --- scripts/updateSources.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/updateSources.ts b/scripts/updateSources.ts index b42ea570..d84968d5 100644 --- a/scripts/updateSources.ts +++ b/scripts/updateSources.ts @@ -29,7 +29,7 @@ async function main(): Promise { // The Swift SDK version to vendor. The matching libzcashlc.xcframework is // downloaded from this release's assets (see rebuildXcframework). -const ZCASH_SWIFT_SDK_VERSION = '2.5.2' +const ZCASH_SWIFT_SDK_VERSION = '2.6.0-alpha.6' // SHA-256 of the libzcashlc.xcframework.zip release asset for the version // above. The download is verified against this pin before it is unpacked, so a @@ -38,14 +38,14 @@ const ZCASH_SWIFT_SDK_VERSION = '2.5.2' // curl -fL https://github.com/zcash/zcash-swift-wallet-sdk/releases/download//libzcashlc.xcframework.zip | shasum -a 256 // (matches the `checksum:` in the SDK tag's own Package.swift binaryTarget) const LIBZCASHLC_XCFRAMEWORK_SHA256 = - '27089796e15eacd0e5a90e7ea01884ea5c40806cf25a6fa9a6aca933dad65813' + 'c58c1714440f8fd40bed33eefa3be325896e58eb568ed8747c05a27dae3a74b2' function downloadSources(): void { getRepo( 'ZcashLightClientKit', 'https://github.com/zcash/zcash-swift-wallet-sdk.git', - // 2.5.2: - 'e725a2482dced83afda91bcebe881bd0791aa359' + // 2.6.0-alpha.6: + '4303068e9282bb8b03bd94807b7d8ad268de75bf' ) // libzcashlc is no longer a separate package as of SDK 2.5.x — it ships as a // binaryTarget zip on the SDK's GitHub release, downloaded in rebuildXcframework().