zh-web-sdk 2.3.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +151 -55
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -72,10 +72,10 @@ The pipeline automatically updates the version in package.json after merge to ma
|
|
|
72
72
|
- default is a patch release (`1.0.0` to `1.0.1`)
|
|
73
73
|
|
|
74
74
|
## Mobile usage
|
|
75
|
-
In order to use our SDK on Mobile Apps you should follow the guide below. You won't need to install or have `zh-web-sdk` as a dependency in your project to use it for Mobile Apps.
|
|
76
|
-
|
|
77
|
-
- Cert: https://sdk-mobile.cert.zerohash.com
|
|
78
|
-
- Prod: https://sdk-mobile.zerohash.com
|
|
75
|
+
In order to use our SDK on Mobile Apps you should follow the guide below. You won't need to install or have `zh-web-sdk` as a dependency in your project to use it for Mobile Apps. We use a proxy server that calls the SDK internally in order to make it work for Mobile Applications. This proxy service is referred to as `sdk-mobile` and the URLs are:
|
|
76
|
+
|
|
77
|
+
- Cert: https://sdk-mobile.cert.zerohash.com/v1
|
|
78
|
+
- Prod: https://sdk-mobile.zerohash.com/v1
|
|
79
79
|
|
|
80
80
|
These are the URLs your `WebView` should use on your Mobile App.
|
|
81
81
|
|
|
@@ -84,22 +84,22 @@ These are the URLs your `WebView` should use on your Mobile App.
|
|
|
84
84
|
#### Events
|
|
85
85
|
We forward events that come from the UI to the Native App using the `postMessage` API. You can handle these events using `onMessage` from the `WebView` component. Currently these are the events we have, for the respective Apps:
|
|
86
86
|
- **Onboarding:**
|
|
87
|
-
- `ONBOARDING_APP_LOADED` Sent when the App is loaded
|
|
87
|
+
- `ONBOARDING_APP_LOADED` Sent when the App is loaded in the first time
|
|
88
88
|
- `ONBOARDING_CLOSE_BUTTON_CLICKED` Sent when the user clicks the Close button on the top-right corner
|
|
89
89
|
- **Crypto Withdrawals:**
|
|
90
|
-
- `CRYPTO_WITHDRAWALS_APP_LOADED` Sent when the App is loaded
|
|
90
|
+
- `CRYPTO_WITHDRAWALS_APP_LOADED` Sent when the App is loaded in the first time
|
|
91
91
|
- `CRYPTO_WITHDRAWALS_CLOSE_BUTTON_CLICKED` Sent when the user clicks the Close button on the top-right corner
|
|
92
92
|
- **ACH Deposits:**
|
|
93
|
-
- `ACH_DEPOSITS_APP_LOADED` Sent when the App is loaded
|
|
93
|
+
- `ACH_DEPOSITS_APP_LOADED` Sent when the App is loaded in the first time
|
|
94
94
|
- `ACH_DEPOSITS_CLOSE_BUTTON_CLICKED` Sent when the user clicks the Close button on the top-right corner
|
|
95
95
|
- **Fiat Withdrawals:**
|
|
96
|
-
- `FIAT_WITHDRAWALS_APP_LOADED` Sent when the App is loaded
|
|
96
|
+
- `FIAT_WITHDRAWALS_APP_LOADED` Sent when the App is loaded in the first time
|
|
97
97
|
- `FIAT_WITHDRAWALS_CLOSE_BUTTON_CLICKED` Sent when the user clicks the Close button on the top-right corner
|
|
98
98
|
- **Crypto Buy:**
|
|
99
|
-
- `CRYPTO_BUY_APP_LOADED` Sent when the App is loaded
|
|
99
|
+
- `CRYPTO_BUY_APP_LOADED` Sent when the App is loaded in the first time
|
|
100
100
|
- `CRYPTO_BUY_CLOSE_BUTTON_CLICKED` Sent when the user clicks the Close button on the top-right corner
|
|
101
101
|
- **Crypto Sell:**
|
|
102
|
-
- `CRYPTO_SELL_APP_LOADED` Sent when the App is loaded
|
|
102
|
+
- `CRYPTO_SELL_APP_LOADED` Sent when the App is loaded in the first time
|
|
103
103
|
- `CRYPTO_SELL_CLOSE_BUTTON_CLICKED` Sent when the user clicks the Close button on the top-right corner
|
|
104
104
|
|
|
105
105
|
#### Messages
|
|
@@ -123,33 +123,51 @@ To control the `WebView` you can also send messages *down*, using the `postMessa
|
|
|
123
123
|
- `{type: "OPEN_MODAL", payload:{jwt: "<JWT_HERE>", appIdentifier: "crypto-sell"} }`: It will open the Crypto sell modal with the JWT provided
|
|
124
124
|
- `{type: "CLOSE_MODAL", payload:{appIdentifier: "crypto-sell"}}`: It will close the Crypto sell modal
|
|
125
125
|
|
|
126
|
+
#### Notes
|
|
127
|
+
A postMessage call is required to open the modal when the webview is loaded (type: OPEN_MODAL). This requirement was added in version `https://{SDK_SERVER_URL}/v1` and is not present in `https://{SDK_SERVER_URL}/`, which opens the onboarding app automatically. The latter will be deprecated and will not be available for use in the future.
|
|
128
|
+
|
|
126
129
|
The example below shows how you can implement the mentioned methods in a `react-native` project
|
|
127
130
|
|
|
128
131
|
```jsx
|
|
129
|
-
const sdkMobileServer = 'https://sdk-mobile.cert.zerohash.com/'
|
|
132
|
+
const sdkMobileServer = 'https://sdk-mobile.cert.zerohash.com/v1'
|
|
130
133
|
const zeroHashAppsURL = 'https://web-sdk.zerohash.com/'
|
|
131
134
|
const App = () => {
|
|
132
135
|
const webViewRef = useRef<WebView>(null)
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
136
|
+
const [isWebViewOpen, setIsWebViewOpen] = React.useState(false)
|
|
137
|
+
const currentAppIdentifier = 'onboarding'
|
|
138
|
+
const mockJWT =
|
|
139
|
+
'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ6ZXJvaGFzaC5jb20iLCJzdWIiOiJ0ZXN0U3ViamVjdCIsImF1ZCI6WyJ6ZXJvaGFzaC5jb20iXSwiZXhwIjoxNjk1OTc2OTMzLCJpYXQiOjE2OTMzODQ5MzMsInBheWxvYWQiOnsiZW1haWwiOiJteS1lbWFpbEB0ZXN0LmNvbSIsInBhcnRpY2lwYW50X2NvZGUiOiJwYXJ0aWNpcGFudC1jb2RlIiwicGxhdGZvcm1fbmFtZSI6InBsYXRmb3JtLW5hbWUiLCJwbGF0Zm9ybV9jb2RlIjoicGxhdGZvcm0tY29kZSIsInBsYXRmb3JtX2FncmVlbWVudF9saW5rIjoicGxhdGZvcm0tYWdyZWVtZW50LWxpbmsifX0.r549t4J_iQ8wP5pnD2uTdRaRm4nHLO722lDmhbGoIc0E_cKVyVYnxZTO1DnXJ6NUJ6a3DvnkGv78iQHqvnFTmg'
|
|
140
|
+
const apps = {
|
|
141
|
+
achDeposits: { identifier: 'ach-deposits', jwt: mockJWT },
|
|
142
|
+
cryptoBuy: { identifier: 'crypto-buy', jwt: mockJWT },
|
|
143
|
+
cryptoSell: { identifier: 'crypto-sell', jwt: mockJWT },
|
|
144
|
+
cryptoWithdrawals: { identifier: 'crypto-withdrawals', jwt: mockJWT },
|
|
145
|
+
fiatWithdrawals: { identifier: 'fiat-withdrawals', jwt: mockJWT },
|
|
146
|
+
userOnboarding: { identifier: 'onboarding', jwt: mockJWT },
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Receive messages from sdk-mobile. Currently we expose the following event types:
|
|
151
|
+
* "ONBOARDING_APP_LOADED", "ONBOARDING_CLOSE_BUTTON_CLICKED",
|
|
152
|
+
* "CRYPTO_WITHDRAWALS_APP_LOADED", "CRYPTO_WITHDRAWALS_CLOSE_BUTTON_CLICKED",
|
|
153
|
+
* "ACH_DEPOSITS_APP_LOADED", "ACH_DEPOSITS_CLOSE_BUTTON_CLICKED",
|
|
154
|
+
* "FIAT_WITHDRAWALS_APP_LOADED", "FIAT_WITHDRAWALS_CLOSE_BUTTON_CLICKED",
|
|
155
|
+
* "CRYPTO_BUY_APP_LOADED", "CRYPTO_BUY_CLOSE_BUTTON_CLICKED",
|
|
156
|
+
* "CRYPTO_SELL_APP_LOADED", "CRYPTO_SELL_CLOSE_BUTTON_CLICKED",
|
|
157
|
+
* you should be able to take action based on these events.
|
|
158
|
+
*/
|
|
144
159
|
const handleMessage = (event: WebViewMessageEvent) => {
|
|
160
|
+
const closeModalEvents = [
|
|
161
|
+
'ONBOARDING_CLOSE_BUTTON_CLICKED',
|
|
162
|
+
'CRYPTO_WITHDRAWALS_CLOSE_BUTTON_CLICKED',
|
|
163
|
+
'ACH_DEPOSITS_CLOSE_BUTTON_CLICKED',
|
|
164
|
+
'FIAT_WITHDRAWALS_CLOSE_BUTTON_CLICKED',
|
|
165
|
+
'CRYPTO_BUY_CLOSE_BUTTON_CLICKED',
|
|
166
|
+
'CRYPTO_SELL_CLOSE_BUTTON_CLICKED',
|
|
167
|
+
]
|
|
145
168
|
try {
|
|
146
169
|
const parsedMessage = JSON.parse(event.nativeEvent.data)
|
|
147
|
-
if (parsedMessage.type
|
|
148
|
-
// setOnboardingAppLoaded(true)
|
|
149
|
-
}
|
|
150
|
-
if (
|
|
151
|
-
parsedMessage.type === "ONBOARDING_CLOSE_BUTTON_CLICKED"
|
|
152
|
-
) {
|
|
170
|
+
if (closeModalEvents.includes(parsedMessage.type)) {
|
|
153
171
|
setIsWebViewOpen(false)
|
|
154
172
|
}
|
|
155
173
|
} catch (e) {
|
|
@@ -158,47 +176,125 @@ const App = () => {
|
|
|
158
176
|
)
|
|
159
177
|
}
|
|
160
178
|
}
|
|
161
|
-
|
|
179
|
+
/**
|
|
180
|
+
* You can also send messages to sdk-mobile, currently we accept the following messages:
|
|
162
181
|
* "OPEN_MODAL" and "CLOSE_MODAL"
|
|
163
182
|
* Note that the "true;" after the postMessage is required
|
|
164
183
|
* and recommended by the official react-native-webview docs
|
|
165
184
|
* https://github.com/react-native-webview/react-native-webview/blob/master/docs/Guide.md#the-injectedjavascript-prop
|
|
166
185
|
*/
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
186
|
+
const makeEventType = (
|
|
187
|
+
eventAppIdentifier: string,
|
|
188
|
+
eventType: string,
|
|
189
|
+
useJWT = false,
|
|
190
|
+
) => {
|
|
191
|
+
if (
|
|
192
|
+
!Object.entries(apps).some(
|
|
193
|
+
([_, { identifier }]) => identifier === eventAppIdentifier,
|
|
194
|
+
)
|
|
195
|
+
) {
|
|
196
|
+
throw new Error('Invalid app identifier')
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (useJWT) {
|
|
200
|
+
// You can send events with JWTs. See the example below
|
|
201
|
+
// { "type": "OPEN_MODAL", "payload": { "appIdentifier": "onboarding", "jwt": "some-jwt-token"}}
|
|
202
|
+
// { "type": "CLOSE_MODAL", "payload": { "appIdentifier": "onboarding", "jwt": "some-jwt-token"}}
|
|
203
|
+
return `{ "type": "${eventType}", "payload": { "appIdentifier": "${eventAppIdentifier}", "jwt": "${apps[eventAppIdentifier].jwt}"}}`
|
|
204
|
+
}
|
|
205
|
+
// Send events without JWTs if you already set in the URL with query parameters and don't want to send it again
|
|
206
|
+
// { "type": "OPEN_MODAL", "payload": { "appIdentifier": "onboarding"}}
|
|
207
|
+
// { "type": "CLOSE_MODAL", "payload": { "appIdentifier": "onboarding"}}
|
|
208
|
+
return `{ "type": "${eventType}", "payload": { "appIdentifier": "${eventAppIdentifier}"}}`
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const openModal = () => {
|
|
212
|
+
setIsWebViewOpen(true)
|
|
171
213
|
webViewRef.current?.injectJavaScript(
|
|
172
|
-
`window.postMessage(${
|
|
214
|
+
`window.postMessage(${makeEventType(currentAppIdentifier, 'OPEN_MODAL')});true;`,
|
|
173
215
|
)
|
|
174
216
|
}
|
|
175
|
-
const
|
|
176
|
-
const closeOnboardingModal = () =>
|
|
217
|
+
const closeModal = () => {
|
|
177
218
|
webViewRef.current?.injectJavaScript(
|
|
178
|
-
`window.postMessage(${
|
|
219
|
+
`window.postMessage(${makeEventType(currentAppIdentifier, 'CLOSE_MODAL')});true;`,
|
|
179
220
|
)
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Generate the URL with the query parameters required and the JWTs for the apps
|
|
224
|
+
*/
|
|
225
|
+
const generateURL = () => {
|
|
226
|
+
const jwtParams = Object.entries(apps)
|
|
227
|
+
.filter(([_, { jwt }]) => jwt)
|
|
228
|
+
.map(([key, { jwt }]) => `${key}JWT=${encodeURIComponent(jwt)}`)
|
|
229
|
+
.join('&')
|
|
230
|
+
|
|
231
|
+
return `${sdkMobileServer}?zeroHashAppsURL=${encodeURIComponent(zeroHashAppsURL)}&${jwtParams}`
|
|
232
|
+
}
|
|
180
233
|
return (
|
|
181
234
|
<SafeAreaProvider style={{ flex: 1 }}>
|
|
182
|
-
<SafeAreaView
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
235
|
+
<SafeAreaView
|
|
236
|
+
style={{
|
|
237
|
+
flex: 1,
|
|
238
|
+
padding: 0,
|
|
239
|
+
}}
|
|
240
|
+
>
|
|
241
|
+
{!isWebViewOpen && (
|
|
242
|
+
<View
|
|
243
|
+
style={{
|
|
244
|
+
flex: 1,
|
|
245
|
+
alignContent: 'center',
|
|
246
|
+
flexDirection: 'row',
|
|
247
|
+
justifyContent: 'center',
|
|
248
|
+
alignItems: 'center',
|
|
249
|
+
}}
|
|
250
|
+
>
|
|
251
|
+
<TouchableOpacity
|
|
252
|
+
style={{
|
|
253
|
+
backgroundColor: '#00f197',
|
|
254
|
+
padding: 10,
|
|
255
|
+
margin: 10,
|
|
256
|
+
borderRadius: 5,
|
|
257
|
+
alignItems: 'center',
|
|
258
|
+
justifyContent: 'center',
|
|
259
|
+
}}
|
|
260
|
+
onPress={() => setIsWebViewOpen(true)}
|
|
261
|
+
>
|
|
262
|
+
<Text>Open modal</Text>
|
|
263
|
+
</TouchableOpacity>
|
|
264
|
+
<TouchableOpacity
|
|
265
|
+
style={{
|
|
266
|
+
backgroundColor: '#00f197',
|
|
267
|
+
padding: 10,
|
|
268
|
+
margin: 10,
|
|
269
|
+
borderRadius: 5,
|
|
270
|
+
alignItems: 'center',
|
|
271
|
+
justifyContent: 'center',
|
|
272
|
+
}}
|
|
273
|
+
onPress={() => closeModal()}
|
|
274
|
+
>
|
|
275
|
+
<Text>Close modal</Text>
|
|
276
|
+
</TouchableOpacity>
|
|
277
|
+
</View>
|
|
278
|
+
)}
|
|
279
|
+
<View style={{ display: isWebViewOpen ? 'flex' : 'none', flex: 1 }}>
|
|
280
|
+
{isWebViewOpen && (
|
|
281
|
+
<WebView
|
|
282
|
+
ref={webViewRef}
|
|
283
|
+
onMessage={handleMessage}
|
|
284
|
+
source={{ uri: generateURL() }}
|
|
285
|
+
onNavigationStateChange={(navState) => {
|
|
286
|
+
if (!navState.loading) {
|
|
287
|
+
setTimeout(() => {
|
|
288
|
+
openModal()
|
|
289
|
+
}, 100)
|
|
290
|
+
}
|
|
291
|
+
}}
|
|
292
|
+
/>
|
|
293
|
+
)}
|
|
294
|
+
</View>
|
|
200
295
|
</SafeAreaView>
|
|
201
296
|
</SafeAreaProvider>
|
|
202
297
|
)
|
|
203
298
|
}
|
|
299
|
+
export default App
|
|
204
300
|
```
|