@zerohash-sdk/capacitor
v1.0.6
Published
Capacitor plugin bridging zerohash's native iOS and Android SDKs
Readme
@zerohash-sdk/capacitor
Capacitor plugin for embedding zerohash's Fund (deposit) and crypto-withdrawals flows into your iOS and Android app. It wraps the native zerohash iOS and Android SDKs and presents their UI over your app.
Install
npm install @zerohash-sdk/capacitor
npx cap syncRequirements
- iOS 17+
- Android
minSdkVersion24+
Setup
Android
No extra steps — the plugin's Android side pulls in the native zerohash Android
SDK (com.zerohash:zerohash-android) from Maven Central, which a standard
Gradle setup already resolves.
iOS
No extra steps — npx cap sync wires the native SDK in automatically via Swift
Package Manager.
Usage
Both flows work the same way: register your listeners, then present. Each flow
has its own completion event, while close, error and event fire for
whichever flow is active. Only one flow can be presented at a time — presenting
while another is active rejects.
jwt is a short-lived session token your backend mints from the zerohash API.
environment defaults to production, theme to system.
Fund (deposit)
import { Zerohash } from '@zerohash-sdk/capacitor';
// Register listeners before presenting.
await Zerohash.addListener('fundCompleted', (event) => {
console.log('Deposit complete', event.assetSymbol, event.amount);
});
// A terminal failed deposit is a flow outcome, not an error — it arrives here,
// not on 'error'.
await Zerohash.addListener('fundFailed', (event) => {
console.log('Deposit failed', event.transactionId);
});
await Zerohash.addListener('close', () => console.log('Flow closed'));
await Zerohash.addListener('error', (e) => console.error(e.code, e.message));
await Zerohash.presentFund({
jwt: '<session-jwt>',
environment: 'production', // or 'sandbox'
theme: 'system', // 'light' | 'dark' | 'system'
});Crypto withdrawals
import { Zerohash } from '@zerohash-sdk/capacitor';
// Register listeners before presenting.
await Zerohash.addListener('withdrawalCompleted', (event) => {
console.log('Withdrawal submitted', event.withdrawalRequestId);
});
await Zerohash.addListener('withdrawalFailed', (event) => {
console.log('Withdrawal failed', event.withdrawalRequestId);
});
await Zerohash.addListener('close', () => console.log('Flow closed'));
await Zerohash.addListener('error', (e) => console.error(e.code, e.message));
await Zerohash.presentCryptoWithdrawals({
jwt: '<session-jwt>',
environment: 'production', // or 'sandbox'
theme: 'system', // 'light' | 'dark' | 'system'
});Dismissing and tearing down
Both flows share these: Zerohash.cancel() dismisses whichever flow is
presented, Zerohash.isActive() reports whether one is, and
Zerohash.removeAllListeners() unregisters every listener the plugin holds.
API
presentFund(...)presentCryptoWithdrawals(...)cancel()isActive()addListener('close', ...)addListener('error', ...)addListener('event', ...)addListener('loaded', ...)addListener('fundCompleted', ...)addListener('fundFailed', ...)addListener('fundDeposit', ...)addListener('withdrawalCompleted', ...)addListener('withdrawalFailed', ...)removeAllListeners()- Interfaces
- Type Aliases
presentFund(...)
presentFund(options: PresentOptions) => Promise<void>Present the Fund (deposit) flow. Rejects if a session is already active.
| Param | Type |
| ------------- | --------------------------------------------------------- |
| options | PresentOptions |
presentCryptoWithdrawals(...)
presentCryptoWithdrawals(options: PresentOptions) => Promise<void>Present the crypto-withdrawals flow. Rejects if a session is already active.
| Param | Type |
| ------------- | --------------------------------------------------------- |
| options | PresentOptions |
cancel()
cancel() => Promise<void>Dismiss the active session, if any.
isActive()
isActive() => Promise<{ isActive: boolean; }>Whether a session is currently presented.
Returns: Promise<{ isActive: boolean; }>
addListener('close', ...)
addListener(eventName: 'close', listenerFunc: () => void) => Promise<PluginListenerHandle>The user closed the flow.
| Param | Type |
| ------------------ | -------------------------- |
| eventName | 'close' |
| listenerFunc | () => void |
Returns: Promise<PluginListenerHandle>
addListener('error', ...)
addListener(eventName: 'error', listenerFunc: (event: ZerohashErrorEvent) => void) => Promise<PluginListenerHandle>The flow reported an SDK or request error (network, auth, validation).
A terminal failed transaction is not an error — see fundFailed /
withdrawalFailed.
One exception: a failed crypto withdrawal currently emits this as well as
withdrawalFailed, for backwards compatibility with hosts written before
withdrawalFailed existed. See withdrawalFailed.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------- |
| eventName | 'error' |
| listenerFunc | (event: ZerohashErrorEvent) => void |
Returns: Promise<PluginListenerHandle>
addListener('event', ...)
addListener(eventName: 'event', listenerFunc: (event: GenericEvent) => void) => Promise<PluginListenerHandle>A low-level event was forwarded from the flow.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------- |
| eventName | 'event' |
| listenerFunc | (event: GenericEvent) => void |
Returns: Promise<PluginListenerHandle>
addListener('loaded', ...)
addListener(eventName: 'loaded', listenerFunc: () => void) => Promise<PluginListenerHandle>The flow finished loading and is ready.
| Param | Type |
| ------------------ | -------------------------- |
| eventName | 'loaded' |
| listenerFunc | () => void |
Returns: Promise<PluginListenerHandle>
addListener('fundCompleted', ...)
addListener(eventName: 'fundCompleted', listenerFunc: (event: FundCompletedEvent) => void) => Promise<PluginListenerHandle>A deposit completed successfully.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------- |
| eventName | 'fundCompleted' |
| listenerFunc | (event: FundCompletedEvent) => void |
Returns: Promise<PluginListenerHandle>
addListener('fundFailed', ...)
addListener(eventName: 'fundFailed', listenerFunc: (event: FundCompletedEvent) => void) => Promise<PluginListenerHandle>A deposit reached a terminal failed state. Carries the same payload as
fundCompleted — which event fired tells you the outcome.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------- |
| eventName | 'fundFailed' |
| listenerFunc | (event: FundCompletedEvent) => void |
Returns: Promise<PluginListenerHandle>
addListener('fundDeposit', ...)
addListener(eventName: 'fundDeposit', listenerFunc: (event: FundDepositEvent) => void) => Promise<PluginListenerHandle>The status of a deposit funded from an external source (the "connect an
account" flow). Deposits on that path emit only this event —
fundCompleted / fundFailed cover the manual and Pay paths.
Not terminal. It also fires while account matching is verifying, and can
arrive more than once for the same deposit, so read the outcome off
status / success rather than treating the event itself as completion.
| Param | Type |
| ------------------ | --------------------------------------------------------------------------------- |
| eventName | 'fundDeposit' |
| listenerFunc | (event: FundDepositEvent) => void |
Returns: Promise<PluginListenerHandle>
addListener('withdrawalCompleted', ...)
addListener(eventName: 'withdrawalCompleted', listenerFunc: (event: CryptoWithdrawalsCompletedEvent) => void) => Promise<PluginListenerHandle>A withdrawal was submitted successfully.
| Param | Type |
| ------------------ | --------------------------------------------------------------------------------------------------------------- |
| eventName | 'withdrawalCompleted' |
| listenerFunc | (event: CryptoWithdrawalsCompletedEvent) => void |
Returns: Promise<PluginListenerHandle>
addListener('withdrawalFailed', ...)
addListener(eventName: 'withdrawalFailed', listenerFunc: (event: CryptoWithdrawalsCompletedEvent) => void) => Promise<PluginListenerHandle>A withdrawal reached a terminal failed state. Carries the same payload as
withdrawalCompleted.
A failed withdrawal also emits error, for backwards compatibility with
hosts written before this event existed — error was this flow's only
failure signal. Listen here; if you listen to both, guard against counting
one failure twice. The compatibility error is deprecated and will be
removed in a future major version. fundFailed does not do this — a failed
deposit emits only fundFailed.
| Param | Type |
| ------------------ | --------------------------------------------------------------------------------------------------------------- |
| eventName | 'withdrawalFailed' |
| listenerFunc | (event: CryptoWithdrawalsCompletedEvent) => void |
Returns: Promise<PluginListenerHandle>
removeAllListeners()
removeAllListeners() => Promise<void>Remove all listeners registered by this plugin.
Interfaces
PresentOptions
| Prop | Type | Description |
| ----------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| jwt | string | Short-lived session JWT, minted by your backend from the zerohash API. |
| environment | ZerohashEnvironment | Defaults to production. |
| theme | ZerohashTheme | Defaults to system. |
| allowList | string[] | Restrict the hosts the embedded WebView may load. Android only — passing it on iOS rejects the call. |
PluginListenerHandle
| Prop | Type |
| ------------ | ----------------------------------------- |
| remove | () => Promise<void> |
ZerohashErrorEvent
Payload of the error event.
| Prop | Type |
| ------------- | ------------------- |
| code | string |
| message | string |
GenericEvent
Payload of the low-level event events forwarded from the flow.
| Prop | Type |
| ---------- | ---------------------------------------- |
| type | string |
| data | { [key: string]: unknown; } |
FundCompletedEvent
Payload of the fundCompleted event, emitted when a deposit completes.
Any field the flow does not provide is null.
| Prop | Type |
| -------------------- | --------------------------- |
| depositAddress | string | null |
| network | string | null |
| assetSymbol | string | null |
| amount | string | null |
| transactionId | string | null |
| fundId | string | null |
| notionalAmount | string | null |
FundDepositEvent
Payload of the fundDeposit event — the status of a deposit funded from an
external source. Any field the flow does not provide is null.
| Prop | Type | Description |
| --------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| depositId | string | null | Unique identifier for the deposit. |
| status | string | null | Status value, e.g. PROCESSED, FAILED, PENDING. |
| statusDetails | string | null | Human-readable detail for the status. |
| statusOccurredAt | string | null | When the status occurred (ISO 8601). |
| success | boolean | true once the deposit is processed; false while pending, verifying or failed. |
| assetId | string | null | Asset identifier (e.g. USDC). |
| networkId | string | null | Network identifier (e.g. ethereum). |
| amount | string | null | Amount deposited. |
| accountMatchingStatus | string | null | Account-matching validation status, e.g. PENDING, VALID, INVALID, ERROR. |
| accountMatchingReason | string | null | Why account matching failed. On a name mismatch this is the only explanation available anywhere in the stack, so prefer it over reporting a bare id. |
CryptoWithdrawalsCompletedEvent
Payload of the withdrawalCompleted event, emitted when a withdrawal is submitted.
| Prop | Type | Description |
| ------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| withdrawalRequestId | string | null | The withdrawal request ID returned from the API. |
| status | string | null | Terminal status value, e.g. CONFIRMED or FAILED. |
| statusDetails | string | null | Human-readable reason for the status. On a failure this is the only explanation available anywhere in the stack, so prefer it over reporting a bare id. |
| assetId | string | null | Asset identifier (e.g. btc, eth). |
| networkId | string | null | Network identifier (e.g. bitcoin, ethereum). |
| amount | string | null | Amount withdrawn. |
Type Aliases
ZerohashEnvironment
Which zerohash environment the session runs against.
'sandbox' | 'production'
ZerohashTheme
Colour scheme for the zerohash UI. system follows the device setting.
'light' | 'dark' | 'system'
