mirror of
https://github.com/selfxyz/self.git
synced 2026-01-06 21:34:13 -05:00
small collection bugfixes for two point nine (#1446)
* fix addhaar typo * consolidate mobile app links and add tests * fix caching issues for pipelines * fix gitleaks * update binary merkle root.circom package source * fix cache * update path * rename lockfile * fix qrcode error * fix mobile ci tests and prettier * fix qr code typing * fix qrcode pipelines * fix integration test
This commit is contained in:
12
.github/actions/cache-bundler/action.yml
vendored
12
.github/actions/cache-bundler/action.yml
vendored
@@ -24,12 +24,22 @@ outputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- id: get-hash
|
||||
name: Hash lock file
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f "${{ inputs.lock-file }}" ]; then
|
||||
echo "hash=$(shasum -a 256 "${{ inputs.lock-file }}" | awk '{ print $1 }')" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "::warning::Lock file '${{ inputs.lock-file }}' not found."
|
||||
echo "hash=no-lock-file" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- id: cache
|
||||
name: Cache Ruby gems
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ inputs.path }}
|
||||
key: ${{ runner.os }}-gems-${{ inputs.cache-version }}-${{ hashFiles(inputs.lock-file) }}
|
||||
key: ${{ runner.os }}-gems-${{ inputs.cache-version }}-${{ steps.get-hash.outputs.hash }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gems-${{ inputs.cache-version }}-
|
||||
${{ runner.os }}-gems-
|
||||
|
||||
2
.github/actions/cache-gradle/action.yml
vendored
2
.github/actions/cache-gradle/action.yml
vendored
@@ -29,7 +29,7 @@ runs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ inputs.path }}
|
||||
key: ${{ runner.os }}-gradle-${{ inputs.cache-version }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
key: ${{ runner.os }}-gradle-${{ inputs.cache-version }}-${{ hashFiles('**/build.gradle', '**/settings.gradle', '**/gradle-wrapper.properties', '**/gradle.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-${{ inputs.cache-version }}-
|
||||
${{ runner.os }}-gradle-
|
||||
|
||||
4
.github/actions/cache-pods/action.yml
vendored
4
.github/actions/cache-pods/action.yml
vendored
@@ -9,7 +9,7 @@ inputs:
|
||||
default: |
|
||||
ios/Pods
|
||||
~/Library/Caches/CocoaPods
|
||||
lock-file:
|
||||
lockfile:
|
||||
description: Path to Podfile.lock
|
||||
required: false
|
||||
default: ios/Podfile.lock
|
||||
@@ -31,7 +31,7 @@ runs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ inputs.path }}
|
||||
key: ${{ runner.os }}-pods-${{ inputs.cache-version }}-${{ hashFiles(inputs.lock-file) }}
|
||||
key: ${{ runner.os }}-pods-${{ inputs.cache-version }}-${{ hashFiles(inputs.lockfile) }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pods-${{ inputs.cache-version }}-
|
||||
${{ runner.os }}-pods-
|
||||
|
||||
12
.github/actions/cache-yarn/action.yml
vendored
12
.github/actions/cache-yarn/action.yml
vendored
@@ -25,12 +25,22 @@ outputs:
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- id: get-hash
|
||||
name: Hash lock file
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f "${{ inputs.lock-file }}" ]; then
|
||||
echo "hash=$(shasum -a 256 "${{ inputs.lock-file }}" | awk '{ print $1 }')" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "::warning::Lock file '${{ inputs.lock-file }}' not found."
|
||||
echo "hash=no-lock-file" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- id: cache
|
||||
name: Cache Yarn dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ inputs.path }}
|
||||
key: ${{ runner.os }}-yarn-${{ inputs.cache-version }}-${{ hashFiles(inputs.lock-file) }}
|
||||
key: ${{ runner.os }}-yarn-${{ inputs.cache-version }}-${{ steps.get-hash.outputs.hash }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-${{ inputs.cache-version }}-
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
25
.github/actions/yarnrc-hash/action.yml
vendored
Normal file
25
.github/actions/yarnrc-hash/action.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Compute .yarnrc.yml hash
|
||||
|
||||
description: Compute a stable hash for .yarnrc.yml to use in cache keys.
|
||||
|
||||
outputs:
|
||||
hash:
|
||||
description: Hash of .yarnrc.yml (or "no-yarnrc" if the file is missing)
|
||||
value: ${{ steps.compute-yarnrc-hash.outputs.hash }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Compute .yarnrc.yml hash
|
||||
id: compute-yarnrc-hash
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f .yarnrc.yml ]; then
|
||||
if command -v shasum >/dev/null 2>&1; then
|
||||
echo "hash=$(shasum -a 256 .yarnrc.yml | awk '{ print $1 }')" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "hash=$(sha256sum .yarnrc.yml | awk '{ print $1 }')" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
else
|
||||
echo "hash=no-yarnrc" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
45
.github/workflows/mobile-bundle-analysis.yml
vendored
45
.github/workflows/mobile-bundle-analysis.yml
vendored
@@ -37,32 +37,26 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Cache Node Modules
|
||||
uses: actions/cache@v4
|
||||
- name: Cache Yarn
|
||||
uses: ./.github/actions/cache-yarn
|
||||
with:
|
||||
path: |
|
||||
.yarn/cache
|
||||
node_modules
|
||||
app/node_modules
|
||||
key: ${{ runner.os }}-node-${{ env.NODE_VERSION_SANITIZED }}-yarn-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-${{ env.NODE_VERSION_SANITIZED }}-yarn-
|
||||
- name: Cache Ruby Bundler
|
||||
uses: actions/cache@v4
|
||||
cache-version: node-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Cache Bundler
|
||||
uses: ./.github/actions/cache-bundler
|
||||
with:
|
||||
path: app/vendor/bundle
|
||||
key: ${{ runner.os }}-ruby${{ env.RUBY_VERSION }}-gems-${{ hashFiles('app/Gemfile.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ruby${{ env.RUBY_VERSION }}-gems-
|
||||
lock-file: app/Gemfile.lock
|
||||
cache-version: ruby${{ env.RUBY_VERSION }}
|
||||
- name: Cache Gradle
|
||||
uses: actions/cache@v4
|
||||
uses: ./.github/actions/cache-gradle
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('app/android/**/gradle-wrapper.properties', 'app/android/**/gradle-wrapper.jar') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Install Mobile Dependencies
|
||||
uses: ./.github/actions/mobile-setup
|
||||
with:
|
||||
@@ -100,30 +94,25 @@ jobs:
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Cache Node Modules
|
||||
uses: actions/cache@v4
|
||||
- name: Cache Yarn
|
||||
uses: ./.github/actions/cache-yarn
|
||||
with:
|
||||
path: |
|
||||
.yarn/cache
|
||||
node_modules
|
||||
app/node_modules
|
||||
key: ${{ runner.os }}-node${{ env.NODE_VERSION }}-yarn-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node${{ env.NODE_VERSION }}-yarn-
|
||||
- name: Cache Ruby Bundler
|
||||
uses: actions/cache@v4
|
||||
cache-version: node-${{ env.NODE_VERSION_SANITIZED }}
|
||||
- name: Cache Bundler
|
||||
uses: ./.github/actions/cache-bundler
|
||||
with:
|
||||
path: app/vendor/bundle
|
||||
key: ${{ runner.os }}-ruby${{ env.RUBY_VERSION }}-gems-${{ hashFiles('app/Gemfile.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ruby${{ env.RUBY_VERSION }}-gems-
|
||||
lock-file: app/Gemfile.lock
|
||||
cache-version: ruby${{ env.RUBY_VERSION }}
|
||||
- name: Cache CocoaPods
|
||||
uses: actions/cache@v4
|
||||
uses: ./.github/actions/cache-pods
|
||||
with:
|
||||
path: app/ios/Pods
|
||||
key: ${{ runner.os }}-pods-${{ hashFiles('app/ios/Podfile.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pods-
|
||||
lock-file: app/ios/Podfile.lock
|
||||
- name: Install Mobile Dependencies
|
||||
uses: ./.github/actions/mobile-setup
|
||||
with:
|
||||
|
||||
12
.github/workflows/mobile-deploy.yml
vendored
12
.github/workflows/mobile-deploy.yml
vendored
@@ -367,6 +367,10 @@ jobs:
|
||||
echo "Xcode path:"
|
||||
xcode-select -p
|
||||
|
||||
- name: Compute .yarnrc.yml hash
|
||||
id: yarnrc-hash
|
||||
uses: ./.github/actions/yarnrc-hash
|
||||
|
||||
- name: Cache Yarn artifacts
|
||||
id: yarn-cache
|
||||
uses: ./.github/actions/cache-yarn
|
||||
@@ -375,7 +379,7 @@ jobs:
|
||||
.yarn/cache
|
||||
.yarn/install-state.gz
|
||||
.yarn/unplugged
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-node-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('.yarnrc.yml') }}
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-node-${{ env.NODE_VERSION_SANITIZED }}-${{ steps.yarnrc-hash.outputs.hash }}
|
||||
|
||||
- name: Cache Ruby gems
|
||||
id: gems-cache
|
||||
@@ -976,6 +980,10 @@ jobs:
|
||||
# Use version-manager script to apply versions
|
||||
node ${{ env.APP_PATH }}/scripts/version-manager.cjs apply "$VERSION" "$IOS_BUILD" "$ANDROID_BUILD"
|
||||
|
||||
- name: Compute .yarnrc.yml hash
|
||||
id: yarnrc-hash
|
||||
uses: ./.github/actions/yarnrc-hash
|
||||
|
||||
- name: Cache Yarn artifacts
|
||||
id: yarn-cache
|
||||
uses: ./.github/actions/cache-yarn
|
||||
@@ -984,7 +992,7 @@ jobs:
|
||||
.yarn/cache
|
||||
.yarn/install-state.gz
|
||||
.yarn/unplugged
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-node-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('.yarnrc.yml') }}
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-node-${{ env.NODE_VERSION_SANITIZED }}-${{ steps.yarnrc-hash.outputs.hash }}
|
||||
|
||||
- name: Cache Ruby gems
|
||||
id: gems-cache
|
||||
|
||||
10
.github/workflows/mobile-e2e.yml
vendored
10
.github/workflows/mobile-e2e.yml
vendored
@@ -56,6 +56,9 @@ jobs:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- run: corepack enable
|
||||
- run: corepack prepare yarn@4.6.0 --activate
|
||||
- name: Compute .yarnrc.yml hash
|
||||
id: yarnrc-hash
|
||||
uses: ./.github/actions/yarnrc-hash
|
||||
- name: Cache Yarn dependencies
|
||||
uses: ./.github/actions/cache-yarn
|
||||
with:
|
||||
@@ -63,7 +66,7 @@ jobs:
|
||||
.yarn/cache
|
||||
.yarn/install-state.gz
|
||||
.yarn/unplugged
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-node-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('.yarnrc.yml') }}
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-node-${{ env.NODE_VERSION_SANITIZED }}-${{ steps.yarnrc-hash.outputs.hash }}
|
||||
- name: Toggle Yarn hardened mode for trusted PRs
|
||||
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false }}
|
||||
run: echo "YARN_ENABLE_HARDENED_MODE=0" >> $GITHUB_ENV
|
||||
@@ -246,6 +249,9 @@ jobs:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- run: corepack enable
|
||||
- run: corepack prepare yarn@4.6.0 --activate
|
||||
- name: Compute .yarnrc.yml hash
|
||||
id: yarnrc-hash
|
||||
uses: ./.github/actions/yarnrc-hash
|
||||
- name: Cache Yarn dependencies
|
||||
uses: ./.github/actions/cache-yarn
|
||||
with:
|
||||
@@ -253,7 +259,7 @@ jobs:
|
||||
.yarn/cache
|
||||
.yarn/install-state.gz
|
||||
.yarn/unplugged
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-node-${{ env.NODE_VERSION_SANITIZED }}-${{ hashFiles('.yarnrc.yml') }}
|
||||
cache-version: ${{ env.GH_CACHE_VERSION }}-node-${{ env.NODE_VERSION_SANITIZED }}-${{ steps.yarnrc-hash.outputs.hash }}
|
||||
- name: Toggle Yarn hardened mode for trusted PRs
|
||||
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false }}
|
||||
run: echo "YARN_ENABLE_HARDENED_MODE=0" >> $GITHUB_ENV
|
||||
|
||||
2
.github/workflows/npm-publish.yml
vendored
2
.github/workflows/npm-publish.yml
vendored
@@ -14,7 +14,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
id-token: write # Required for OIDC
|
||||
id-token: write # Required for OIDC
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
4
.github/workflows/qrcode-sdk-ci.yml
vendored
4
.github/workflows/qrcode-sdk-ci.yml
vendored
@@ -68,6 +68,7 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
yarn workspace @selfxyz/common build
|
||||
yarn workspace @selfxyz/sdk-common build
|
||||
yarn workspace @selfxyz/qrcode build
|
||||
|
||||
- name: Cache build artifacts
|
||||
@@ -258,6 +259,9 @@ jobs:
|
||||
key: qrcode-sdk-build-${{ env.GH_SDK_CACHE_VERSION }}-${{ github.sha }}
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Build SDK common dependency
|
||||
run: yarn workspace @selfxyz/sdk-common build
|
||||
|
||||
- name: Run tests
|
||||
run: yarn workspace @selfxyz/qrcode test
|
||||
|
||||
|
||||
@@ -658,6 +658,8 @@ regexes = [
|
||||
stopwords = [
|
||||
"000000",
|
||||
"6fe4476ee5a1832882e326b506d14126",
|
||||
"8853c3c635164864da68a6dbbcec7148506c3bcf",
|
||||
"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMDQwMTAwODA2NDc2NTA5MzU5MzgiLCJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20ifQ.signature",
|
||||
"_ec2_",
|
||||
"aaaaaa",
|
||||
"about",
|
||||
@@ -3188,4 +3190,3 @@ id = "zendesk-secret-key"
|
||||
description = "Detected a Zendesk Secret Key, risking unauthorized access to customer support services and sensitive ticketing data."
|
||||
regex = '''(?i)[\w.-]{0,50}?(?:zendesk)(?:[ \t\w.-]{0,20})[\s'"]{0,3}(?:=|>|:{1,3}=|\|\||:|=>|\?=|,)[\x60'"\s=]{0,5}([a-z0-9]{40})(?:[\x60'"\s;]|\\[nr]|$)'''
|
||||
keywords = ["zendesk"]
|
||||
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
1b461a626e0a4a93d4e1c727e7aed8c955aa728c:common/src/utils/passports/validate.test.ts:generic-api-key:73
|
||||
1b461a626e0a4a93d4e1c727e7aed8c955aa728c:common/src/utils/passports/validate.test.ts:generic-api-key:74
|
||||
8bc1e85075f73906767652ab35d5563efce2a931:packages/mobile-sdk-alpha/src/animations/passport_verify.json:aws-access-token:6
|
||||
f506113a22e5b147132834e4659f5af308448389:app/tests/utils/deeplinks.test.ts:generic-api-key:183
|
||||
5a67b5cc50f291401d1da4e51706d0cfcf1c2316:app/tests/utils/deeplinks.test.ts:generic-api-key:182
|
||||
0e4555eee6589aa9cca68f451227b149277d8c90:app/tests/src/utils/points/api.test.ts:generic-api-key:34
|
||||
app/ios/Podfile.lock:generic-api-key:2594
|
||||
app/tests/src/navigation/deeplinks.test.ts:generic-api-key:208
|
||||
circuits/circuits/gcp_jwt_verifier/example_jwt.txt:jwt:1
|
||||
cadd7ae5b768c261230f84426eac879c1853ce70:app/ios/Podfile.lock:generic-api-key:2586
|
||||
|
||||
@@ -6,6 +6,8 @@ import React from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
import { Anchor, styled } from 'tamagui';
|
||||
|
||||
import { androidBackupDocsUrl, appleICloudDocsUrl } from '@/consts/links';
|
||||
|
||||
const StyledAnchor = styled(Anchor, {
|
||||
fontSize: 15,
|
||||
fontFamily: 'DINOT-Medium',
|
||||
@@ -15,16 +17,13 @@ const StyledAnchor = styled(Anchor, {
|
||||
const BackupDocumentationLink: React.FC = () => {
|
||||
if (Platform.OS === 'ios') {
|
||||
return (
|
||||
<StyledAnchor unstyled href="https://support.apple.com/en-us/102651">
|
||||
<StyledAnchor unstyled href={appleICloudDocsUrl}>
|
||||
iCloud data
|
||||
</StyledAnchor>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<StyledAnchor
|
||||
unstyled
|
||||
href="https://developer.android.com/identity/data/autobackup"
|
||||
>
|
||||
<StyledAnchor unstyled href={androidBackupDocsUrl}>
|
||||
Android Backup
|
||||
</StyledAnchor>
|
||||
);
|
||||
|
||||
@@ -21,6 +21,7 @@ import CogHollowIcon from '@/assets/icons/cog_hollow.svg';
|
||||
import PlusCircleIcon from '@/assets/icons/plus_circle.svg';
|
||||
import ScanIcon from '@/assets/icons/qr_scan.svg';
|
||||
import { NavBar } from '@/components/navbar/BaseNavBar';
|
||||
import { apiBaseUrl } from '@/consts/links';
|
||||
import { buttonTap } from '@/integrations/haptics';
|
||||
import { extraYPadding } from '@/utils/styleUtils';
|
||||
|
||||
@@ -40,7 +41,7 @@ export const HomeNavBar = (props: NativeStackHeaderProps) => {
|
||||
if (uuidRegex.test(content)) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://api.self.xyz/consume-deferred-linking-token?token=${content}`,
|
||||
`${apiBaseUrl}/consume-deferred-linking-token?token=${content}`,
|
||||
);
|
||||
const result = await response.json();
|
||||
if (result.status !== 'success') {
|
||||
|
||||
@@ -29,6 +29,7 @@ import StarBlackIcon from '@/assets/icons/star_black.svg';
|
||||
import LogoInversed from '@/assets/images/logo_inversed.svg';
|
||||
import MajongImage from '@/assets/images/majong.png';
|
||||
import { PointHistoryList } from '@/components/PointHistoryList';
|
||||
import { appsUrl } from '@/consts/links';
|
||||
import { useIncomingPoints, usePoints } from '@/hooks/usePoints';
|
||||
import { usePointsGuardrail } from '@/hooks/usePointsGuardrail';
|
||||
import type { RootStackParamList } from '@/navigation';
|
||||
@@ -428,7 +429,7 @@ const Points: React.FC = () => {
|
||||
onPress={() => {
|
||||
selfClient.trackEvent(PointEvents.EXPLORE_APPS);
|
||||
navigation.navigate('WebView', {
|
||||
url: 'https://apps.self.xyz',
|
||||
url: appsUrl,
|
||||
title: 'Explore Apps',
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -2,22 +2,40 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
// =============================================================================
|
||||
// External Links
|
||||
// =============================================================================
|
||||
// All external URLs used in the mobile app are centralized here for easy
|
||||
// maintenance and testing. Links are sorted alphabetically.
|
||||
|
||||
export const androidBackupDocsUrl =
|
||||
'https://developer.android.com/identity/data/autobackup';
|
||||
export const apiBaseUrl = 'https://api.self.xyz';
|
||||
export const apiPingUrl = 'https://api.self.xyz/ping';
|
||||
export const appStoreUrl = 'https://apps.apple.com/app/self-zk/id6478563710';
|
||||
|
||||
export const appleICloudDocsUrl = 'https://support.apple.com/en-us/102651';
|
||||
export const appsUrl = 'https://apps.self.xyz';
|
||||
export const gitHubUrl = 'https://github.com/selfxyz/self';
|
||||
|
||||
export const googleDriveAppDataScope =
|
||||
'https://www.googleapis.com/auth/drive.appdata';
|
||||
export const googleOAuthAuthorizationEndpoint =
|
||||
'https://accounts.google.com/o/oauth2/v2/auth';
|
||||
export const googleOAuthTokenEndpoint = 'https://oauth2.googleapis.com/token';
|
||||
export const notificationApiStagingUrl =
|
||||
'https://notification.staging.self.xyz';
|
||||
export const notificationApiUrl = 'https://notification.self.xyz';
|
||||
export const playStoreUrl =
|
||||
'https://play.google.com/store/apps/details?id=com.proofofpassportapp';
|
||||
|
||||
export const pointsApiBaseUrl = 'https://points.self.xyz';
|
||||
export const privacyUrl = 'https://self.xyz/privacy';
|
||||
|
||||
export const referralBaseUrl = 'https://referral.self.xyz';
|
||||
export const selfLogoReverseUrl =
|
||||
'https://storage.googleapis.com/self-logo-reverse/Self%20Logomark%20Reverse.png';
|
||||
export const selfUrl = 'https://self.xyz';
|
||||
|
||||
export const supportedBiometricIdsUrl =
|
||||
'https://docs.self.xyz/use-self/self-map-countries-list';
|
||||
|
||||
export const telegramUrl = 'https://t.me/selfprotocolbuilder';
|
||||
|
||||
export const termsUrl = 'https://self.xyz/terms';
|
||||
|
||||
export const turnkeyOAuthRedirectAndroidUri = 'https://redirect.self.xyz';
|
||||
export const turnkeyOAuthRedirectIosUri = 'https://oauth-redirect.turnkey.com';
|
||||
export const xUrl = 'https://x.com/selfprotocol';
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
// Turnkey OAuth redirect URIs
|
||||
export const TURNKEY_OAUTH_REDIRECT_URI_ANDROID = 'https://redirect.self.xyz';
|
||||
import {
|
||||
turnkeyOAuthRedirectAndroidUri,
|
||||
turnkeyOAuthRedirectIosUri,
|
||||
} from '@/consts/links';
|
||||
|
||||
export const TURNKEY_OAUTH_REDIRECT_URI_IOS =
|
||||
'https://oauth-redirect.turnkey.com';
|
||||
// Turnkey OAuth redirect URIs
|
||||
export const TURNKEY_OAUTH_REDIRECT_URI_ANDROID =
|
||||
turnkeyOAuthRedirectAndroidUri;
|
||||
|
||||
export const TURNKEY_OAUTH_REDIRECT_URI_IOS = turnkeyOAuthRedirectIosUri;
|
||||
|
||||
// Re-export all mocks for easier imports
|
||||
export { parseScanResponse, scan } from '@/devtools/mocks/nfcScanner';
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Linking, Platform } from 'react-native';
|
||||
|
||||
import { SettingsEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
|
||||
|
||||
import { apiPingUrl } from '@/consts/links';
|
||||
import { useModal } from '@/hooks/useModal';
|
||||
import { useNetInfo } from '@/hooks/useNetInfo';
|
||||
import { navigationRef } from '@/navigation';
|
||||
@@ -34,7 +35,7 @@ const connectionModalParams = {
|
||||
|
||||
export default function useConnectionModal() {
|
||||
const { isConnected, isInternetReachable } = useNetInfo({
|
||||
reachabilityUrl: 'https://api.self.xyz/ping',
|
||||
reachabilityUrl: apiPingUrl,
|
||||
});
|
||||
const { showModal, dismissModal, visible } = useModal(connectionModalParams);
|
||||
//isConnected and isInternetReachable can be null for unknown state
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { referralBaseUrl } from '@/consts/links';
|
||||
import { getOrGeneratePointsAddress } from '@/providers/authProvider';
|
||||
import { useSettingStore } from '@/stores/settingStore';
|
||||
|
||||
@@ -15,8 +16,7 @@ interface ReferralMessageResult {
|
||||
const buildReferralMessageFromAddress = (
|
||||
userPointsAddress: string,
|
||||
): ReferralMessageResult => {
|
||||
const baseDomain = 'https://referral.self.xyz';
|
||||
const referralLink = `${baseDomain}/referral/${userPointsAddress}`;
|
||||
const referralLink = `${referralBaseUrl}/referral/${userPointsAddress}`;
|
||||
return {
|
||||
message: `Join Self and use my referral link:\n\n${referralLink}`,
|
||||
referralLink,
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
NativeStackScreenProps,
|
||||
} from '@react-navigation/native-stack';
|
||||
|
||||
import { selfUrl } from '@/consts/links';
|
||||
import type { SharedRoutesParamList } from '@/navigation/types';
|
||||
import ComingSoonScreen from '@/screens/shared/ComingSoonScreen';
|
||||
import { WebViewScreen } from '@/screens/shared/WebViewScreen';
|
||||
@@ -33,7 +34,7 @@ const sharedScreens: { [K in ScreenName]: ScreenConfig<K> } = {
|
||||
headerShown: false,
|
||||
} as NativeStackNavigationOptions,
|
||||
initialParams: {
|
||||
url: 'https://self.xyz',
|
||||
url: selfUrl,
|
||||
title: undefined,
|
||||
shareTitle: undefined,
|
||||
shareMessage: undefined,
|
||||
|
||||
@@ -174,7 +174,7 @@ const AadhaarUploadScreen: React.FC = () => {
|
||||
<BodyText
|
||||
style={{ fontWeight: 'bold', fontSize: 18, textAlign: 'center' }}
|
||||
>
|
||||
Generate a QR code from the mAadaar app
|
||||
Generate a QR code from the Aadhaar app
|
||||
</BodyText>
|
||||
<BodyText
|
||||
style={{ fontSize: 16, textAlign: 'center', color: slate500 }}
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
|
||||
import { WebViewNavBar } from '@/components/navbar/WebViewNavBar';
|
||||
import { WebViewFooter } from '@/components/WebViewFooter';
|
||||
import { selfUrl } from '@/consts/links';
|
||||
import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout';
|
||||
import type { SharedRoutesParamList } from '@/navigation/types';
|
||||
|
||||
@@ -39,7 +40,7 @@ type WebViewScreenProps = NativeStackScreenProps<
|
||||
'WebView'
|
||||
>;
|
||||
|
||||
const defaultUrl = 'https://self.xyz';
|
||||
const defaultUrl = selfUrl;
|
||||
|
||||
export const WebViewScreen: React.FC<WebViewScreenProps> = ({ route }) => {
|
||||
const navigation = useNavigation();
|
||||
|
||||
@@ -7,6 +7,12 @@ import { authorize } from 'react-native-app-auth';
|
||||
import { GOOGLE_SIGNIN_ANDROID_CLIENT_ID } from '@env';
|
||||
import { GDrive } from '@robinbobin/react-native-google-drive-api-wrapper';
|
||||
|
||||
import {
|
||||
googleDriveAppDataScope,
|
||||
googleOAuthAuthorizationEndpoint,
|
||||
googleOAuthTokenEndpoint,
|
||||
} from '@/consts/links';
|
||||
|
||||
// Ensure the client ID is available at runtime (skip in test environment)
|
||||
const isTestEnvironment =
|
||||
process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID;
|
||||
@@ -22,10 +28,10 @@ const config: AuthConfiguration = {
|
||||
// ensure this prints the correct values before calling authorize
|
||||
clientId: GOOGLE_SIGNIN_ANDROID_CLIENT_ID || 'mock-client-id',
|
||||
redirectUrl: 'com.proofofpassportapp:/oauth2redirect',
|
||||
scopes: ['https://www.googleapis.com/auth/drive.appdata'],
|
||||
scopes: [googleDriveAppDataScope],
|
||||
serviceConfiguration: {
|
||||
authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
|
||||
tokenEndpoint: 'https://oauth2.googleapis.com/token',
|
||||
authorizationEndpoint: googleOAuthAuthorizationEndpoint,
|
||||
tokenEndpoint: googleOAuthTokenEndpoint,
|
||||
},
|
||||
additionalParameters: { access_type: 'offline', prompt: 'consent' as const },
|
||||
};
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { notificationApiStagingUrl, notificationApiUrl } from '@/consts/links';
|
||||
|
||||
export interface DeviceTokenRegistration {
|
||||
session_id: string;
|
||||
device_token: string;
|
||||
@@ -18,9 +20,9 @@ export interface RemoteMessage {
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export const API_URL = 'https://notification.self.xyz';
|
||||
export const API_URL = notificationApiUrl;
|
||||
|
||||
export const API_URL_STAGING = 'https://notification.staging.self.xyz';
|
||||
export const API_URL_STAGING = notificationApiStagingUrl;
|
||||
export const getStateMessage = (state: string): string => {
|
||||
switch (state) {
|
||||
case 'idle':
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
export const POINTS_API_BASE_URL = 'https://points.self.xyz';
|
||||
import { pointsApiBaseUrl } from '@/consts/links';
|
||||
|
||||
export const POINTS_API_BASE_URL = pointsApiBaseUrl;
|
||||
|
||||
@@ -6,6 +6,7 @@ import { v4 } from 'uuid';
|
||||
|
||||
import { SelfAppBuilder } from '@selfxyz/common/utils/appType';
|
||||
|
||||
import { selfLogoReverseUrl } from '@/consts/links';
|
||||
import { getOrGeneratePointsAddress } from '@/providers/authProvider';
|
||||
import { POINTS_API_BASE_URL } from '@/services/points/constants';
|
||||
import type { IncomingPoints } from '@/services/points/types';
|
||||
@@ -175,8 +176,7 @@ export const pointsSelfApp = async () => {
|
||||
userId: v4(),
|
||||
userIdType: 'uuid',
|
||||
disclosures: {},
|
||||
logoBase64:
|
||||
'https://storage.googleapis.com/self-logo-reverse/Self%20Logomark%20Reverse.png',
|
||||
logoBase64: selfLogoReverseUrl,
|
||||
header: '',
|
||||
});
|
||||
|
||||
|
||||
126
app/tests/src/consts/links.test.ts
Normal file
126
app/tests/src/consts/links.test.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
|
||||
|
||||
import { describe, expect, it } from '@jest/globals';
|
||||
|
||||
import * as links from '@/consts/links';
|
||||
|
||||
describe('links', () => {
|
||||
describe('URL format validation', () => {
|
||||
it('should export only valid HTTPS URLs', () => {
|
||||
const allLinks = Object.entries(links);
|
||||
|
||||
allLinks.forEach(([_name, url]) => {
|
||||
expect(url).toMatch(/^https:\/\/.+/);
|
||||
expect(url).not.toContain(' ');
|
||||
// Ensure no trailing slashes (consistency)
|
||||
expect(url).not.toMatch(/\/$/);
|
||||
});
|
||||
});
|
||||
|
||||
it('should have unique URLs (no duplicates)', () => {
|
||||
const allUrls = Object.values(links);
|
||||
const uniqueUrls = new Set(allUrls);
|
||||
|
||||
expect(uniqueUrls.size).toBe(allUrls.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Critical URL validation', () => {
|
||||
it('should have correct Telegram URL', () => {
|
||||
// This test would have caught the wrong Telegram URL bug!
|
||||
expect(links.telegramUrl).toBe('https://t.me/selfprotocolbuilder');
|
||||
});
|
||||
|
||||
it('should have correct GitHub URL', () => {
|
||||
expect(links.gitHubUrl).toBe('https://github.com/selfxyz/self');
|
||||
});
|
||||
|
||||
it('should have correct X (Twitter) URL', () => {
|
||||
expect(links.xUrl).toBe('https://x.com/selfprotocol');
|
||||
});
|
||||
|
||||
it('should have correct Self main URL', () => {
|
||||
expect(links.selfUrl).toBe('https://self.xyz');
|
||||
});
|
||||
|
||||
it('should have correct privacy policy URL', () => {
|
||||
expect(links.privacyUrl).toBe('https://self.xyz/privacy');
|
||||
});
|
||||
|
||||
it('should have correct terms URL', () => {
|
||||
expect(links.termsUrl).toBe('https://self.xyz/terms');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Self platform URLs', () => {
|
||||
it('should use self.xyz domain for platform URLs', () => {
|
||||
expect(links.selfUrl).toContain('self.xyz');
|
||||
expect(links.privacyUrl).toContain('self.xyz');
|
||||
expect(links.termsUrl).toContain('self.xyz');
|
||||
expect(links.appsUrl).toContain('self.xyz');
|
||||
expect(links.referralBaseUrl).toContain('self.xyz');
|
||||
expect(links.apiBaseUrl).toContain('self.xyz');
|
||||
expect(links.pointsApiBaseUrl).toContain('self.xyz');
|
||||
expect(links.notificationApiUrl).toContain('self.xyz');
|
||||
});
|
||||
});
|
||||
|
||||
describe('App store URLs', () => {
|
||||
it('should have valid App Store URL', () => {
|
||||
expect(links.appStoreUrl).toMatch(/^https:\/\/apps\.apple\.com\//);
|
||||
expect(links.appStoreUrl).toContain('id6478563710');
|
||||
});
|
||||
|
||||
it('should have valid Play Store URL', () => {
|
||||
expect(links.playStoreUrl).toMatch(
|
||||
/^https:\/\/play\.google\.com\/store\//,
|
||||
);
|
||||
expect(links.playStoreUrl).toContain('com.proofofpassportapp');
|
||||
});
|
||||
});
|
||||
|
||||
describe('OAuth URLs', () => {
|
||||
it('should have valid Google OAuth endpoints', () => {
|
||||
expect(links.googleOAuthAuthorizationEndpoint).toBe(
|
||||
'https://accounts.google.com/o/oauth2/v2/auth',
|
||||
);
|
||||
expect(links.googleOAuthTokenEndpoint).toBe(
|
||||
'https://oauth2.googleapis.com/token',
|
||||
);
|
||||
});
|
||||
|
||||
it('should have valid Turnkey redirect URIs', () => {
|
||||
expect(links.turnkeyOAuthRedirectAndroidUri).toContain('self.xyz');
|
||||
expect(links.turnkeyOAuthRedirectIosUri).toContain('turnkey.com');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Export completeness', () => {
|
||||
it('should export at least 20 links', () => {
|
||||
// Ensures we don't accidentally remove links
|
||||
const linkCount = Object.keys(links).length;
|
||||
expect(linkCount).toBeGreaterThanOrEqual(20);
|
||||
});
|
||||
|
||||
it('should have descriptive variable names', () => {
|
||||
const allLinks = Object.keys(links);
|
||||
|
||||
allLinks.forEach(name => {
|
||||
// Should be camelCase
|
||||
expect(name).toMatch(/^[a-z][a-zA-Z0-9]*$/);
|
||||
// Should end with Url, Uri, Endpoint, or Scope
|
||||
const isValid =
|
||||
name.endsWith('Url') ||
|
||||
name.endsWith('Uri') ||
|
||||
name.endsWith('Endpoint') ||
|
||||
name.endsWith('Scope');
|
||||
if (!isValid) {
|
||||
console.log(`Invalid variable name: ${name}`);
|
||||
}
|
||||
expect(isValid).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -228,7 +228,7 @@ describe('deeplinks', () => {
|
||||
.mockImplementation(() => {});
|
||||
|
||||
const url =
|
||||
'https://redirect.self.xyz?scheme=https#code=4/0Ab32j93MfuUU-vJKJth_t0fnnPkg1O7&id_token=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMDQwMTAwODA2NDc2NTA5MzU5MzgiLCJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20ifQ.signature';
|
||||
'https://redirect.self.xyz?scheme=https#code=4/0Ab32j93MfuUU-vJKJth_t0fnnPkg1O7&id_token=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMDQwMTAwODA2NDc2NTA5MzU5MzgiLCJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20ifQ.signature'; // gitleaks:allow
|
||||
handleUrl({} as SelfClient, url);
|
||||
|
||||
const { navigationRef } = require('@/navigation');
|
||||
@@ -265,7 +265,7 @@ describe('deeplinks', () => {
|
||||
.mockImplementation(() => {});
|
||||
|
||||
const url =
|
||||
'https://redirect.self.xyz?scheme=https#id_token=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMDQwMTAwODA2NDc2NTA5MzU5MzgiLCJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20ifQ.signature&scope=email%20profile';
|
||||
'https://redirect.self.xyz?scheme=https#id_token=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMDQwMTAwODA2NDc2NTA5MzU5MzgiLCJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20ifQ.signature&scope=email%20profile'; // gitleaks:allow
|
||||
handleUrl({} as SelfClient, url);
|
||||
|
||||
const { navigationRef } = require('@/navigation');
|
||||
@@ -530,7 +530,7 @@ describe('deeplinks', () => {
|
||||
|
||||
it('returns id_token and scope parameters', () => {
|
||||
const url =
|
||||
'https://redirect.self.xyz?scheme=https#id_token=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMDQwMTAwODA2NDc2NTA5MzU5MzgiLCJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20ifQ.signature&scope=email%20profile';
|
||||
'https://redirect.self.xyz?scheme=https#id_token=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxMDQwMTAwODA2NDc2NTA5MzU5MzgiLCJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20ifQ.signature&scope=email%20profile'; // gitleaks:allow
|
||||
const result = parseAndValidateUrlParams(url);
|
||||
expect(result.id_token).toBeTruthy();
|
||||
expect(result.scope).toBe('email profile');
|
||||
|
||||
@@ -12,23 +12,27 @@ describe('provingUtils', () => {
|
||||
const plaintext = 'hello world';
|
||||
const encrypted = encryptAES256GCM(plaintext, forge.util.createBuffer(key));
|
||||
|
||||
// Convert arrays to Uint8Array first to ensure proper byte conversion
|
||||
const nonceBytes = new Uint8Array(encrypted.nonce);
|
||||
const authTagBytes = new Uint8Array(encrypted.auth_tag);
|
||||
const cipherTextBytes = new Uint8Array(encrypted.cipher_text);
|
||||
|
||||
// Validate tag length (128 bits = 16 bytes)
|
||||
expect(authTagBytes.length).toBe(16);
|
||||
|
||||
const decipher = forge.cipher.createDecipher(
|
||||
'AES-GCM',
|
||||
forge.util.createBuffer(key),
|
||||
);
|
||||
decipher.start({
|
||||
iv: forge.util.createBuffer(
|
||||
Buffer.from(encrypted.nonce).toString('binary'),
|
||||
),
|
||||
iv: forge.util.createBuffer(Buffer.from(nonceBytes).toString('binary')),
|
||||
tagLength: 128,
|
||||
tag: forge.util.createBuffer(
|
||||
Buffer.from(encrypted.auth_tag).toString('binary'),
|
||||
Buffer.from(authTagBytes).toString('binary'),
|
||||
),
|
||||
});
|
||||
decipher.update(
|
||||
forge.util.createBuffer(
|
||||
Buffer.from(encrypted.cipher_text).toString('binary'),
|
||||
),
|
||||
forge.util.createBuffer(Buffer.from(cipherTextBytes).toString('binary')),
|
||||
);
|
||||
const success = decipher.finish();
|
||||
const decrypted = decipher.output.toString();
|
||||
|
||||
@@ -55,7 +55,8 @@
|
||||
"@babel/runtime": "^7.28.3",
|
||||
"js-sha1": "^0.7.0",
|
||||
"react": "^18.3.1",
|
||||
"react-native": "0.76.9"
|
||||
"react-native": "0.76.9",
|
||||
"uuid": "^13.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/cli-server-api": "^16.0.3",
|
||||
|
||||
@@ -27,13 +27,13 @@ import { useNavigation } from '../navigation/NavigationProvider';
|
||||
* Routes not in this map are not supported in the demo app.
|
||||
*/
|
||||
const ROUTE_TO_SCREEN_MAP: Partial<Record<RouteName, ScreenName>> = {
|
||||
'Home': 'Home',
|
||||
'CountryPicker': 'CountrySelection',
|
||||
'IDPicker': 'IDSelection',
|
||||
'DocumentCamera': 'MRZ',
|
||||
'DocumentNFCScan': 'NFC',
|
||||
'ManageDocuments': 'Documents',
|
||||
'AccountVerifiedSuccess': 'Success',
|
||||
Home: 'Home',
|
||||
CountryPicker: 'CountrySelection',
|
||||
IDPicker: 'IDSelection',
|
||||
DocumentCamera: 'MRZ',
|
||||
DocumentNFCScan: 'NFC',
|
||||
ManageDocuments: 'Documents',
|
||||
AccountVerifiedSuccess: 'Success',
|
||||
// Routes not implemented in demo app:
|
||||
// 'DocumentOnboarding': null,
|
||||
// 'SaveRecoveryPhrase': null,
|
||||
@@ -173,7 +173,9 @@ export function SelfClientProvider({ children, onNavigate }: SelfClientProviderP
|
||||
// This is safe because we control the route mapping
|
||||
navigation.navigate(screenName, params as any);
|
||||
} else {
|
||||
console.warn(`[SelfClientProvider] SDK route "${routeName}" is not mapped to a demo screen. Ignoring navigation request.`);
|
||||
console.warn(
|
||||
`[SelfClientProvider] SDK route "${routeName}" is not mapped to a demo screen. Ignoring navigation request.`,
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -97,7 +97,7 @@ const SelfQRcode = ({
|
||||
return <BounceLoader loading={true} size={200} color="#94FBAB" />;
|
||||
case QRcodeSteps.PROOF_GENERATION_FAILED:
|
||||
return (
|
||||
//@ts-ignore
|
||||
// @ts-expect-error Lottie typings don't match the default export shape
|
||||
<LottieComponent
|
||||
animationData={X_ANIMATION}
|
||||
style={{ width: 200, height: 200 }}
|
||||
@@ -109,7 +109,7 @@ const SelfQRcode = ({
|
||||
);
|
||||
case QRcodeSteps.PROOF_VERIFIED:
|
||||
return (
|
||||
//@ts-ignore
|
||||
// @ts-expect-error Lottie typings don't match the default export shape
|
||||
<LottieComponent
|
||||
animationData={CHECK_ANIMATION}
|
||||
style={{ width: 200, height: 200 }}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
"prepublishOnly": "yarn build",
|
||||
"publish": "yarn npm publish --access public",
|
||||
"test": "echo 'no tests found'",
|
||||
"types": "yarn build"
|
||||
"types": "yarn workspace @selfxyz/sdk-common build && tsc -p tsconfig.json --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@selfxyz/sdk-common": "workspace:^",
|
||||
|
||||
Reference in New Issue
Block a user