├── Cartfile.private
├── Cartfile.resolved
├── Tests
├── Responses
│ ├── JWTTokenExpired.json
│ ├── VenmoAccountWrongFormatAccountId.json
│ ├── VenmoAccountMissingAccountId.json
│ ├── PayPalAccountResponseWithInvalidEmail.json
│ ├── PayPalAccountResponseWithMissingEmail.json
│ ├── PayPalAccountResponseNotProfileEmail.json
│ ├── StatusTransitionMockedResponseInvalidTransition.json
│ ├── BankCardErrorResponseWithInvalidBranchId.json
│ ├── BankCardErrorResponseWithMissingCardNumber.json
│ ├── BankAccountErrorResponseWithMissingBankId.json
│ ├── BankCardErrorResponseWithInvalidCardNumber.json
│ ├── Transfer
│ │ ├── CreateTransferResponseInvalidDestinationToken.json
│ │ ├── ScheduleTransferResponse.json
│ │ ├── CreateTransferResponse.json
│ │ └── ListTransferResponse.json
│ ├── PaperCheck
│ │ ├── PaperCheckErrorResponseWithMissingStateProvince.json
│ │ ├── PaperCheckIndividualResponse.json
│ │ ├── PaperCheckBusinessResponse.json
│ │ └── ListPaperCheckResponse.json
│ ├── AuthenticationTokens
│ │ ├── AuthenticationTokenIndividualResponse.json
│ │ └── AuthenticationTokenBusinessResponse.json
│ ├── VenmoAccountResponse.json
│ ├── StatusTransitionMockedResponseSuccess.json
│ ├── PayPalAccountResponse.json
│ ├── BankCardResponse.json
│ ├── PrepaidCardResponse.json
│ ├── VenmoAccountList.json
│ ├── ListPayPalAccountResponse.json
│ ├── UserIndividualResponse.json
│ ├── BankAccount
│ │ ├── BankAccountIndividualResponse.json
│ │ ├── WireAccountIndividualResponse.json
│ │ ├── BankAccountBusinessResponse.json
│ │ └── WireAccountBusinessResponse.json
│ ├── UserBusinessResponse.json
│ ├── TransferMethodUpdateConfigurationFieldsVenmoResponse.json
│ ├── ListPrepaidCardReceiptResponse.json
│ ├── TransferMethodConfigurationKeysWithoutFeeResponse.json
│ ├── TransferMethodUpdateConfigurationFieldsPaypalResponse.json
│ ├── TransferMethodConfigurationGraphQlResponse.json
│ ├── ListPrepaidCardResponse.json
│ ├── TransferMethodConfigurationFeeAndProcessingTimeResponse.json
│ ├── TransferMethodMockedSuccessResponse.json
│ ├── TransferMethodUpdateConfigurationFieldsBankCardResponse.json
│ └── ListBankAccountResponse.json
├── Balance
│ ├── ListUserBalancesResponseWithCurrencyFilter.json
│ ├── ListPrepaidCardBalancesResponseSuccess.json
│ ├── ListUserBalancesResponseSuccess.json
│ └── ListUserBalancesResponseSortCurrencyDesc.json
├── Info.plist
├── Helper
│ ├── HTTPClientMock.swift
│ ├── AuthenticationProviderMock.swift
│ ├── AuthenticationTokenGeneratorMock.swift
│ └── HyperwalletTestHelper.swift
├── GraphQL
│ ├── Query
│ │ ├── HyperwalletTransferMethodConfigurationFeeAndProcessingTimeQueryTests.swift
│ │ └── HyperwalletTransferMethodConfigurationFieldQueryTests.swift
│ └── TransferMethodConfigurationKeyResultTests.swift
├── ConfigurationTests.swift
├── AnyCodableTests.swift
└── AuthenticationTokenDecoderTests.swift
├── .github
└── workflows
│ ├── dependency-review.yml
│ ├── documentation.yml
│ ├── codeql.yml
│ └── ci.yml
├── HyperwalletSDK.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ ├── IDETemplateMacros.plist
│ └── xcschemes
│ └── HyperwalletSDK.xcscheme
├── .jazzy.yaml
├── Sources
├── Info.plist
├── HTTPMethod.swift
├── Model
│ ├── GraphQL
│ │ ├── GraphQlResult.swift
│ │ ├── Connection.swift
│ │ ├── GraphQlError.swift
│ │ ├── Query
│ │ │ ├── GraphQlQuery.swift
│ │ │ └── HyperwalletTransferMethodUpdateConfigurationQueries.swift
│ │ ├── HyperwalletTransferMethodUpdateConfigurationField.swift
│ │ ├── HyperwalletTransferMethodConfigurationField.swift
│ │ └── HyperwalletTransferMethodConfigurationKey.swift
│ ├── Balance
│ │ ├── HyperwalletBalance.swift
│ │ ├── HyperwalletPrepaidCardBalanceQueryParam.swift
│ │ └── HyperwalletBalanceQueryParam.swift
│ ├── TransferMethod
│ │ ├── HyperwalletBankCardQueryParam.swift
│ │ ├── HyperwalletVenmoQueryParam.swift
│ │ ├── HyperwalletPaperCheckQueryParam.swift
│ │ ├── HyperwalletPrepaidCardQueryParam.swift
│ │ ├── HyperwalletPayPalAccountQueryParam.swift
│ │ ├── HyperwalletBankAccountQueryParam.swift
│ │ ├── HyperwalletTransferMethodQueryParam.swift
│ │ ├── HyperwalletPayPalAccount.swift
│ │ ├── HyperwalletVenmoAccount.swift
│ │ ├── HyperwalletBankCard.swift
│ │ └── HyperwalletPrepaidCard.swift
│ ├── Paging
│ │ ├── HyperwalletPageList.swift
│ │ └── QueryParam.swift
│ ├── Transfer
│ │ └── HyperwalletTransferQueryParam.swift
│ └── Receipt
│ │ └── HyperwalletReceiptQueryParam.swift
├── HyperwalletSDK.h
├── Extensions
│ ├── ISO8601DateFormatter.swift
│ └── OSLog.swift
├── HTTPClient.swift
├── Configuration.swift
├── PrivacyInfo.xcprivacy
├── HyperwalletAuthenticationTokenProvider.swift
├── AuthenticationTokenDecoder.swift
├── AnyCodable.swift
└── TransactionType.swift
├── LICENSE
├── HyperwalletSDK.podspec
├── .gitignore
├── .swiftlint.yml
├── fastlane
└── Fastfile
└── CHANGELOG.md
/Cartfile.private:
--------------------------------------------------------------------------------
1 | github "JanGorman/Hippolyte" "1.4.1"
2 |
--------------------------------------------------------------------------------
/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "JanGorman/Hippolyte" "1.4.1"
2 |
--------------------------------------------------------------------------------
/Tests/Responses/JWTTokenExpired.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors":[
3 | {
4 | "message":"JWT expired",
5 | "code":"JWT_EXPIRED"
6 | }
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/Tests/Responses/VenmoAccountWrongFormatAccountId.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors" : [ {
3 | "message" : "Mobile Number is invalid. The maximum length of this field is 10.",
4 | "code" : "CONSTRAINT_VIOLATIONS"
5 | } ]
6 | }
--------------------------------------------------------------------------------
/Tests/Responses/VenmoAccountMissingAccountId.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors" : [ {
3 | "message" : "Mobile Number is required. The Mobile Number cannot be left blank. Please enter a valid US Mobile Number.",
4 | "code" : "CONSTRAINT_VIOLATIONS"
5 | } ]
6 | }
--------------------------------------------------------------------------------
/.github/workflows/dependency-review.yml:
--------------------------------------------------------------------------------
1 | name: Dependency Review
2 |
3 | on:
4 | pull_request:
5 | branches: [ master ]
6 |
7 | jobs:
8 | dependency-review:
9 | uses: hyperwallet/public-security-workflows/.github/workflows/dependency-review.yml@main
--------------------------------------------------------------------------------
/Tests/Responses/PayPalAccountResponseWithInvalidEmail.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "Email is invalid",
5 | "fieldName": "email",
6 | "code": "INVALID_EMAIL_ADDRESS"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/Tests/Responses/PayPalAccountResponseWithMissingEmail.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "You have left the email field empty",
5 | "fieldName": "email",
6 | "code": "MISSING_FIELD"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/Tests/Responses/PayPalAccountResponseNotProfileEmail.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "PayPal transfer method email address should be same as profile email address.",
5 | "code": "CONSTRAINT_VIOLATIONS"
6 | }
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/Tests/Responses/StatusTransitionMockedResponseInvalidTransition.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "transition is invalid",
5 | "fieldName": "transition",
6 | "code": "INVALID_FIELD_VALUE"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/Tests/Responses/BankCardErrorResponseWithInvalidBranchId.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "Invalid field length for branch id",
5 | "fieldName": "branchId",
6 | "code": "INVALID_FIELD_LENGTH"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/Tests/Responses/BankCardErrorResponseWithMissingCardNumber.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "You have left the cardNumber field empty",
5 | "fieldName": "cardNumber",
6 | "code": "MISSING_FIELD"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/HyperwalletSDK.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Tests/Responses/BankAccountErrorResponseWithMissingBankId.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "You have to provide a value for this field",
5 | "fieldName": "bankId",
6 | "code": "CONSTRAIN_VALIDATION"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/Tests/Responses/BankCardErrorResponseWithInvalidCardNumber.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "Invalid field length for cardNumber",
5 | "fieldName": "cardNumber",
6 | "code": "INVALID_FIELD_LENGTH"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/Tests/Responses/Transfer/CreateTransferResponseInvalidDestinationToken.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "The destination token you provided doesn’t exist or is not a valid destination.",
5 | "code": "INVALID_DESTINATION_TOKEN"
6 | }
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/Tests/Responses/PaperCheck/PaperCheckErrorResponseWithMissingStateProvince.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "You have to provide a value for this field",
5 | "fieldName": "stateProvince",
6 | "code": "CONSTRAINT_VALIDATION"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/HyperwalletSDK.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Tests/Responses/AuthenticationTokens/AuthenticationTokenIndividualResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ1c3ItdG9rZW4iLCJpYXQiOjE1NDk1ODAzOTQsImV4cCI6MjU0OTU4MDk5NCwiYXVkIjoicGd1LXRva2VuIiwiaXNzIjoicHJnLXRva2VuIiwicmVzdC11cmkiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVzdC92My8iLCJncmFwaHFsLXVyaSI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9ncmFwaHFsIn0.3psQuyNB7p6tRrQwqyIzIH5OWdJYYBNyngS5k9pUxnfLEeEOfXOQUJwYc_4gFx-U4m3_LwUvkU2oFANOrF4-DQ"
3 | }
4 |
--------------------------------------------------------------------------------
/Tests/Balance/ListUserBalancesResponseWithCurrencyFilter.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 1,
3 | "offset": 0,
4 | "limit": 10,
5 | "data": [
6 | {
7 | "currency": "USD",
8 | "amount": "9933.35"
9 | }
10 | ],
11 | "links": [
12 | {
13 | "params": {
14 | "rel": "self"
15 | },
16 | "href": "https://localhost:8181/rest/v3/users/usr-112233/balances?offset=0&limit=10"
17 | }
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/Tests/Responses/VenmoAccountResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token" : "trm-123456789",
3 | "type" : "VENMO_ACCOUNT",
4 | "status" : "ACTIVATED",
5 | "createdOn" : "2020-08-21T17:12:02",
6 | "transferMethodCountry" : "US",
7 | "transferMethodCurrency" : "USD",
8 | "accountId" : "9876543210",
9 | "userToken" : "usr-123456789",
10 | "links" : [ {
11 | "params" : {
12 | "rel" : "self"
13 | },
14 | "href" : "https://localhost/rest/v3/users/usr-123456789/venmo-accounts/trm-123456789"
15 | } ]
16 | }
--------------------------------------------------------------------------------
/Tests/Balance/ListPrepaidCardBalancesResponseSuccess.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 1,
3 | "offset": 0,
4 | "limit": 10,
5 | "data": [
6 | {
7 | "currency": "USD",
8 | "amount": "9933.35"
9 | }
10 | ],
11 | "links": [
12 | {
13 | "params": {
14 | "rel": "self"
15 | },
16 | "href": "https://localhost:8181/rest/v3/users/usr-112233/prepaid-cards/trm-1234/balances?offset=0&limit=10"
17 | }
18 | ]
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/.jazzy.yaml:
--------------------------------------------------------------------------------
1 | author: Hyperwallet Systems Inc
2 | clean: true
3 | author_url: https://www.hyperwallet.com/
4 | github_url: https://github.com/hyperwallet/hyperwallet-ios-sdk
5 | copyright: Copyright (c) 2018-present, Hyperwallet Systems Inc. All rights reserved.
6 | module: HyperwalletSDK
7 | module_version: 0.0.1
8 | hide_documentation_coverage: true
9 | podspec: HyperwalletSDK.podspec
10 | readme: README.md
11 | skip_undocumented: true
12 | source_directory: Sources
13 | theme: fullwidth
14 | use_safe_filenames: true
15 | output: docs
16 |
--------------------------------------------------------------------------------
/Tests/Responses/Transfer/ScheduleTransferResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "sts-123456",
3 | "changedOn": "2019-05-01T00:01:50",
4 | "transition": "SCHEDULED",
5 | "fromStatus": "QUOTED",
6 | "toStatus": "SCHEDULED",
7 | "notes": "Completing the Partial-Balance Transfer",
8 | "links": [
9 | {
10 | "params": {
11 | "rel": "self"
12 | },
13 | "href": "https://hyperwallet/rest/v3/transfers/trf-123456/status-transitions/sts-123456"
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/Tests/Responses/StatusTransitionMockedResponseSuccess.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "sts-0000",
3 | "createdOn": "2017-10-30T18:50:20",
4 | "transition": "DE_ACTIVATED",
5 | "fromStatus": "ACTIVATED",
6 | "toStatus": "DE_ACTIVATED",
7 | "notes": "Closing this account.",
8 | "links": [
9 | {
10 | "params": {
11 | "rel": "self"
12 | },
13 | "href": "https://localhost/rest/v3/users/usr-0000/bank-accounts/trm-0000/status-transitions/sts-0000"
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/Tests/Responses/PayPalAccountResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "trm-123456789",
3 | "type": "PAYPAL_ACCOUNT",
4 | "status": "ACTIVATED",
5 | "createdOn": "2019-01-09T22:50:14",
6 | "transferMethodCountry": "US",
7 | "transferMethodCurrency": "USD",
8 | "email": "test@paypal.com",
9 | "profileType":"INDIVIDUAL",
10 | "links": [
11 | {
12 | "params": {
13 | "rel": "self"
14 | },
15 | "href": "https://localhost/rest/v3/users/usr-123456789/paypal-accounts/trm-123456789"
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/Tests/Responses/BankCardResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "trm-123",
3 | "type": "BANK_CARD",
4 | "status": "ACTIVATED",
5 | "createdOn": "2019-01-22T22:50:14",
6 | "transferMethodCountry": "US",
7 | "transferMethodCurrency": "USD",
8 | "cardType": "DEBIT",
9 | "cardNumber": "************0114",
10 | "cardBrand": "VISA",
11 | "dateOfExpiry": "2022-12",
12 | "links": [
13 | {
14 | "params": {
15 | "rel": "self"
16 | },
17 | "href": "https://localhost/rest/v3/users/usr-123/bank-cards/trm-123"
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/Tests/Responses/AuthenticationTokens/AuthenticationTokenBusinessResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ1c3ItOGQwYTRlY2MtZTg0NC00NzgzLTg1MGItZmQwNTViNDc3MGVhIiwiaWF0IjoxNTU4MzU1MDM3LCJleHAiOjE1NTgzNTU2MzcsImF1ZCI6InBndS03YTEyMzJlOC0xNDc5LTQzNzAtOWY1NC03ODc1ZjdiMTg2NmMiLCJpc3MiOiJwcmctY2NhODAyNWUtODVhMy0xMWU2LTg2MGEtNThhZDVlY2NlNjFkIiwicmVzdC11cmkiOiJodHRwczovL3FhbWFzdGVyLWh5cGVyd2FsbGV0LmF3cy5wYXlsdXRpb24ubmV0L3Jlc3QvdjMvIiwiZ3JhcGhxbC11cmkiOiJodHRwczovL3FhbWFzdGVyLWh5cGVyd2FsbGV0LmF3cy5wYXlsdXRpb24ubmV0L2dyYXBocWwifQ.1NgGiPg-2e9XrZjW0fQcJ2mX8Yip5YC7LKU1b_MhNKLWWbePSGxFnCEidNNM8I226JSuZq2Sg1QbE2mit7heyg"
3 | }
4 |
--------------------------------------------------------------------------------
/Tests/Responses/PrepaidCardResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "trm-123",
3 | "type": "PREPAID_CARD",
4 | "status": "DEACTIVATED",
5 | "verificationStatus": "NOT_REQUIRED",
6 | "createdOn": "2019-06-20T21:21:43",
7 | "transferMethodCountry": "CA",
8 | "transferMethodCurrency": "USD",
9 | "cardType": "VIRTUAL",
10 | "cardPackage": "L1",
11 | "cardNumber": "************6198",
12 | "cardBrand": "VISA",
13 | "dateOfExpiry": "2023-06",
14 | "links": [
15 | {
16 | "params": {
17 | "rel": "self"
18 | },
19 | "href": "https://localhost/rest/v3/users/usr-123/prepaid-cards/trm-123"
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Tests/Helper/HTTPClientMock.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | @testable import HyperwalletSDK
3 |
4 | class HTTPClientMock: HTTPClientProtocol {
5 | var hasPerformed = false
6 | var request: URLRequest?
7 | var data: Data? = Data("{}".utf8)
8 | var urlResponse: URLResponse?
9 | var error: Error?
10 |
11 | /// Resets mock status
12 | func reset() {
13 | hasPerformed = false
14 | request = nil
15 | data = Data("{}".utf8)
16 | urlResponse = nil
17 | error = nil
18 | }
19 |
20 | func perform(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) {
21 | self.hasPerformed = true
22 | self.request = request
23 | completionHandler(data, urlResponse, error)
24 | }
25 |
26 | func invalidateSession() {
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Tests/Responses/VenmoAccountList.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 1,
3 | "offset": 0,
4 | "limit": 10,
5 | "data": [
6 | {
7 | "token": "trm-123456789",
8 | "type": "VENMO_ACCOUNT",
9 | "status": "ACTIVATED",
10 | "createdOn": "2020-08-09T22:50:14",
11 | "transferMethodCountry": "US",
12 | "transferMethodCurrency": "USD",
13 | "accountId": "9876543210",
14 | "links": [
15 | {
16 | "params": {
17 | "rel": "self"
18 | },
19 | "href": "https://localhost/rest/v3/users/usr-12345678/venmo-accounts/trm-12345678"
20 | }
21 | ]
22 | }
23 | ],
24 | "links": [
25 | {
26 | "params": {
27 | "rel": "self"
28 | },
29 | "href": "https://localhost/rest/v3/users/usr-12345678/venmo-accounts?offset=0&limit=10"
30 | }
31 | ]
32 | }
--------------------------------------------------------------------------------
/Sources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | HyperwalletSDK
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | TAG_VERSION
24 | 1.0.1
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Tests/Helper/AuthenticationProviderMock.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | @testable import HyperwalletSDK
3 |
4 | class AuthenticationProviderMock: HyperwalletAuthenticationTokenProvider {
5 | /// Authentication token
6 | let authorizationData: String?
7 | var error: HyperwalletAuthenticationErrorType?
8 |
9 | /// Indicates the `completionHandler` has been performed
10 | var hasRequestedClientToken = false
11 |
12 | init(authorizationData: String?, error: HyperwalletAuthenticationErrorType? = nil) {
13 | self.authorizationData = authorizationData
14 | self.error = error
15 | }
16 |
17 | /// Resets mock status
18 | func reset() {
19 | hasRequestedClientToken = false
20 | error = nil
21 | }
22 |
23 | func retrieveAuthenticationToken(
24 | completionHandler authenticationTokenHandler: @escaping AuthenticationProviderMock.CompletionHandler) {
25 | hasRequestedClientToken = true
26 | authenticationTokenHandler(authorizationData, error)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.github/workflows/documentation.yml:
--------------------------------------------------------------------------------
1 | name: Update Documentation
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - master
8 |
9 | jobs:
10 | documentation:
11 | name: Documentation
12 | strategy:
13 | matrix:
14 | include:
15 | - os: macos-13
16 | runs-on: ${{ matrix.os }}
17 | steps:
18 | - uses: actions/checkout@v3
19 |
20 | - name: Install Jazz
21 | run: gem install jazzy
22 |
23 | - name: Generate documentation
24 | run: |
25 | jazzy \
26 | --min-acl public \
27 | --no-hide-documentation-coverage \
28 | --theme fullwidth \
29 | --title HyperwalletSDK \
30 | --module HyperwalletSDK \
31 | --output ./docs \
32 | --documentation=./*.md
33 |
34 | - name: Publish on GitHub Pages
35 | uses: ftnext/action-push-ghpages@v1.0.0
36 | with:
37 | build_dir: docs
38 | github_token: ${{ secrets.GITHUB_TOKEN }}
39 |
--------------------------------------------------------------------------------
/Tests/Responses/ListPayPalAccountResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 1,
3 | "offset": 0,
4 | "limit": 10,
5 | "data": [
6 | {
7 | "token": "trm-123456789",
8 | "type": "PAYPAL_ACCOUNT",
9 | "status": "ACTIVATED",
10 | "createdOn": "2019-04-30T18:20:44",
11 | "transferMethodCountry": "US",
12 | "transferMethodCurrency": "USD",
13 | "email": "test@paypal.com",
14 | "profileType":"INDIVIDUAL",
15 | "links": [
16 | {
17 | "params": {
18 | "rel": "self"
19 | },
20 | "href": "https://localhost/rest/v3/users/usr-123456789/paypal-accounts/trm-123456789"
21 | }
22 | ]
23 | }
24 | ],
25 | "links": [
26 | {
27 | "params": {
28 | "rel": "self"
29 | },
30 | "href": "https://localhost/rest/v3/users/usr-123456789/paypal-accounts?offset=0&limit=10"
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/Tests/Responses/Transfer/CreateTransferResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "trf-123456",
3 | "status": "QUOTED",
4 | "createdOn": "2019-05-01T00:00:00",
5 | "clientTransferId": "6712348070812",
6 | "sourceToken": "usr-123456",
7 | "sourceAmount": "80",
8 | "sourceCurrency": "CAD",
9 | "destinationToken": "trm-123456",
10 | "destinationAmount": "62.29",
11 | "destinationFeeAmount": "1.20",
12 | "destinationCurrency": "USD",
13 | "foreignExchanges": [
14 | {
15 | "sourceAmount": "100.00",
16 | "sourceCurrency": "CAD",
17 | "destinationAmount": "63.49",
18 | "destinationCurrency": "USD",
19 | "rate": "0.79"
20 | }
21 | ],
22 | "notes": "Partial-Balance Transfer",
23 | "memo": "TransferClientId56387",
24 | "expiresOn": "2019-05-01T00:02:00",
25 | "links": [
26 | {
27 | "params": {
28 | "rel": "self"
29 | },
30 | "href": "https://localhost:8181/rest/v3/transfers/trf-123456"
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Hyperwallet Systems Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Tests/Responses/UserIndividualResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "YourUserToken",
3 | "status": "ACTIVATED",
4 | "verificationStatus": "NOT_REQUIRED",
5 | "createdOn": "2019-04-30T00:01:53",
6 | "clientUserId": "myAppUserId01",
7 | "profileType": "INDIVIDUAL",
8 | "firstName": "Stan",
9 | "middleName": "Albert",
10 | "lastName": "Fung",
11 | "dateOfBirth": "1980-01-01",
12 | "gender": "MALE",
13 | "phoneNumber": "000-000000",
14 | "mobileNumber": "000-000-0000",
15 | "email": "user01@myApp.com",
16 | "governmentId": "0000000000",
17 | "addressLine1": "abc",
18 | "addressLine2": "def",
19 | "city": "Phoenix",
20 | "stateProvince": "AZ",
21 | "country": "US",
22 | "postalCode": "12345",
23 | "language": "en",
24 | "timeZone": "PST",
25 | "countryOfBirth": "US",
26 | "driversLicenseId": "000123",
27 | "governmentIdType": "PASSPORT",
28 | "passportId": "00000",
29 | "employerId": "001",
30 | "programToken": "prg-00000000-0000-0000-0000-000000000000",
31 | "links": [
32 | {
33 | "params": {
34 | "rel": "self"
35 | },
36 | "href": "https://localhost/rest/v3/users/usr-00000000-0000-0000-0000-000000000000"
37 | }
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/HyperwalletSDK.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |spec|
2 | spec.name = 'HyperwalletSDK'
3 | spec.version = '1.0.1'
4 | spec.summary = 'Hyperwallet Core SDK for iOS to integrate with Hyperwallet Platform'
5 | spec.homepage = 'https://github.com/hyperwallet/hyperwallet-ios-sdk'
6 | spec.license = { :type => 'MIT', :file => 'LICENSE' }
7 | spec.author = { 'Hyperwallet Systems Inc' => 'devsupport@hyperwallet.com' }
8 | spec.platform = :ios
9 | spec.ios.deployment_target = '13.0'
10 | spec.source = { :git => 'https://github.com/hyperwallet/hyperwallet-ios-sdk.git', :tag => "#{spec.version}" }
11 | spec.source_files = 'Sources/**/*.swift'
12 | spec.requires_arc = true
13 | spec.swift_version = '5.0'
14 | spec.resource_bundles = { 'HyperwalletSDK' => ['Sources/PrivacyInfo.xcprivacy'] }
15 |
16 | spec.test_spec 'Tests' do |test_spec|
17 | test_spec.source_files = 'Tests/**/*.swift'
18 | test_spec.resources = 'Tests/**/*.json'
19 | test_spec.dependency 'Hippolyte'
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/Tests/Responses/PaperCheck/PaperCheckIndividualResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token":"trm-12345",
3 | "type":"PAPER_CHECK",
4 | "status":"ACTIVATED",
5 | "createdOn":"2017-10-31T16:47:15",
6 | "transferMethodCountry":"US",
7 | "transferMethodCurrency":"USD",
8 | "profileType":"INDIVIDUAL",
9 | "firstName":"Some",
10 | "lastName":"Guy",
11 | "middleName": "Good",
12 | "dateOfBirth": "1991-01-01",
13 | "addressLine1": "575 Market Street",
14 | "addressLine2": "57 Market Street",
15 | "city":"San Francisco",
16 | "stateProvince":"CA",
17 | "country":"US",
18 | "postalCode":"94105",
19 | "phoneNumber": "604-345-1777",
20 | "mobileNumber": "604-345-1888",
21 | "countryOfBirth": "US",
22 | "driversLicenseId": "1234",
23 | "employerId": "1234",
24 | "governmentId": "12898",
25 | "governmentIdType": "PASSPORT",
26 | "gender": "MALE",
27 | "passportId": "112323",
28 | "shippingMethod": "STANDARD",
29 | "bankAccountRelationship": "SELF",
30 | "links":[
31 | {
32 | "params":{
33 | "rel":"self"
34 | },
35 | "href":"https://localhost/rest/v3/users/usr-0000/paper-checks/trm-12345"
36 | }
37 | ]
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/HTTPMethod.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | /// HTTP method definitions.
20 | enum HTTPMethod: String {
21 | case get = "GET"
22 | case post = "POST"
23 | case put = "PUT"
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Model/GraphQL/GraphQlResult.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | struct GraphQlResult: Codable {
22 | let data: T?
23 | let errors: [GraphQlError]?
24 | }
25 |
--------------------------------------------------------------------------------
/Tests/Balance/ListUserBalancesResponseSuccess.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 10,
3 | "offset": 0,
4 | "limit": 10,
5 | "data": [
6 | {
7 | "currency": "CAD",
8 | "amount": "988.03"
9 | },
10 | {
11 | "currency": "EUR",
12 | "amount": "10000.00"
13 | },
14 | {
15 | "currency": "GBP",
16 | "amount": "0.00"
17 | },
18 | {
19 | "currency": "ILS",
20 | "amount": "0.00"
21 | },
22 | {
23 | "currency": "KES",
24 | "amount": "0.00"
25 | },
26 | {
27 | "currency": "KRW",
28 | "amount": "0"
29 | },
30 | {
31 | "currency": "NZD",
32 | "amount": "0.00"
33 | },
34 | {
35 | "currency": "SEK",
36 | "amount": "0.00"
37 | },
38 | {
39 | "currency": "TWD",
40 | "amount": "0"
41 | },
42 | {
43 | "currency": "USD",
44 | "amount": "9933.35"
45 | }
46 | ],
47 | "links": [
48 | {
49 | "params": {
50 | "rel": "self"
51 | },
52 | "href": "https://localhost:8181/rest/v3/users/usr-112233/balances?offset=0&limit=10"
53 | }
54 | ]
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/Tests/Responses/BankAccount/BankAccountIndividualResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token":"trm-12345",
3 | "type":"BANK_ACCOUNT",
4 | "status":"ACTIVATED",
5 | "createdOn":"2017-10-31T16:47:15",
6 | "transferMethodCountry":"US",
7 | "transferMethodCurrency":"USD",
8 | "branchId":"026009593",
9 | "branchName": "XYZ",
10 | "bankAccountId":"675825206",
11 | "bankAccountRelationship":"SELF",
12 | "bankAccountPurpose":"CHECKING",
13 | "bankName": "ABC",
14 | "profileType":"INDIVIDUAL",
15 | "firstName":"Some",
16 | "lastName":"Guy",
17 | "middleName": "Good",
18 | "dateOfBirth": "1991-01-01",
19 | "addressLine1": "575 Market Street",
20 | "addressLine2": "57 Market Street",
21 | "city":"San Francisco",
22 | "stateProvince":"CA",
23 | "country":"US",
24 | "postalCode":"94105",
25 | "phoneNumber": "604-345-1777",
26 | "mobileNumber": "604-345-1888",
27 | "countryOfBirth": "US",
28 | "driversLicenseId": "1234",
29 | "employerId": "1234",
30 | "governmentId": "12898",
31 | "governmentIdType": "PASSPORT",
32 | "gender": "MALE",
33 | "passportId": "112323",
34 | "links":[
35 | {
36 | "params":{
37 | "rel":"self"
38 | },
39 | "href":"https://localhost/rest/v3/users/usr-0000/bank-accounts/trm-12345"
40 | }
41 | ]
42 | }
43 |
--------------------------------------------------------------------------------
/Tests/Balance/ListUserBalancesResponseSortCurrencyDesc.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "count": 10,
4 | "offset": 0,
5 | "limit": 10,
6 | "data": [
7 | {
8 | "currency": "USD",
9 | "amount": "9933.35"
10 | },
11 | {
12 | "currency": "TWD",
13 | "amount": "0"
14 | },
15 | {
16 | "currency": "SEK",
17 | "amount": "0.00"
18 | },
19 | {
20 | "currency": "NZD",
21 | "amount": "0.00"
22 | },
23 | {
24 | "currency": "KRW",
25 | "amount": "0"
26 | },
27 | {
28 | "currency": "KES",
29 | "amount": "0.00"
30 | },
31 | {
32 | "currency": "ILS",
33 | "amount": "0.00"
34 | },
35 | {
36 | "currency": "GBP",
37 | "amount": "0.00"
38 | },
39 | {
40 | "currency": "EUR",
41 | "amount": "10000.00"
42 | },
43 | {
44 | "currency": "CAD",
45 | "amount": "988.03"
46 | }
47 | ],
48 | "links": [
49 | {
50 | "params": {
51 | "rel": "self"
52 | },
53 | "href": "https://localhost:8181/rest/v3/users/usr-112233/balances?offset=0&limit=10"
54 | }
55 | ]
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/Sources/Model/GraphQL/Connection.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the GraphQL's Connection type
22 | public struct Connection: Codable {
23 | /// Array of Connection type
24 | public let nodes: [T]?
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Model/Balance/HyperwalletBalance.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Details of the balance.
22 | public struct HyperwalletBalance: Decodable {
23 | /// The currency of balance
24 | public let currency: String?
25 | /// The amount of balance
26 | public let amount: String?
27 | }
28 |
--------------------------------------------------------------------------------
/HyperwalletSDK.xcodeproj/xcshareddata/IDETemplateMacros.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FILEHEADER
6 |
7 | // Copyright 2018 - Present Hyperwallet
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
10 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
11 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
12 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all copies or
16 | // substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
19 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## OS X
6 | .DS_Store
7 |
8 | ## Build generated
9 | build/
10 | DerivedData/
11 | docs/
12 |
13 | ## Various settings
14 | *.pbxuser
15 | !default.pbxuser
16 | *.mode1v3
17 | !default.mode1v3
18 | *.mode2v3
19 | !default.mode2v3
20 | *.perspectivev3
21 | !default.perspectivev3
22 | xcuserdata/
23 | *.lock
24 |
25 | ## Other
26 | *.moved-aside
27 | *.xccheckout
28 | *.xcscmblueprint
29 | .idea/
30 |
31 | ## Obj-C/Swift specific
32 | *.hmap
33 | *.ipa
34 | *.dSYM.zip
35 | *.dSYM
36 |
37 | ## Playgrounds
38 | timeline.xctimeline
39 | playground.xcworkspace
40 |
41 | # Swift Package Manager
42 | #
43 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
44 | # Packages/
45 | # Package.pins
46 | # Package.resolved
47 | .build/
48 |
49 | # CocoaPods
50 | #
51 | # We recommend against adding the Pods directory to your .gitignore. However
52 | # you should judge for yourself, the pros and cons are mentioned at:
53 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
54 | #
55 | Pods/
56 |
57 | # Carthage
58 | #
59 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
60 | # Carthage/Checkouts
61 | Carthage/
62 |
63 | # Fastlane
64 | fastlane/README.md
65 | fastlane/report.xml
66 | fastlane/test_output
67 | coverage
68 | output
69 |
--------------------------------------------------------------------------------
/Tests/Responses/UserBusinessResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "YourUserToken",
3 | "status": "PRE_ACTIVATED",
4 | "verificationStatus": "NOT_REQUIRED",
5 | "createdOn": "2019-03-05T19:18:23",
6 | "clientUserId": "myBusinessIdd01",
7 | "profileType": "BUSINESS",
8 | "businessType": "CORPORATION",
9 | "businessName": "Your Business LTD",
10 | "businessRegistrationId": "ABC0000",
11 | "businessOperatingName": "My Business LTD",
12 | "businessRegistrationStateProvince": "BCA",
13 | "businessRegistrationCountry": "US",
14 | "businessContactRole": "DIRECTOR",
15 | "businessContactCountry": "US",
16 | "businessContactAddressLine1": "Business-Address",
17 | "businessContactAddressLine2": "Business-Address 2",
18 | "businessContactCity": "Flagstaff",
19 | "businessContactPostalCode": "0000",
20 | "businessContactStateProvince": "AZ",
21 | "firstName": "John",
22 | "middleName": "Anthony",
23 | "lastName": "John",
24 | "dateOfBirth": "1980-01-01",
25 | "gender": "MALE",
26 | "phoneNumber": "000-00000",
27 | "email": "director@mybusiness.net",
28 | "governmentId": "000000000",
29 | "addressLine1": "Business-Address",
30 | "city": "Phonenix",
31 | "stateProvince": "AZ",
32 | "country": "US",
33 | "postalCode": "V0Z0L0",
34 | "language": "en",
35 | "countryOfNationality": "US",
36 | "programToken": "prg-0000",
37 | "links": [
38 | {
39 | "params": {
40 | "rel": "self"
41 | },
42 | "href": "https://localhost/rest/v3/users/usr-00000000-0000-0000-0000-000000000000"
43 | }
44 | ]
45 | }
46 |
--------------------------------------------------------------------------------
/Tests/Responses/Transfer/ListTransferResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 2,
3 | "offset": 0,
4 | "limit": 10,
5 | "data": [
6 | {
7 | "token": "trf-123456",
8 | "status": "EXPIRED",
9 | "createdOn": "2019-06-13T22:18:18",
10 | "clientTransferId": "67123480708101213",
11 | "sourceToken": "usr-123456",
12 | "sourceAmount": "5.00",
13 | "sourceCurrency": "USD",
14 | "destinationToken": "trm-123456",
15 | "destinationAmount": "3.00",
16 | "destinationFeeAmount": "2.00",
17 | "destinationCurrency": "USD",
18 | "expiresOn": "2019-06-13T22:20:18"
19 | },
20 | {
21 | "token": "trf-123457",
22 | "status": "EXPIRED",
23 | "createdOn": "2019-06-14T21:40:11",
24 | "clientTransferId": "67123480708101213",
25 | "sourceToken": "usr-123456",
26 | "sourceAmount": "127.00",
27 | "sourceCurrency": "USD",
28 | "destinationToken": "trm-123456",
29 | "destinationAmount": "125.00",
30 | "destinationFeeAmount": "2.00",
31 | "destinationCurrency": "USD",
32 | "expiresOn": "2019-06-14T21:42:11"
33 | }
34 | ],
35 | "links": [
36 | {
37 | "params": {
38 | "rel": "self"
39 | },
40 | "href": "https://localhost/rest/v3/transfers/?offset=0&limit=10&sourceToken=usr-123456"
41 | }
42 | ]
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/Model/GraphQL/GraphQlError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | struct GraphQlError: Codable {
22 | var extensions: Extension?
23 | var locations: [Location]?
24 | var message: String?
25 | var path: [AnyCodable]?
26 | }
27 |
28 | struct Location: Codable {
29 | var column: Int?
30 | var line: Int?
31 | }
32 |
33 | struct Extension: Codable {
34 | var code: String?
35 | var timestamp: String?
36 | }
37 |
--------------------------------------------------------------------------------
/Sources/HyperwalletSDK.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | #import
20 |
21 | //! Project version number for HyperwalletSDK.
22 | FOUNDATION_EXPORT double HyperwalletSDKVersionNumber;
23 |
24 | //! Project version string for HyperwalletSDK.
25 | FOUNDATION_EXPORT const unsigned char HyperwalletSDKVersionString[];
26 |
27 | // In this header, you should import all the public headers of your framework using statements like #import
28 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | excluded:
2 | - Carthage
3 | disabled_rules: # rule identifiers to exclude from running
4 | - type_body_length
5 | - file_length
6 | type_name:
7 | max_length: # warning and error
8 | warning: 60
9 | error: 100
10 | identifier_name:
11 | max_length: # warning and error
12 | warning: 60
13 | error: 100
14 | opt_in_rules: # some rules are only opt-in
15 | - first_where
16 | - empty_count
17 | - empty_string
18 | - empty_xctest_method
19 | - explicit_init
20 | - closure_body_length
21 | - closure_end_indentation
22 | - closure_spacing
23 | - collection_alignment
24 | - conditional_returns_on_newline
25 | - contains_over_first_not_nil
26 | - array_init
27 | - attributes
28 | - fallthrough
29 | - identical_operands
30 | - implicit_return
31 | - joined_default_parameter
32 | - last_where
33 | - literal_expression_end_indentation
34 | - missing_docs
35 | - modifier_order
36 | - multiline_arguments
37 | - multiline_function_chains
38 | - multiline_literal_brackets
39 | - multiline_parameters
40 | - operator_usage_whitespace
41 | - override_in_extension
42 | - pattern_matching_keywords
43 | - redundant_nil_coalescing
44 | - redundant_type_annotation
45 | - single_test_class
46 | - sorted_first_last
47 | - sorted_imports
48 | - static_operator
49 | - strict_fileprivate
50 | - unavailable_function
51 | - untyped_error_in_catch
52 | - unused_import
53 | - vertical_parameter_alignment_on_call
54 | - vertical_whitespace_between_cases
55 | - vertical_whitespace_closing_braces
56 | - vertical_whitespace_opening_braces
57 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletBankCardQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the bank card query parameters.
22 | public class HyperwalletBankCardQueryParam: HyperwalletTransferMethodQueryParam {
23 | override public func toQuery() -> [String: String] {
24 | var query = super.toQuery()
25 |
26 | if type != nil {
27 | query[QueryParam.type.rawValue] = QueryType.bankCard.rawValue
28 | }
29 | return query
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Extensions/ISO8601DateFormatter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Date extension.
22 | public extension ISO8601DateFormatter {
23 | /// The thread-safe date formatter to work with ISO8601 date representations.
24 | /// The time zone is ignored.
25 | static let ignoreTimeZone: ISO8601DateFormatter = {
26 | let formatter = ISO8601DateFormatter()
27 | formatter.formatOptions.remove(ISO8601DateFormatter.Options.withTimeZone)
28 | return formatter
29 | }()
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletVenmoQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2020 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the common Venmo's query parameters.
22 | public class HyperwalletVenmoQueryParam: HyperwalletTransferMethodQueryParam {
23 | override public func toQuery() -> [String: String] {
24 | var query = super.toQuery()
25 |
26 | if type != nil {
27 | query[QueryParam.type.rawValue] = QueryType.venmoAccount.rawValue
28 | }
29 | return query
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Tests/Responses/PaperCheck/PaperCheckBusinessResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "trm-000",
3 | "type": "PAPER_CHECK",
4 | "status": "ACTIVATED",
5 | "verificationStatus": "NOT_REQUIRED",
6 | "createdOn": "2019-05-22T11:30:39",
7 | "transferMethodCountry": "US",
8 | "transferMethodCurrency": "USD",
9 | "profileType": "BUSINESS",
10 | "businessType": "CORPORATION",
11 | "businessName": "US BANK NA",
12 | "businessRegistrationId": "123455511",
13 | "businessRegistrationStateProvince": "BC",
14 | "businessRegistrationCountry": "CA",
15 | "businessContactRole": "OWNER",
16 | "businessOperatingName": "AZaz09お元ですか你好ผซอéüõäÄÜÖ-ßḑņžÇĞÿĀſƀɏɐʯʰͰϿЀӿꙀꚗ",
17 | "firstName": "Shyang",
18 | "middleName": "Alma",
19 | "lastName": "Koong",
20 | "dateOfBirth": "2001-01-01",
21 | "countryOfBirth": "US",
22 | "countryOfNationality": "FR",
23 | "gender": "FEMALE",
24 | "phoneNumber": "604-345-1777",
25 | "mobileNumber": "604-345-1888",
26 | "governmentId": "999000999",
27 | "passportId": "123456789",
28 | "driversLicenseId": "234234243",
29 | "employerId": "123456789",
30 | "addressLine1": "1234, Broadway",
31 | "addressLine2": "57 Market Street",
32 | "city": "Test City",
33 | "stateProvince": "WA",
34 | "country": "US",
35 | "postalCode": "12345",
36 | "shippingMethod": "STANDARD",
37 | "bankAccountRelationship": "OWN_COMPANY",
38 | "links": [
39 | {
40 | "params": {
41 | "rel": "self"
42 | },
43 | "href": "https://localhost/rest/v3/users/usr-0000/paper-checks/trm-0000"
44 | }
45 | ]
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletPaperCheckQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the paper check query parameters.
22 | public class HyperwalletPaperCheckQueryParam: HyperwalletTransferMethodQueryParam {
23 | override public func toQuery() -> [String: String] {
24 | var query = super.toQuery()
25 |
26 | if type != nil {
27 | query[QueryParam.type.rawValue] = QueryType.paperCheck.rawValue
28 | }
29 | return query
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletPrepaidCardQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the prepaid card query parameters.
22 | public class HyperwalletPrepaidCardQueryParam: HyperwalletTransferMethodQueryParam {
23 | override public func toQuery() -> [String: String] {
24 | var query = super.toQuery()
25 |
26 | if type != nil {
27 | query[QueryParam.type.rawValue] = QueryType.prepaidCard.rawValue
28 | }
29 | return query
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Tests/Responses/BankAccount/WireAccountIndividualResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "trm-12345",
3 | "type": "WIRE_ACCOUNT",
4 | "status": "ACTIVATED",
5 | "verificationStatus": "NOT_REQUIRED",
6 | "createdOn": "2019-06-11T15:47:12",
7 | "transferMethodCountry": "US",
8 | "transferMethodCurrency": "USD",
9 | "bankName": "Bank of America NA",
10 | "branchId": "026009593",
11 | "bankAccountId": "675825207",
12 | "bankAccountRelationship": "SELF",
13 | "bankAccountPurpose": "CHECKING",
14 | "profileType": "INDIVIDUAL",
15 | "firstName": "Tommy",
16 | "lastName": "Gray",
17 | "phoneNumber": "604-345-1777",
18 | "mobileNumber": "604-345-1888",
19 | "dateOfBirth": "1991-01-01",
20 | "addressLine1": "575 Market Street",
21 | "addressLine2": "57 Market Street",
22 | "city": "San Francisco",
23 | "stateProvince": "CA",
24 | "country": "US",
25 | "postalCode": "94105",
26 | "intermediaryBankAccountId": "246810",
27 | "intermediaryBankAddressLine1": "5 Market Street",
28 | "intermediaryBankAddressLine2": "75 Market Street",
29 | "intermediaryBankCity": "New York",
30 | "intermediaryBankCountry": "US",
31 | "intermediaryBankId": "12345678901",
32 | "intermediaryBankName": "Intermediary Big Bank",
33 | "intermediaryBankPostalCode": "134679",
34 | "intermediaryBankStateProvince": "PA",
35 | "wireInstructions": "This is instruction",
36 | "links": [
37 | {
38 | "params": {
39 | "rel": "self"
40 | },
41 | "href": "https://localhost/rest/v3/users/usr-123456/bank-accounts/trm-12345"
42 | }
43 | ]
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletPayPalAccountQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the PayPal account query parameters.
22 | public class HyperwalletPayPalAccountQueryParam: HyperwalletTransferMethodQueryParam {
23 | override public func toQuery() -> [String: String] {
24 | var query = super.toQuery()
25 |
26 | if type != nil {
27 | query[QueryParam.type.rawValue] = QueryType.payPalAccount.rawValue
28 | }
29 | return query
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Tests/Responses/TransferMethodUpdateConfigurationFieldsVenmoResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "transferMethodUpdateUIConfigurations": {
4 | "nodes": [
5 | {
6 | "country": "US",
7 | "currency": "USD",
8 | "transferMethodType": "VENMO_ACCOUNT",
9 | "profile": "INDIVIDUAL",
10 | "fieldGroups": {
11 | "nodes": [
12 | {
13 | "group": "ACCOUNT_INFORMATION",
14 | "isEditable": true,
15 | "instruction": {
16 | },
17 | "fields": [
18 | {
19 | "category": "ACCOUNT",
20 | "value": "5555555555",
21 | "dataType": "TEXT",
22 | "isRequired": true,
23 | "isEditable": true,
24 | "label": "Mobile Number",
25 | "maxLength": 10,
26 | "minLength": 10,
27 | "name": "accountId",
28 | "placeholder": "",
29 | "regularExpression": "^([0-9]{10})$",
30 | "validationMessage": {
31 | "length": "The exact length of this field is 10.",
32 | "pattern": "is invalid. The number you provided is not a valid US mobile number. Please use this format: 5555555555",
33 | "empty": "You must provide a value for this field"
34 | },
35 | "fieldValueMasked": false
36 | }
37 | ]
38 | }
39 | ]
40 | }
41 | }
42 | ]
43 | }
44 | }
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/Tests/Responses/ListPrepaidCardReceiptResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "data" : [ {
3 | "journalId": "CC002F14A570",
4 | "type": "DEPOSIT",
5 | "createdOn": "2019-05-27T16:01:10",
6 | "entry": "CREDIT",
7 | "destinationToken": "trm-a4b44375",
8 | "amount": "18.05",
9 | "currency": "USD",
10 | "details": {
11 | "cardNumber": "************7917"
12 | }
13 | }, {
14 | "journalId": "CC002F14A571",
15 | "type": "TRANSFER_TO_BANK_ACCOUNT",
16 | "createdOn": "2019-05-27T15:57:49",
17 | "entry": "DEBIT",
18 | "destinationToken" : "trm-987654",
19 | "amount": "10.25",
20 | "currency": "USD",
21 | "details": {
22 | "cardNumber": "************7917"
23 | }
24 | }, {
25 | "journalId": "CC002F14A572",
26 | "type": "PAYMENT",
27 | "createdOn": "2017-11-01T17:12:19",
28 | "entry": "CREDIT",
29 | "destinationToken": "trm-97a31",
30 | "amount": "11.00",
31 | "currency": "USD",
32 | "details": {
33 | "cardNumber": "************7917"
34 | }
35 | }, {
36 | "journalId": "CC002F14A572",
37 | "type": "PAYMENT",
38 | "createdOn": "2017-11-01T17:12:19",
39 | "entry": "CREDIT",
40 | "destinationToken": "trm-97a31",
41 | "amount": "11.00",
42 | "currency": "USD",
43 | "details": {
44 | "cardNumber": "************7917"
45 | }
46 | }],
47 | "links": [ {
48 | "params": {
49 | "rel": "self"
50 | },
51 | "href": "https://localhost:8181/rest/v3/users/usr-112233/prepaid-cards/trm-213141/receipts"
52 | } ]
53 | }
54 |
--------------------------------------------------------------------------------
/Sources/Model/GraphQL/Query/GraphQlQuery.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// The `GraphQlQuery` protocol for creating a GraphQL query with the Hyperwallet platform.
22 | protocol GraphQlQuery: Encodable {
23 | /// Returns a formatted query string that can be posted to the Hyperwallet platforms GraphQL schema.
24 | ///
25 | /// - Parameter userToken: the unique identifier for the User that the query pertains to
26 | /// - Returns: a formatted query string that can be posted to the Hyperwallet platforms GraphQL schema
27 | func toGraphQl(userToken: String) -> String
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletBankAccountQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the bank account query parameters.
22 | public class HyperwalletBankAccountQueryParam: HyperwalletTransferMethodQueryParam {
23 | override public func toQuery() -> [String: String] {
24 | var query = super.toQuery()
25 |
26 | if let type = type, type == QueryType.wireAccount.rawValue {
27 | query[QueryParam.type.rawValue] = type
28 | } else if type != nil {
29 | query[QueryParam.type.rawValue] = QueryType.bankAccount.rawValue
30 | }
31 | return query
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Tests/Responses/BankAccount/BankAccountBusinessResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "trm-000",
3 | "type": "BANK_ACCOUNT",
4 | "status": "ACTIVATED",
5 | "verificationStatus": "NOT_REQUIRED",
6 | "createdOn": "2019-05-22T11:30:39",
7 | "transferMethodCountry": "US",
8 | "transferMethodCurrency": "USD",
9 | "bankName": "US BANK NA",
10 | "bankId": "102000021",
11 | "branchId": "102000021",
12 | "bankAccountId": "7861012345",
13 | "bankAccountRelationship": "OWN_COMPANY",
14 | "bankAccountPurpose": "CHECKING",
15 | "profileType": "BUSINESS",
16 | "businessType": "CORPORATION",
17 | "businessName": "US BANK NA",
18 | "businessRegistrationId": "123455511",
19 | "businessRegistrationStateProvince": "BC",
20 | "businessRegistrationCountry": "CA",
21 | "businessContactRole": "OWNER",
22 | "businessOperatingName": "AZaz09お元ですか你好ผซอéüõäÄÜÖ-ßḑņžÇĞÿĀſƀɏɐʯʰͰϿЀӿꙀꚗ",
23 | "firstName": "Shyang",
24 | "middleName": "Alma",
25 | "lastName": "Koong",
26 | "dateOfBirth": "2001-01-01",
27 | "countryOfBirth": "US",
28 | "countryOfNationality": "FR",
29 | "gender": "FEMALE",
30 | "phoneNumber": "604-345-1777",
31 | "mobileNumber": "604-345-1888",
32 | "governmentId": "999000999",
33 | "passportId": "123456789",
34 | "driversLicenseId": "234234243",
35 | "employerId": "123456789",
36 | "addressLine1": "1234, Broadway",
37 | "addressLine2": "57 Market Street",
38 | "city": "Test City",
39 | "stateProvince": "WA",
40 | "country": "US",
41 | "postalCode": "12345",
42 | "links": [
43 | {
44 | "params": {
45 | "rel": "self"
46 | },
47 | "href": "https://localhost/rest/v3/users/usr-0000/bank-accounts/trm-0000"
48 | }
49 | ]
50 | }
51 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | name: CodeQL (Swift) - SAST
2 |
3 | # Trigger the workflow on pushes and pull requests targeting the `master` branch
4 | # as well as through manual dispatch from the Actions tab.
5 | on:
6 | push:
7 | branches:
8 | - master
9 | pull_request:
10 | branches:
11 | - master
12 | workflow_dispatch:
13 |
14 | jobs:
15 | analyze:
16 | # The CodeQL analysis will run on macOS with the specified Xcode version.
17 | name: Code Scanning - CodeQL
18 | strategy:
19 | fail-fast: false
20 | matrix:
21 | include:
22 | # Only run the CodeQL scan on macOS. You can add additional entries
23 | # here if you need to support other macOS versions or Xcode releases.
24 | - os: macos-15
25 | xcode_version: 16.2
26 | runs-on: ${{ matrix.os }}
27 | timeout-minutes: 25
28 | permissions:
29 | security-events: write
30 | packages: read
31 | actions: read
32 | contents: read
33 | steps:
34 | # Always check out the repository so the CodeQL scan has access to your source code.
35 | - uses: actions/checkout@v3
36 |
37 | # On macOS runners, set up the requested Xcode version to build Swift code.
38 | - name: Setup Xcode
39 | if: runner.os == 'macOS'
40 | uses: maxim-lobanov/setup-xcode@v1
41 | with:
42 | xcode-version: '${{ matrix.xcode_version }}'
43 |
44 | # Invoke the reusable CodeQL workflow. It will initialize CodeQL with the
45 | # specified language (Swift) and perform an autobuild. The timeout for
46 | # scanning can be customized if needed.
47 | - uses: hyperwallet/public-security-workflows/codeql@main
48 | with:
49 | language: swift
50 | build-mode: autobuild
51 | timeout-minutes: 25
--------------------------------------------------------------------------------
/Tests/Responses/TransferMethodConfigurationKeysWithoutFeeResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "errors": [
3 | {
4 | "message": "Could not find associated fees.",
5 | "locations": [
6 | {
7 | "line": 15,
8 | "column": 33
9 | }
10 | ],
11 | "path": [
12 | "countries",
13 | "nodes",
14 | 2,
15 | "currencies",
16 | "nodes",
17 | 1,
18 | "transferMethodTypes",
19 | "nodes",
20 | 0,
21 | "fees"
22 | ],
23 | "extensions": {
24 | "errorType": "DataFetchingException",
25 | "timestamp": "2019-05-14 07:22:32"
26 | }
27 | }
28 | ],
29 | "data": {
30 | "countries": {
31 | "nodes": [
32 | {
33 | "code": "HR",
34 | "name": "CROATIA (local name: Hrvatska)",
35 | "currencies": {
36 | "nodes": [
37 | {
38 | "code": "HRK",
39 | "name": "HRK",
40 | "transferMethodTypes": {
41 | "nodes": [
42 | {
43 | "code": "BANK_ACCOUNT",
44 | "name": "Bank Account"
45 | }
46 | ]
47 | }
48 | }
49 | ]
50 | }
51 | }
52 | ]
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Sources/Extensions/OSLog.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 | import os.log
21 |
22 | extension OSLog {
23 | private static var subsystem = "com.hyperwallet.ios.HyperwalletSDK"
24 |
25 | // custom categories
26 | static let initialization = OSLog(subsystem: subsystem, category: "initialization")
27 | static let authentication = OSLog(subsystem: subsystem, category: "authentication")
28 | static let data = OSLog(subsystem: subsystem, category: "data")
29 | static let httpRequest = OSLog(subsystem: subsystem, category: "httpRequest")
30 | static let graphQl = OSLog(subsystem: subsystem, category: "graphQl")
31 | static let notification = OSLog(subsystem: subsystem, category: "notification")
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/Model/Balance/HyperwalletPrepaidCardBalanceQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 | /// Representation of the prepaid card balance QueryParam fields.
21 | public class HyperwalletPrepaidCardBalanceQueryParam: QueryParam {
22 | /// Representation of the sortable fields
23 | public enum QuerySortable: String {
24 | /// Sort the result by ascendant amount
25 | case ascendantAmount = "+amount"
26 | /// Sort the result by ascendant currency
27 | case ascendantCurrency = "+currency"
28 | /// Sort the result by descendant amount
29 | case descendantAmount = "-amount"
30 | /// Sort the result by descendant currency
31 | case descendantCurrency = "-currency"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Tests/Responses/TransferMethodUpdateConfigurationFieldsPaypalResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "transferMethodUpdateUIConfigurations": {
4 | "nodes": [
5 | {
6 | "country": "CA",
7 | "currency": "CAD",
8 | "transferMethodType": "PAYPAL_ACCOUNT",
9 | "profile": "INDIVIDUAL",
10 | "fieldGroups": {
11 | "nodes": [
12 | {
13 | "group": "CONTACT_INFORMATION",
14 | "isEditable": true,
15 | "instruction": {
16 | "textBottom": "Email address associated with your PayPal account."
17 | },
18 | "fields": [
19 | {
20 | "category": "ACCOUNT",
21 | "value": "hello@hw.com",
22 | "dataType": "TEXT",
23 | "isRequired": true,
24 | "isEditable": true,
25 | "label": "Email",
26 | "maxLength": 200,
27 | "minLength": 3,
28 | "name": "email",
29 | "placeholder": "",
30 | "regularExpression": "^(?:[a-zA-Z0-9]{1}|[a-zA-Z0-9\\_]{1}[a-zA-Z0-9\\_\\!#$%&\\'*\\/=?^{|}~`\\-\\.+]{0,64}[a-zA-Z0-9\\_\\-+]{1})[@]{1}(?:[a-zA-Z0-9]{1}(?=.*?[\\.])([a-zA-Z0-9-\\.](?!\\.\\.)){0,133})([a-zA-Z0-9]){2}$",
31 | "validationMessage": {
32 | "length": "The minimum length of this field is 3 and maximum length is 200.",
33 | "pattern": "is invalid length or format.",
34 | "empty": "You must provide a value for this field"
35 | },
36 | "fieldValueMasked": false
37 | }
38 | ]
39 | }
40 | ]
41 | }
42 | }
43 | ]
44 | }
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/fastlane/Fastfile:
--------------------------------------------------------------------------------
1 | lane :beta do
2 | version = updateVersion("beta")
3 | update("beta", version)
4 | end
5 |
6 | lane :release_beta do
7 | version = updateVersion("beta")
8 | commit = last_git_commit
9 | message = commit[:message]
10 | add_git_tag(tag: "#{version}", message: "#{message}")
11 | set_github_release(tag_name: "#{version}", description: "#{message}")
12 | push_to_git_remote
13 | pod_push(allow_warnings: true, skip_tests: true)
14 | end
15 |
16 | lane :unit_tests do
17 | run_tests(
18 | project: "HyperwalletSDK.xcodeproj",
19 | devices: ['iPhone 15 Pro'],
20 | derived_data_path: './output',
21 | scheme: "HyperwalletSDK",
22 | configuration: 'Debug',
23 | code_coverage: true,
24 | xcargs: 'ONLY_ACTIVE_ARCH=YES ENABLE_TESTABILITY=YES CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO'
25 | )
26 | end
27 |
28 | def updateVersion(type)
29 | version = last_git_tag
30 | if type == "beta" then
31 | version_components = version.split("beta")
32 | last_component = version_components[-1].to_i + 1
33 | last_component_string = last_component.to_s
34 | if last_component_string.size == 1 then
35 | last_component_string = "0" + last_component_string
36 | end
37 | version_components[-1] = last_component_string
38 | build_version = version_components.join("beta")
39 | end
40 | end
41 |
42 | def update(type, version)
43 | # Update the TAG_VERSION property
44 | info_plist_path = "Sources/Info.plist"
45 | set_info_plist_value(path: info_plist_path, key: "TAG_VERSION", value: version)
46 | podspec_name = "HyperwalletSDK.podspec"
47 | pod_lib_lint(allow_warnings: true, skip_tests: true)
48 | version_bump_podspec(version_number: version, path: podspec_name)
49 | git_add(path: [podspec_name, info_plist_path, "*.md"])
50 | git_commit(path: [podspec_name, info_plist_path, "*.md"], message: "#{version} release")
51 | push_to_git_remote
52 | end
53 |
--------------------------------------------------------------------------------
/Sources/HTTPClient.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | protocol HTTPClientProtocol {
22 | typealias ResultHandler = (Data?, URLResponse?, Error?) -> Void
23 |
24 | func perform(with request: URLRequest, completionHandler: @escaping ResultHandler)
25 |
26 | func invalidateSession()
27 | }
28 |
29 | struct HTTPClient: HTTPClientProtocol {
30 | private let session: URLSession
31 |
32 | init(configuration: URLSessionConfiguration) {
33 | self.session = URLSession(configuration: configuration)
34 | }
35 |
36 | func perform(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) {
37 | let task = session.dataTask(with: request, completionHandler: completionHandler)
38 | task.resume()
39 | }
40 |
41 | func invalidateSession() {
42 | self.session.invalidateAndCancel()
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Tests/Responses/BankAccount/WireAccountBusinessResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "token": "trm-12345",
3 | "type": "WIRE_ACCOUNT",
4 | "status": "ACTIVATED",
5 | "verificationStatus": "NOT_REQUIRED",
6 | "createdOn": "2019-06-11T15:47:12",
7 | "transferMethodCountry": "US",
8 | "transferMethodCurrency": "USD",
9 | "bankId": "13254687",
10 | "bankName": "Bank of America NA",
11 | "branchId": "026009593",
12 | "bankAccountId": "675825208",
13 | "bankAccountRelationship": "OWN_COMPANY",
14 | "bankAccountPurpose": "CHECKING",
15 | "profileType": "BUSINESS",
16 | "businessType": "CORPORATION",
17 | "businessName": "Some company",
18 | "businessRegistrationId": "123455511",
19 | "businessRegistrationStateProvince": "BC",
20 | "businessRegistrationCountry": "CA",
21 | "businessContactRole": "OWNER",
22 | "firstName": "Tommy",
23 | "middleName": "Alma",
24 | "lastName": "Gray",
25 | "dateOfBirth": "1991-01-01",
26 | "countryOfBirth": "US",
27 | "countryOfNationality": "FR",
28 | "phoneNumber": "604-345-1777",
29 | "mobileNumber": "604-345-1888",
30 | "governmentId": "999000999",
31 | "addressLine1": "1234, Broadway",
32 | "addressLine2": "57 Market Street",
33 | "city": "Test City",
34 | "stateProvince": "WA",
35 | "country": "US",
36 | "postalCode": "12345",
37 | "intermediaryBankAccountId": "246810",
38 | "intermediaryBankAddressLine1": "5 Market Street",
39 | "intermediaryBankAddressLine2": "75 Market Street",
40 | "intermediaryBankCity": "New York",
41 | "intermediaryBankCountry": "US",
42 | "intermediaryBankId": "12345678901",
43 | "intermediaryBankName": "Intermediary Big Bank",
44 | "intermediaryBankPostalCode": "134679",
45 | "intermediaryBankStateProvince": "PA",
46 | "wireInstructions": "This is instruction",
47 | "links": [
48 | {
49 | "params": {
50 | "rel": "self"
51 | },
52 | "href": "https://localhost/rest/v3/users/usr-123456/bank-accounts/trm-12345"
53 | }
54 | ]
55 | }
56 |
--------------------------------------------------------------------------------
/Tests/GraphQL/Query/HyperwalletTransferMethodConfigurationFeeAndProcessingTimeQueryTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | @testable import HyperwalletSDK
20 | import XCTest
21 |
22 | // swiftlint:disable type_name
23 | class HyperwalletTransferMethodConfigurationFeeAndProcessingTimeQueryTests: XCTestCase {
24 | func testHashable_fieldQueryNotEqual() {
25 | let usUsdFieldQuery =
26 | HyperwalletTransferMethodTypesFeesAndProcessingTimesQuery(country: "US",
27 | currency: "USD")
28 |
29 | let usCadQuery =
30 | HyperwalletTransferMethodTypesFeesAndProcessingTimesQuery(country: "US",
31 | currency: "CAD")
32 |
33 | XCTAssertNotEqual(usUsdFieldQuery, usCadQuery)
34 | XCTAssertNotEqual(usUsdFieldQuery.hashValue, usCadQuery.hashValue)
35 | }
36 | }
37 | // swiftlint:enable type_name
38 |
--------------------------------------------------------------------------------
/Tests/Responses/TransferMethodConfigurationGraphQlResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "data":{
3 | "transferMethodConfigurations":{
4 | "count":218,
5 | "nodes":[
6 | {
7 | "countries":[
8 | "US"
9 | ],
10 | "currencies":[
11 | "USD"
12 | ],
13 | "transferMethodType":"BANK_ACCOUNT",
14 | "profile":"INDIVIDUAL"
15 | },
16 | {
17 | "countries":[
18 | "US"
19 | ],
20 | "currencies":[
21 | "USD"
22 | ],
23 | "transferMethodType":"BANK_ACCOUNT",
24 | "profile":"BUSINESS"
25 | }
26 | ]
27 | }
28 | },
29 | "errors":[
30 | {
31 | "message":"Name for character with ID 1002 could not be fetched.",
32 | "locations":[
33 | {
34 | "line":6,
35 | "column":7
36 | }
37 | ],
38 | "path":[
39 | "hero",
40 | "heroFriends",
41 | "name"
42 | ],
43 | "extensions":{
44 | "code":"CAN_NOT_FETCH_BY_ID",
45 | "timestamp":"Fri Feb 9 14:33:09 UTC 2018"
46 | }
47 | },
48 | {
49 | "message":"Name for character with ID 1002 could not be fetched.",
50 | "locations":[
51 | {
52 | "line":6,
53 | "column":7
54 | }
55 | ],
56 | "path":[
57 | "hero",
58 | "heroFriends",
59 | "name"
60 | ],
61 | "extensions":{
62 | "code":"CAN_NOT_FETCH_BY_ID",
63 | "timestamp":"Fri Feb 9 14:33:09 UTC 2018"
64 | }
65 | }
66 | ],
67 | "dataPresent":true
68 | }
69 |
--------------------------------------------------------------------------------
/Tests/Responses/ListPrepaidCardResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "count": 2,
3 | "offset": 0,
4 | "limit": 10,
5 | "data": [
6 | {
7 | "token": "trm-123",
8 | "type": "PREPAID_CARD",
9 | "status": "DEACTIVATED",
10 | "verificationStatus": "NOT_REQUIRED",
11 | "createdOn": "2019-06-20T21:21:43",
12 | "transferMethodCountry": "CA",
13 | "transferMethodCurrency": "USD",
14 | "cardType": "VIRTUAL",
15 | "cardPackage": "L1",
16 | "cardNumber": "************6198",
17 | "cardBrand": "VISA",
18 | "dateOfExpiry": "2023-06",
19 | "links": [
20 | {
21 | "params": {
22 | "rel": "self"
23 | },
24 | "href": "https://localhost/rest/v3/users/usr-123/prepaid-cards/trm-123"
25 | }
26 | ]
27 | },
28 | {
29 | "token": "trm-456",
30 | "primaryCardToken": "trm-123",
31 | "type": "PREPAID_CARD",
32 | "status": "DEACTIVATED",
33 | "verificationStatus": "NOT_REQUIRED",
34 | "createdOn": "2019-06-20T22:21:43",
35 | "transferMethodCountry": "CA",
36 | "transferMethodCurrency": "USD",
37 | "cardType": "VIRTUAL",
38 | "cardPackage": "L1",
39 | "cardNumber": "************2345",
40 | "cardBrand": "MASTERCARD",
41 | "dateOfExpiry": "2023-06",
42 | "links": [
43 | {
44 | "params": {
45 | "rel": "self"
46 | },
47 | "href": "https://localhost/rest/v3/users/usr-123/prepaid-cards/trm-456"
48 | }
49 | ]
50 | }
51 | ],
52 | "links": [
53 | {
54 | "params": {
55 | "rel": "self"
56 | },
57 | "href": "https://localhost/rest/v3/users/usr-123/prepaid-cards?offset=0&limit=10&sortBy=-createdOn&createdAfter=2019-05-31T20%3A59%3A58"
58 | }
59 | ]
60 | }
61 |
--------------------------------------------------------------------------------
/Sources/Model/Paging/HyperwalletPageList.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of subset content from a dataset
22 | public struct HyperwalletPageList: Decodable {
23 | /// The amount of the dataset
24 | public let count: Int?
25 | /// The `ListType` items
26 | public let data: [ListType]?
27 | /// The maximum number of records that will be returned per page
28 | public let limit: Int?
29 | /// The links
30 | public let links: [HyperwalletPageLink]?
31 | /// The number of records to skip.
32 | public let offset: Int?
33 | }
34 |
35 | /// Representation of the page link
36 | public struct HyperwalletPageLink: Decodable {
37 | /// The URL of the link
38 | public let href: URL?
39 | /// The `HyperwalletPageParameter`
40 | public let params: HyperwalletPageParameter?
41 | }
42 |
43 | /// Representation of the relationship between the current document and the linked document
44 | public struct HyperwalletPageParameter: Decodable {
45 | /// The relationship
46 | public let rel: String?
47 | }
48 |
--------------------------------------------------------------------------------
/Sources/Model/Balance/HyperwalletBalanceQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the balance QueryParam fields.
22 | public class HyperwalletBalanceQueryParam: QueryParam {
23 | private enum QueryParam: String {
24 | case currency
25 | }
26 | /// A value that identifies the currency of balance
27 | public var currency: String?
28 |
29 | /// Representation of the sortable fields
30 | public enum QuerySortable: String {
31 | /// Sort the result by ascendant amount
32 | case ascendantAmount = "+amount"
33 | /// Sort the result by ascendant currency
34 | case ascendantCurrency = "+currency"
35 | /// Sort the result by descendant amount
36 | case descendantAmount = "-amount"
37 | /// Sort the result by descendant currency
38 | case descendantCurrency = "-currency"
39 | }
40 |
41 | override func toQuery() -> [String: String] {
42 | var query = super.toQuery()
43 | if let currency = currency {
44 | query[QueryParam.currency.rawValue] = currency
45 | }
46 | return query
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Tests/ConfigurationTests.swift:
--------------------------------------------------------------------------------
1 | @testable import HyperwalletSDK
2 | import XCTest
3 |
4 | class ConfigurationTests: XCTestCase {
5 | var issueDate: Date!
6 | var issueTime: Double!
7 |
8 | override func setUp() {
9 | issueDate = Date()
10 | issueTime = Double((issueDate.timeIntervalSince1970).rounded())
11 | }
12 |
13 | func testIsTokenStale_true() {
14 | let expiryOn = Double((Date().addingTimeInterval(0.1).timeIntervalSince1970).rounded())
15 | let configuration = getConfiguration(expiryOn)
16 | XCTAssertTrue(configuration.isTokenStale(), "Token should be stale")
17 | }
18 |
19 | func testIsTokenStale_false() {
20 | let expiryOn = Double((Date().addingTimeInterval(600).timeIntervalSince1970).rounded())
21 | let configuration = getConfiguration(expiryOn)
22 | XCTAssertFalse(configuration.isTokenStale(), "Token should not be stale")
23 | }
24 |
25 | func testIsTokenExpired_true() {
26 | let expiryOn = Double((Date().addingTimeInterval(0.1).timeIntervalSince1970).rounded())
27 | let configuration = getConfiguration(expiryOn)
28 | DispatchQueue.main.asyncAfter(deadline: .now() + 15) {
29 | XCTAssertTrue(configuration.isTokenExpired(), "Token should be expired")
30 | }
31 | }
32 |
33 | func testIsTokenExpired_false() {
34 | let expiryOn = Double((Date().addingTimeInterval(600).timeIntervalSince1970).rounded())
35 |
36 | let configuration = getConfiguration(expiryOn)
37 |
38 | XCTAssertFalse(configuration.isTokenExpired(), "Token should not be expired")
39 | }
40 |
41 | private func getConfiguration(_ expiryOn: Double) -> Configuration {
42 | Configuration(createOn: issueTime,
43 | clientToken: "client-token",
44 | expiresOn: expiryOn,
45 | graphQlUrl: "https://test/graphql",
46 | restUrl: "https://test/restUrl",
47 | environment: "DEV",
48 | insightsUrl: "https://test/insightsUrl",
49 | issuer: "issuer-token",
50 | userToken: "user-token",
51 | programModel: "program-model",
52 | authorization: "")
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Sources/Model/Transfer/HyperwalletTransferQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the user transfers QueryParams fields.
22 | public class HyperwalletTransferQueryParam: QueryParam {
23 | /// A value that identifies the client transfer id.
24 | public var clientTransferId: String?
25 | /// A value that identifies the destination token.
26 | public var destinationToken: String?
27 | /// A value that identifies the source token.
28 | public var sourceToken: String?
29 |
30 | private enum QueryParam: String {
31 | case clientTransferId
32 | case destinationToken
33 | case sourceToken
34 | }
35 |
36 | override func toQuery() -> [String: String] {
37 | var query = super.toQuery()
38 | if let clientTransferId = clientTransferId {
39 | query[QueryParam.clientTransferId.rawValue] = clientTransferId
40 | }
41 | if let destinationToken = destinationToken {
42 | query[QueryParam.destinationToken.rawValue] = destinationToken
43 | }
44 | if let sourceToken = sourceToken {
45 | query[QueryParam.sourceToken.rawValue] = sourceToken
46 | }
47 | return query
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Sources/Model/GraphQL/HyperwalletTransferMethodUpdateConfigurationField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// The `HyperwalletTransferMethodUpdateConfigurationField` protocol for processing the update transfer method
22 | /// configuration field result from the Hyperwallet platform.
23 | public protocol HyperwalletTransferMethodUpdateConfigurationField {
24 | /// Returns `HyperwalletTransferMethodConfiguration`
25 | ///
26 | /// - Returns: `HyperwalletTransferMethodConfiguration`
27 | func transferMethodUpdateConfiguration() -> HyperwalletTransferMethodConfiguration?
28 | }
29 |
30 | final class TransferMethodUpdateConfigurationFieldResult: HyperwalletTransferMethodUpdateConfigurationField {
31 | private let transferMethodUpdateUIConfigurations: [HyperwalletTransferMethodConfiguration]?
32 |
33 | /// Creates a new instance of the 'TransferMethodUpdateConfigurationFieldResult' based on the
34 | /// transfer method configuration result
35 | ///
36 | /// - Parameters:
37 | /// - transferMethodUpdateUIConfigurations: the GraphQL `[HyperwalletTransferMethodConfiguration]`
38 | init(_ transferMethodUpdateUIConfigurations: [HyperwalletTransferMethodConfiguration]?) {
39 | self.transferMethodUpdateUIConfigurations = transferMethodUpdateUIConfigurations
40 | }
41 |
42 | func transferMethodUpdateConfiguration() -> HyperwalletTransferMethodConfiguration? {
43 | transferMethodUpdateUIConfigurations?.first
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Sources/Model/Receipt/HyperwalletReceiptQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the user receipts QueryParam fields.
22 | public class HyperwalletReceiptQueryParam: QueryParam {
23 | private enum QueryParam: String {
24 | case currency
25 | }
26 | /// A value that identifies the user receipts currency.
27 | public var currency: String?
28 |
29 | /// Representation of the field's sortable
30 | public enum QuerySortable: String {
31 | /// Sort the result by ascendant amount
32 | case ascendantAmount = "+amount"
33 | /// Sort the result by ascendant created on
34 | case ascendantCreatedOn = "+createdOn"
35 | /// Sort the result by ascendant currency
36 | case ascendantCurrency = "+currency"
37 | /// Sort the result by ascendant type
38 | case ascendantType = "+type"
39 | /// Sort the result by descendant amount
40 | case descendantAmount = "-amount"
41 | /// Sort the result by descendant created on
42 | case descendantCreatedOn = "-createdOn"
43 | /// Sort the result by descendant currency
44 | case descendantCurrency = "-currency"
45 | /// Sort the result by descendant type
46 | case descendantType = "-type"
47 | }
48 |
49 | override func toQuery() -> [String: String] {
50 | var query = super.toQuery()
51 | if let currency = currency {
52 | query[QueryParam.currency.rawValue] = currency
53 | }
54 | return query
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: iOS Core SDK CI
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - master
8 | - support/SDK-V3
9 | - feature/**
10 | - bugfix/**
11 |
12 | jobs:
13 | test:
14 | name: Test - ${{ matrix.os }} - ${{ matrix.xcode_version }} - ${{ matrix.fastlane_task }}
15 | strategy:
16 | fail-fast: false
17 | matrix:
18 | include:
19 | - os: macos-15
20 | xcode_version: 16.2
21 | fastlane_task: unit_tests
22 |
23 | runs-on: ${{ matrix.os }}
24 | steps:
25 | - uses: actions/checkout@v3
26 |
27 | - name: Setup Xcode
28 | uses: maxim-lobanov/setup-xcode@v1
29 | with:
30 | xcode-version: '${{ matrix.xcode_version }}'
31 |
32 | - name: Carthage [Setup cache]
33 | uses: actions/cache@v3
34 | with:
35 | path: Carthage
36 | key: ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}
37 | restore-keys: |
38 | ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}
39 |
40 | - name: Carthage [Install dependencies]
41 | run: carthage bootstrap
42 | --platform ios
43 | --cache-builds
44 | --use-xcframeworks
45 | --no-use-binaries
46 |
47 | - name: Run ${{ matrix.task_title }}
48 | run: fastlane ${{ matrix.fastlane_task }}
49 |
50 | - name: Install Lint
51 | run:
52 | brew install swiftlint
53 |
54 | - name: Lint validation
55 | run:
56 | swiftlint lint --strict --reporter json
57 |
58 | - name: Code Coverage [Build report]
59 | run: |
60 | brew install llvm
61 | export PATH="$(brew --prefix llvm)/bin:$PATH"
62 | llvm-cov report \
63 | --use-color \
64 | --instr-profile=$(find ./output -name "*.profdata") \
65 | --object $(find ./output -name "HyperwalletSDK") \
66 | -ignore-filename-regex="HyperwalletPrepaidCard.swift|/HyperwalletUser.swift"
67 |
68 | - name: Code Coverage [Export report to lcov format]
69 | run: |
70 | export PATH="$(brew --prefix llvm)/bin:$PATH"
71 | mkdir coverage
72 | llvm-cov export \
73 | --format=lcov > ./coverage/lcov.info \
74 | --instr-profile=$(find ./output -name "*.profdata") \
75 | --object $(find ./output -name "HyperwalletSDK") \
76 | -ignore-filename-regex="HyperwalletPrepaidCard.swift|/HyperwalletUser.swift"
77 |
78 | - name: Post to Coveralls
79 | uses: coverallsapp/github-action@master
80 | with:
81 | github-token: ${{ secrets.GITHUB_TOKEN }}
--------------------------------------------------------------------------------
/Sources/Configuration.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Configuration object retrieved on successful authentication
22 | public struct Configuration: Codable {
23 | let createOn: Double
24 | let clientToken: String
25 | let expiresOn: Double
26 | let graphQlUrl: String
27 | let restUrl: String
28 | /// The environment type
29 | public let environment: String?
30 | /// The insights Url
31 | public let insightsUrl: String?
32 | /// The issuer
33 | public let issuer: String
34 | /// The user token
35 | public let userToken: String
36 | /// The program model
37 | public let programModel: String?
38 | var authorization: String!
39 | private static let stalePeriod = 30.0 // 30 seconds
40 | private let createOnBootTime = ProcessInfo.processInfo.systemUptime
41 |
42 | enum CodingKeys: String, CodingKey {
43 | case createOn = "iat"
44 | case clientToken = "aud"
45 | case expiresOn = "exp"
46 | case graphQlUrl = "graphql-uri"
47 | case issuer = "iss"
48 | case userToken = "sub"
49 | case restUrl = "rest-uri"
50 | case insightsUrl = "insights-uri"
51 | case environment = "environment"
52 | case programModel = "program-model"
53 | }
54 |
55 | func isTokenStale() -> Bool {
56 | let tokenLifespan = expiresOn - createOn
57 | return ProcessInfo.processInfo.systemUptime - createOnBootTime >= tokenLifespan - Configuration.stalePeriod
58 | }
59 |
60 | func isTokenExpired() -> Bool {
61 | let tokenLifespan = expiresOn - createOn
62 | return ProcessInfo.processInfo.systemUptime - createOnBootTime >= tokenLifespan
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Tests/GraphQL/Query/HyperwalletTransferMethodConfigurationFieldQueryTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | @testable import HyperwalletSDK
20 | import XCTest
21 |
22 | class HyperwalletTransferMethodConfigurationFieldQueryTests: XCTestCase {
23 | func testHashable_fieldQueryNotEqual() {
24 | let usUsdFieldQuery = HyperwalletTransferMethodConfigurationFieldQuery(country: "US",
25 | currency: "USD",
26 | transferMethodType: "BANK_CARD",
27 | profile: "INDIVIDUAL")
28 |
29 | let usCadFieldQuery = HyperwalletTransferMethodConfigurationFieldQuery(country: "US",
30 | currency: "CAD",
31 | transferMethodType: "BANK_CARD",
32 | profile: "INDIVIDUAL")
33 |
34 | XCTAssertNotEqual(usUsdFieldQuery, usCadFieldQuery)
35 | XCTAssertNotEqual(usUsdFieldQuery.hashValue, usCadFieldQuery.hashValue)
36 | }
37 |
38 | func testHashable_editFieldQueryNotEqual() {
39 | let fieldQuery = HyperwalletTransferMethodUpdateConfigurationFieldQuery(transferMethodToken: "trm-93939939393")
40 | let fieldQuery1 = HyperwalletTransferMethodUpdateConfigurationFieldQuery(transferMethodToken: "trm-93939939398")
41 | XCTAssertNotEqual(fieldQuery, fieldQuery1)
42 | XCTAssertNotEqual(fieldQuery.hashValue, fieldQuery1.hashValue)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Tests/Responses/TransferMethodConfigurationFeeAndProcessingTimeResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "countries": {
4 | "nodes": [
5 | {
6 | "code": "CA",
7 | "name": "Canada",
8 | "currencies": {
9 | "nodes": [
10 | {
11 | "code": "CAD",
12 | "name": "CAD",
13 | "transferMethodTypes": {
14 | "nodes": [
15 | {
16 | "code": "BANK_ACCOUNT",
17 | "name": "Bank Account",
18 | "processingTimes": {
19 | "nodes": [
20 | {
21 | "country": "CA",
22 | "currency": "CAD",
23 | "transferMethodType": "BANK_ACCOUNT",
24 | "value": "1 - 3 Business days"
25 | }
26 | ]
27 | },
28 | "fees": {
29 | "nodes": [
30 | {
31 | "value": "2.20",
32 | "feeRateType": "FLAT",
33 | "currency": "CAD"
34 | },
35 | {
36 | "value":"8.9",
37 | "feeRateType":"PERCENT",
38 | "currency": "CAD",
39 | "minimum":"0.05",
40 | "maximum":"1.00"
41 | }
42 | ]
43 | }
44 | },
45 | {
46 | "code": "PAPER_CHECK",
47 | "name": "Paper Check",
48 | "processingTimes": {
49 | "nodes": [
50 | {
51 | "country": "CA",
52 | "currency": "CAD",
53 | "transferMethodType": "PAPER_CHECK",
54 | "value": "5 - 7 Business days"
55 | }
56 | ]
57 | },
58 | "fees": {
59 | "nodes": [
60 | {
61 | "currency": "CAD",
62 | "feeRateType": "FLAT",
63 | "value": "3.50"
64 | },
65 | {
66 | "currency": "CAD",
67 | "feeRateType": "PERCENT"
68 | }
69 | ]
70 | }
71 | }
72 | ]
73 | }
74 | }
75 | ]
76 | }
77 | }
78 | ]
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Sources/Model/GraphQL/HyperwalletTransferMethodConfigurationField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// The `HyperwalletTransferMethodConfigurationField` protocol for processing the transfer method
22 | /// configuration field result from the Hyperwallet platform.
23 | public protocol HyperwalletTransferMethodConfigurationField {
24 | /// Returns a list of `HyperwalletField`
25 | ///
26 | /// - Returns: a list of `HyperwalletFieldGroup`
27 | func fieldGroups() -> [HyperwalletFieldGroup]?
28 |
29 | /// Returns the list of transfer method types based on the parameters
30 | ///
31 | /// - Returns: HyperwalletTransferMethodType
32 | func transferMethodType() -> HyperwalletTransferMethodType?
33 | }
34 |
35 | final class TransferMethodConfigurationFieldResult: HyperwalletTransferMethodConfigurationField {
36 | private let transferMethodUIConfigurations: [HyperwalletTransferMethodConfiguration]?
37 | private let country: HyperwalletCountry?
38 |
39 | /// Creates a new instance of the 'HyperwalletTransferMethodConfigurationField' based on the
40 | /// transfer method configuration result
41 | ///
42 | /// - Parameters:
43 | /// - transferMethodUIConfigurations: the GraphQL `[HyperwalletTransferMethodConfiguration]`
44 | /// - country: the GraphQL `HyperwalletCountry`
45 | init(_ transferMethodUIConfigurations: [HyperwalletTransferMethodConfiguration]?, _ country: HyperwalletCountry?) {
46 | self.transferMethodUIConfigurations = transferMethodUIConfigurations
47 | self.country = country
48 | }
49 |
50 | func fieldGroups() -> [HyperwalletFieldGroup]? {
51 | transferMethodUIConfigurations?.first?.fieldGroups?.nodes
52 | }
53 |
54 | func transferMethodType() -> HyperwalletTransferMethodType? {
55 | country?.currencies?.nodes?.first?.transferMethodTypes?.nodes?.first
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyCollectedDataTypes
6 |
7 |
8 | NSPrivacyCollectedDataType
9 | NSPrivacyCollectedDataTypeUserID
10 | NSPrivacyCollectedDataTypeLinked
11 |
12 | NSPrivacyCollectedDataTypeTracking
13 |
14 | NSPrivacyCollectedDataTypePurposes
15 |
16 | NSPrivacyCollectedDataTypePurposeAppFunctionality
17 |
18 |
19 |
20 | NSPrivacyCollectedDataType
21 | NSPrivacyCollectedDataTypeName
22 | NSPrivacyCollectedDataTypeLinked
23 |
24 | NSPrivacyCollectedDataTypeTracking
25 |
26 | NSPrivacyCollectedDataTypePurposes
27 |
28 | NSPrivacyCollectedDataTypePurposeAppFunctionality
29 |
30 |
31 |
32 | NSPrivacyCollectedDataType
33 | NSPrivacyCollectedDataTypeEmailAddress
34 | NSPrivacyCollectedDataTypeLinked
35 |
36 | NSPrivacyCollectedDataTypeTracking
37 |
38 | NSPrivacyCollectedDataTypePurposes
39 |
40 | NSPrivacyCollectedDataTypePurposeAppFunctionality
41 |
42 |
43 |
44 | NSPrivacyCollectedDataType
45 | NSPrivacyCollectedDataTypePhoneNumber
46 | NSPrivacyCollectedDataTypeLinked
47 |
48 | NSPrivacyCollectedDataTypeTracking
49 |
50 | NSPrivacyCollectedDataTypePurposes
51 |
52 | NSPrivacyCollectedDataTypePurposeAppFunctionality
53 |
54 |
55 |
56 | NSPrivacyCollectedDataType
57 | NSPrivacyCollectedDataTypePhysicalAddress
58 | NSPrivacyCollectedDataTypeLinked
59 |
60 | NSPrivacyCollectedDataTypeTracking
61 |
62 | NSPrivacyCollectedDataTypePurposes
63 |
64 | NSPrivacyCollectedDataTypePurposeAppFunctionality
65 |
66 |
67 |
68 | NSPrivacyCollectedDataType
69 | NSPrivacyCollectedDataTypePaymentInfo
70 | NSPrivacyCollectedDataTypeLinked
71 |
72 | NSPrivacyCollectedDataTypeTracking
73 |
74 | NSPrivacyCollectedDataTypePurposes
75 |
76 | NSPrivacyCollectedDataTypePurposeAppFunctionality
77 |
78 |
79 |
80 | NSPrivacyTracking
81 |
82 | NSPrivacyAccessedAPITypes
83 |
84 |
85 | NSPrivacyAccessedAPIType
86 | NSPrivacyAccessedAPICategorySystemBootTime
87 | NSPrivacyAccessedAPITypeReasons
88 |
89 | 35F9.1
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/Tests/AnyCodableTests.swift:
--------------------------------------------------------------------------------
1 | @testable import HyperwalletSDK
2 | import XCTest
3 |
4 | // swiftlint:disable force_cast force_try
5 | class AnyCodableTests: XCTestCase {
6 | func testEncode() {
7 | // Given
8 | let bankAccount = HyperwalletBankAccount
9 | .Builder(transferMethodCountry: "US",
10 | transferMethodCurrency: "USD",
11 | transferMethodProfileType: "INDIVIDUAL",
12 | transferMethodType: "BANK_ACCOUNT")
13 | .bankAccountId("12345")
14 | .branchId("123456")
15 | .bankAccountPurpose("CHECKING")
16 | .build()
17 |
18 | // When
19 | let jsonBody = try! JSONEncoder().encode(bankAccount)
20 |
21 | // Then
22 | XCTAssertNotNil(jsonBody)
23 | let jsonBodyString = String(bytes: jsonBody, encoding: .utf8)
24 | XCTAssertNotNil(jsonBodyString)
25 | XCTAssertTrue(((jsonBodyString!.contains("USD"))))
26 | }
27 |
28 | func testDecode() {
29 | // Given
30 | let jsonBody = HyperwalletTestHelper.getDataFromJson("BankAccountIndividualResponse")
31 |
32 | // When
33 | let decoder = JSONDecoder()
34 | let bankAccount = try! decoder.decode(HyperwalletBankAccount.self, from: jsonBody)
35 |
36 | // Then
37 | XCTAssertNotNil(bankAccount)
38 | XCTAssertEqual(bankAccount.token, "trm-12345")
39 | let links = bankAccount.getFields()["links"]!.value as! [Any]
40 | XCTAssertNotNil(links)
41 | XCTAssertNotNil(links.first)
42 | }
43 |
44 | func testEncode_supportedPrimitiveTypes() {
45 | // Given
46 | let data: [String: AnyCodable] = [
47 | "stringVal": AnyCodable(value: "String"),
48 | "intVal": AnyCodable(value: 1),
49 | "doubleVal": AnyCodable(value: 1.2),
50 | "boolVal": AnyCodable(value: false)
51 | ]
52 |
53 | // When
54 | let jsonBody = try! JSONEncoder().encode(data)
55 |
56 | // Then
57 | XCTAssertNotNil(jsonBody)
58 | }
59 |
60 | func testEncode_unsupportedType() {
61 | let data: [String: AnyCodable] = [
62 | "int64Val": AnyCodable(value: Int64(100))
63 | ]
64 |
65 | XCTAssertThrowsError(try JSONEncoder().encode(data)) { error in
66 | XCTAssertEqual((error as! HyperwalletErrorType).getHyperwalletErrors()?.errorList?.first?.code,
67 | "PARSE_ERROR")
68 | }
69 | }
70 |
71 | func testDecode_arraySupportedTypes() {
72 | // Given
73 | let jsonBody = Data("[1, \"String\", 1.2, true, null]".utf8)
74 |
75 | // When
76 | let result = try! JSONDecoder().decode(Array.self, from: jsonBody)
77 |
78 | // Then
79 | XCTAssertNotNil(result)
80 | XCTAssertNotNil(result[0].value as! Int, "1")
81 | XCTAssertNotNil(result[1].value as! String, "String")
82 | XCTAssertNotNil(result[2].value as! Double, "1.2")
83 | XCTAssertNotNil(result[3].value as! Bool, "true")
84 | XCTAssertNotNil(result[4].value as! String, "") // null
85 | }
86 | }
87 | // swiftlint:enable force_cast force_try
88 |
--------------------------------------------------------------------------------
/Sources/Model/Paging/QueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the common query parameters.
22 | public class QueryParam {
23 | /// Returns user receipts created after this datetime.
24 | public var createdAfter: Date?
25 | /// Returns user receipts created before this datetime.
26 | public var createdBefore: Date?
27 | /// The maximum number of records that will be returned per page
28 | public var limit: Int?
29 | /// The number of records to skip. If no filters are applied, records will be skipped from the beginning
30 | /// (based on default sort criteria). Default value is 0. Range is from 0 to {n-1} where n = number of
31 | /// matching records for the query.
32 | public var offset: Int?
33 | /// The user receipts attribute to sort the result set by.
34 | public var sortBy: String?
35 |
36 | private enum QueryParam: String {
37 | case createdAfter
38 | case createdBefore
39 | case limit
40 | case offset
41 | case sortBy
42 | }
43 |
44 | /// Creates a new instance of `QueryParam`]
45 | public init() {
46 | limit = 10
47 | offset = 0
48 | }
49 |
50 | /// Builds the URL Queries
51 | ///
52 | /// - Returns: Returns the URL Query's dictionary.
53 | func toQuery() -> [String: String] {
54 | var query = [String: String]()
55 |
56 | if let offset = offset {
57 | query[QueryParam.offset.rawValue] = String(offset)
58 | }
59 | if let limit = limit {
60 | query[QueryParam.limit.rawValue] = String(limit)
61 | }
62 | if let date = createdAfter {
63 | query[QueryParam.createdAfter.rawValue] = ISO8601DateFormatter.ignoreTimeZone.string(from: date)
64 | }
65 | if let date = createdBefore {
66 | query[QueryParam.createdBefore.rawValue] = ISO8601DateFormatter.ignoreTimeZone.string(from: date)
67 | }
68 | if let sortBy = sortBy {
69 | query[QueryParam.sortBy.rawValue] = sortBy
70 | }
71 | return query
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Sources/HyperwalletAuthenticationTokenProvider.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// The `HyperwalletAuthenticationTokenProvider` protocol provides the Hyperwallet iOS Core SDK with an
22 | /// abstraction to retrieve an authentication token. An authentication token is a JSON Web Token that will be used
23 | /// to authenticate the User to the Hyperwallet platform.
24 | ///
25 | /// Implementations of `HyperwalletAuthenticationTokenProvider` are expected to be non-blocking and thread safe.
26 | @objc
27 | public protocol HyperwalletAuthenticationTokenProvider {
28 | /// A callback interface to handle the submission of an authentication token or an error message in case of failure.
29 | ///
30 | /// The authentication token is a JSON web token that contains as part of its claim set the principal that will
31 | /// be interacting with the Hyperwallet platform.
32 | ///
33 | /// Authentication token will be used until it expires.
34 | ///
35 | /// The `HyperwalletAuthenticationErrorType` will contain error in case authentication token
36 | /// is not retrieved successfully.
37 | ///
38 | /// - Parameters:
39 | /// - authenticationToken: a JWT token identifying a Hyperwallet User principal
40 | /// - error: an `HyperwalletAuthenticationErrorType` indicating the cause of the authentication
41 | /// token retrieval error
42 | typealias CompletionHandler = (_ authenticationToken: String?, _ error: Error?) -> Void
43 |
44 | /// Invoked when the Hyperwallet iOS Core SDK requires an authentication token.
45 | ///
46 | /// Implementations of this function are expected to call the
47 | /// `HyperwalletAuthenticationTokenProvider.CompletionHandler(String, nil)` method when an authentication token is
48 | /// retrieved and the `HyperwalletAuthenticationTokenProvider.CompletionHandler(nil, AuthenticationErrorType)`
49 | /// when an authentication token is not retrieved.
50 | ///
51 | /// - Parameter completionHandler: A completion handler for authentication tokens
52 | func retrieveAuthenticationToken(completionHandler: @escaping CompletionHandler)
53 | }
54 |
--------------------------------------------------------------------------------
/Tests/Responses/TransferMethodMockedSuccessResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "count":2,
3 | "offset":0,
4 | "limit":10,
5 | "data":[
6 | {
7 | "token":"trm-00001",
8 | "type":"BANK_ACCOUNT",
9 | "status":"ACTIVATED",
10 | "verificationStatus":"NOT_REQUIRED",
11 | "createdOn":"2018-12-15T00:30:12",
12 | "transferMethodCountry":"US",
13 | "transferMethodCurrency":"USD",
14 | "bankId":"021000021",
15 | "branchId":"021000021",
16 | "bankAccountId":"25589087",
17 | "bankAccountRelationship":"SELF",
18 | "bankAccountPurpose":"CHECKING",
19 | "profileType":"INDIVIDUAL",
20 | "firstName":"Uriel",
21 | "lastName":"Kenyon",
22 | "dateOfBirth":"1980-01-01",
23 | "countryOfBirth":"US",
24 | "countryOfNationality":"CA",
25 | "gender":"MALE",
26 | "phoneNumber":"+1 604 6666666",
27 | "mobileNumber":"604 666 6666",
28 | "governmentId":"987654321",
29 | "addressLine1":"950 Granville Street",
30 | "city":"Vancouver",
31 | "stateProvince":"BC",
32 | "country":"CA",
33 | "postalCode":"V6Z1L2",
34 | "links":[
35 | {
36 | "params":{
37 | "rel":"self"
38 | },
39 | "href":"https://localhost/rest/v3/users/usr-0000/transfer-methods/trm-00001"
40 | }
41 | ]
42 | },
43 | {
44 | "token":"trm-00002",
45 | "type":"BANK_CARD",
46 | "status":"ACTIVATED",
47 | "createdOn":"2018-12-15T00:30:17",
48 | "transferMethodCountry":"US",
49 | "transferMethodCurrency":"USD",
50 | "cardType":"DEBIT",
51 | "cardNumber":"************1358",
52 | "cardBrand":"VISA",
53 | "dateOfExpiry":"2022-12",
54 | "links":[
55 | {
56 | "params":{
57 | "rel":"self"
58 | },
59 | "href":"https://localhost/rest/v3/users/usr-0000/transfer-methods/trm-00002"
60 | }
61 | ]
62 | }
63 | ],
64 | "links":[
65 | {
66 | "params":{
67 | "rel":"self"
68 | },
69 | "href":"https://localhost/rest/v3/users/usr-0000/transfer-methods?offset=0&limit=10&createdBefore=2018-12-18T00%3A30%3A11.000Z&sortBy=+createdOn&createdAfter=2018-12-15T00%3A30%3A11.000Z"
70 | },
71 | {
72 | "params":{
73 | "rel":"next"
74 | },
75 | "href":"https://localhost/rest/v3/users/usr-0000/transfer-methods?offset=10&limit=10&createdBefore=2018-12-18T00%3A30%3A11.000Z&sortBy=+createdOn&createdAfter=2018-12-15T00%3A30%3A11.000Z"
76 | },
77 | {
78 | "params":{
79 | "rel":"last"
80 | },
81 | "href":"https://localhost/rest/v3/users/usr-0000/transfer-methods?offset=299&limit=10&createdBefore=2018-12-18T00%3A30%3A11.000Z&sortBy=+createdOn&createdAfter=2018-12-15T00%3A30%3A11.000Z"
82 | }
83 | ]
84 | }
85 |
--------------------------------------------------------------------------------
/Sources/AuthenticationTokenDecoder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Decodes a Authentication token into an object that holds the decoded body.
22 | /// If the token cannot be decoded a `Hyperwallet ErrorType` will be thrown.
23 | struct AuthenticationTokenDecoder {
24 | /// Retrieves the `Configuration` based on the Authentication Token payload
25 | ///
26 | /// - parameter from: The authentication token data.
27 | ///
28 | /// - throws: An error if the authentication token cannot be decoded
29 | ///
30 | /// - returns: A `Configuration` instance.
31 | static func decode(from token: String?) throws -> Configuration {
32 | guard let token = token else {
33 | throw ErrorTypeHelper.parseError(message: "Invalid Authnetication token")
34 | }
35 | let parts = token.components(separatedBy: ".")
36 | guard parts.count == 3,
37 | !parts[1].isEmpty,
38 | let payload = base64UrlDecode(parts[1]),
39 | var config = try? JSONDecoder().decode(Configuration.self, from: payload) else {
40 | throw ErrorTypeHelper.parseError(message: "Invalid Authnetication token")
41 | }
42 |
43 | config.authorization = token
44 | return config
45 | }
46 |
47 | /// Converts the `value` encoded in Base64URL to Base64
48 | ///
49 | /// - returns: an `Data` encoded in base64.
50 | private static func base64UrlDecode(_ value: String) -> Data? {
51 | var base64 = value
52 | .replacingOccurrences(of: "-", with: "+")
53 | .replacingOccurrences(of: "_", with: "/")
54 | let length = Double(base64.lengthOfBytes(using: String.Encoding.utf8))
55 | // Add the mandatory `=` if the length is different
56 | let requiredLength = 4 * ceil(length / 4.0)
57 | let paddingLength = requiredLength - length
58 | if paddingLength > 0 {
59 | let padding = "".padding(toLength: Int(paddingLength), withPad: "=", startingAt: 0)
60 | base64.append(padding)
61 | }
62 | return Data(base64Encoded: base64, options: .ignoreUnknownCharacters)
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Tests/Responses/TransferMethodUpdateConfigurationFieldsBankCardResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "data": {
3 | "transferMethodUpdateUIConfigurations": {
4 | "nodes": [
5 | {
6 | "country": "US",
7 | "currency": "USD",
8 | "transferMethodType": "BANK_CARD",
9 | "profile": "INDIVIDUAL",
10 | "fieldGroups": {
11 | "nodes": [
12 | {
13 | "group": "ACCOUNT_INFORMATION",
14 | "isEditable": true,
15 | "instruction": {
16 | "textBottom": "CVV is a 3 digit number, typically found on the back of a debit card."
17 | },
18 | "fields": [
19 | {
20 | "category": "ACCOUNT",
21 | "value": "****0006",
22 | "dataType": "NUMBER",
23 | "isRequired": true,
24 | "isEditable": true,
25 | "label": "Card Number",
26 | "maxLength": 19,
27 | "minLength": 13,
28 | "name": "cardNumber",
29 | "placeholder": "",
30 | "regularExpression": "^[0-9]{13,19}$",
31 | "validationMessage": {
32 | "length": "The minimum length of this field is 13 and maximum length is 19.",
33 | "pattern": "is invalid length or format.",
34 | "empty": "You must provide a value for this field"
35 | },
36 | "fieldValueMasked": true,
37 | "mask": {
38 | "defaultPattern": "#### #### #### ####",
39 | "scrubRegex": " "
40 | }
41 | },
42 | {
43 | "category": "ACCOUNT",
44 | "value": "2024-10-01",
45 | "dataType": "EXPIRY_DATE",
46 | "isRequired": true,
47 | "isEditable": true,
48 | "label": "Expiration Date",
49 | "maxLength": 7,
50 | "minLength": 7,
51 | "name": "dateOfExpiry",
52 | "placeholder": "",
53 | "regularExpression": "^[0-9]{4}-(1[0-2]|0[1-9])$",
54 | "validationMessage": {
55 | "length": "The exact length of this field is 7.",
56 | "pattern": "is invalid length or format.",
57 | "empty": "You must provide a value for this field"
58 | },
59 | "fieldValueMasked": false
60 | },
61 | {
62 | "category": "ACCOUNT",
63 | "dataType": "NUMBER",
64 | "isRequired": true,
65 | "isEditable": true,
66 | "label": "CVV (Card Security Code)",
67 | "maxLength": 4,
68 | "minLength": 3,
69 | "name": "cvv",
70 | "placeholder": "",
71 | "regularExpression": "^[0-9]{3,4}$",
72 | "validationMessage": {
73 | "length": "The minimum length of this field is 3 and maximum length is 4.",
74 | "pattern": "is invalid length or format.",
75 | "empty": "You must provide a value for this field"
76 | },
77 | "fieldValueMasked": false,
78 | "mask": {
79 | "defaultPattern": "###"
80 | }
81 | }
82 | ]
83 | }
84 | ]
85 | }
86 | }
87 | ]
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Tests/Responses/ListBankAccountResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "count":2,
3 | "offset":0,
4 | "limit":10,
5 | "data":[
6 | {
7 | "token":"trm-12345",
8 | "type":"BANK_ACCOUNT",
9 | "status":"DE_ACTIVATED",
10 | "verificationStatus":"NOT_REQUIRED",
11 | "createdOn":"2018-12-15T00:00:55",
12 | "transferMethodCountry":"US",
13 | "transferMethodCurrency":"USD",
14 | "bankId":"021000021",
15 | "branchId":"021000021",
16 | "bankAccountId":"54629074",
17 | "bankAccountRelationship":"SELF",
18 | "bankAccountPurpose":"CHECKING",
19 | "profileType":"INDIVIDUAL",
20 | "firstName":"Uriel",
21 | "lastName":"Kenyon",
22 | "dateOfBirth":"1980-01-01",
23 | "countryOfBirth":"US",
24 | "countryOfNationality":"CA",
25 | "gender":"MALE",
26 | "phoneNumber":"+1 604 6666666",
27 | "mobileNumber":"604 666 6666",
28 | "governmentId":"987654321",
29 | "addressLine1":"950 Granville Street",
30 | "city":"Vancouver",
31 | "stateProvince":"BC",
32 | "country":"CA",
33 | "postalCode":"V6Z1L2",
34 | "links":[
35 | {
36 | "params":{
37 | "rel":"self"
38 | },
39 | "href":"https://localhost/rest/v3/users/usr-0000/bank-accounts/trm-12345"
40 | }
41 | ]
42 | },
43 | {
44 | "token":"trm-12345",
45 | "type":"BANK_ACCOUNT",
46 | "status":"DE_ACTIVATED",
47 | "verificationStatus":"NOT_REQUIRED",
48 | "createdOn":"2018-12-15T00:30:11",
49 | "transferMethodCountry":"US",
50 | "transferMethodCurrency":"USD",
51 | "bankId":"021000021",
52 | "branchId":"021000021",
53 | "bankAccountId":"87930292",
54 | "bankAccountRelationship":"SELF",
55 | "bankAccountPurpose":"CHECKING",
56 | "profileType":"INDIVIDUAL",
57 | "firstName":"Uriel",
58 | "lastName":"Kenyon",
59 | "dateOfBirth":"1980-01-01",
60 | "countryOfBirth":"US",
61 | "countryOfNationality":"CA",
62 | "gender":"MALE",
63 | "phoneNumber":"+1 604 6666666",
64 | "mobileNumber":"604 666 6666",
65 | "governmentId":"987654321",
66 | "addressLine1":"950 Granville Street",
67 | "city":"Vancouver",
68 | "stateProvince":"BC",
69 | "country":"CA",
70 | "postalCode":"V6Z1L2",
71 | "links":[
72 | {
73 | "params":{
74 | "rel":"self"
75 | },
76 | "href":"https://localhost/rest/v3/users/usr-0000/bank-accounts/trm-12345"
77 | }
78 | ]
79 | }
80 | ],
81 | "links":[
82 | {
83 | "params":{
84 | "rel":"self"
85 | },
86 | "href":"https://localhost/rest/v3/users/abc-00000000-0000/bank-accounts?offset=0&limit=10"
87 | },
88 | {
89 | "params":{
90 | "rel":"next"
91 | },
92 | "href":"https://localhost/rest/v3/users/abc-00000000-0000/bank-accounts?offset=10&limit=10"
93 | },
94 | {
95 | "params":{
96 | "rel":"last"
97 | },
98 | "href":"https://localhost/rest/v3/users/abc-00000000-0000/bank-accounts?offset=194&limit=10"
99 | }
100 | ]
101 | }
102 |
--------------------------------------------------------------------------------
/Tests/Responses/PaperCheck/ListPaperCheckResponse.json:
--------------------------------------------------------------------------------
1 | {
2 | "count":2,
3 | "offset":0,
4 | "limit":10,
5 | "data":[
6 | {
7 | "token":"trm-001",
8 | "type":"PAPER_CHECK",
9 | "status":"ACTIVATED",
10 | "createdOn":"2017-10-31T16:47:15",
11 | "transferMethodCountry":"US",
12 | "transferMethodCurrency":"USD",
13 | "profileType":"INDIVIDUAL",
14 | "firstName":"Some",
15 | "lastName":"Guy",
16 | "middleName": "Good",
17 | "dateOfBirth": "1991-01-01",
18 | "addressLine1": "575 Market Street",
19 | "addressLine2": "57 Market Street",
20 | "city":"San Francisco",
21 | "stateProvince":"CA",
22 | "country":"US",
23 | "postalCode":"94105",
24 | "phoneNumber": "604-345-1777",
25 | "mobileNumber": "604-345-1888",
26 | "countryOfBirth": "US",
27 | "driversLicenseId": "1234",
28 | "employerId": "1234",
29 | "governmentId": "12898",
30 | "governmentIdType": "PASSPORT",
31 | "gender": "MALE",
32 | "passportId": "112323",
33 | "shippingMethod": "STANDARD",
34 | "bankAccountRelationship": "SELF",
35 | "links":[
36 | {
37 | "params":{
38 | "rel":"self"
39 | },
40 | "href":"https://localhost/rest/v3/users/usr-0000/paper-checks/trm-001"
41 | }
42 | ]
43 | },
44 | {
45 | "token":"trm-002",
46 | "type":"PAPER_CHECK",
47 | "status":"ACTIVATED",
48 | "createdOn":"2017-10-31T16:47:15",
49 | "transferMethodCountry":"US",
50 | "transferMethodCurrency":"USD",
51 | "profileType":"INDIVIDUAL",
52 | "firstName":"Some",
53 | "lastName":"Guy",
54 | "middleName": "Good",
55 | "dateOfBirth": "1991-01-01",
56 | "addressLine1": "575 Market Street",
57 | "addressLine2": "57 Market Street",
58 | "city":"San Francisco",
59 | "stateProvince":"CA",
60 | "country":"US",
61 | "postalCode":"94105",
62 | "phoneNumber": "604-345-1777",
63 | "mobileNumber": "604-345-1888",
64 | "countryOfBirth": "US",
65 | "driversLicenseId": "1234",
66 | "employerId": "1234",
67 | "governmentId": "12898",
68 | "governmentIdType": "PASSPORT",
69 | "gender": "MALE",
70 | "passportId": "112323",
71 | "shippingMethod": "STANDARD",
72 | "bankAccountRelationship": "SELF",
73 | "links":[
74 | {
75 | "params":{
76 | "rel":"self"
77 | },
78 | "href":"https://localhost/rest/v3/users/usr-0000/paper-checks/trm-002"
79 | }
80 | ]
81 | }
82 | ],
83 | "links":[
84 | {
85 | "params":{
86 | "rel":"self"
87 | },
88 | "href":"https://localhost/rest/v3/users/usr-0000/paper-checks?offset=0&limit=10"
89 | },
90 | {
91 | "params":{
92 | "rel":"next"
93 | },
94 | "href":"https://localhost/rest/v3/users/usr-0000/paper-checks?offset=10&limit=10"
95 | },
96 | {
97 | "params":{
98 | "rel":"last"
99 | },
100 | "href":"https://localhost/rest/v3/users/usr-0000/paper-checks?offset=194&limit=10"
101 | }
102 | ]
103 | }
104 |
--------------------------------------------------------------------------------
/Sources/AnyCodable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | struct AnyCodable: Codable {
22 | var value: Any
23 |
24 | init(value: Any) {
25 | self.value = value
26 | }
27 |
28 | private struct CodingKeys: CodingKey {
29 | var stringValue: String
30 | var intValue: Int?
31 | init?(intValue: Int) {
32 | self.stringValue = "\(intValue)"
33 | self.intValue = intValue
34 | }
35 | init?(stringValue: String) { self.stringValue = stringValue }
36 | }
37 |
38 | func encode(to encoder: Encoder) throws {
39 | var container = encoder.singleValueContainer()
40 | if let intVal = value as? Int {
41 | try container.encode(intVal)
42 | } else if let doubleVal = value as? Double {
43 | try container.encode(doubleVal)
44 | } else if let boolVal = value as? Bool {
45 | try container.encode(boolVal)
46 | } else if let stringVal = value as? String {
47 | try container.encode(stringVal)
48 | } else {
49 | throw ErrorTypeHelper.parseError(fieldName: container.codingPath.first?.stringValue)
50 | }
51 | }
52 |
53 | init(from decoder: Decoder) throws {
54 | if let container = try? decoder.container(keyedBy: CodingKeys.self) {
55 | var result = [String: Any]()
56 | try container.allKeys.forEach { (key) throws in
57 | result[key.stringValue] = try container.decode(AnyCodable.self, forKey: key).value
58 | }
59 | value = result
60 | } else if var container = try? decoder.unkeyedContainer() {
61 | var result = [Any]()
62 | while !container.isAtEnd {
63 | result.append(try container.decode(AnyCodable.self).value)
64 | }
65 | value = result
66 | } else if let container = try? decoder.singleValueContainer() {
67 | if let intVal = try? container.decode(Int.self) {
68 | value = intVal
69 | } else if let doubleVal = try? container.decode(Double.self) {
70 | value = doubleVal
71 | } else if let boolVal = try? container.decode(Bool.self) {
72 | value = boolVal
73 | } else if let stringVal = try? container.decode(String.self) {
74 | value = stringVal
75 | } else if container.decodeNil() {
76 | value = ""
77 | } else {
78 | throw ErrorTypeHelper.parseError(message: "the container contains nothing serializable")
79 | }
80 | } else {
81 | throw ErrorTypeHelper.parseError(message: "Could not serialize",
82 | fieldName: decoder.codingPath.first?.stringValue)
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Tests/Helper/AuthenticationTokenGeneratorMock.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | /// Generates a mock Authentication Token
4 | struct AuthenticationTokenGeneratorMock {
5 | private var userToken: String
6 | private var restUrl: String
7 | private var graphQlUrl: String
8 | private var minuteExpireIn: Int
9 | private let insightsUrl: String?
10 | private let environment: String?
11 |
12 | init(hostName: String = "localhost",
13 | minuteExpireIn: Int = 10,
14 | userToken: String = "YourUserToken") {
15 | self.restUrl = "https://\(hostName)/rest/v3/"
16 | self.graphQlUrl = "https://\(hostName)/graphql"
17 | self.minuteExpireIn = minuteExpireIn
18 | self.userToken = userToken
19 | self.insightsUrl = "http://insights.url"
20 | self.environment = "DEV"
21 | }
22 |
23 | init(
24 | restUrl: String = "https://localhost/rest/v3/",
25 | graphQlUrl: String = "https://localhost/graphql") {
26 | self.restUrl = restUrl
27 | self.graphQlUrl = graphQlUrl
28 | self.minuteExpireIn = 10
29 | self.userToken = "YourUserToken"
30 | self.insightsUrl = "http://insights.url"
31 | self.environment = "DEV"
32 | }
33 |
34 | /// Returns the Authentication Token
35 | var token: String {
36 | let headerBase64 = Data(header.utf8).base64EncodedString()
37 | let payloadBase64 = Data(payload.utf8).base64EncodedString()
38 | let signatureBase64 = Data("fake Signature".utf8).base64EncodedString()
39 |
40 | return "\(headerBase64).\(payloadBase64).\(signatureBase64)"
41 | }
42 |
43 | private var payload: String {
44 | let currentDate = Date()
45 | let expireIn = buildFutureDate(baseDate: currentDate, minute: minuteExpireIn)
46 | return """
47 | {
48 | "sub": "\(userToken)",
49 | "iat": \(Int(currentDate.timeIntervalSince1970)),
50 | "exp": \(expireIn),
51 | "aud": "abc-00000-00000",
52 | "iss": "cbd-00000-00000",
53 | "rest-uri": "\(restUrl)",
54 | "graphql-uri": "\(graphQlUrl)",
55 | "insights-uri": "\(insightsUrl!)",
56 | "environment": "\(environment!)",
57 | }
58 | """
59 | }
60 |
61 | /// Returns the Authentication Token
62 | var tokenWithoutInsightsProperties: String {
63 | let headerBase64 = Data(header.utf8).base64EncodedString()
64 | let payloadBase64 = Data(payloadWithoutInsightsProperties.utf8).base64EncodedString()
65 | let signatureBase64 = Data("fake Signature".utf8).base64EncodedString()
66 |
67 | return "\(headerBase64).\(payloadBase64).\(signatureBase64)"
68 | }
69 |
70 | private var payloadWithoutInsightsProperties: String {
71 | let currentDate = Date()
72 | let expireIn = buildFutureDate(baseDate: currentDate, minute: minuteExpireIn)
73 | return """
74 | {
75 | "sub": "\(userToken)",
76 | "iat": \(Int(currentDate.timeIntervalSince1970)),
77 | "exp": \(expireIn),
78 | "aud": "abc-00000-00000",
79 | "iss": "cbd-00000-00000",
80 | "rest-uri": "\(restUrl)",
81 | "graphql-uri": "\(graphQlUrl)",
82 | }
83 | """
84 | }
85 |
86 | /// Returns the Authentication header
87 | private var header: String {
88 | """
89 | {
90 | "alg": "ALGORITHM"
91 | }
92 | """
93 | }
94 |
95 | /// Generates the future date based at the attributes `baseDate` and `minute`
96 | private func buildFutureDate(baseDate: Date = Date(), minute: Int = 10) -> Int {
97 | var dateComponent = DateComponents()
98 | dateComponent.minute = minute
99 |
100 | guard let expiredDate = Calendar.current.date(byAdding: dateComponent, to: baseDate) else {
101 | return 0
102 | }
103 | return Int(expiredDate.timeIntervalSince1970)
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/Tests/AuthenticationTokenDecoderTests.swift:
--------------------------------------------------------------------------------
1 | @testable import HyperwalletSDK
2 | import XCTest
3 |
4 | class AuthenticationTokenDecoderTests: XCTestCase {
5 | func testDecode_nilAuthenticationToken_throwsParseError() {
6 | let authenticationToken: String? = nil
7 | performDecodeThrowsParseError(authenticationToken)
8 | }
9 |
10 | func testDecode_emptyAuthenticationToken_throwsParseError() {
11 | performDecodeThrowsParseError("")
12 | }
13 |
14 | func testDecode_authenticationTokenWithTwoParts_throwsParseError() {
15 | let authenticationToken = "123.hJQWHABDBjoPHorYF5xghQ"
16 |
17 | performDecodeThrowsParseError(authenticationToken)
18 | }
19 |
20 | func testDecode_badAuthenticationToken_throwsParseError() {
21 | let authenticationToken = "123.hJQWHABDBjoPHorYF5xghQ.00123"
22 |
23 | performDecodeThrowsParseError(authenticationToken)
24 | }
25 |
26 | func testDecode_validConfiguration() {
27 | do {
28 | let configuration = try AuthenticationTokenDecoder.decode(from: HyperwalletTestHelper.authenticationToken)
29 | XCTAssertNotNil(configuration.clientToken, "The clientToken has not been initialized")
30 | XCTAssertGreaterThan(configuration.createOn, 0, "The createOn has not been initialized")
31 | XCTAssertGreaterThan(configuration.expiresOn, 0, "The expiresOn has not been initialized")
32 | XCTAssertFalse(configuration.graphQlUrl.isEmpty, "The graphQlUrl has not been initialized")
33 | XCTAssertFalse(configuration.restUrl.isEmpty, "The restUrl has not been initialized")
34 | XCTAssertFalse(configuration.issuer.isEmpty, "The issuer has not been initialized")
35 | XCTAssertNotNil(configuration.authorization, "The authorization has not been initialized")
36 | XCTAssertNotNil(configuration.authorization, "The authorization has not been initialized")
37 | XCTAssertNotNil(configuration.insightsUrl, "The insightsUrl has not been initialized")
38 | XCTAssertNotNil(configuration.environment, "The environment has not been initialized")
39 | } catch {
40 | XCTFail("should be unexpected error")
41 | }
42 | }
43 |
44 | func testDecode_validConfiguration_withoutInsightsProperties() {
45 | do {
46 | let authenticationToken =
47 | AuthenticationTokenGeneratorMock(hostName: "localhost").tokenWithoutInsightsProperties
48 | let configuration = try AuthenticationTokenDecoder.decode(from: authenticationToken)
49 | XCTAssertNotNil(configuration.clientToken, "The clientToken has not been initialized")
50 | XCTAssertGreaterThan(configuration.createOn, 0, "The createOn has not been initialized")
51 | XCTAssertGreaterThan(configuration.expiresOn, 0, "The expiresOn has not been initialized")
52 | XCTAssertFalse(configuration.graphQlUrl.isEmpty, "The graphQlUrl has not been initialized")
53 | XCTAssertFalse(configuration.restUrl.isEmpty, "The restUrl has not been initialized")
54 | XCTAssertFalse(configuration.issuer.isEmpty, "The issuer has not been initialized")
55 | XCTAssertNotNil(configuration.authorization, "The authorization has not been initialized")
56 | XCTAssertNotNil(configuration.authorization, "The authorization has not been initialized")
57 | XCTAssertNil(configuration.insightsUrl, "The insightsUrl should be empty")
58 | XCTAssertNil(configuration.environment, "The environment should be empty")
59 | } catch {
60 | XCTFail("should be unexpected error")
61 | }
62 | }
63 |
64 | private func performDecodeThrowsParseError(_ authenticationToken: String?) {
65 | XCTAssertThrowsError(try AuthenticationTokenDecoder.decode(from: authenticationToken)) { error in
66 | XCTAssertNotNil(error as? HyperwalletErrorType)
67 | let errorType = error as? HyperwalletErrorType
68 | XCTAssertEqual(errorType?.getHyperwalletErrors()?.errorList?.first?.code, "PARSE_ERROR")
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Sources/Model/GraphQL/HyperwalletTransferMethodConfigurationKey.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// The `HyperwalletTransferMethodConfigurationKey` protocol for processing the transfer method configuration
22 | /// key result from the Hyperwallet platform.
23 | public protocol HyperwalletTransferMethodConfigurationKey {
24 | /// Returns the list of countries
25 | ///
26 | /// - Returns: a list of HyperwalletCountry object
27 | func countries() -> [HyperwalletCountry]?
28 |
29 | /// Returns the list of currencies based on the country
30 | ///
31 | /// - Parameter countryCode: the 2 letter ISO 3166-1 country code
32 | /// - Returns: a list of HyperwalletCurrency object
33 | func currencies(from countryCode: String) -> [HyperwalletCurrency]?
34 |
35 | /// Returns the list of transfer method types based on the parameters
36 | ///
37 | /// - Parameters:
38 | /// - countryCode: the 2 letter ISO 3166-1 country code
39 | /// - currencyCode: the 3 letter ISO 4217-1 currency code
40 | /// - Returns: a list of HyperwalletTransferMethodTypes
41 | func transferMethodTypes(countryCode: String, currencyCode: String) -> [HyperwalletTransferMethodType]?
42 | }
43 |
44 | /// The 'TransferMethodConfigurationKeyResult' class processes the GraphQL transfer method configuration result
45 | final class TransferMethodConfigurationKeyResult: HyperwalletTransferMethodConfigurationKey {
46 | private let hyperwalletCountries: [HyperwalletCountry]?
47 |
48 | /// Creates a new instance of the 'HyperwalletTransferMethodConfigurationKey' based on the
49 | /// transfer method configuration result
50 | ///
51 | /// - Parameter hyperwalletCountries: the GraphQL `Connection`
52 | init(_ hyperwalletCountries: [HyperwalletCountry]?) {
53 | self.hyperwalletCountries = hyperwalletCountries
54 | }
55 |
56 | /// Returns the list of countries
57 | ///
58 | /// - Returns: a list of countries
59 | func countries() -> [HyperwalletCountry]? {
60 | hyperwalletCountries
61 | }
62 |
63 | /// Returns the list of currencies based on the country
64 | ///
65 | /// - Parameter countryCode: the 2 letter ISO 3166-1 country code
66 | /// - Returns: a list of currencies
67 | func currencies(from countryCode: String) -> [HyperwalletCurrency]? {
68 | hyperwalletCountries?.first(where: { $0.code == countryCode })?.currencies?.nodes
69 | }
70 |
71 | /// Returns the list of transfer method types based on the parameters
72 | ///
73 | /// - Parameters:
74 | /// - countryCode: the 2 letter ISO 3166-1 country code
75 | /// - currencyCode: the 3 letter ISO 4217-1 currency code
76 | /// - Returns: a list of transfer method types
77 | func transferMethodTypes(countryCode: String, currencyCode: String) -> [HyperwalletTransferMethodType]? {
78 | currencies(from: countryCode)?.first(where: { $0.code == currencyCode })?.transferMethodTypes?.nodes
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletTransferMethodQueryParam.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the common transfer method's query parameters.
22 | public class HyperwalletTransferMethodQueryParam: QueryParam {
23 | enum QueryParam: String {
24 | case status
25 | case type
26 | }
27 |
28 | /// Returns transfer method with this status.
29 | public var status: String?
30 | /// Returns transfer method of that type
31 | public var type: String?
32 |
33 | /// Representation of the transfer method status
34 | public enum QueryStatus: String {
35 | /// Filter by activated transfer methods
36 | case activated = "ACTIVATED"
37 | /// Filter by deActivated transfer methods
38 | case deActivated = "DE_ACTIVATED"
39 | /// Filter only invalid transfer methods
40 | case invalid = "INVALID"
41 | /// Filter only lost or stolen prepaid cards
42 | case lostOrStolen = "LOST_OR_STOLEN"
43 | /// Filter by preActivated prepaid cards
44 | case preActivated = "PRE_ACTIVATED"
45 | /// Filter only suspended prepaid cards
46 | case suspended = "SUSPENDED"
47 | /// Filter only verified transfer methods
48 | case verified = "VERIFIED"
49 | }
50 |
51 | /// Representation of the field's sortable
52 | public enum QuerySortable: String {
53 | /// Sort the result by ascendant created on
54 | case ascendantCreatedOn = "+createdOn"
55 | /// Sort the result by ascendant status
56 | case ascendantStatus = "+status"
57 | /// Sort the result by descendant created on
58 | case descendantCreatedOn = "-createdOn"
59 | /// Sort the result by descendant status
60 | case descendantStatus = "-status"
61 | }
62 |
63 | /// Representation of the transfer method's type
64 | public enum QueryType: String {
65 | /// When the transfer method is Bank Account
66 | case bankAccount = "BANK_ACCOUNT"
67 | /// When the transfer method is Bank Card
68 | case bankCard = "BANK_CARD"
69 | /// When the transfer method is PayPal Account
70 | case payPalAccount = "PAYPAL_ACCOUNT"
71 | /// When the transfer method is Wire Account
72 | case wireAccount = "WIRE_ACCOUNT"
73 | /// When the transfer method is Prepaid Card
74 | case prepaidCard = "PREPAID_CARD"
75 | /// When the transfer method is Venmo Account
76 | case venmoAccount = "VENMO_ACCOUNT"
77 | /// When the transfer method is Paper Check
78 | case paperCheck = "PAPER_CHECK"
79 | }
80 |
81 | override public func toQuery() -> [String: String] {
82 | var query = super.toQuery()
83 |
84 | if let status = status {
85 | query[QueryParam.status.rawValue] = status
86 | }
87 | if let type = type {
88 | query[QueryParam.type.rawValue] = type
89 | }
90 | return query
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Tests/GraphQL/TransferMethodConfigurationKeyResultTests.swift:
--------------------------------------------------------------------------------
1 | @testable import HyperwalletSDK
2 | import XCTest
3 |
4 | // swiftlint:disable force_try
5 | class TransferMethodConfigurationKeyResultTests: XCTestCase {
6 | var transferMethodConfigurationKey: TransferMethodConfigurationKey!
7 | var keyResult: TransferMethodConfigurationKeyResult!
8 |
9 | override func setUp() {
10 | transferMethodConfigurationKey = hyperwalletGraphQlKey(data:
11 | HyperwalletTestHelper.getDataFromJson("TransferMethodConfigurationKeysResponse"))!
12 | keyResult = TransferMethodConfigurationKeyResult(transferMethodConfigurationKey.countries?.nodes)
13 | }
14 |
15 | func testCountries_success() {
16 | let countries = keyResult.countries()
17 | XCTAssertEqual(countries?.count, 4)
18 | }
19 |
20 | func testTransferMethods_countryUSCurrencyUSDIndividual_success() {
21 | let transferMethodTypes = keyResult.transferMethodTypes(countryCode: "US", currencyCode: "USD")
22 | XCTAssertEqual(transferMethodTypes?.count, 3)
23 | XCTAssertNotNil(transferMethodTypes?.first { $0.code == "BANK_ACCOUNT" })
24 | XCTAssertNotNil(transferMethodTypes?.first { $0.code == "PAYPAL_ACCOUNT" })
25 | }
26 |
27 | func testTransferMethodKeyResults_countryUS_currencyUSD_Individual_success() {
28 | let transferMethodTypes = keyResult.transferMethodTypes(countryCode: "US", currencyCode: "USD")
29 |
30 | XCTAssertEqual(transferMethodTypes?.count, 3)
31 |
32 | let transferMethodFilterByBankAccount = transferMethodTypes?.filter { $0.code == "BANK_ACCOUNT" }
33 |
34 | if let bankAccount = transferMethodFilterByBankAccount?.first?.code {
35 | XCTAssertEqual(bankAccount, "BANK_ACCOUNT", "Invalid transferMethod")
36 | } else {
37 | XCTFail("The BANK_ACCOUNT has not been found")
38 | }
39 |
40 | let transferMethodFilterByPayPalAccount = transferMethodTypes?.filter { $0.code == "PAYPAL_ACCOUNT" }
41 | if let payPalAccount = transferMethodFilterByPayPalAccount?.first?.code {
42 | XCTAssertEqual(payPalAccount, "PAYPAL_ACCOUNT", "Invalid transferMethod")
43 | } else {
44 | XCTFail("The PAYPAL_ACCOUNT has not been found")
45 | }
46 | }
47 |
48 | func testTransferMethods_countryCACurrencyCADIndividual_success() {
49 | let transferMethodTypes = keyResult.transferMethodTypes(countryCode: "CA", currencyCode: "CAD")
50 | XCTAssertEqual(transferMethodTypes?.count, 2)
51 | XCTAssertNotNil(transferMethodTypes?.first { $0.code == "BANK_ACCOUNT" })
52 | XCTAssertNotNil(transferMethodTypes?.last { $0.code == "PAYPAL_ACCOUNT" })
53 | }
54 |
55 | func testCurrencies_success() {
56 | assertCurrencies(keyResult, from: "US", amount: 2)
57 | }
58 |
59 | func testCurrencies_invalidCountry() {
60 | assertCurrencies(keyResult, from: "ZZ", amount: nil)
61 | }
62 |
63 | func testFees_success() {
64 | let keyFees = keyResult.transferMethodTypes(countryCode: "CA", currencyCode: "CAD")?.first?.fees?.nodes
65 |
66 | XCTAssertNotNil(keyFees)
67 | XCTAssertEqual(keyFees?.last?.feeRateType, "PERCENT", "Type should be PERCENT")
68 | }
69 |
70 | func testFees_empty() {
71 | let keyFees = keyResult.transferMethodTypes(countryCode: "HR", currencyCode: "HRK")?.first?.fees?.nodes
72 | XCTAssertNil(keyFees)
73 | }
74 |
75 | private func assertCurrencies(_ result: TransferMethodConfigurationKeyResult,
76 | from country: String,
77 | amount: Int?) {
78 | let currencies = result.currencies(from: country)
79 | XCTAssertEqual(currencies?.count, amount, "The amount of elements is different")
80 | }
81 |
82 | private func hyperwalletGraphQlKey(data: Data) -> TransferMethodConfigurationKey? {
83 | let decoder = JSONDecoder()
84 |
85 | let graphQlResult = try! decoder.decode(GraphQlResult.self, from: data)
86 | return graphQlResult.data
87 | }
88 | }
89 | // swiftlint:enable force_try
90 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Changelog
2 | =========
3 | [1.0.1](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.1)
4 | -------------------
5 | - Fetch Default currency on list of Transfer Method country.
6 |
7 | [1.0.0-beta20](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta20)
8 | -------------------
9 | - Add privacy manifest on CocoaPods Spec
10 | - Update Privacy manifest by declaring systemUptime
11 | [1.0.0-beta19](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta19)
12 | -------------------
13 | - Updated ci to xcode version 15
14 | - Add privacy manifest
15 |
16 | [1.0.0-beta18](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta18)
17 | -------------------
18 | - Address swiftlint issues
19 |
20 | [1.0.0-beta17](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta17)
21 | -------------------
22 | - Handle HTTP 401
23 |
24 | [1.0.0-beta16](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta16)
25 | -------------------
26 | - iOS upgrade to version 13
27 |
28 | [1.0.0-beta15](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta15)
29 | -------------------
30 | - Connection timeout increased
31 |
32 | [1.0.0-beta14](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta14)
33 | -------------------
34 | - Performance update for Add Transfer Method GraphQL
35 |
36 | [1.0.0-beta13](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta13)
37 | -------------------
38 | - Fixed Xcode 12 issue
39 |
40 | [1.0.0-beta12](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta12)
41 | -------------------
42 | - Added support for iOS 14
43 |
44 | [1.0.0-beta11](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta11)
45 | -------------------
46 | - Support Paper Check as a transfer method
47 | - Support update transfer method
48 | - Enhancements
49 |
50 | [1.0.0-beta10](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta10)
51 | -------------------
52 | - Added Venmo as a Transfer method
53 | - Added support for List Prepaid Card Balances
54 | - Enhancements
55 |
56 | [1.0.0-beta09](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta09)
57 | -------------------
58 | - Increased API response timeout
59 |
60 | [1.0.0-beta08](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta08)
61 | -------------------
62 | - Fixed Cocoapod issue
63 |
64 | [1.0.0-beta07](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta07)
65 | -------------------
66 | - Enhancements
67 |
68 | [1.0.0-beta06](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta06)
69 | -------------------
70 | - Added support to List User Balances
71 | - Enhancements
72 |
73 | [1.0.0-beta05](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta05)
74 | -------------------
75 | - Enhancements
76 |
77 | [1.0.0-beta04](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta04)
78 | -------------------
79 | - Added support to the following
80 | * Create Transfer
81 | * Schedule Transfer
82 | * Get Transfer
83 |
84 | [1.0.0-beta03](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta03)
85 | -------------------
86 | - Enhancements to Add Transfer Method
87 | - Added support to the following:
88 | * List Prepaid Cards
89 | * List Prepaid Card Receipts
90 | * List User Receipts
91 |
92 | [1.0.0-beta02](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta02)
93 | -------------------
94 | - Added PayPal as a Transfer method
95 | - Added support to get User object
96 |
97 | [1.0.0-beta01](https://github.com/hyperwallet/hyperwallet-ios-sdk/releases/tag/1.0.0-beta01)
98 | -------------------
99 | - Initial beta release of Hyperwallet Core SDK for iOS. This beta release has the following functionality:
100 | * Create Bank Account and Bank Card for United States (USD)
101 | * Retrieve field requirements for bank Accounts and Bank Cards
102 | * List Accounts
103 | * Deactivate (Remove) Accounts
104 |
--------------------------------------------------------------------------------
/Sources/Model/GraphQL/Query/HyperwalletTransferMethodUpdateConfigurationQueries.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// The `HyperwalletTransferMethodUpdateConfigurationFieldQuery`
22 | /// struct defines and builds a query to retrieve the fields
23 | /// required to update a transfer method (Bank Account, Bank Card, PayPal Account, Prepaid Card, Paper Check and Venmo)
24 | /// with the Hyperwallet platform.
25 | public struct HyperwalletTransferMethodUpdateConfigurationFieldQuery: GraphQlQuery, Hashable {
26 | private var transferMethodToken: String
27 | private var query = """
28 | query QueryUpdateTransferMethod(
29 | $trmToken: String = "%@"
30 | ){
31 | transferMethodUpdateUIConfigurations (
32 | trmToken: $trmToken
33 | ) {
34 | nodes {
35 | country
36 | currency
37 | transferMethodType
38 | profile
39 | fieldGroups {
40 | nodes {
41 | group
42 | isEditable
43 | fields {
44 | category
45 | value
46 | dataType
47 | isRequired
48 | isEditable
49 | label
50 | maxLength
51 | minLength
52 | name
53 | placeholder
54 | regularExpression
55 | fieldSelectionOptions {
56 | label
57 | value
58 | }
59 | validationMessage {
60 | length
61 | pattern
62 | empty
63 | }
64 | fieldValueMasked
65 | mask {
66 | conditionalPatterns {
67 | pattern
68 | regex
69 | }
70 | defaultPattern
71 | scrubRegex
72 | }
73 | }
74 | }
75 | }
76 | }
77 | }
78 | }
79 | """
80 |
81 | /// Create a new `HyperwalletTransferMethodUpdateConfigurationFieldQuery` from the transferMethodToken
82 | ///
83 | /// - Parameters:
84 | /// - transferMethodToken: token from the transfer method
85 | public init(transferMethodToken: String) {
86 | self.transferMethodToken = transferMethodToken
87 | }
88 |
89 | public func toGraphQl(userToken: String) -> String {
90 | String(format: query, transferMethodToken)
91 | }
92 |
93 | public func hash(into hasher: inout Hasher) {
94 | hasher.combine(transferMethodToken)
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletPayPalAccount.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 | /// Representation of the user's PayPal account
21 | @objcMembers
22 | public final class HyperwalletPayPalAccount: HyperwalletTransferMethod {
23 | override private init(data: [String: AnyCodable]) {
24 | super.init(data: data)
25 | }
26 | /// The required initializer
27 | public required init(from decoder: Decoder) throws {
28 | try super.init(from: decoder)
29 | }
30 |
31 | /// The email address.
32 | public var email: String? {
33 | getField(TransferMethodField.email.rawValue)
34 | }
35 |
36 | /// A helper class to build the `HyperwalletPayPalAccount` instance.
37 | public final class Builder {
38 | private var storage = [String: AnyCodable]()
39 |
40 | /// Creates a new instance of the `HyperwalletPayPalAccount` based on the required parameter to update
41 | /// PayPal account.
42 | ///
43 | /// - Parameter token: The PayPal account token.
44 | public init(token: String) {
45 | storage[TransferMethodField.token.rawValue] = AnyCodable(value: token)
46 | }
47 |
48 | /// Creates a new instance of the `HyperwalletPayPalAccount` based on the required parameters to create
49 | /// PayPal account.
50 | ///
51 | /// - Parameters:
52 | /// - transferMethodCountry: The PayPal account country.
53 | /// - transferMethodCurrency: The PayPal account currency.
54 | /// - transferMethodProfileType: The bank account holder's profile type, e.g. INDIVIDUAL or BUSINESS
55 | public init(transferMethodCountry: String, transferMethodCurrency: String, transferMethodProfileType: String) {
56 | storage[TransferMethodField.type.rawValue] = AnyCodable(value: TransferMethodType.payPalAccount.rawValue)
57 | storage[TransferMethodField.transferMethodCountry.rawValue] = AnyCodable(value: transferMethodCountry)
58 | storage[TransferMethodField.transferMethodCurrency.rawValue] = AnyCodable(value: transferMethodCurrency)
59 | storage[TransferMethodField.profileType.rawValue] = AnyCodable(value: transferMethodProfileType)
60 | }
61 |
62 | /// Sets the email address
63 | ///
64 | /// - Parameter email: The email address user want to create a PayPal account
65 | /// - Returns: a self `HyperwalletPayPalAccount.Builder` instance.
66 | public func email(_ email: String) -> Builder {
67 | storage[TransferMethodField.email.rawValue] = AnyCodable(value: email)
68 | return self
69 | }
70 |
71 | /// Sets the bank account holder's profile type.
72 | ///
73 | /// - Parameter profileType: The bank account holder's profile type, e.g. INDIVIDUAL or BUSINESS
74 | /// - Returns: a self `HyperwalletBankAccount.Builder` instance.
75 | public func profileType(_ profileType: String) -> Builder {
76 | storage[TransferMethodField.profileType.rawValue] = AnyCodable(value: profileType)
77 | return self
78 | }
79 |
80 | /// Builds a new instance of the `HyperwalletPayPalAccount`.
81 | ///
82 | /// - Returns: a new instance of the `HyperwalletPayPalAccount`.
83 | public func build() -> HyperwalletPayPalAccount {
84 | HyperwalletPayPalAccount(data: self.storage)
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletVenmoAccount.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2020 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the user's Venmo account
22 | @objcMembers
23 | public final class HyperwalletVenmoAccount: HyperwalletTransferMethod {
24 | override private init(data: [String: AnyCodable]) {
25 | super.init(data: data)
26 | }
27 | /// The required initializer
28 | public required init(from decoder: Decoder) throws {
29 | try super.init(from: decoder)
30 | }
31 |
32 | /// The accountId as phone number.
33 | public var accountId: String? {
34 | getField(TransferMethodField.accountId.rawValue)
35 | }
36 |
37 | /// A helper class to build the `HyperwalletVenmoAccount` instance.
38 | public final class Builder {
39 | private var storage = [String: AnyCodable]()
40 |
41 | /// Creates a new instance of the `HyperwalletVenmoAccount` based on the required parameter to update
42 | /// Venmo account.
43 | ///
44 | /// - Parameter token: The Venmo account token.
45 | public init(token: String) {
46 | storage[TransferMethodField.token.rawValue] = AnyCodable(value: token)
47 | }
48 |
49 | /// Creates a new instance of the `HyperwalletVenmoAccount` based on the required parameters to create
50 | /// Venmo account.
51 | ///
52 | /// - Parameters:
53 | /// - transferMethodCountry: The Venmo account country.
54 | /// - transferMethodCurrency: The Venmo account currency.
55 | /// - transferMethodProfileType: The Venmo account holder's profile type, e.g. INDIVIDUAL or BUSINESS
56 | public init(transferMethodCountry: String, transferMethodCurrency: String, transferMethodProfileType: String) {
57 | storage[TransferMethodField.type.rawValue] = AnyCodable(value: TransferMethodType.venmoAccount.rawValue)
58 | storage[TransferMethodField.transferMethodCountry.rawValue] = AnyCodable(value: transferMethodCountry)
59 | storage[TransferMethodField.transferMethodCurrency.rawValue] = AnyCodable(value: transferMethodCurrency)
60 | storage[TransferMethodField.profileType.rawValue] = AnyCodable(value: transferMethodProfileType)
61 | }
62 |
63 | /// Sets the accountId address
64 | ///
65 | /// - Parameter accountId: The accountId as phone number user want to create a Venmo account
66 | /// - Returns: a self `HyperwalletVenmoAccount.Builder` instance.
67 | public func accountId(_ accountId: String) -> Builder {
68 | storage[TransferMethodField.accountId.rawValue] = AnyCodable(value: accountId)
69 | return self
70 | }
71 |
72 | /// Sets the bank account holder's profile type.
73 | ///
74 | /// - Parameter profileType: The Venmo account holder's profile type, e.g. INDIVIDUAL or BUSINESS
75 | /// - Returns: a self `HyperwalletVenmoAccount.Builder` instance.
76 | public func profileType(_ profileType: String) -> Builder {
77 | storage[TransferMethodField.profileType.rawValue] = AnyCodable(value: profileType)
78 | return self
79 | }
80 |
81 | /// Builds a new instance of the `HyperwalletVenmoAccount`.
82 | ///
83 | /// - Returns: a new instance of the `HyperwalletVenmoAccount`.
84 | public func build() -> HyperwalletVenmoAccount {
85 | HyperwalletVenmoAccount(data: self.storage)
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/HyperwalletSDK.xcodeproj/xcshareddata/xcschemes/HyperwalletSDK.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
32 |
33 |
39 |
40 |
41 |
42 |
48 |
49 |
50 |
51 |
53 |
59 |
60 |
61 |
62 |
63 |
73 |
74 |
80 |
81 |
82 |
83 |
89 |
90 |
96 |
97 |
98 |
99 |
101 |
102 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/Tests/Helper/HyperwalletTestHelper.swift:
--------------------------------------------------------------------------------
1 | import Hippolyte
2 | @testable import HyperwalletSDK
3 | import XCTest
4 |
5 | class HyperwalletTestHelper {
6 | static let applicationJson = "application/json"
7 | static let authenticationToken = AuthenticationTokenGeneratorMock(hostName: "localhost").token
8 | static let authenticationProvider = AuthenticationProviderMock(authorizationData: authenticationToken)
9 | static let contentType = "Content-Type"
10 | static let graphQlURL = "https://localhost/graphql"
11 | static let insightsUrl = "https://localhost/insight"
12 | static let environment = "DEV"
13 | static let restURL = "https://localhost/rest/v3/"
14 | static let userPath = "users/YourUserToken"
15 | static let userRestURL = "\(restURL)\(userPath)"
16 |
17 | // MARK: Build Requests
18 | static func buildPostRequest(baseUrl: String, _ response: StubResponse) -> StubRequest {
19 | StubRequest.Builder()
20 | .stubRequest(withMethod: .POST, url: URL(string: baseUrl)!)
21 | .addHeader(withKey: contentType, value: applicationJson)
22 | .addResponse(response)
23 | .build()
24 | }
25 |
26 | static func buildGetRequest(baseUrl: String, _ response: StubResponse) -> StubRequest {
27 | StubRequest.Builder()
28 | .stubRequest(withMethod: .GET, url: URL(string: baseUrl)!)
29 | .addHeader(withKey: contentType, value: applicationJson)
30 | .addResponse(response)
31 | .build()
32 | }
33 |
34 | static func buildGetRequestRegexMatcher(pattern: String, _ response: StubResponse) -> StubRequest {
35 | let regex = try? NSRegularExpression(pattern: pattern, options: [])
36 | return StubRequest.Builder()
37 | .stubRequest(withMethod: .GET, urlMatcher: RegexMatcher(regex: regex!))
38 | .addHeader(withKey: contentType, value: applicationJson)
39 | .addResponse(response)
40 | .build()
41 | }
42 |
43 | static func buildPutRequest(baseUrl: String, _ response: StubResponse) -> StubRequest {
44 | StubRequest.Builder()
45 | .stubRequest(withMethod: .PUT, url: URL(string: baseUrl)!)
46 | .addHeader(withKey: contentType, value: applicationJson)
47 | .addResponse(response)
48 | .build()
49 | }
50 |
51 | // MARK: - StubResponses
52 |
53 | /// Builts the stub HTTP 200 - OK
54 | ///
55 | /// - Parameter for: The response file name will be loaded by `getDataFromJson(responseFileName)`
56 | /// - Returns: the StubResponse
57 | static func okHTTPResponse(for responseFileName: String) -> StubResponse {
58 | let data = HyperwalletTestHelper.getDataFromJson(responseFileName)
59 | return setUpMockedResponse(payload: data, httpCode: 200)
60 | }
61 |
62 | /// Builts the stub HTTP 204 - No Content
63 | ///
64 | /// - Returns: the StubResponse
65 | static func noContentHTTPResponse() -> StubResponse {
66 | setUpMockedResponse(payload: Data(), httpCode: 204)
67 | }
68 |
69 | /// Builts the stub HTTP 400 - Bad Request
70 | ///
71 | /// - Parameter for: The response file name will be loaded by `getDataFromJson(responseFileName)`
72 | /// - Returns: the StubResponse
73 | static func badRequestHTTPResponse(for responseFileName: String) -> StubResponse {
74 | let data = HyperwalletTestHelper.getDataFromJson(responseFileName)
75 | return setUpMockedResponse(payload: data, httpCode: 400)
76 | }
77 |
78 | /// Receives data from JSON file
79 | ///
80 | /// - Parameter fileName: File Name
81 | /// - Returns: Data
82 | static func getDataFromJson(_ fileName: String) -> Data {
83 | let path = Bundle(for: self).path(forResource: fileName, ofType: "json")!
84 | return NSData(contentsOfFile: path)! as Data
85 | }
86 |
87 | static func setUpMockServer(request: StubRequest) {
88 | Hippolyte.shared.add(stubbedRequest: request)
89 | Hippolyte.shared.start()
90 | }
91 |
92 | static func setUpMockedResponse(payload: Data,
93 | error: NSError? = nil,
94 | httpCode: Int = 200,
95 | contentType: String = HyperwalletTestHelper.applicationJson) -> StubResponse {
96 | responseBuilder(payload, httpCode, error)
97 | .addHeader(withKey: HyperwalletTestHelper.contentType, value: contentType)
98 | .build()
99 | }
100 |
101 | private static func responseBuilder(_ payload: Data,
102 | _ httpCode: Int,
103 | _ error: NSError? = nil) -> StubResponse.Builder {
104 | let stubResponseBuilder = StubResponse.Builder().defaultResponse()
105 | guard let error = error else {
106 | return stubResponseBuilder
107 | .stubResponse(withStatusCode: httpCode)
108 | .addBody(payload)
109 | }
110 | return stubResponseBuilder
111 | .stubResponse(withError: error)
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletBankCard.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Representation of the user's bank card
22 | @objcMembers
23 | public class HyperwalletBankCard: HyperwalletTransferMethod {
24 | override private init(data: [String: AnyCodable]) {
25 | super.init(data: data)
26 | }
27 | /// The required initializer
28 | public required init(from decoder: Decoder) throws {
29 | try super.init(from: decoder)
30 | }
31 |
32 | /// The card brand
33 | public var cardBrand: String? {
34 | getField(TransferMethodField.cardBrand.rawValue)
35 | }
36 |
37 | /// The card number
38 | public var cardNumber: String? {
39 | getField(TransferMethodField.cardNumber.rawValue)
40 | }
41 |
42 | /// The card type
43 | public var cardType: String? {
44 | getField(TransferMethodField.cardType.rawValue)
45 | }
46 |
47 | /// The expiration date.
48 | public var dateOfExpiry: String? {
49 | getField(TransferMethodField.dateOfExpiry.rawValue)
50 | }
51 |
52 | /// A helper class to build the `HyperwalletBankCard` instance.
53 | public final class Builder {
54 | private var storage = [String: AnyCodable]()
55 |
56 | /// Creates a new instance of the `HyperwalletBankCard.Builder` based on the required parameter to update
57 | /// Bank card.
58 | ///
59 | /// - Parameter token: The bank card token.
60 | public init(token: String) {
61 | storage[TransferMethodField.token.rawValue] = AnyCodable(value: token)
62 | }
63 |
64 | /// Creates a new instance of the `HyperwalletBankCard.Builder` based on the required parameters to create
65 | /// Bank card.
66 | ///
67 | /// - Parameters:
68 | /// - transferMethodCountry: The bank card country.
69 | /// - transferMethodCurrency: The bank card currency.
70 | /// - transferMethodProfileType: The method profile type
71 | public init(transferMethodCountry: String, transferMethodCurrency: String, transferMethodProfileType: String) {
72 | storage[TransferMethodField.type.rawValue] = AnyCodable(value: TransferMethodType.bankCard.rawValue)
73 | storage[TransferMethodField.transferMethodCountry.rawValue] = AnyCodable(value: transferMethodCountry)
74 | storage[TransferMethodField.transferMethodCurrency.rawValue] = AnyCodable(value: transferMethodCurrency)
75 | storage[TransferMethodField.profileType.rawValue] = AnyCodable(value: transferMethodProfileType)
76 | }
77 |
78 | /// Builds a new instance of the `HyperwalletBankCard`.
79 | ///
80 | /// - Returns: a new instance of the `HyperwalletBankCard`.
81 | public func build() -> HyperwalletBankCard {
82 | HyperwalletBankCard(data: self.storage)
83 | }
84 |
85 | /// Sets the card number
86 | ///
87 | /// - Parameter cardNumber: The 16-digit card number
88 | /// - Returns: a self reference of `HyperwalletBankCard.Builder` instance.
89 | public func cardNumber(_ cardNumber: String) -> Builder {
90 | storage[TransferMethodField.cardNumber.rawValue] = AnyCodable(value: cardNumber)
91 | return self
92 | }
93 |
94 | /// Sets the card security code which is embossed or printed on the card.
95 | ///
96 | /// - Parameter cvv: the card security code which is embossed or printed on the card
97 | /// - Returns: a self reference of `HyperwalletBankCard.Builder` instance.
98 | public func cvv(_ cvv: String) -> Builder {
99 | storage[TransferMethodField.cvv.rawValue] = AnyCodable(value: cvv)
100 | return self
101 | }
102 |
103 | /// Sets the expiration date.
104 | ///
105 | /// - Parameter dateOfExpiry: the expiration date for the card (YYYY-MM).
106 | /// - Returns: a self reference of `HyperwalletBankCard.Builder` instance.
107 | public func dateOfExpiry(_ dateOfExpiry: String) -> Builder {
108 | storage[TransferMethodField.dateOfExpiry.rawValue] = AnyCodable(value: dateOfExpiry)
109 | return self
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/Sources/Model/TransferMethod/HyperwalletPrepaidCard.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 | /// Representation of the user's Prepaid card account
21 | @objcMembers
22 | public final class HyperwalletPrepaidCard: HyperwalletTransferMethod {
23 | override private init(data: [String: AnyCodable]) {
24 | super.init(data: data)
25 | }
26 | /// The required initializer
27 | public required init(from decoder: Decoder) throws {
28 | try super.init(from: decoder)
29 | }
30 |
31 | /// The prepaid card's type
32 | public var cardType: String? {
33 | getField(TransferMethodField.cardType.rawValue)
34 | }
35 |
36 | /// The prepaid card's package
37 | public var cardPackage: String? {
38 | getField(TransferMethodField.cardPackage.rawValue)
39 | }
40 |
41 | /// The prepaid card's number
42 | public var cardNumber: String? {
43 | getField(TransferMethodField.cardNumber.rawValue)
44 | }
45 |
46 | /// The prepaid card's brand
47 | public var cardBrand: String? {
48 | getField(TransferMethodField.cardBrand.rawValue)
49 | }
50 |
51 | /// The prepaid card's expiry date
52 | public var dateOfExpiry: String? {
53 | getField(TransferMethodField.dateOfExpiry.rawValue)
54 | }
55 |
56 | /// The primary prepaid card's token
57 | public var primaryCardToken: String? {
58 | getField(TransferMethodField.primaryCardToken.rawValue)
59 | }
60 |
61 | /// The prepaid card's user token (instant issue cards only)
62 | public var userToken: String? {
63 | getField(TransferMethodField.userToken.rawValue)
64 | }
65 |
66 | /// A helper class to build the `HyperwalletPrepaidCard` instance.
67 | public final class Builder {
68 | private var storage = [String: AnyCodable]()
69 |
70 | /// Creates a new instance of the `HyperwalletPayPalAccount` based on the required parameter to update
71 | /// PayPal account.
72 | ///
73 | /// - Parameter token: The PayPal account token.
74 | public init(token: String) {
75 | storage[TransferMethodField.token.rawValue] = AnyCodable(value: token)
76 | }
77 |
78 | /// Creates a new instance of the `HyperwalletPrepaidCard` based on the required parameters to create
79 | /// prepaid card account.
80 | ///
81 | /// - Parameters:
82 | /// - transferMethodProfileType: The prepaid card account holder's profile type, e.g. INDIVIDUAL or BUSINESS
83 | public init(transferMethodProfileType: String) {
84 | storage[TransferMethodField.type.rawValue] = AnyCodable(value: TransferMethodType.prepaidCard.rawValue)
85 | storage[TransferMethodField.profileType.rawValue] = AnyCodable(value: transferMethodProfileType)
86 | }
87 |
88 | /// Sets the card package
89 | ///
90 | /// - Parameter cardPackage: The card package name or identifier. You must provide an exact cardPackage value
91 | /// that has been been configured for the program or leave it blank.
92 | /// If left blank, the default card package will be automatically selected.
93 | /// - Returns: a self `HyperwalletPrepaidCard.Builder` instance.
94 | public func cardPackage(_ cardPackage: String) -> Builder {
95 | storage[TransferMethodField.cardPackage.rawValue] = AnyCodable(value: cardPackage)
96 | return self
97 | }
98 |
99 | /// Sets userToken for an instant issue card
100 | ///
101 | /// - Parameter userToken: The unique, auto-generated user identifier. Max 64 characters, prefixed with "usr-".
102 | /// - Returns: a self `HyperwalletPrepaidCard.Builder` instance.
103 | public func userToken(_ userToken: String) -> Builder {
104 | storage[TransferMethodField.userToken.rawValue] = AnyCodable(value: userToken)
105 | return self
106 | }
107 |
108 | /// Builds a new instance of the `HyperwalletPrepaidCard`.
109 | ///
110 | /// - Returns: a new instance of the `HyperwalletPrepaidCard`.
111 | public func build() -> HyperwalletPrepaidCard {
112 | HyperwalletPrepaidCard(data: self.storage)
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/Sources/TransactionType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright 2018 - Present Hyperwallet
3 | //
4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | // and associated documentation files (the "Software"), to deal in the Software without restriction,
6 | // including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | // furnished to do so, subject to the following conditions:
9 | //
10 | // The above copyright notice and this permission notice shall be included in all copies or
11 | // substantial portions of the Software.
12 | //
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | import Foundation
20 |
21 | /// Transaction type definitions.
22 | ///
23 | /// - rest: Represents a REST transaction.
24 | /// - graphQl: Represents a GraphQL transaction.
25 | internal enum TransactionType {
26 | case rest
27 | case graphQl
28 |
29 | /// Creates URLRequest depending on transaction type
30 | ///
31 | /// - Parameters:
32 | /// - configuration: Configuration
33 | /// - method: HTTPMethod
34 | /// - path: urlPath
35 | /// - query: urlQuery
36 | /// - httpBody:
37 | /// - Returns: URLRequest
38 | func createRequest(_ configuration: Configuration,
39 | method: HTTPMethod,
40 | urlPath path: String,
41 | urlQuery query: [String: String]? = nil,
42 | httpBody: Body?) throws -> URLRequest where Body: Encodable {
43 | switch self {
44 | case .graphQl:
45 | return try createGraphQlRequest(configuration,
46 | method: method,
47 | urlPath: path,
48 | httpBody: httpBody)
49 |
50 | case .rest:
51 | return try createRestRequest(configuration,
52 | method: method,
53 | urlPath: path,
54 | urlQuery: query,
55 | httpBody: httpBody)
56 | }
57 | }
58 |
59 | private func createRestRequest(_ configuration: Configuration,
60 | method: HTTPMethod,
61 | urlPath path: String,
62 | urlQuery query: [String: String]? = nil,
63 | httpBody: Body?) throws -> URLRequest where Body: Encodable {
64 | let formattedPath = String(format: path, configuration.userToken)
65 | let baseURL = URL(string: configuration.restUrl + formattedPath)
66 | // let baseURL = url(configuration, path)
67 | guard let url = addQueryIfRequired(baseURL, query) else {
68 | throw ErrorTypeHelper.invalidUrl()
69 | }
70 | var request = URLRequest(url: url)
71 | request.addValue("Bearer " + configuration.authorization, forHTTPHeaderField: "Authorization")
72 | request.httpMethod = method.rawValue
73 | if httpBody != nil, method == .post || method == .put {
74 | let encoder = JSONEncoder()
75 | let data = try? encoder.encode(httpBody)
76 | request.httpBody = data
77 | }
78 | return request
79 | }
80 |
81 | private func createGraphQlRequest(_ configuration: Configuration,
82 | method: HTTPMethod,
83 | urlPath path: String,
84 | httpBody: Body?) throws -> URLRequest where Body: Encodable {
85 | guard let baseURL = URL(string: configuration.graphQlUrl) else {
86 | throw ErrorTypeHelper.invalidUrl()
87 | }
88 | var request = URLRequest(url: baseURL)
89 | request.addValue("Bearer " + configuration.authorization, forHTTPHeaderField: "Authorization")
90 | request.httpMethod = method.rawValue
91 | if let httpBody = httpBody, let graphQl = httpBody as? GraphQlQuery {
92 | let graphQlQuery = graphQl.toGraphQl(userToken: configuration.userToken)
93 | request.httpBody = graphQlQuery.data(using: .utf8)
94 | }
95 |
96 | return request
97 | }
98 |
99 | private func addQueryIfRequired(_ baseUrl: URL?, _ query: [String: String]?) -> URL? {
100 | guard let baseUrl = baseUrl else {
101 | return nil
102 | }
103 |
104 | if let urlQuery = query {
105 | var urlComponent = URLComponents(url: baseUrl, resolvingAgainstBaseURL: false)
106 | urlComponent?.queryItems = urlQuery.map { URLQueryItem(name: $0, value: $1) }
107 | return urlComponent?.url
108 | }
109 | return baseUrl
110 | }
111 | }
112 |
--------------------------------------------------------------------------------