Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ABW-2735] AppsFlyer integration #1073

Merged
merged 13 commits into from
Apr 5, 2024
Merged
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
1 change: 1 addition & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ jobs:
git config user.name $GIT_USER
git config user.email $GIT_USER
echo "${{ env.WALLET_FASTLANE_SECRETS_BASE64 }}" | base64 --decode > fastlane/.env.secret
echo "${{ env.WALLET_GENERAL_SECRETS_BASE64 }}" | base64 --decode > .env.secret
brew install xcbeautify
env:
GIT_USER: ${{ env.WALLET_RADIX_BOT_USERNAME }}
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ DerivedData/
.netrc
fastlane/report.xml
fastlane/test_output/
fastlane/.env.secret
.env.secret
GhenadieVP marked this conversation as resolved.
Show resolved Hide resolved
.bundle
vendor
.design
.design
Aux/SensitiveInfo.plist
10 changes: 10 additions & 0 deletions Aux/SensitiveInfo-Sample.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>APPS_FLYER_APP_ID</key>
<string>placeholder</string>
<key>APPS_FLYER_DEV_KEY</key>
<string>placeholder</string>
</dict>
</plist>
76 changes: 76 additions & 0 deletions RadixWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,12 @@
48FFFB082ADC6FD300B2B213 /* SwiftUINavigationCore in Frameworks */ = {isa = PBXBuildFile; productRef = 48FFFB072ADC6FD300B2B213 /* SwiftUINavigationCore */; };
48FFFB0A2ADC721800B2B213 /* Atomics in Frameworks */ = {isa = PBXBuildFile; productRef = 48FFFB092ADC721800B2B213 /* Atomics */; };
48FFFB0D2ADC744700B2B213 /* TextBuilder in Frameworks */ = {isa = PBXBuildFile; productRef = 48FFFB0C2ADC744700B2B213 /* TextBuilder */; };
5B1C4FD52BBB0B0C00B9436F /* AppsFlyerLib-Strict in Frameworks */ = {isa = PBXBuildFile; productRef = 5B1C4FD42BBB0B0C00B9436F /* AppsFlyerLib-Strict */; };
5B1C4FD82BBB0C1E00B9436F /* AppsFlyerClient+Interface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B1C4FD72BBB0C1E00B9436F /* AppsFlyerClient+Interface.swift */; };
5B1C4FDA2BBB0DCF00B9436F /* AppsFlyerClient+Live.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B1C4FD92BBB0DCF00B9436F /* AppsFlyerClient+Live.swift */; };
5B9846BD2BBD5C8800E814F3 /* SensitiveInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5B9846BC2BBD5C8800E814F3 /* SensitiveInfo.plist */; };
5B9846C02BBD5F0800E814F3 /* SensitiveInfoClient+Interface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B9846BF2BBD5F0800E814F3 /* SensitiveInfoClient+Interface.swift */; };
5B9846C22BBD5F7600E814F3 /* SensitiveInfoClient+Live.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B9846C12BBD5F7600E814F3 /* SensitiveInfoClient+Live.swift */; };
5BBC43A92BBAC6B0005747B1 /* AppTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BBC43A82BBAC6B0005747B1 /* AppTextEditor.swift */; };
830818482B9F1621002D8351 /* HTTPClient+Live.swift in Sources */ = {isa = PBXBuildFile; fileRef = 830818472B9F1621002D8351 /* HTTPClient+Live.swift */; };
8308184A2B9F162B002D8351 /* HTTPClient+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 830818492B9F162B002D8351 /* HTTPClient+Mock.swift */; };
Expand Down Expand Up @@ -2382,6 +2388,11 @@
48F9CFE62B03A0A000657755 /* ProfileBuilderTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileBuilderTest.swift; sourceTree = "<group>"; };
48FF43142AE43C7C00C568B9 /* TimeLimit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeLimit.swift; sourceTree = "<group>"; };
48FFFAF12ADC23AC00B2B213 /* Exports.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Exports.swift; sourceTree = "<group>"; };
5B1C4FD72BBB0C1E00B9436F /* AppsFlyerClient+Interface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppsFlyerClient+Interface.swift"; sourceTree = "<group>"; };
5B1C4FD92BBB0DCF00B9436F /* AppsFlyerClient+Live.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppsFlyerClient+Live.swift"; sourceTree = "<group>"; };
5B9846BC2BBD5C8800E814F3 /* SensitiveInfo.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = SensitiveInfo.plist; sourceTree = "<group>"; };
5B9846BF2BBD5F0800E814F3 /* SensitiveInfoClient+Interface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SensitiveInfoClient+Interface.swift"; sourceTree = "<group>"; };
5B9846C12BBD5F7600E814F3 /* SensitiveInfoClient+Live.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SensitiveInfoClient+Live.swift"; sourceTree = "<group>"; };
5BBC43A82BBAC6B0005747B1 /* AppTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTextEditor.swift; sourceTree = "<group>"; };
830818472B9F1621002D8351 /* HTTPClient+Live.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HTTPClient+Live.swift"; sourceTree = "<group>"; };
830818492B9F162B002D8351 /* HTTPClient+Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HTTPClient+Mock.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2649,6 +2660,7 @@
48FFFAFB2ADC241A00B2B213 /* HashTreeCollections in Frameworks */,
48FFFAC52ADC211700B2B213 /* JSONTesting in Frameworks */,
48FFFB062ADC6FD300B2B213 /* SwiftUINavigation in Frameworks */,
5B1C4FD52BBB0B0C00B9436F /* AppsFlyerLib-Strict in Frameworks */,
48FFFB032ADC6F8100B2B213 /* Builders in Frameworks */,
48FFFAB72ADC207B00B2B213 /* NavigationTransitions in Frameworks */,
48FFFA992ADC1EEC00B2B213 /* AsyncExtensions in Frameworks */,
Expand Down Expand Up @@ -5080,6 +5092,8 @@
48CFBF522ADC10D900E77A5C /* Clients */ = {
isa = PBXGroup;
children = (
5B9846BE2BBD5EF600E814F3 /* SensitiveInfoClient */,
5B1C4FD62BBB0C0100B9436F /* AppsFlyerClient */,
8370FC5A2B99C732007AD882 /* NPSSurveyClient */,
83823EA82B72362600827211 /* TokenPriceClient */,
83823EA52B722D9000827211 /* HTTPClient */,
Expand Down Expand Up @@ -6690,6 +6704,7 @@
48CFC6972ADC110800E77A5C /* InfoPlist.strings */,
48CFC6992ADC110800E77A5C /* Config */,
48CFC6AD2ADC110800E77A5C /* Radix-Wallet--iOS--Info.plist */,
5B9846BC2BBD5C8800E814F3 /* SensitiveInfo.plist */,
);
path = Aux;
sourceTree = "<group>";
Expand Down Expand Up @@ -6771,6 +6786,24 @@
path = KeychainClientTests;
sourceTree = "<group>";
};
5B1C4FD62BBB0C0100B9436F /* AppsFlyerClient */ = {
isa = PBXGroup;
children = (
5B1C4FD72BBB0C1E00B9436F /* AppsFlyerClient+Interface.swift */,
5B1C4FD92BBB0DCF00B9436F /* AppsFlyerClient+Live.swift */,
);
path = AppsFlyerClient;
sourceTree = "<group>";
};
5B9846BE2BBD5EF600E814F3 /* SensitiveInfoClient */ = {
isa = PBXGroup;
children = (
5B9846BF2BBD5F0800E814F3 /* SensitiveInfoClient+Interface.swift */,
5B9846C12BBD5F7600E814F3 /* SensitiveInfoClient+Live.swift */,
);
path = SensitiveInfoClient;
sourceTree = "<group>";
};
830EA9D42AE94014004C8051 /* AccountAndPersonaHidingFeature */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -7661,6 +7694,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 48CFBC5D2ADC106400E77A5C /* Build configuration list for PBXNativeTarget "RadixWallet" */;
buildPhases = (
5B9846C32BBD643700E814F3 /* Create SensitiveInfo Sample */,
48CFBC4B2ADC106300E77A5C /* Sources */,
48CFBC4C2ADC106300E77A5C /* Frameworks */,
48CFBC4D2ADC106300E77A5C /* Resources */,
Expand Down Expand Up @@ -7712,6 +7746,7 @@
E63D123C2ADD1FC00001CBB1 /* SwiftUIIntrospect */,
A47571FE2B29B0860059A95D /* IOSSecuritySuite */,
A415574F2B757C5E0040AD4E /* ComposableArchitecture */,
5B1C4FD42BBB0B0C00B9436F /* AppsFlyerLib-Strict */,
);
productName = RadixWallet;
productReference = 48CFBC4F2ADC106300E77A5C /* Radix Wallet Dev.app */;
Expand Down Expand Up @@ -7781,6 +7816,7 @@
48FFFB0B2ADC744700B2B213 /* XCRemoteSwiftPackageReference "TextBuilder" */,
A47571FD2B29B0860059A95D /* XCRemoteSwiftPackageReference "IOSSecuritySuite" */,
A415574E2B757C5E0040AD4E /* XCRemoteSwiftPackageReference "swift-composable-architecture" */,
5B1C4FD32BBB0B0C00B9436F /* XCRemoteSwiftPackageReference "AppsFlyerFramework-Strict" */,
);
productRefGroup = 48CFBC502ADC106300E77A5C /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -7833,6 +7869,7 @@
48CFC6B82ADC110800E77A5C /* Project-Debug-Opt.xcconfig in Resources */,
48CFC6BD2ADC110800E77A5C /* Project-Beta.xcconfig in Resources */,
48CFC6B02ADC110800E77A5C /* iOS-dev.xcconfig in Resources */,
5B9846BD2BBD5C8800E814F3 /* SensitiveInfo.plist in Resources */,
48CFC6AE2ADC110800E77A5C /* InfoPlist.strings in Resources */,
48CFC5F72ADC10DA00E77A5C /* IBMPlexSans-Medium.ttf in Resources */,
48CFC6B32ADC110800E77A5C /* iOS-shared.xcconfig in Resources */,
Expand All @@ -7853,6 +7890,28 @@
};
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
GhenadieVP marked this conversation as resolved.
Show resolved Hide resolved
5B9846C32BBD643700E814F3 /* Create SensitiveInfo Sample */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Create SensitiveInfo Sample";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/SensitiveInfo.plist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# The SensitiveInfo.plist contains the secret tokens that we don't want publicly available.\n# As this file is ignored from SourceControl, this script will create a placeholder version\n# of it if it isn't already present.\nCONFIG_FILE_BASE_NAME=\"SensitiveInfo\"\n \nCONFIG_FILE_NAME=${CONFIG_FILE_BASE_NAME}.plist\nSAMPLE_CONFIG_FILE_NAME=${CONFIG_FILE_BASE_NAME}-Sample.plist\n \nCONFIG_FILE_PATH=$SRCROOT/Aux/$CONFIG_FILE_NAME\nSAMPLE_CONFIG_FILE_PATH=$SRCROOT/Aux/$SAMPLE_CONFIG_FILE_NAME\n \nif [ -f \"$CONFIG_FILE_PATH\" ]; then\n echo \"$CONFIG_FILE_PATH exists.\"\nelse\n echo \"$CONFIG_FILE_PATH does not exist, copying sample\"\n cp -v \"${SAMPLE_CONFIG_FILE_PATH}\" \"${CONFIG_FILE_PATH}\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
481B43AC2ADC7F1A007945C1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
Expand Down Expand Up @@ -8400,9 +8459,11 @@
48CFC66D2ADC10DB00E77A5C /* SecurityQuestionsFactorSource.swift in Sources */,
48CFC6022ADC10DA00E77A5C /* P2P+LedgerHardwareWallet.swift in Sources */,
48CFC46A2ADC10DA00E77A5C /* ImportLegacyWalletClient+Live.swift in Sources */,
5B1C4FD82BBB0C1E00B9436F /* AppsFlyerClient+Interface.swift in Sources */,
830EA9D62AE94033004C8051 /* AccountAndPersonaHiding+Reducer.swift in Sources */,
48CFC5052ADC10DA00E77A5C /* TransactionPreviewResponseLogsInner.swift in Sources */,
48CFC2FF2ADC10D900E77A5C /* AccountSecurity+View.swift in Sources */,
5B1C4FDA2BBB0DCF00B9436F /* AppsFlyerClient+Live.swift in Sources */,
48CFC56B2ADC10DA00E77A5C /* MetadataU8ArrayValue.swift in Sources */,
A4CFB55F2BAA821E00778BDD /* HScrollBar.swift in Sources */,
48CFC2F92ADC10D900E77A5C /* InfoOfNewPersona+Reducer.swift in Sources */,
Expand Down Expand Up @@ -8760,6 +8821,7 @@
48CFC3EE2ADC10D900E77A5C /* DataChannelAssembledMessage.swift in Sources */,
48CFC2972ADC10D900E77A5C /* AdvancedFeesCustomization.swift in Sources */,
48CFC4CB2ADC10DA00E77A5C /* Extensions.swift in Sources */,
5B9846C22BBD5F7600E814F3 /* SensitiveInfoClient+Live.swift in Sources */,
48CFC4302ADC10DA00E77A5C /* Collection+Extra.swift in Sources */,
83EE47832AF0EE3C00155F03 /* ProgrammaticScryptoSborValuePreciseDecimal.swift in Sources */,
48CFC2D62ADC10D900E77A5C /* ChooseAccountsRow.swift in Sources */,
Expand Down Expand Up @@ -8910,6 +8972,7 @@
48CFC6332ADC10DB00E77A5C /* UnsecuredEntityControl.swift in Sources */,
48CFC4D32ADC10DA00E77A5C /* StreamTransactionsRequest.swift in Sources */,
48CFC64D2ADC10DB00E77A5C /* PersonaData+PostalAddress.swift in Sources */,
5B9846C02BBD5F0800E814F3 /* SensitiveInfoClient+Interface.swift in Sources */,
48CFC5EE2ADC10DA00E77A5C /* SlideUpPanel+View.swift in Sources */,
48CFC3492ADC10D900E77A5C /* PersonaDataPermissionBox.swift in Sources */,
5BBC43A92BBAC6B0005747B1 /* AppTextEditor.swift in Sources */,
Expand Down Expand Up @@ -9802,6 +9865,14 @@
minimumVersion = 3.0.1;
};
};
5B1C4FD32BBB0B0C00B9436F /* XCRemoteSwiftPackageReference "AppsFlyerFramework-Strict" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/AppsFlyerSDK/AppsFlyerFramework-Strict";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 6.13.2;
};
};
A415574E2B757C5E0040AD4E /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/pointfreeco/swift-composable-architecture";
Expand Down Expand Up @@ -10011,6 +10082,11 @@
package = 48FFFB0B2ADC744700B2B213 /* XCRemoteSwiftPackageReference "TextBuilder" */;
productName = TextBuilder;
};
5B1C4FD42BBB0B0C00B9436F /* AppsFlyerLib-Strict */ = {
isa = XCSwiftPackageProductDependency;
package = 5B1C4FD32BBB0B0C00B9436F /* XCRemoteSwiftPackageReference "AppsFlyerFramework-Strict" */;
productName = "AppsFlyerLib-Strict";
};
A415574F2B757C5E0040AD4E /* ComposableArchitecture */ = {
isa = XCSwiftPackageProductDependency;
package = A415574E2B757C5E0040AD4E /* XCRemoteSwiftPackageReference "swift-composable-architecture" */;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"originHash" : "3313f884630244f405efa4cdbbcb2486d097b16289931114ea3c6826384f24b9",
"pins" : [
{
"identity" : "anycodable",
Expand All @@ -9,6 +10,15 @@
"version" : "0.6.7"
}
},
{
"identity" : "appsflyerframework-strict",
"kind" : "remoteSourceControl",
"location" : "https://github.com/AppsFlyerSDK/AppsFlyerFramework-Strict",
"state" : {
"revision" : "a22ea3af34d4631123bd54f55f95f7b7a9cd905f",
"version" : "6.13.2"
}
},
{
"identity" : "asyncextensions",
"kind" : "remoteSourceControl",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// MARK: - AppsFlyerClient
struct AppsFlyerClient: Sendable {
var start: Start
}

// MARK: AppsFlyerClient.Start
extension AppsFlyerClient {
typealias Start = @Sendable () -> Void
}

extension DependencyValues {
var appsFlyerClient: AppsFlyerClient {
get { self[AppsFlyerClient.self] }
set { self[AppsFlyerClient.self] = newValue }
}
}
26 changes: 26 additions & 0 deletions RadixWallet/Clients/AppsFlyerClient/AppsFlyerClient+Live.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import AppsFlyerLib

extension AppsFlyerClient: DependencyKey {
static var liveValue: AppsFlyerClient {
@Dependency(\.sensitiveInfoClient) var sensitiveInfoClient

return .init(
start: {
guard
let devKey = sensitiveInfoClient.read(.appsFlyerDevKey),
let appId = sensitiveInfoClient.read(.appsFlyerAppId)
else {
return
}
AppsFlyerLib.shared().appsFlyerDevKey = devKey
AppsFlyerLib.shared().appleAppID = appId

#if DEBUG
AppsFlyerLib.shared().isDebug = true
#endif

AppsFlyerLib.shared().start()
}
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// MARK: - SensitiveInfoClient
struct SensitiveInfoClient: Sendable {
var read: Read
}

// MARK: SensitiveInfoClient.Read
extension SensitiveInfoClient {
typealias Read = @Sendable (_ key: Key) -> String?
}

extension DependencyValues {
var sensitiveInfoClient: SensitiveInfoClient {
get { self[SensitiveInfoClient.self] }
set { self[SensitiveInfoClient.self] = newValue }
}
}

// MARK: - SensitiveInfoClient.Key
extension SensitiveInfoClient {
enum Key: String {
case appsFlyerAppId = "APPS_FLYER_APP_ID"
case appsFlyerDevKey = "APPS_FLYER_DEV_KEY"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
extension SensitiveInfoClient: DependencyKey {
static var liveValue: SensitiveInfoClient {
.init(
read: { key in
guard let filePath = Bundle.main.path(forResource: "SensitiveInfo", ofType: "plist") else {
assertionFailure("Couldn't find file 'SensitiveInfo.plist'")
return nil
}
let plist = NSDictionary(contentsOfFile: filePath)
guard let value = plist?.object(forKey: key.rawValue) as? String else {
assertionFailure("Couldn't find value for key '\(key.rawValue)' in 'SensitiveInfo.plist'.")
return nil
}
if value.starts(with: "placeholder") {
loggerGlobal.warning("Please set up your sensitive info tokens in 'SensitiveInfo.plist'")
}
return value
}
)
}
}
7 changes: 7 additions & 0 deletions RadixWallet/Features/AppFeature/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@ public final class AppDelegate: NSObject, UIApplicationDelegate {
sceneConfig.delegateClass = SceneDelegate.self
return sceneConfig
}

public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
@Dependency(\.appsFlyerClient) var appsFlyerClient
appsFlyerClient.start()

return true
}
}
13 changes: 10 additions & 3 deletions SETUP_DEV.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,16 @@ gem install bundler -v 2.3.25
bundle install
```

### Setup secrets

There are two types of secrets required by the project: `General` & `Fastlane`. In order to download them, you will need access to RDX Works 1Password team.
Once you have it, you will be to download each secrets file and place it in the folder detailed in the next steps. After downloading each file, be sure to remove the leading underscore from the file name.

- Download [general secrets][general_secrets] and put the downloaded file in root folder.
- Download [fastlane secrets][fastlane_secrets] and put the downloaded file in [fastlane](fastlane) folder.

### Setup `fastlane`

- Download [fastlane secrets][secret] (requires RDX Works 1Password access).
- Put the downloaded file in [fastlane](fastlane) folder. Be sure to remove the leading underscore from the file name.
- Run the below command to bring the necessary certificates for development:

```sh
Expand All @@ -58,4 +64,5 @@ After the above setup, you are good to go with building and running the app on i

[rbenv]: https://github.com/rbenv/rbenv
[bundler]: https://bundler.io
[secret]: https://start.1password.com/open/i?a=JWO4INKPOFHCDMZ2CYQMY4DRY4&v=srjnzoh2conosxfpkekxlakwzq&i=c75l3mugtfopfd5ebrcn22hssu&h=rdxworks.1password.com
[general_secrets]: https://start.1password.com/open/i?a=JWO4INKPOFHCDMZ2CYQMY4DRY4&v=btoakzspnaugf5miuybcfh5fey&i=hb34e2be37ep5cym3vo7fuvsu4&h=rdxworks.1password.com
[fastlane_secrets]: https://start.1password.com/open/i?a=JWO4INKPOFHCDMZ2CYQMY4DRY4&v=btoakzspnaugf5miuybcfh5fey&i=xpfwvtmc65hbja4xwujp2e6vfq&h=rdxworks.1password.com
Loading
Loading