Add referral program under feature flag

Add acquisition backend methods

Init referrals sharing UI

Add invite on home screen

Use i18n for strings

Lint

Update status go

Pull acquisition contract to get SNT amount

Use new invite component

f pulling

go

Use screen instead of bottom sheet

Handle android install referrer

Post referrer to backend if present

go go

Add async storage for referral decisions

Update with the stage backend

Update contract methods

Modal

UI

Full handling of advertiser type

UI

test

UI

Handle with universal link

Allow multiple acquisition per installation

Fix android bottom sheet

Do not call service if no click-id received

Disable invite in release

Parse query params for referrer

Adapt UI changes

Add push notification

update deps

Mock react-native-push-notification

Request push notifications permission on press accept

Store transaction to local storage and load it back on login

Separate acquisition into smaller ns

Add chat invite

Get referrer only on first install

fix string

Fix firebase crash

Handle outdate click-id

Cleanup business logic

Update contract

Revert pn

Minor update to advertiser modal copy

OLD -  Welcome to Status! Here is some crypto to get you started
NEW - Here’s some crypto to get you started! Use it to get stickers, an ENS name and try dapps

OLD - By accepting you agree to the starter pack
NEW - By accepting you agree to the referral program

upgrade status-go

Add mainnet

Signed-off-by: Gheorghe Pinzaru <feross95@gmail.com>
This commit is contained in:
Gheorghe Pinzaru 2020-05-08 18:08:53 +03:00
parent d0ce6f11d8
commit 3c42360b30
No known key found for this signature in database
GPG Key ID: C9A094959935A952
52 changed files with 1512 additions and 61 deletions

1
.env
View File

@ -22,3 +22,4 @@ STATUS_GO_ENABLE_NIMBUS=0
KEYCARD_TEST_MENU=0
QR_READ_TEST_MENU=1
ENABLE_ROOT_ALERT=1
ENABLE_REFERRAL_INVITE=1

View File

@ -21,4 +21,5 @@ TOOLTIP_EVENTS=1
COMMANDS_ENABLED=1
KEYCARD_TEST_MENU=1
QR_READ_TEST_MENU=1
ENABLE_ROOT_ALERT=0
ENABLE_ROOT_ALERT=0
ENABLE_REFERRAL_INVITE=1

View File

@ -19,4 +19,5 @@ PARTITIONED_TOPIC=0
CONTRACT_NODES=1
STATUS_GO_ENABLE_NIMBUS=0
KEYCARD_TEST_MENU=0
ENABLE_ROOT_ALERT=1
ENABLE_ROOT_ALERT=1
ENABLE_REFERRAL_INVITE=1

View File

@ -16,4 +16,5 @@ SNOOPY=0
RPC_NETWORKS_ONLY=0
PARTITIONED_TOPIC=0
CONTRACT_NODES=1
ENABLE_ROOT_ALERT=1
ENABLE_ROOT_ALERT=1
ENABLE_REFERRAL_INVITE=1

View File

@ -15,4 +15,5 @@ POW_TIME=1
SNOOPY=0
RPC_NETWORKS_ONLY=1
PARTITIONED_TOPIC=0
ENABLE_ROOT_ALERT=1
ENABLE_ROOT_ALERT=1
ENABLE_REFERRAL_INVITE=0

View File

@ -328,10 +328,14 @@ PODS:
- React
- ReactNativeDarkMode (0.2.2):
- React
- RNCAsyncStorage (1.11.0):
- React
- RNCClipboard (1.2.2):
- React
- RNCMaskedView (0.1.9):
- React
- RNDeviceInfo (5.6.1):
- React
- RNFS (2.16.6):
- React
- RNGestureHandler (1.6.1):
@ -434,8 +438,10 @@ DEPENDENCIES:
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- "ReactNativeAudioToolkit (from `../node_modules/@react-native-community/audio-toolkit`)"
- ReactNativeDarkMode (from `../node_modules/react-native-dark-mode`)
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)"
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNFS (from `../node_modules/react-native-fs`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
@ -548,10 +554,14 @@ EXTERNAL SOURCES:
:path: "../node_modules/@react-native-community/audio-toolkit"
ReactNativeDarkMode:
:path: "../node_modules/react-native-dark-mode"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
RNCClipboard:
:path: "../node_modules/@react-native-community/clipboard"
RNCMaskedView:
:path: "../node_modules/@react-native-community/masked-view"
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNFS:
:path: "../node_modules/react-native-fs"
RNGestureHandler:
@ -628,8 +638,10 @@ SPEC CHECKSUMS:
ReactCommon: ed4e11d27609d571e7eee8b65548efc191116eb3
ReactNativeAudioToolkit: de9610f323e855ac6574be8c99621f3d57c5df06
ReactNativeDarkMode: 0178ffca3b10f6a7c9f49d6f9810232b328fa949
RNCAsyncStorage: d059c3ee71738c39834a627476322a5a8cd5bf36
RNCClipboard: 8148e21ac347c51fd6cd4b683389094c216bb543
RNCMaskedView: 71fc32d971f03b7f03d6ab6b86b730c4ee64f5b6
RNDeviceInfo: b6e650fbd234732c759544218657d549b4339038
RNFS: 2bd9eb49dc82fa9676382f0585b992c424cd59df
RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38
RNImageCropPicker: 38865ab4af1b0b2146ad66061196bc0184946855

View File

@ -1301,6 +1301,20 @@
}
},
{
"path": "com/android/installreferrer/installreferrer/1.1.2/installreferrer-1.1.2",
"host": "https://dl.google.com/dl/android/maven2",
"type": "aar",
"pom": {
"sha1": "4bdcf06a3ab05a52dfe2fa9da23bd68a1d8e947d",
"sha256": "1800bwlh71xvczpbf4pjg1plqyqjwcragjwnpbbja3q1d5m62pfy"
},
"jar": {
"sha1": "4d7db3af2818a333a61776d48ad10455a008f421",
"sha256": "1iv3jjkscx52017ahlscay822qbjmrkxwr1cbyiidlldzbvp5xyq"
}
},
{
"path": "com/android/support/animated-vector-drawable/26.0.2/animated-vector-drawable-26.0.2",
"host": "https://dl.google.com/dl/android/maven2",
@ -3513,6 +3527,20 @@
}
},
{
"path": "com/google/android/gms/play-services-basement/17.0.0/play-services-basement-17.0.0",
"host": "https://dl.google.com/dl/android/maven2",
"type": "aar",
"pom": {
"sha1": "45c1c43219354319ea73c7cc7376b4f83adaf240",
"sha256": "0rjbl990ncim4zx344qis8j545qhd97n7hxl9dw2vv5jkrfjksgz"
},
"jar": {
"sha1": "f94e0b893e0d5d2a922577986c8b2a31fd79f634",
"sha256": "1753ax2qa2i4jhksyp3vjsgd8hygsg7lgj4zcgivyj5wbdwa296k"
}
},
{
"path": "com/google/android/gms/play-services-base/16.0.1/play-services-base-16.0.1",
"host": "https://dl.google.com/dl/android/maven2",
@ -3527,6 +3555,20 @@
}
},
{
"path": "com/google/android/gms/play-services-base/17.0.0/play-services-base-17.0.0",
"host": "https://dl.google.com/dl/android/maven2",
"type": "aar",
"pom": {
"sha1": "77505aa02852800097ec02562d5905723f37114f",
"sha256": "096r6jb1qf3r9f3b3g008l1qbpj3diys8sig4wcixm75ig9qj163"
},
"jar": {
"sha1": "7fe5a19c8a10b304800a0dac51ffd7ae0acc0648",
"sha256": "1iscqvpwij7ild7jgay7s2pc2dy23n0713mmw93d7q19yznq02fx"
}
},
{
"path": "com/google/android/gms/play-services-clearcut/16.0.0/play-services-clearcut-16.0.0",
"host": "https://dl.google.com/dl/android/maven2",
@ -3555,6 +3597,20 @@
}
},
{
"path": "com/google/android/gms/play-services-iid/17.0.0/play-services-iid-17.0.0",
"host": "https://dl.google.com/dl/android/maven2",
"type": "aar",
"pom": {
"sha1": "bf9f241f0eb754a65abf06dab1df551e5368d564",
"sha256": "0zzdyfg92zbfn3vp57zhihhfqjxwlw9jds3ycir4nx314llhnpr2"
},
"jar": {
"sha1": "5dc043b659c2ed77a937c514b06532049fb54bc1",
"sha256": "0s8qk60knf3ws2arsvdnz7v5q7s6xdwi4rbi2c4mpphjhsncxpfp"
}
},
{
"path": "com/google/android/gms/play-services-phenotype/16.0.0/play-services-phenotype-16.0.0",
"host": "https://dl.google.com/dl/android/maven2",
@ -3583,6 +3639,20 @@
}
},
{
"path": "com/google/android/gms/play-services-stats/17.0.0/play-services-stats-17.0.0",
"host": "https://dl.google.com/dl/android/maven2",
"type": "aar",
"pom": {
"sha1": "a86ccdcbbff8207e5700392933c77ad81e183f85",
"sha256": "16x1vs7zvgsyf53vkclqr2n2n8fwvxgrhxk9c5zqa8rrc6425xhn"
},
"jar": {
"sha1": "5ed3441a1bcdb224b0fed0cc175257ed15174755",
"sha256": "1zm6hcmq6gq9av834fyy9jm371rrvb9qrkgsicjy4w9ba505pbp8"
}
},
{
"path": "com/google/android/gms/play-services-tasks/16.0.1/play-services-tasks-16.0.1",
"host": "https://dl.google.com/dl/android/maven2",
@ -3597,6 +3667,20 @@
}
},
{
"path": "com/google/android/gms/play-services-tasks/17.0.0/play-services-tasks-17.0.0",
"host": "https://dl.google.com/dl/android/maven2",
"type": "aar",
"pom": {
"sha1": "ab81ab94f07c15697696e3da7fb026046403e0b9",
"sha256": "19kl9nwid519nr5pgjx5rmsjhv94fb82iakw03kbp57bq8137ngx"
},
"jar": {
"sha1": "18299a334d48bc5abfe3c9446c2a9e1a3b3f38e1",
"sha256": "198j66zyfdky344q09dfdrsb65vpp609g2q3gbzg6irnnww1fv9f"
}
},
{
"path": "com/google/android/gms/play-services-vision-common/17.0.2/play-services-vision-common-17.0.2",
"host": "https://dl.google.com/dl/android/maven2",
@ -6537,6 +6621,44 @@
}
},
{
"path": "net/bytebuddy/byte-buddy-agent/1.10.5/byte-buddy-agent-1.10.5",
"host": "https://repo.maven.apache.org/maven2",
"type": "jar",
"pom": {
"sha1": "ff5249283e247e83ca52318c199a37d07c87a9c6",
"sha256": "05vhcrrhm77r4l66y0zgl20hjhb3hy0a8gsyxyb4af15s8hj44qy"
},
"jar": {
"sha1": "d1c949ee74c3421ffd3d9159c867777ded928448",
"sha256": "0nvym15y0sgnsn1azw521zs55sbwcjrz7fhmvc6q3xayjqq9j319"
}
},
{
"path": "net/bytebuddy/byte-buddy-parent/1.10.5/byte-buddy-parent-1.10.5",
"host": "https://repo.maven.apache.org/maven2",
"type": "pom",
"pom": {
"sha1": "6dcc6df682d0de2a216bc9952960ca83f8e9b1f7",
"sha256": "06n6c00v7mjxglmx2qa9iapyb2v2qirh8njz1n9mh83168c5b6nh"
}
},
{
"path": "net/bytebuddy/byte-buddy/1.10.5/byte-buddy-1.10.5",
"host": "https://repo.maven.apache.org/maven2",
"type": "jar",
"pom": {
"sha1": "f82260b7f4dad0d5560c571be5fcf4bfc7856473",
"sha256": "10lxs0lj0nry0zw0hy1my11imgw5v2gx2zvdpk0dkrv1r2f50hab"
},
"jar": {
"sha1": "d39f2a6c7a3550e03fb12a870e0829b0fa87f036",
"sha256": "1x6isxjm8fszz95s0xr9j81dcxxlwsd9x8hs5ibni7dvf0wn171w"
}
},
{
"path": "net/java/jvnet-parent/1/jvnet-parent-1",
"host": "https://repo.maven.apache.org/maven2",
@ -7501,6 +7623,20 @@
}
},
{
"path": "org/apiguardian/apiguardian-api/1.1.0/apiguardian-api-1.1.0",
"host": "https://repo.maven.apache.org/maven2",
"type": "jar",
"pom": {
"sha1": "41f951c2aff248588037007e8f915467b9971a6f",
"sha256": "0497hss6262ckzx0kxfrb7pp1h1yqicyci0qf4n7pdyrbk5vjid9"
},
"jar": {
"sha1": "fc9dff4bb36d627bdc553de77e1f17efd790876c",
"sha256": "1m7xvh40nadvzffwmlxvdwj7q9hn5gl7b4gp30m7mqg3ibzykam9"
}
},
{
"path": "org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48",
"host": "https://repo.maven.apache.org/maven2",
@ -8757,6 +8893,34 @@
}
},
{
"path": "org/junit/jupiter/junit-jupiter-api/5.5.2/junit-jupiter-api-5.5.2",
"host": "https://repo.maven.apache.org/maven2",
"type": "jar",
"pom": {
"sha1": "9f25eaf1bc6a4fe8c111c64a61231e7525d301f4",
"sha256": "0q4811nzfmvf90js92qrj6ylyc1pxcn2s52v79d1lyjqv205v8bn"
},
"jar": {
"sha1": "6393db7e4c0265152d8fc4ff146633d1a7d36c47",
"sha256": "074vqw62xy6410y4dq0izkh9d114xl4cl04d5708f6cksgdjz6i4"
}
},
{
"path": "org/junit/platform/junit-platform-commons/1.5.2/junit-platform-commons-1.5.2",
"host": "https://repo.maven.apache.org/maven2",
"type": "jar",
"pom": {
"sha1": "0d21e5c12e2555dc54c67174209a2c7dc5d88779",
"sha256": "1nmakw0a2d94av6rmf5wssqp3rwx05j6gyw7ln6aza1jsvgd9l1v"
},
"jar": {
"sha1": "9703df63b65d415b2a027d43ce908c625b3aedce",
"sha256": "041cd0g91dkcldljsbfn1wgbrwxfh4r99rv63bkqa37jq3gsyi7w"
}
},
{
"path": "org/jvnet/staxex/stax-ex/1.7.7/stax-ex-1.7.7",
"host": "https://repo.maven.apache.org/maven2",
@ -8785,6 +8949,30 @@
}
},
{
"path": "org/mockito/mockito-core/3.3.3/mockito-core-3.3.3",
"host": "https://repo.maven.apache.org/maven2",
"type": "jar",
"pom": {
"sha1": "1f5ef203a284440a02e4c9f5ad6c7312c3832603",
"sha256": "04wnqg81hsk40kwvgzjx83a8mb1i9s8y8583v7ks4r0rcf63pwfg"
},
"jar": {
"sha1": "4878395d4e63173f3825e17e5e0690e8054445f1",
"sha256": "0sq38gx7ssavmnljn9wj7dd807ccc86h09d8ddla9ysn0k2lirjb"
}
},
{
"path": "org/objenesis/objenesis-parent/2.6/objenesis-parent-2.6",
"host": "https://repo.maven.apache.org/maven2",
"type": "pom",
"pom": {
"sha1": "cfc0966402e8174fbacd5c5dd355b5815364a4fe",
"sha256": "1aivk380s7n1lzhd9gxvar92ngk4n33cgpk3n00685rw5b5gw99q"
}
},
{
"path": "org/objenesis/objenesis-parent/3.1/objenesis-parent-3.1",
"host": "https://repo.maven.apache.org/maven2",
@ -8795,6 +8983,20 @@
}
},
{
"path": "org/objenesis/objenesis/2.6/objenesis-2.6",
"host": "https://repo.maven.apache.org/maven2",
"type": "jar",
"pom": {
"sha1": "b6d1f689e0d2b2d96b0730fad7b5d96902bf64d8",
"sha256": "1wfkl6z4i55ga8bkyd8kbr2axxfyiczm0xghj6yz2bf6kn80f4sc"
},
"jar": {
"sha1": "639033469776fd37c08358c6b92a4761feb2af4b",
"sha256": "13bhn2p9k0sxy82l1mvvb97dd8k76h6fypxag4yayl62zdl865jy"
}
},
{
"path": "org/objenesis/objenesis/3.1/objenesis-3.1",
"host": "https://repo.maven.apache.org/maven2",
@ -8809,6 +9011,20 @@
}
},
{
"path": "org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0",
"host": "https://repo.maven.apache.org/maven2",
"type": "jar",
"pom": {
"sha1": "b5c66f49b69c36797c1fb7f4ec57776f261303ad",
"sha256": "157r6rcl0ri2w172npfsfyrdynq23wjcjx7cpl1qizy12qc6fvm9"
},
"jar": {
"sha1": "28c11eb91f9b6d8e200631d46e20a7f407f2a046",
"sha256": "1wka53y7j9188i89y92azlc4qq660pd64fzgh7xpdncq13k2v0aq"
}
},
{
"path": "org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3",
"host": "https://repo.maven.apache.org/maven2",

View File

@ -91,6 +91,7 @@ com.android.databinding:baseLibrary:3.5.3
com.android.databinding:compilerCommon:1.0-rc5
com.android.databinding:compilerCommon:3.0.0
com.android.databinding:compilerCommon:3.0.1
com.android.installreferrer:installreferrer:1.1.2
com.android.tools.analytics-library:crash:26.2.1
com.android.tools.analytics-library:crash:26.3.1
com.android.tools.analytics-library:crash:26.5.3
@ -307,12 +308,17 @@ com.googlecode.json-simple:json-simple:1.1
com.googlecode.juniversalchardet:juniversalchardet:1.0.3
com.google.android.gms:play-services-auth-base:16.0.0
com.google.android.gms:play-services-basement:16.1.0
com.google.android.gms:play-services-basement:17.0.0
com.google.android.gms:play-services-base:16.0.1
com.google.android.gms:play-services-base:17.0.0
com.google.android.gms:play-services-clearcut:16.0.0
com.google.android.gms:play-services-flags:16.0.1
com.google.android.gms:play-services-iid:17.0.0
com.google.android.gms:play-services-phenotype:16.0.0
com.google.android.gms:play-services-stats:16.0.1
com.google.android.gms:play-services-stats:17.0.0
com.google.android.gms:play-services-tasks:16.0.1
com.google.android.gms:play-services-tasks:17.0.0
com.google.android.gms:play-services-vision-common:17.0.2
com.google.android.gms:play-services-vision-image-label:17.0.2
com.google.android.gms:play-services-vision:17.0.2
@ -365,6 +371,8 @@ javax.inject:javax.inject:1
javax.xml.bind:jaxb-api:2.2.12-b140109.1041
junit:junit:4.12
me.zhanghai.android.materialprogressbar:library:1.4.2
net.bytebuddy:byte-buddy-agent:1.10.5
net.bytebuddy:byte-buddy:1.10.5
net.sf.jopt-simple:jopt-simple:4.9
net.sf.kxml:kxml2:2.3.0
net.sf.proguard:proguard-base:5.1
@ -397,6 +405,7 @@ org.apache.httpcomponents:httpcore:4.4.10
org.apache.httpcomponents:httpmime:4.1
org.apache.httpcomponents:httpmime:4.5.2
org.apache.httpcomponents:httpmime:4.5.6
org.apiguardian:apiguardian-api:1.1.0
org.bouncycastle:bcpkix-jdk15on:1.48
org.bouncycastle:bcpkix-jdk15on:1.56
org.bouncycastle:bcprov-jdk15on:1.48
@ -455,7 +464,12 @@ org.jetbrains.kotlin:kotlin-stdlib:1.3.50
org.jetbrains.kotlin:kotlin-util-io:1.3.50
org.jetbrains.trove4j:trove4j:20160824
org.jetbrains:annotations:13.0
org.junit.jupiter:junit-jupiter-api:5.5.2
org.junit.platform:junit-platform-commons:1.5.2
org.jvnet.staxex:stax-ex:1.7.7
org.mockito:mockito-core:3.3.3
org.objenesis:objenesis:2.6
org.opentest4j:opentest4j:1.2.0
org.ow2.asm:asm-analysis:5.0.3
org.ow2.asm:asm-analysis:5.1
org.ow2.asm:asm-analysis:6.0

View File

@ -91,6 +91,7 @@ https://dl.google.com/dl/android/maven2/com/android/databinding/baseLibrary/3.3.
https://dl.google.com/dl/android/maven2/com/android/databinding/baseLibrary/3.5.3/baseLibrary-3.5.3.pom
https://dl.google.com/dl/android/maven2/com/android/databinding/compilerCommon/3.0.0/compilerCommon-3.0.0.pom
https://dl.google.com/dl/android/maven2/com/android/databinding/compilerCommon/3.0.1/compilerCommon-3.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/installreferrer/installreferrer/1.1.2/installreferrer-1.1.2.pom
https://dl.google.com/dl/android/maven2/com/android/support/animated-vector-drawable/26.0.2/animated-vector-drawable-26.0.2.pom
https://dl.google.com/dl/android/maven2/com/android/support/animated-vector-drawable/27.0.1/animated-vector-drawable-27.0.1.pom
https://dl.google.com/dl/android/maven2/com/android/support/appcompat-v7/26.0.2/appcompat-v7-26.0.2.pom
@ -249,12 +250,17 @@ https://dl.google.com/dl/android/maven2/com/android/tools/sdk-common/26.5.3/sdk-
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-auth-base/16.0.0/play-services-auth-base-16.0.0.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-basement/16.0.1/play-services-basement-16.0.1.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-basement/16.1.0/play-services-basement-16.1.0.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-basement/17.0.0/play-services-basement-17.0.0.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-base/16.0.1/play-services-base-16.0.1.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-base/17.0.0/play-services-base-17.0.0.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-clearcut/16.0.0/play-services-clearcut-16.0.0.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-flags/16.0.1/play-services-flags-16.0.1.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-iid/17.0.0/play-services-iid-17.0.0.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-phenotype/16.0.0/play-services-phenotype-16.0.0.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-stats/16.0.1/play-services-stats-16.0.1.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-stats/17.0.0/play-services-stats-17.0.0.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-tasks/16.0.1/play-services-tasks-16.0.1.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-tasks/17.0.0/play-services-tasks-17.0.0.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-vision-common/17.0.2/play-services-vision-common-17.0.2.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-vision-image-label/17.0.2/play-services-vision-image-label-17.0.2.pom
https://dl.google.com/dl/android/maven2/com/google/android/gms/play-services-vision/17.0.2/play-services-vision-17.0.2.pom
@ -477,6 +483,9 @@ https://repo.maven.apache.org/maven2/javax/xml/stream/stax-api/1.0-2/stax-api-1.
https://repo.maven.apache.org/maven2/junit/junit/4.12/junit-4.12.pom
https://repo.maven.apache.org/maven2/junit/junit/4.13/junit-4.13.pom
https://repo.maven.apache.org/maven2/me/zhanghai/android/materialprogressbar/library/1.4.2/library-1.4.2.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-agent/1.10.5/byte-buddy-agent-1.10.5.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy-parent/1.10.5/byte-buddy-parent-1.10.5.pom
https://repo.maven.apache.org/maven2/net/bytebuddy/byte-buddy/1.10.5/byte-buddy-1.10.5.pom
https://repo.maven.apache.org/maven2/net/java/jvnet-parent/1/jvnet-parent-1.pom
https://repo.maven.apache.org/maven2/net/java/jvnet-parent/3/jvnet-parent-3.pom
https://repo.maven.apache.org/maven2/net/java/jvnet-parent/4/jvnet-parent-4.pom
@ -559,6 +568,7 @@ https://repo.maven.apache.org/maven2/org/apache/httpcomponents/httpmime/4.5.2/ht
https://repo.maven.apache.org/maven2/org/apache/httpcomponents/httpmime/4.5.6/httpmime-4.5.6.pom
https://repo.maven.apache.org/maven2/org/apache/httpcomponents/project/4.1.1/project-4.1.1.pom
https://repo.maven.apache.org/maven2/org/apache/httpcomponents/project/7/project-7.pom
https://repo.maven.apache.org/maven2/org/apiguardian/apiguardian-api/1.1.0/apiguardian-api-1.1.0.pom
https://repo.maven.apache.org/maven2/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48.pom
https://repo.maven.apache.org/maven2/org/bouncycastle/bcpkix-jdk15on/1.56/bcpkix-jdk15on-1.56.pom
https://repo.maven.apache.org/maven2/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.pom
@ -653,10 +663,16 @@ https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.3.50/k
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.3.70/kotlin-stdlib-1.3.70.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.3.72/kotlin-stdlib-1.3.72.pom
https://repo.maven.apache.org/maven2/org/jetbrains/kotlin/kotlin-util-io/1.3.50/kotlin-util-io-1.3.50.pom
https://repo.maven.apache.org/maven2/org/junit/jupiter/junit-jupiter-api/5.5.2/junit-jupiter-api-5.5.2.pom
https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-commons/1.5.2/junit-platform-commons-1.5.2.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/1.7.7/stax-ex-1.7.7.pom
https://repo.maven.apache.org/maven2/org/jvnet/staxex/stax-ex/2.0.0-M2/stax-ex-2.0.0-M2.pom
https://repo.maven.apache.org/maven2/org/mockito/mockito-core/3.3.3/mockito-core-3.3.3.pom
https://repo.maven.apache.org/maven2/org/objenesis/objenesis-parent/2.6/objenesis-parent-2.6.pom
https://repo.maven.apache.org/maven2/org/objenesis/objenesis-parent/3.1/objenesis-parent-3.1.pom
https://repo.maven.apache.org/maven2/org/objenesis/objenesis/2.6/objenesis-2.6.pom
https://repo.maven.apache.org/maven2/org/objenesis/objenesis/3.1/objenesis-3.1.pom
https://repo.maven.apache.org/maven2/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.pom
https://repo.maven.apache.org/maven2/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3.pom
https://repo.maven.apache.org/maven2/org/ow2/asm/asm-analysis/5.1/asm-analysis-5.1.pom
https://repo.maven.apache.org/maven2/org/ow2/asm/asm-analysis/6.0/asm-analysis-6.0.pom

View File

@ -1,6 +1,7 @@
app
react-native-background-timer
react-native-camera
react-native-community_async-storage
react-native-community_audio-toolkit
react-native-community_cameraroll
react-native-community_clipboard
@ -9,6 +10,7 @@ react-native-community_netinfo
react-native-community_slider
react-native-config
react-native-dark-mode
react-native-device-info
react-native-dialogs
react-native-fs
react-native-gesture-handler

View File

@ -10,6 +10,7 @@
"app:android": "react-native run-android"
},
"dependencies": {
"@react-native-community/async-storage": "^1.11.0",
"@react-native-community/audio-toolkit": "git+https://github.com/tbenr/react-native-audio-toolkit.git#v2.0.3-status-v6",
"@react-native-community/cameraroll": "^1.6.1",
"@react-native-community/clipboard": "^1.2.2",
@ -37,6 +38,7 @@
"react-native-camera": "^3.3.3",
"react-native-config": "git+https://github.com/status-im/react-native-config.git#v0.11.2-3-status",
"react-native-dark-mode": "^0.2.2",
"react-native-device-info": "^5.6.1",
"react-native-dialogs": "^1.0.4",
"react-native-fetch-polyfill": "^1.1.2",
"react-native-fs": "^2.14.1",

View File

@ -183,6 +183,13 @@
:addEventListener (fn []),
:removeEventListener (fn [])}}))
(def react-native-device-info
#js {:getInstallReferrer identity})
(def react-native-push-notification
#js {:localNotification identity
:requestPermission identity})
;; Update i18n_resources.cljs
(defn mock [module]
(case module
@ -210,6 +217,8 @@
"react-native-mail" react-native-mail
"react-native-image-resizer" image-resizer
"react-native-haptic-feedback" react-native-haptic-feedback
"react-native-device-info" react-native-device-info
"react-native-push-notification" react-native-push-notification
"./fleets.js" default-fleets
"./chats.js" default-chats
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))

View File

@ -22,6 +22,7 @@
:secondary {:color (:text-02 @colors/theme)}
:secondary-inverse {:color (:text-03 @colors/theme)}
:link {:color (:text-04 @colors/theme)}
:inverse {:color (:text-05 @colors/theme)}
:positive {:color (:positive-01 @colors/theme)}
:negative {:color (:negative-01 @colors/theme)}
:inherit nil)

View File

@ -43,7 +43,8 @@
:icon-05 "rgba(255,255,255,1)" ; Icons inverse on accent background
:shadow-01 "rgba(0,9,26,0.12)" ; Main shadow color
:backdrop "rgba(0,0,0,0.4)" ; Backdrop for modals and bottom sheet
})
:border-01 "rgba(238,242,245,1)"
:border-02 "rgba(67, 96, 223, 0.1)"})
(def dark-theme
{:positive-01 "rgba(68,208,88,1)"
@ -68,7 +69,9 @@
:icon-04 "rgba(97,119,229,1)"
:icon-05 "rgba(20,20,20,1)"
:shadow-01 "rgba(0,0,0,0.75)"
:backdrop "rgba(0,0,0,0.4)"})
:backdrop "rgba(0,0,0,0.4)"
:border-01 "rgba(37,37,40,1)"
:border-02 "rgba(97,119,229,0.1)"})
(def theme (reagent/atom light-theme))

View File

@ -0,0 +1,29 @@
(ns status-im.acquisition.advertiser
(:require [status-im.utils.fx :as fx]
[status-im.popover.core :as popover]
[status-im.ethereum.core :as ethereum]
[status-im.acquisition.gateway :as gateway]
[status-im.acquisition.claim :as claim]
[status-im.acquisition.persistance :as persistence]))
(fx/defn start-acquisition
[cofx _]
(popover/show-popover cofx
{:prevent-closing? true
:view :accept-invite}))
(fx/defn advertiser-decide
{:events [::decision]}
[{:keys [db] :as cofx} decision]
(let [referral (get-in db [:acquisition :referrer])
payload {:chat_key (get-in db [:multiaccount :public-key])
:address (ethereum/default-address db)
:invite_code referral}]
(fx/merge cofx
(if (= decision :accept)
(gateway/handle-acquisition {:message payload
:method "PATCH"
:url (gateway/get-url :clicks referral)
:on-success ::claim/success-starter-pack-claim})
{::persistence/set-referrer-state :declined})
(popover/hide-popover))))

View File

@ -0,0 +1,36 @@
(ns status-im.acquisition.chat
(:require [re-frame.core :as re-frame]
[status-im.utils.fx :as fx]
[status-im.acquisition.claim :as claim]
[status-im.ethereum.core :as ethereum]
[status-im.acquisition.persistance :as persistence]
[status-im.acquisition.gateway :as gateway]
[status-im.chat.models :as chat]))
(fx/defn start-acquisition
[{:keys [db] :as cofx} {:keys [key] :as referrer}]
{:db (assoc-in db [:acquisition :chat-referrer key] referrer)
::persistence/chat-initialized? (fn [state]
(when-not (= "initialized" state)
(re-frame/dispatch [::start-chat referrer])))})
(fx/defn start-chat
{:events [::start-chat]}
[cofx {:keys [key] :as referrer}]
(fx/merge cofx
{::persistence/chat-initalized! true}
(chat/start-chat key)))
(fx/defn accept-pack
{:events [::accept-pack]}
[{:keys [db] :as cofx} decision]
(let [referral (get-in db [:acquisition :referrer])
payload {:chat_key (get-in db [:multiaccount :public-key])
:address (ethereum/default-address db)
:invite_code referral}]
(fx/merge cofx
{:db (update db :acquisition dissoc :chat-referrer)}
(gateway/handle-acquisition {:message payload
:method "PATCH"
:url (gateway/get-url :clicks referral)
:on-success ::claim/success-starter-pack-claim}))))

View File

@ -0,0 +1,31 @@
(ns status-im.acquisition.claim
(:require [status-im.i18n :as i18n]
[status-im.utils.fx :as fx]
[status-im.ethereum.transactions.core :as transaction]
[status-im.notifications.core :as notifications]
[status-im.acquisition.persistance :as persistence]))
(fx/defn success-tx-received
{:events [::success-tx-received]}
[_]
{::persistence/set-referrer-state :claimed
::notifications/local-notification {:title (i18n/label :t/starter-pack-received)
:message (i18n/label :t/starter-pack-received-description)}})
(fx/defn add-tx-watcher
[cofx tx]
(transaction/watch-transaction cofx
tx
{:trigger-fn (constantly true)
:on-trigger
(fn []
{:dispatch [::success-tx-received]})}))
(fx/defn success-starter-pack-claim
{:events [::success-starter-pack-claim]}
[cofx {:keys [tx]}]
(fx/merge cofx
{::persistence/set-watch-tx tx
::persistence/set-referrer-state :accepted}
(add-tx-watcher tx)
(notifications/request-permission)))

View File

@ -0,0 +1,95 @@
(ns status-im.acquisition.core
(:require [re-frame.core :as re-frame]
[status-im.utils.fx :as fx]
[status-im.acquisition.chat :as chat]
[status-im.acquisition.advertiser :as advertiser]
[status-im.acquisition.persistance :as persistence]
[status-im.acquisition.gateway :as gateway]
[status-im.acquisition.install-referrer :as install-referrer]))
(def not-found-code "notfound.click_id")
(def advertiser-type "advertiser")
(def chat-type "chat")
(fx/defn handle-registration
[cofx {:keys [message on-success]}]
(gateway/handle-acquisition cofx
{:message message
:on-success on-success
:method "POST"
:url (gateway/get-url :registrations nil)}))
(re-frame/reg-fx
::get-referrer
(fn []
(persistence/get-referrer-flow-state
(fn [^js data]
(install-referrer/get-referrer
(fn [install-referrer]
(persistence/set-referrer install-referrer)
(when (not= install-referrer "unknown")
(when-let [referrer (install-referrer/parse-referrer install-referrer)]
(re-frame/dispatch [::has-referrer data referrer])))))))))
(re-frame/reg-fx
::check-referrer
(fn [external-referrer]
(persistence/get-referrer-flow-state
(fn [^js data]
(if external-referrer
(re-frame/dispatch [::has-referrer data external-referrer])
(persistence/get-referrer
(fn [install-referrer]
(when (not= install-referrer "unknown")
(when-let [referrer (install-referrer/parse-referrer install-referrer)]
(re-frame/dispatch [::has-referrer data referrer]))))))))))
(fx/defn referrer-registered
{:events [::referrer-registered]}
[{:keys [db] :as cofx} referrer {:keys [type attributed] :as referrer-meta}]
(when-not attributed
(fx/merge cofx
{:db (assoc-in db [:acquisition :metadata] referrer-meta)}
(cond
(= type advertiser-type)
(advertiser/start-acquisition referrer-meta)
(= type chat-type)
(chat/start-acquisition referrer-meta)))))
(fx/defn outdated-referrer
{:events [::outdated-referrer]}
[_ _]
{::persistence/set-referrer-state :outdated})
(fx/defn has-referrer
{:events [::has-referrer]}
[{:keys [db] :as cofx} flow-state referrer]
(when referrer
(fx/merge cofx
{:db (-> db
(assoc-in [:acquisition :referrer] referrer)
(assoc-in [:acquisition :flow-state] flow-state))}
(cond
(nil? flow-state)
(gateway/get-referrer
referrer
(fn [resp] [::referrer-registered referrer resp])
(fn [{:keys [code]}] (= code not-found-code))
(fn [resp] [::outdated-referrer resp]))
(= flow-state (:accepted persistence/referrer-state))
(fn [_]
{::persistence/check-tx-state (fn [tx]
(when-not (nil? tx)
(re-frame/dispatch [::add-tx-watcher tx])))})))))
(fx/defn create
{}
[_]
{::get-referrer nil})
(fx/defn login
{}
[_]
{::check-referrer nil})

View File

@ -0,0 +1,64 @@
(ns status-im.acquisition.gateway
(:require [re-frame.core :as re-frame]
[status-im.utils.fx :as fx]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.waku.core :as waku]
[status-im.utils.types :as types]))
(def acquisition-gateway "https://test-referral.status.im")
(def acquisition-routes {:clicks (str acquisition-gateway "/clicks")
:registrations (str acquisition-gateway "/registrations")})
(defn get-url [type referral]
(if (= type :clicks)
(str (get acquisition-routes :clicks) "/" referral)
(get acquisition-routes :registrations)))
(fx/defn handle-error
{:events [::on-error]}
[_ error]
{:utils/show-popup {:title "Request failed"
:content (str error)}})
(fx/defn handle-acquisition
{:events [::handle-acquisition]}
[{:keys [db] :as cofx} {:keys [message on-success method url]}]
(let [msg (types/clj->json message)]
{::json-rpc/call [{:method (json-rpc/call-ext-method (waku/enabled? cofx) "signMessageWithChatKey")
:params [msg]
:on-error #(re-frame/dispatch [::on-error "Could not sign message"])
:on-success #(re-frame/dispatch [::call-acquisition-gateway
{:chat-key (get-in db [:multiaccount :public-key])
:message msg
:method method
:url url
:on-success on-success} %])}]}))
(fx/defn call-acquisition-gateway
{:events [::call-acquisition-gateway]}
[cofx
{:keys [chat-key message on-success type url method] :as kek}
sig]
(let [payload {:chat_key chat-key
:msg message
:sig sig
:version 2}]
{:http-post {:url url
:opts {:headers {"Content-Type" "application/json"}
:method method}
:data (types/clj->json payload)
:success-event-creator (fn [response]
[on-success (types/json->clj (get response :response-body))])
:failure-event-creator (fn [error]
[::on-error (:error (types/json->clj (get error :response-body)))])}}))
(fx/defn get-referrer
[cofx referrer on-success handled-error handle-error]
{:http-get {:url (get-url :clicks referrer)
:success-event-creator (fn [response]
(on-success (types/json->clj response)))
:failure-event-creator (fn [response]
(let [error (types/json->clj response)]
(if (handled-error error)
(handle-error error)
[::on-error (:error error)])))}})

View File

@ -0,0 +1,34 @@
(ns status-im.acquisition.install-referrer
(:require [taoensso.timbre :as log]
[clojure.string :as cstr]
["react-native-device-info" :refer [getInstallReferrer]]))
(defn- split-param [param]
(->
(cstr/split param #"=")
(concat (repeat ""))
(->>
(take 2))))
(defn- url-decode
[string]
(some-> string str (cstr/replace #"\+" "%20") (js/decodeURIComponent)))
(defn- query->map
[qstr]
(when-not (cstr/blank? qstr)
(some->> (cstr/split qstr #"&")
seq
(mapcat split-param)
(map url-decode)
(apply hash-map))))
(defn parse-referrer
"Google return query params for referral with all utm tags"
[referrer]
(-> referrer query->map (get "referrer")))
(defn get-referrer [cb]
(-> (getInstallReferrer)
(.then cb)
(.catch #(log/error "[install-referrer]" %))))

View File

@ -0,0 +1,82 @@
(ns status-im.acquisition.persistance
(:require [re-frame.core :as re-frame]
[taoensso.timbre :as log]
["@react-native-community/async-storage" :default async-storage]))
(def chat-initialized-key "acquisition-chat-initialized")
(def referrer-flow-state-key "acquisition-referrer-flow-state")
(def tx-store-key "acquisition-watch-tx")
(def referrer-key "acquisition-referrer")
(def referrer-state {:accepted "accepted"
:declined "declined"
:claimed "claimed"
:outdated "outdated"})
(re-frame/reg-fx
::set-referrer-state
(fn [decision]
(-> ^js async-storage
(.setItem referrer-flow-state-key (get referrer-state decision))
(.then (fn []
(re-frame/dispatch [:set-in [:acquisition :flow-state] decision])))
(.catch (fn [error]
(log/error "[async-storage]" error))))))
(defn get-referrer-flow-state [on-success]
(-> ^js async-storage
(.getItem referrer-flow-state-key)
(.then (fn [^js data]
(on-success data)))
(.catch (fn [error]
(log/error "[async-storage]" error)))))
(re-frame/reg-fx
::check-tx-state
(fn [on-success]
(-> ^js async-storage
(.getItem tx-store-key)
(.then (fn [^js tx]
(on-success tx)))
(.catch (fn [error]
(log/error "[async-storage]" error))))))
(re-frame/reg-fx
::set-watch-tx
(fn [tx]
(-> ^js async-storage
(.setItem tx-store-key tx)
(.catch (fn [error]
(log/error "[async-storage]" error))))))
(re-frame/reg-fx
::chat-initalized!
(fn []
(-> ^js async-storage
(.setItem chat-initialized-key "initialized")
(.catch (fn [error]
(log/error "[async-storage]" error))))))
(re-frame/reg-fx
::chat-initialized?
(fn [on-success]
(-> ^js async-storage
(.getItem chat-initialized-key)
(.then (fn [^js data]
(on-success data)))
(.catch (fn [error]
(log/error "[async-storage]" error))))))
(defn set-referrer [referrer]
(-> ^js async-storage
(.setItem referrer-key referrer)
(.catch (fn [error]
(log/error "[async-storage]" error)))))
(defn get-referrer [on-success]
(-> ^js async-storage
(.getItem referrer-key)
(.then (fn [^js data]
(on-success data)))
(.catch (fn [error]
(log/error "[async-storage]" error)))))

View File

@ -246,7 +246,7 @@
(fx/defn start-chat
"Start a chat, making sure it exists"
[{:keys [db] :as cofx} chat-id _]
[{:keys [db] :as cofx} chat-id]
;; don't allow to open chat with yourself
(when (not= (multiaccounts.model/current-public-key cofx) chat-id)
(fx/merge cofx

View File

@ -15,7 +15,10 @@
:mainnet "0x12824271339304d3a9f7e096e62a2a7e73b4a7e7"}
:status/sticker-pack
{:testnet "0xf852198d0385c4b871e0b91804ecd47c6ba97351"
:mainnet "0x110101156e8F0743948B2A61aFcf3994A8Fb172e"}})
:mainnet "0x110101156e8F0743948B2A61aFcf3994A8Fb172e"}
:status/acquisition
{:rinkeby "0x719C016d16ff0396274d488Efc4D8aEaAA126b48"
:mainnet "0x81142267f927bffc6dba200a928c376fbf6675a8"}})
(defn get-address
[db contract]

View File

@ -88,6 +88,7 @@
"shhext_declineRequestTransaction" {}
"shhext_sendTransaction" {}
"shhext_acceptRequestTransaction" {}
"shhext_signMessageWithChatKey" {}
"wakuext_post" {}
"wakuext_startMessenger" {}
"wakuext_sendPairInstallation" {}
@ -142,6 +143,7 @@
"wakuext_declineRequestTransaction" {}
"wakuext_sendTransaction" {}
"wakuext_acceptRequestTransaction" {}
"wakuext_signMessageWithChatKey" {}
"status_chats" {}
"wallet_getTransfers" {}
"wallet_getTokensBalances" {}

View File

@ -774,7 +774,11 @@
{:symbol :WIBB
:name "WIBB"
:address "0x7d4ccf6af2f0fdad48ee7958bcc28bdef7b732c7"
:decimals 18}])
:decimals 18}
{:name "Status Test Token"
:symbol :STT
:decimals 18
:address "0x43d5adc3b49130a575ae6e4b00dfa4bc55c71621"}])
:xdai
(resolve-icons :xdai
@ -806,3 +810,7 @@
(= (:symbol native-coin) symbol))
native-coin
(symbol->token all-tokens symbol))))
(defn symbol->icon [sym]
(:icon (first (filter #(= sym (:symbol %))
(:mainnet all-default-tokens)))))

View File

@ -482,8 +482,8 @@
(handlers/register-handler-fx
:chat.ui/start-chat
(fn [cofx [_ contact-id opts]]
(chat/start-chat cofx contact-id opts)))
(fn [cofx [_ contact-id]]
(chat/start-chat cofx contact-id)))
(handlers/register-handler-fx
:chat.ui/start-public-chat
@ -857,7 +857,7 @@
:contact.ui/send-message-pressed
[(re-frame/inject-cofx :random-id-generator)]
(fn [cofx [_ {:keys [public-key]}]]
(chat/start-chat cofx public-key {:navigation-reset? true})))
(chat/start-chat cofx public-key)))
(handlers/register-handler-fx
:contact.ui/contact-code-submitted
@ -867,7 +867,7 @@
(fx/merge cofx
#(if new-contact?
(contact/add-contact % public-key)
(chat/start-chat % public-key {:navigation-reset? true}))
(chat/start-chat % public-key))
#(when new-contact?
(navigation/navigate-back %))
#(when ens-name
@ -1103,7 +1103,7 @@
(assert public-key)
(fx/merge cofx
(navigation/navigate-back)
(chat/start-chat public-key nil)
(chat/start-chat public-key)
;; TODO send
#_(commands.sending/send public-key
request-command

View File

@ -4,7 +4,8 @@
[status-im.keycard.card :as card]
[status-im.native-module.core :as status]
[status-im.utils.platform :as platform]
["react-native" :refer (AsyncStorage BackHandler)]))
["react-native" :refer (BackHandler)]
["@react-native-community/async-storage" :default AsyncStorage]))
(re-frame/reg-fx
:keycard/get-application-info

View File

@ -28,6 +28,7 @@
[status-im.utils.utils :as utils]
[status-im.wallet.core :as wallet]
[status-im.wallet.prices :as prices]
[status-im.acquisition.core :as acquisition]
[taoensso.timbre :as log]))
(re-frame/reg-fx
@ -256,7 +257,11 @@
(fx/defn multiaccount-login-success
[{:keys [db now] :as cofx}]
(let [{:keys [key-uid password save-password? creating?]} (:multiaccounts/login db)
multiaccounts (:multiaccounts/multiaccounts db)
recovering? (get-in db [:intro-wizard :recovering?])
first-account? (and creating?
(not recovering?)
(empty? multiaccounts))
login-only? (not (or creating?
recovering?
(keycard-setup? cofx)))
@ -282,6 +287,9 @@
(if login-only?
(login-only-events key-uid password save-password?)
(create-only-events))
(if first-account?
(acquisition/create)
(acquisition/login))
(when recovering?
(navigation/navigate-to-cofx :tabs {:screen :chat-stack
:params {:screen :home}})))))

View File

@ -1,7 +1,25 @@
(ns status-im.notifications.core
(:require [re-frame.core :as re-frame]
[taoensso.timbre :as log]
[status-im.utils.fx :as fx]
[status-im.native-module.core :as status]))
;; FIXME: Repalce with request permission from audio messages PR lib
(re-frame/reg-fx
::request-permission
identity)
(fx/defn request-permission
{:events [::request-permission]}
[_]
{::request-permission true})
(re-frame/reg-fx
::local-notification
(fn [{:keys [title message]}]
(log/info {:title title
:message message})))
(re-frame/reg-fx
::enable
(fn [_]

View File

@ -0,0 +1,88 @@
(ns status-im.ui.components.invite.advertiser
(:require [re-frame.core :as re-frame]
[quo.react-native :as rn]
[quo.core :as quo]
[status-im.i18n :as i18n]
[status-im.ui.components.invite.events :as invite]
[quo.design-system.colors :as colors]
[status-im.ui.components.invite.utils :as utils]
[status-im.acquisition.advertiser :as advertiser]))
(defn perk [{name :name
{source :source} :icon} value]
[rn/view {:style {:flex-direction :row
:align-items :center
:padding-vertical 4}}
[rn/view {:style {:flex-direction :row}}
[rn/image {:source (if (fn? source) (source) source)
:style {:width 20
:height 20
:margin-right 8}}]
[quo/text {:size :small
:weight :medium}
(str value " ")]
[quo/text {:size :small
:weight :medium}
name]]])
(defn token-icon-style [idx]
{:align-items :center
:shadow-radius 16
:shadow-opacity 1
:shadow-color (:shadow-01 @colors/theme)
:shadow-offset {:width 0 :height 4}
:width 40
:height 40
:border-radius 20
:left (* idx -20)})
(defn accept-popover []
(fn []
(let [pack @(re-frame/subscribe [::invite/starter-pack])
tokens (utils/transform-tokens pack)]
[rn/view {:style {:align-items :center
:padding-vertical 16
:padding-horizontal 16}}
[rn/view {:flex-direction :row
:height 40
:left 10}
(for [[{name :name
{source :source} :icon} _ i] tokens]
^{:key name}
[rn/view {:style (token-icon-style i)}
[rn/image {:source (if (fn? source) (source) source)
:style {:width 40
:height 40}}]])]
[rn/view {:style {:padding 8}}
[quo/text {:style {:margin-bottom 8}
:align :center
:size :x-large}
(i18n/label :t/advertiser-starter-pack-title)]
[quo/text {:align :center}
(i18n/label :t/advertiser-starter-pack-description)]]
[rn/view {:style {:border-radius 8
:border-width 1
:border-color (:ui-02 @colors/theme)
:width "100%"
:margin-vertical 8
:padding-vertical 8
:padding-horizontal 12}}
(for [[k v] tokens]
^{:key (:name k)}
[perk k v])]
[rn/view {:style {:margin-vertical 8}}
[quo/button {:on-press #(re-frame/dispatch [::advertiser/decision :accept])}
(i18n/label :t/advertiser-starter-pack-accept)]]
[quo/button {:type :secondary
:on-press #(re-frame/dispatch [::advertiser/decision :decline])}
(i18n/label :t/advertiser-starter-pack-decline)]
[rn/view {:padding-vertical 8}
[quo/text {:color :secondary
:align :center
:size :small}
(i18n/label :t/invite-privacy-policy1)]
[quo/text {:color :link
:align :center
:size :small
:on-press #(re-frame/dispatch [::invite/terms-and-conditions])}
(i18n/label :t/invite-privacy-policy2)]]])))

View File

@ -0,0 +1,113 @@
(ns status-im.ui.components.invite.chat
(:require [clojure.string :as cstr]
[quo.design-system.colors :as colors]
[quo.design-system.spacing :as spacing]
[quo.react-native :as rn]
[re-frame.core :as re-frame]
[status-im.ui.components.invite.utils :as utils]
[quo.core :as quo]
[status-im.acquisition.chat :as acquisition]
[status-im.ui.components.invite.events :as invite]
[status-im.i18n :as i18n]
[status-im.ui.components.invite.style :as styles]))
(defn messages-wrapper []
(:small spacing/padding-vertical))
(defn message-wrapper []
{:padding-right 96
:padding-left 8
:flex-direction :row})
(defn message-view []
{:border-top-left-radius 16
:border-top-right-radius 16
:border-bottom-right-radius 16
:border-radius 8
:border-bottom-left-radius 4
:border-width 1
:margin-bottom 4
:border-color (:border-01 @colors/theme)})
(defn message-text []
(merge (:small spacing/padding-horizontal)
{:padding-vertical 6}))
(defn author-text []
(merge (:small spacing/padding-horizontal)
{:padding-top (:tiny spacing/spacing)
:paddingbottom (:x-tiny spacing/spacing)}))
(defn button-message []
{:flex-direction :row
:justify-content :center
:align-items :center})
(defn starter-pack-style []
(merge (:small spacing/padding-horizontal)
(:small spacing/padding-vertical)
{:background-color (:interactive-02 @colors/theme)
:flex-direction :row
:border-bottom-width 1
:border-top-width 1
:border-color (:border-02 @colors/theme)}))
(defn starter-pack []
(let [pack @(re-frame/subscribe [::invite/starter-pack])
tokens (utils/transform-tokens pack)
reward-text (cstr/join ", " (map (comp name :symbol first) tokens))]
[rn/view {:style (starter-pack-style)}
[rn/view {:style {:padding-right 16}}
(doall
(for [[{name :name
{source :source} :icon} _ idx] tokens]
^{:key name}
[rn/view {:style (styles/reward-token-icon idx)}
[rn/image {:source (if (fn? source) (source) source)
:style {:width 40
:height 40}}]]))]
[rn/view {:style styles/reward-description}
[quo/text {:weight :medium}
(i18n/label :t/invite-chat-starter-pack)]
[quo/text {} reward-text]]]))
(defn render-message [{:keys [content]}]
[rn/view {:style (message-wrapper)}
[rn/view {:style (message-view)}
(for [{:keys [type value]} content]
(case type
:text [rn/view {:style (message-text)}
[quo/text value]]
:pack [starter-pack]
:author [rn/view {:style (author-text)}
[quo/text {:color :secondary}
value]]
:button [rn/view {:style (button-message)}
value]
nil))]])
(defn reward-messages []
(let [pending-invite @(re-frame/subscribe [::invite/pending-chat-invite])
messages [{:content [{:type :text
:value "👋"}]}
{:content [{:type :author
:value (i18n/label :t/invite-chat-name)}
{:type :text
:value (i18n/label :t/invite-chat-intro)}
{:type :pack}
{:type :button
:value [quo/button {:type :secondary
:on-press #(re-frame/dispatch [::acquisition/accept-pack])}
(i18n/label :t/invite-chat-accept)]}]}
{:content [{:type :text
:value (i18n/label :t/invite-chat-rule)}]}
{:content [{:type :text
:value [:<>
(i18n/label :t/invite-privacy-policy1) " "
[quo/text {:color :link
:on-press #(re-frame/dispatch [::invite/terms-and-conditions])}
(i18n/label :t/invite-privacy-policy2)]]}]}]]
(when pending-invite
[rn/view {:style (messages-wrapper)}
(for [message messages]
[render-message message])])))

View File

@ -0,0 +1,180 @@
(ns status-im.ui.components.invite.events
(:require [re-frame.core :as re-frame]
[reagent.ratom :refer [make-reaction]]
[status-im.utils.fx :as fx]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.ethereum.contracts :as contracts]
[status-im.ethereum.core :as ethereum]
[status-im.ui.components.react :as react]
[status-im.navigation :as navigation]
[status-im.utils.universal-links.core :as universal-links]
[status-im.acquisition.core :as acquisition]
[status-im.utils.money :as money]))
(def privacy-policy-link "https://get.status.im")
(re-frame/reg-fx
::share
(fn [content]
(.share ^js react/sharing (clj->js content))))
(fx/defn share-link
{:events [::share-link]}
[{:keys [db]} response]
(let [{:keys [public-key preferred-name]} (get db :multiaccount)
invite-id (get response :invite_code)
profile-link (universal-links/generate-link :user :external
(or preferred-name public-key))
share-link (cond-> profile-link
invite-id
(str "?invite=" invite-id))
message (str "Hey join me on Status: " share-link)]
{::share {:message message}}))
(fx/defn generate-invite
{:events [::generate-invite]}
[{:keys [db] :as cofx} {:keys [address]}]
(acquisition/handle-registration cofx
{:message {:address address
:interaction_address (get-in db [:multiaccount :public-key])}
:on-success ::share-link}))
(re-frame/reg-sub
::pending-chat-invite
(fn [db]
(let [chat-id (get db :current-chat-id)
{:keys [flow-state]} (get db :acquisition)
{:keys [attributed]
:as chat-referrer} (get-in db [:acquisition :chat-referrer chat-id])]
(and chat-referrer
(not attributed)
(nil? flow-state)))))
(fx/defn go-to-invite
{:events [::open-invite]}
[{:keys [db] :as cofx}]
(let [contract (contracts/get-address db :status/acquisition)
accounts (filter #(not= (:type %) :watch) (get db :multiaccount/accounts))]
(fx/merge cofx
{::get-rewards (mapv (fn [{:keys [address]}]
{:address address
:contract contract
:on-success (fn [type data]
(re-frame/dispatch [::get-reward-success address type data]))})
accounts)}
(navigation/navigate-to-cofx :referral-invite nil))))
(re-frame/reg-fx
::terms-and-conditions
(fn []
(.openURL ^js react/linking privacy-policy-link)))
(fx/defn open-privacy-policy-link
{:events [::terms-and-conditions]}
[_]
{::terms-and-conditions nil})
;; Invite reward
(re-frame/reg-sub
:invite/accounts-reward
(fn [db]
(get-in db [:acquisition :accounts])))
(re-frame/reg-sub
:invite/account-reward
:<- [:invite/accounts-reward]
(fn [accounts [_ account]]
(get accounts account)))
(defn- get-reward [contract address on-success]
(json-rpc/eth-call
{:contract contract
:method "getReferralReward(address,bool)"
:params [address false]
;; [uint ethAmount, uint tokenLen, uint maxThreshold, uint attribCount]
:outputs ["uint256" "uint256" "uint256" "uint256"]
:on-success (fn [[eth-amount tokens-count max-threshold attrib-count]]
(on-success :reward [eth-amount tokens-count max-threshold attrib-count])
(dotimes [id tokens-count]
(json-rpc/eth-call
{:contract contract
:method "getReferralRewardTokens(address,bool,uint256)"
:params [address false id]
:outputs ["address" "uint256"]
:on-success (fn [token-data]
(on-success :token token-data))})))}))
(re-frame/reg-fx
::get-rewards
(fn [accounts]
(doseq [{:keys [contract address on-success]} accounts]
(get-reward contract address on-success))))
(fx/defn default-reward-success
{:events [::default-reward-success]}
[{:keys [db]} type data]
(if (= :reward type)
(let [[eth-amount tokens-count max-threshold attrib-count] data]
{:db (assoc-in db [:acquisition :referral-reward] {:eth-amount (money/wei->ether eth-amount)
:tokens-count tokens-count
:max-threshold max-threshold
:attrib-count attrib-count})})
(let [[address amount] data]
{:db (assoc-in db [:acquisition :referral-reward :tokens address] (money/wei->ether amount))})))
(fx/defn get-reward-success
{:events [::get-reward-success]}
[{:keys [db]} account type data]
(if (= :reward type)
(let [[eth-amount _ max-threshold attrib-count] data]
{:db (assoc-in db [:acquisition :accounts account] {:eth-amount (money/wei->ether eth-amount)
:max-threshold max-threshold
:attrib-count attrib-count})})
(let [[address amount] data]
{:db (assoc-in db [:acquisition :accounts account :tokens address] (money/wei->ether amount))})))
(fx/defn get-default-reward
{:events [::get-default-reward]}
[{:keys [db]}]
{::get-rewards [{:contract (contracts/get-address db :status/acquisition)
:address (ethereum/default-address db)
:on-success (fn [type data]
(re-frame/dispatch [::default-reward-success type data]))}]})
(re-frame/reg-sub-raw
::default-reward
(fn [db]
(re-frame/dispatch [::get-default-reward])
(make-reaction
(fn []
(get-in @db [:acquisition :referral-reward])))))
;; Starter pack
(fx/defn get-starter-pack-amount
{:events [::starter-pack-amount]}
[{:keys [db]} [_ eth-amount tokens tokens-amount sticker-packs]]
{:db (assoc-in db [:acquisition :starter-pack :pack]
{:eth-amount (money/wei->ether eth-amount)
:tokens (zipmap tokens
(map money/wei->ether tokens-amount))
:sticker-packs sticker-packs})})
(fx/defn starter-pack
{:events [::starter-pack]}
[{:keys [db]}]
(let [contract (contracts/get-address db :status/acquisition)]
{::json-rpc/eth-call [{:contract contract
:method "getDefaultPack()"
:outputs ["address" "uint256" "address[]" "uint256[]" "uint256[]"]
:on-success #(re-frame/dispatch [::starter-pack-amount (vec %) (prn %)])}]}))
(re-frame/reg-sub-raw
::starter-pack
(fn [db]
(re-frame/dispatch [::starter-pack])
(make-reaction
(fn []
(get-in @db [:acquisition :starter-pack :pack])))))

View File

@ -0,0 +1,34 @@
(ns status-im.ui.components.invite.style
(:require [quo.design-system.spacing :as spacing]
[quo.design-system.colors :as colors]))
(def reward-item-title (merge (:base spacing/padding-horizontal)
{:padding-top 12
:padding-bottom 4}))
(defn reward-item-content []
(merge (:base spacing/padding-horizontal)
(:base spacing/padding-vertical)
{:background-color (:interactive-02 @colors/theme)
:flex-direction :row
:border-bottom-width 1
:border-top-width 1
:border-color (:border-02 @colors/theme)}))
(defn reward-token-icon [idx]
{:align-items :center
:shadow-radius 16
:shadow-opacity 1
:shadow-color (:shadow-01 @colors/theme)
:shadow-offset {:width 0 :height 4}
:width 40
:height 40
:border-radius 20
:position :absolute
:top (* idx 20)})
(def reward-description {:flex 1})
(defn reward-tokens-icons [c]
{:margin-right 16
:width 40
:height (- (* 40 c) (* 20 (dec c)))})

View File

@ -0,0 +1,14 @@
(ns status-im.ui.components.invite.utils
(:require [status-im.ethereum.tokens :as tokens]
[re-frame.core :as re-frame]))
(defn transform-tokens [{:keys [tokens eth-amount]}]
(let [all-tokens @(re-frame/subscribe [:wallet/all-tokens])
chain @(re-frame/subscribe [:ethereum/chain-keyword])]
(cond-> (mapv (fn [[k v] i]
[(tokens/address->token all-tokens k) v i])
tokens
(range))
(pos? eth-amount)
(conj [(get tokens/all-native-currencies chain) eth-amount (count tokens)]))))

View File

@ -0,0 +1,274 @@
(ns status-im.ui.components.invite.views
(:require [quo.core :as quo]
[reagent.core :as reagent]
[re-frame.core :as re-frame]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.toolbar :as toolbar]
[status-im.utils.utils :as utils]
[status-im.i18n :as i18n]
[status-im.ethereum.tokens :as tokens]
[quo.design-system.spacing :as spacing]
[quo.design-system.colors :as colors]
[status-im.ui.components.invite.style :as styles]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.components.invite.events :as events]
[status-im.ui.components.invite.utils :refer [transform-tokens]]
[status-im.utils.config :as config]
[quo.react-native :as rn]
[clojure.string :as cstr]))
(defn- threshold-badge [max-threshold attrib-count]
(when (pos? max-threshold)
[rn/view {:flex-direction :row}
[rn/view {:padding-horizontal 8
:padding-vertical 2
:border-radius 11
:background-color (:interactive-01 @colors/theme)}
[quo/text {:weight :medium
:size :small
:color :inverse}
(i18n/label :t/attribution-received {:max max-threshold
:attrib attrib-count})]]]))
;; Select account sheet
(defn- render-account [current-account change-account]
(fn [account]
(let [{:keys [max-threshold attrib-count]}
@(re-frame/subscribe [:invite/account-reward (:address account)])]
[quo/list-item
{:theme :accent
:active (= (:address current-account) (:address account))
:disabled (and max-threshold attrib-count
(< max-threshold (inc attrib-count)))
:accessory :radio
:icon [chat-icon/custom-icon-view-list (:name account) (:color account)]
:title (:name account)
:subtitle [:<>
[quo/text {:monospace true
:color :secondary}
(utils/get-shortened-checksum-address (:address account))]
[threshold-badge max-threshold attrib-count]]
:on-press #(change-account account)}])))
(defn- accounts-list [accounts current-account change-account]
(fn []
[rn/view {:flex 1}
[rn/view {:style (merge (:base spacing/padding-horizontal)
(:tiny spacing/padding-vertical))}
[quo/text {:align :center}
(i18n/label :t/invite-select-account)]]
[rn/flat-list {:data accounts
:key-fn :address
:render-fn (render-account current-account change-account)}]]))
;; Invite sheet
(defn- step [{:keys [number description]}]
[rn/view {:style (merge
(:small spacing/padding-vertical)
{:flex-direction :row
:flex 1
:align-items :center})}
[rn/view {:style {:width 40
:height 40
:border-radius 20
:border-width 1
:justify-content :center
:align-items :center
:border-color (:ui-01 @colors/theme)}}
[quo/text {:weight :bold
:size :large}
number]]
[rn/view {:padding-left (:base spacing/spacing)
:flex 1}
[quo/text (i18n/label description)]]])
(def steps-values [{:number 1
:description :t/invite-instruction-first}
{:number 2
:description :t/invite-instruction-second}
{:number 3
:description :t/invite-instruction-third}
{:number 4
:description :t/invite-instruction-fourth}])
(defn- referral-steps []
[rn/view {:style (merge
(:tiny spacing/padding-vertical)
(:base spacing/padding-horizontal)
{:border-bottom-width 1
:border-bottom-color (:ui-01 @colors/theme)})}
[rn/view {:style {:padding-top (:small spacing/spacing)
:padding-bottom (:x-tiny spacing/spacing)}}
[quo/text {:color :secondary}
(i18n/label :t/invite-instruction)]]
[rn/view {:flex 1}
(for [s steps-values]
^{:key (str (:number s))}
[step s])]])
(defn bottom-sheet-content [accounts account change-account]
(fn []
[accounts-list accounts account (fn [a]
(re-frame/dispatch [:bottom-sheet/hide])
(change-account a))]))
(defn- referral-account []
(fn [{:keys [account accounts change-account]}]
(let [{:keys [max-threshold attrib-count]}
@(re-frame/subscribe [:invite/account-reward (:address account)])]
[rn/view {:style (:tiny spacing/padding-vertical)}
[rn/view {:style (merge (:base spacing/padding-horizontal)
(:x-tiny spacing/padding-vertical))}
[quo/text {:color :secondary}
(i18n/label :t/invite-receive-account)]]
[quo/list-item
{:icon [chat-icon/custom-icon-view-list (:name account) (:color account)]
:title (:name account)
:subtitle [:<>
[quo/text {:monospace true
:color :secondary}
(utils/get-shortened-checksum-address (:address account))]
[threshold-badge max-threshold attrib-count]]
:on-press #(re-frame/dispatch
[:bottom-sheet/show-sheet
{:content (bottom-sheet-content accounts account change-account)}])}]])))
(defn reward-item [data description]
(let [tokens (transform-tokens data)
reward-text (->> tokens
(map (fn [[{:keys [symbol]} value _]]
(str value " " (name symbol))))
(cstr/join ", "))]
[rn/view {}
[rn/view {:style styles/reward-item-title}
[quo/text {:weight :medium}
[quo/text {:color :link
:weight :inherit}
(i18n/label :t/invite-reward-you)]
(i18n/label :t/invite-reward-you-name)]]
[rn/view {:style (styles/reward-item-content)}
[rn/view {:style (styles/reward-tokens-icons (count tokens))}
(doall
(for [[{name :name
{source :source} :icon} _ idx] tokens]
^{:key name}
[rn/view {:style (styles/reward-token-icon idx)}
[rn/image {:source (if (fn? source) (source) source)
:style {:width 40
:height 40}}]]))]
[rn/view {:style styles/reward-description}
[quo/text {}
(i18n/label description {:reward reward-text})]]]]))
(defn friend-reward-item [starter-pack-amount description]
(let [tokens (transform-tokens starter-pack-amount)
reward-text (cstr/join ", " (map (comp name :symbol first) tokens))]
[rn/view {}
[rn/view {:style styles/reward-item-title}
[quo/text {:weight :medium}
[quo/text {:color :link
:weight :inherit}
(i18n/label :t/invite-reward-friend)]
(i18n/label :t/invite-reward-friend-name)]]
[rn/view {:style (styles/reward-item-content)}
[rn/view {:style (styles/reward-tokens-icons (count tokens))}
(doall
(for [[{name :name
{source :source} :icon} _ idx] tokens]
^{:key name}
[rn/view {:style (styles/reward-token-icon idx)}
[rn/image {:source (if (fn? source) (source) source)
:style {:width 40
:height 40}}]]))]
[rn/view {:style styles/reward-description}
[quo/text {}
(i18n/label description {:reward reward-text})]]]]))
(defn referral-invite []
(let [account* (reagent/atom nil)]
(fn []
(let [accounts @(re-frame/subscribe [:accounts-without-watch-only])
default-account @(re-frame/subscribe [:multiaccount/default-account])
account (or @account* default-account)
reward @(re-frame/subscribe [::events/default-reward])
starter-pack @(re-frame/subscribe [::events/starter-pack])]
[rn/view {:flex 1}
[topbar/topbar {:modal? true
:show-border? true
:title (i18n/label :t/invite-friends)}]
[rn/scroll-view {:flex 1}
[reward-item reward :t/invite-reward-you-description]
[friend-reward-item starter-pack :t/invite-reward-friend-description]
[referral-account {:account account
:change-account #(reset! account* %)
:accounts accounts}]
[referral-steps]
[rn/view {:padding-vertical 10
:padding-horizontal 16}
[quo/text {}
(i18n/label :t/invite-privacy-policy1)
" "
[quo/text {:color :link
:on-press #(re-frame/dispatch [::events/terms-and-conditions])}
(i18n/label :t/invite-privacy-policy2)]]]]
[toolbar/toolbar
{:show-border? true
:center
[quo/button {:type :secondary
:on-press #(re-frame/dispatch [::events/generate-invite
{:address (get account :address)}])}
(i18n/label :t/invite-button)]}]]))))
(defn button []
(if-not config/referrals-invite-enabled?
[rn/view {:style {:align-items :center}}
[rn/view {:style (:tiny spacing/padding-vertical)}
[quo/button {:on-press #(re-frame/dispatch [::events/share-link nil])
:accessibility-label :invite-friends-button}
(i18n/label :t/invite-friends)]]]
(let [reward @(re-frame/subscribe [::events/default-reward])]
[rn/view {:style {:align-items :center}}
[rn/view {:style (:tiny spacing/padding-vertical)}
[quo/button {:on-press #(re-frame/dispatch [::events/open-invite])
:accessibility-label :invite-friends-button}
(i18n/label :t/invite-friends)]]
[rn/view {:style (merge (:tiny spacing/padding-vertical)
(:base spacing/padding-horizontal))}
(when reward
[rn/view {:style {:flex-direction :row
:align-items :center
:justify-content :center}}
[rn/view {:style (:tiny spacing/padding-horizontal)}
(when-let [{:keys [source]} (tokens/symbol->icon :SNT)]
[rn/image {:style {:width 20
:height 20}
:source (source)}])]
[quo/text {:align :center}
(i18n/label :t/invite-reward {:value (str (get reward :eth-amount) " ETH")})]])]])))
(defn list-item [{:keys [accessibility-label]}]
(if-not config/referrals-invite-enabled?
[quo/list-item
{:theme :accent
:title (i18n/label :t/invite-friends)
:icon :main-icons/share
:accessibility-label accessibility-label
:on-press (fn []
(re-frame/dispatch [:bottom-sheet/hide])
(js/setTimeout
#(re-frame/dispatch [::events/share-link nil]) 250))}]
(let [amount @(re-frame/subscribe [::events/default-reward])]
[quo/list-item
{:theme :accent
:title (i18n/label :t/invite-friends)
:subtitle (i18n/label :t/invite-reward {:value (str (get amount :eth-amount) " ETH")})
:icon :main-icons/share
:accessibility-label accessibility-label
:on-press #(do
(re-frame/dispatch [:bottom-sheet/hide])
(re-frame/dispatch [::events/open-invite]))}])))

View File

@ -91,7 +91,7 @@
(fx/merge cofx
(contact/add-contact contact-identity)
(navigation/navigate-to-cofx :contacts-list {}))
(chat/start-chat cofx contact-identity {:navigation-reset? true}))
(chat/start-chat cofx contact-identity))
(and (string? contact-identity) (ul/match-url contact-identity ul/profile-regex))
(qr-code-scanned cofx (ul/match-url contact-identity ul/profile-regex) opts)

View File

@ -21,8 +21,7 @@
(multiaccounts/displayed-photo row)]
:chevron true
:on-press #(re-frame/dispatch [:chat.ui/start-chat
(:public-key row)
{:navigation-reset? true}])}])
(:public-key row)])}])
(defn- icon-wrapper [color icon]
[react/view

View File

@ -88,7 +88,7 @@
outgoing colors/mention-outgoing
:else colors/mention-incoming)}
:on-press (when-not (= content-type constants/content-type-system-text)
#(re-frame/dispatch [:chat.ui/start-chat literal {:navigation-reset? true}]))}
#(re-frame/dispatch [:chat.ui/start-chat literal]))}
[mention-element literal]])
"status-tag"
(conj acc [react/text-class

View File

@ -24,6 +24,7 @@
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.chat.group :as chat.group]
[status-im.ui.screens.chat.message.gap :as gap]
[status-im.ui.components.invite.chat :as invite.chat]
[status-im.ui.screens.chat.components.accessory :as accessory]
[status-im.ui.screens.chat.components.input :as components]
[status-im.ui.screens.chat.message.datemark :as message-datemark])
@ -148,7 +149,10 @@
:ref #(reset! messages-list-ref %)
:header (when (and group-chat (not public?))
[chat.group/group-chat-footer chat-id])
:footer [chat-intro-header-container chat no-messages?]
:footer [:<>
[chat-intro-header-container chat no-messages?]
(when (and (not group-chat) (not public?))
[invite.chat/reward-messages])]
:data messages
:inverted true
:render-fn (fn [{:keys [outgoing type] :as message} idx]

View File

@ -6,7 +6,7 @@
[status-im.ui.components.react :as react]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.i18n :as i18n]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.invite.views :as invite]
[quo.core :as quo]
[status-im.ui.components.topbar :as topbar])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
@ -53,10 +53,7 @@
[react/view {:align-items :center :flex 1 :justify-content :center}
[react/text {:style {:color colors/gray :margin-vertical 24}}
(i18n/label :t/you-dont-have-contacts)]
[quo/button
{:accessibility-label :invite-friends
:on-press #(list-selection/open-share {:message (i18n/label :t/get-status-at)})}
(i18n/label :t/invite-friends)]])]]))
[invite/button]])]]))
(defview blocked-users-list []
(letsubs [blocked-contacts [:contacts/blocked]]

View File

@ -12,7 +12,7 @@
[status-im.ui.components.keyboard-avoid-presentation
:as
kb-presentation]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.invite.views :as invite]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[status-im.ui.components.search-input.view :as search]
@ -69,9 +69,6 @@
(defn- group-toggle-participant [allow-new-users? contact]
[toggle-item allow-new-users? :is-participant-selected? contact on-toggle-participant])
(defn- handle-invite-friends-pressed []
(list-selection/open-share {:message (i18n/label :t/get-status-at)}))
(defn toggle-list [{:keys [contacts render-fn]}]
[react/scroll-view {:flex 1}
[list/flat-list {:data contacts
@ -84,10 +81,7 @@
[react/text
{:style (styles/no-contact-text)}
no-contacts]
[quo/button
{:type :secondary
:on-press handle-invite-friends-pressed}
(i18n/label :t/invite-friends)]])
[invite/button]])
(defn filter-contacts [filter-text contacts]
(let [lower-filter-text (string/lower-case (str filter-text))

View File

@ -1,10 +1,10 @@
(ns status-im.ui.screens.home.sheet.views
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react]
[quo.core :as quo]
[status-im.utils.config :as config]))
[status-im.i18n :as i18n]
[status-im.utils.config :as config]
[status-im.ui.components.invite.views :as invite]))
(defn hide-sheet-and-dispatch [event]
(re-frame/dispatch [:bottom-sheet/hide])
@ -31,17 +31,8 @@
:accessibility-label :join-public-chat-button
:icon :main-icons/public-chat
:on-press #(hide-sheet-and-dispatch [:navigate-to :new-public-chat])}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/invite-friends)
:accessibility-label :chats-menu-invite-friends-button
:icon :main-icons/share
:on-press (fn []
(re-frame/dispatch [:bottom-sheet/hide])
;; https://github.com/facebook/react-native/pull/26839
(js/setTimeout
#(list-selection/open-share {:message (i18n/label :t/get-status-at)})
250))}]])
[invite/list-item
{:accessibility-label :chats-menu-invite-friends-button}]])
(def add-new
{:content add-new-view})

View File

@ -9,7 +9,6 @@
[status-im.ui.components.react :as react]
[status-im.ui.screens.home.styles :as styles]
[status-im.ui.screens.home.views.inner-item :as inner-item]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.colors :as colors]
[status-im.ui.screens.add-new.new-public-chat.view :as new-public-chat]
[quo.core :as quo]
@ -19,6 +18,7 @@
[status-im.utils.debounce :as debounce]
[status-im.utils.utils :as utils]
[cljs-bean.core :as bean]
[status-im.ui.components.invite.views :as invite]
[status-im.ui.components.topbar :as topbar])
(:require-macros [status-im.utils.views :as views]))
@ -64,12 +64,10 @@
:on-press #(re-frame/dispatch [:multiaccounts.ui/hide-home-tooltip])
:accessibility-label :hide-home-button}
[icons/icon :main-icons/close-circle {:color colors/gray}]]]]
[react/i18n-text {:style styles/no-chats-text :key :chat-and-transact}]
[react/view {:align-items :center :margin-top 16}
[quo/button {:on-press #(list-selection/open-share {:message (i18n/label :t/get-status-at)})
:accessibility-label :invite-friends-button}
(i18n/label :t/invite-friends)]]
[react/view {:align-items :center :margin-top 16}
[react/view {:style {:padding-bottom 8}}
[react/i18n-text {:style styles/no-chats-text :key :chat-and-transact}]]
[invite/button]
[react/view {:align-items :center :padding-top 8}
[react/view {:style (styles/hr-wrapper)}]
[react/i18n-text {:style (styles/or-text) :key :or}]]
[react/view {:margin-top 16}

View File

@ -9,6 +9,7 @@
[status-im.ui.screens.wallet.request.views :as request]
[status-im.ui.screens.profile.user.views :as profile.user]
["react-native" :refer (BackHandler)]
[status-im.ui.components.invite.advertiser :as invite]
[status-im.ui.screens.multiaccounts.recover.views :as multiaccounts.recover]
[status-im.ui.screens.signing.views :as signing]
[status-im.ui.screens.biometric.views :as biometric]
@ -142,6 +143,9 @@
(= :frozen-card view)
[frozen-card/frozen-card]
(= :accept-invite view)
[invite/accept-popover]
:else
[view])]]]]])))})))

View File

@ -10,7 +10,7 @@
(defn send-transaction [chat-id cofx]
;;TODO start send transaction command flow
(chat-models/start-chat cofx chat-id {:navigation-reset? true}))
(chat-models/start-chat cofx chat-id))
(defn- valid-name? [name]
(spec/valid? :profile/name name))

View File

@ -17,6 +17,7 @@
[status-im.ui.screens.routing.profile-stack :as profile-stack]
[status-im.ui.screens.routing.browser-stack :as browser-stack]
[status-im.ui.components.tabbar.core :as tabbar]
[status-im.ui.components.invite.views :as invite]
[status-im.ui.screens.routing.core :as navigation]
[status-im.utils.platform :as platform]
[status-im.ui.screens.chat.image.preview.views :as image-preview]
@ -85,6 +86,10 @@
{:name :create-group-chat
:transition :presentation-ios
:component chat-stack/new-group-chat}
{:name :referral-invite
:transition :presentation-ios
:insets {:bottom true}
:component invite/referral-invite}
{:name :add-participants-toggle-list
:on-focus [::group.events/add-participants-toggle-list]
:transition :presentation-ios

View File

@ -39,6 +39,7 @@
(def commands-enabled? (enabled? (get-config :COMMANDS_ENABLED "0")))
(def keycard-test-menu-enabled? (enabled? (get-config :KEYCARD_TEST_MENU "0")))
(def qr-test-menu-enabled? (enabled? (get-config :QR_READ_TEST_MENU "0")))
(def referrals-invite-enabled? (enabled? (get-config :ENABLE_REFERRAL_INVITE "0")))
;; CONFIG VALUES
(def log-level

View File

@ -35,16 +35,19 @@
(fn [error]
(utils/show-popup "Error" url (str error))))))))
;; FIXME: Should be more extensible and accept multiple methods
(defn post
"Performs an HTTP POST request"
([url data on-success]
(post url data on-success nil))
([url data on-success on-error]
(post url data on-success on-error nil))
([url data on-success on-error {:keys [valid-response? timeout-ms headers]}]
([url data on-success on-error
{:keys [valid-response? method timeout-ms headers]
:or {method "POST"}}]
(-> (fetch
url
(clj->js (merge {:method "POST"
(clj->js (merge {:method method
:body data
:timeout (or timeout-ms http-request-default-timeout-ms)}
(when headers

View File

@ -14,6 +14,7 @@
[status-im.navigation :as navigation]
[status-im.utils.fx :as fx]
[taoensso.timbre :as log]
[status-im.acquisition.core :as acquisition]
[status-im.wallet.choose-recipient.core :as choose-recipient]))
;; TODO(yenda) investigate why `handle-universal-link` event is
@ -23,6 +24,7 @@
(def public-chat-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:chat/public/([a-z0-9\-]+)$|([a-z0-9\-]+))$")
(def profile-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:u/(0x.*)$|u/(.*)$|user/(.*))$")
(def browse-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:b/(.*)$|browse/(.*))$")
(def referral-link-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:referral/(.*))$")
;; domains should be without the trailing slash
(def domains {:external "https://join.status.im"
@ -64,7 +66,7 @@
(fx/defn handle-private-chat [cofx chat-id]
(log/info "universal-links: handling private chat" chat-id)
(chat/start-chat cofx chat-id {}))
(chat/start-chat cofx chat-id))
(fx/defn handle-public-chat [cofx public-chat]
(log/info "universal-links: handling public chat" public-chat)
@ -95,6 +97,9 @@
:else
(log/info "universal-link: no pub-key for ens-name " ens-name)))}})))
(fx/defn handle-referrer-url [_ referrer]
{::acquisition/check-referrer referrer})
(fx/defn handle-eip681 [cofx url]
(fx/merge cofx
(choose-recipient/parse-eip681-uri-and-resolve-ens url)
@ -115,6 +120,9 @@
[cofx url]
(cond
(match-url url referral-link-regex)
(handle-referrer-url cofx (match-url url referral-link-regex))
(match-url url private-chat-regex)
(handle-private-chat cofx (match-url url private-chat-regex))

View File

@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im",
"repo": "status-go",
"version": "v0.56.5",
"commit-sha1": "ab01a05cd63df0f749862d16d01a90fdd5f694e8",
"src-sha256": "004zjm66gykgz4mlrzsmv797x4pdqjm61dr2dcn1dnbdbdhnglz2"
"version": "v0.56.6",
"commit-sha1": "2d0818d873fee570a73867d8ed4bc8e792215cf1",
"src-sha256": "0d9k0c2srhmm5dpzx3dkzn1h0p60x9zwjzim6x08gp9yd87h3zmv"
}

View File

@ -548,7 +548,36 @@
"invalid-pairing-password": "Invalid pairing password",
"invalid-range": "Invalid format, must be between {{min}} and {{max}}",
"invite-friends": "Invite friends",
"invite-reward": "Earn {{value}} for every friend you invite!",
"invite-select-account": "Select an account to receive your referral bonus",
"invited": "invited",
"invite-button": "Invite",
"invite-receive-account": "Account to receive your referral bonus",
"invite-instruction": "How it works",
"invite-instruction-first": "You send a unique invite link to your friend to download and join Status",
"invite-instruction-second": "Your friend downloads Status and creates an account (on Android)",
"invite-instruction-third": "A chat with your friend is started, where they confirm your referral",
"invite-instruction-fourth": "You receive your referral bonus and your friend the Starter Pack",
"invite-reward-you": "You: ",
"invite-reward-you-name": "Referral bonus",
"invite-reward-you-description": "Invite a friend and receive {{reward}} as a token of our gratitude.",
"invite-reward-friend": "Friend: ",
"invite-reward-friend-name": "Starter Pack",
"invite-reward-friend-description": "Your friend will receive a Starter Pack consisting of some {{reward}} to get started",
"invite-privacy-policy1": "By accepting you agree to the referral program",
"invite-privacy-policy2": "Terms and Conditions.",
"invite-chat-name": "Friend referral",
"invite-chat-starter-pack": "Starter Pack",
"invite-chat-intro": "You were referred by a friend to join Status. Heres some crypto to get you started! Use it to register an ENS name or buy a sticker pack",
"invite-chat-accept": "Accept",
"invite-chat-rule": "Accepting will also reward your friend with a crypto referral bonus",
"attribution-received": "{{attrib}} out of {{max}} bonuses received",
"advertiser-starter-pack-title": "Starter Pack",
"advertiser-starter-pack-description": "Heres some crypto to get you started! Use it to get stickers, an ENS name and try dapps",
"advertiser-starter-pack-accept": "Accept",
"advertiser-starter-pack-decline": "Decline",
"starter-pack-received": "Starter Pack received",
"starter-pack-received-description": "Heres some crypto to get you started! Use it to get stickers, an ENS name and try dapps",
"join-group-chat": "Join group",
"join-group-chat-description": "{{username}} invited you to join the group {{group-name}}",
"joined-group-chat-description": "You've joined {{group-name}} from invitation by {{username}}",

View File

@ -1207,6 +1207,13 @@
"@types/yargs" "^15.0.0"
chalk "^3.0.0"
"@react-native-community/async-storage@^1.11.0":
version "1.11.0"
resolved "https://registry.yarnpkg.com/@react-native-community/async-storage/-/async-storage-1.11.0.tgz#bf81b8813080846f150c67f531987c429b442166"
integrity sha512-Pq9LlmvtCEKAGdkyrgTcRxNh2fnHFykEj2qnRYijOl1pDIl2MkD5IxaXu5eOL0wgOtAl4U//ff4z40Td6XR5rw==
dependencies:
deep-assign "^3.0.0"
"@react-native-community/audio-toolkit@git+https://github.com/tbenr/react-native-audio-toolkit.git#v2.0.3-status-v6":
version "2.0.3"
resolved "git+https://github.com/tbenr/react-native-audio-toolkit.git#7ae9055cf6169b30f5089bda7bfcfc1c40a715e5"
@ -2882,6 +2889,13 @@ decompress-response@^3.3.0:
dependencies:
mimic-response "^1.0.0"
deep-assign@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-3.0.0.tgz#c8e4c4d401cba25550a2f0f486a2e75bc5f219a2"
integrity sha512-YX2i9XjJ7h5q/aQ/IM9PEwEnDqETAIYbggmdDB3HLTlSgo1CxPsj6pvhPG68rq6SVE0+p+6Ywsm5fTYNrYtBWw==
dependencies:
is-obj "^1.0.0"
deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
@ -4165,6 +4179,11 @@ is-number@^7.0.0:
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@ -6511,6 +6530,11 @@ react-native-dark-mode@^0.2.2:
events "^3.0.0"
toolkit.ts "^0.0.2"
react-native-device-info@^5.6.1:
version "5.6.1"
resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-5.6.1.tgz#3ae88d8659b7b64d204dbfc39f69126b769363d4"
integrity sha512-FxjenoDZJKT53pp/Tl5gMsw5DA82Y5tOuySQlKS5AaDmw+Bu6EqEJjt0z4TRhJOVoqVJ35oCiZ3xViVbz/hB0w==
react-native-dialogs@^1.0.4:
version "1.1.0"
resolved "https://registry.yarnpkg.com/react-native-dialogs/-/react-native-dialogs-1.1.0.tgz#8f7ee7f9d96574fc878fb7c1be101611fb4af517"