@formo/analytics-react-native 0.1.4 → 1.0.0
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 +25 -0
- package/lib/commonjs/FormoAnalytics.js +158 -79
- package/lib/commonjs/FormoAnalytics.js.map +1 -1
- package/lib/commonjs/FormoAnalyticsProvider.js +32 -26
- package/lib/commonjs/FormoAnalyticsProvider.js.map +1 -1
- package/lib/commonjs/constants/events.js +5 -1
- package/lib/commonjs/constants/events.js.map +1 -1
- package/lib/commonjs/constants/index.js +3 -3
- package/lib/commonjs/constants/storage.js +8 -1
- package/lib/commonjs/constants/storage.js.map +1 -1
- package/lib/commonjs/index.js +7 -7
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/lib/consent/index.js +8 -8
- package/lib/commonjs/lib/consent/index.js.map +1 -1
- package/lib/commonjs/lib/event/EventFactory.js +135 -52
- package/lib/commonjs/lib/event/EventFactory.js.map +1 -1
- package/lib/commonjs/lib/event/EventManager.js +6 -6
- package/lib/commonjs/lib/event/EventManager.js.map +1 -1
- package/lib/commonjs/lib/event/EventQueue.js +35 -24
- package/lib/commonjs/lib/event/EventQueue.js.map +1 -1
- package/lib/commonjs/lib/event/index.js +4 -4
- package/lib/commonjs/lib/installReferrer/index.js +193 -0
- package/lib/commonjs/lib/installReferrer/index.js.map +1 -0
- package/lib/commonjs/lib/lifecycle/index.js +24 -17
- package/lib/commonjs/lib/lifecycle/index.js.map +1 -1
- package/lib/commonjs/lib/session/index.js +13 -13
- package/lib/commonjs/lib/session/index.js.map +1 -1
- package/lib/commonjs/lib/storage/AsyncStorageAdapter.js +10 -10
- package/lib/commonjs/lib/storage/AsyncStorageAdapter.js.map +1 -1
- package/lib/commonjs/lib/storage/MemoryStorage.js +1 -1
- package/lib/commonjs/lib/storage/StorageBlueprint.js +2 -2
- package/lib/commonjs/lib/storage/StorageBlueprint.js.map +1 -1
- package/lib/commonjs/lib/storage/StorageManager.js +6 -6
- package/lib/commonjs/lib/storage/StorageManager.js.map +1 -1
- package/lib/commonjs/lib/storage/index.js +4 -4
- package/lib/commonjs/lib/wagmi/WagmiEventHandler.js +31 -36
- package/lib/commonjs/lib/wagmi/WagmiEventHandler.js.map +1 -1
- package/lib/commonjs/lib/wagmi/index.js +2 -2
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/solana/address.js +110 -0
- package/lib/commonjs/solana/address.js.map +1 -0
- package/lib/commonjs/solana/index.js +28 -0
- package/lib/commonjs/solana/index.js.map +1 -0
- package/lib/commonjs/solana/types.js +47 -0
- package/lib/commonjs/solana/types.js.map +1 -0
- package/lib/commonjs/types/events.js.map +1 -1
- package/lib/commonjs/types/index.js +2 -2
- package/lib/commonjs/utils/address.js +60 -6
- package/lib/commonjs/utils/address.js.map +1 -1
- package/lib/commonjs/utils/hash.js +44 -6
- package/lib/commonjs/utils/hash.js.map +1 -1
- package/lib/commonjs/utils/index.js +5 -5
- package/lib/commonjs/utils/trafficSource.js +74 -13
- package/lib/commonjs/utils/trafficSource.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/module/FormoAnalytics.js +107 -26
- package/lib/module/FormoAnalytics.js.map +1 -1
- package/lib/module/FormoAnalyticsProvider.js +21 -13
- package/lib/module/FormoAnalyticsProvider.js.map +1 -1
- package/lib/module/constants/config.js +2 -0
- package/lib/module/constants/config.js.map +1 -1
- package/lib/module/constants/events.js +6 -0
- package/lib/module/constants/events.js.map +1 -1
- package/lib/module/constants/index.js +5 -3
- package/lib/module/constants/index.js.map +1 -1
- package/lib/module/constants/storage.js +9 -0
- package/lib/module/constants/storage.js.map +1 -1
- package/lib/module/index.js +6 -4
- package/lib/module/index.js.map +1 -1
- package/lib/module/lib/consent/index.js +4 -2
- package/lib/module/lib/consent/index.js.map +1 -1
- package/lib/module/lib/event/EventFactory.js +116 -33
- package/lib/module/lib/event/EventFactory.js.map +1 -1
- package/lib/module/lib/event/EventManager.js +5 -3
- package/lib/module/lib/event/EventManager.js.map +1 -1
- package/lib/module/lib/event/EventQueue.js +18 -5
- package/lib/module/lib/event/EventQueue.js.map +1 -1
- package/lib/module/lib/event/index.js +6 -4
- package/lib/module/lib/event/index.js.map +1 -1
- package/lib/module/lib/event/types.js +2 -0
- package/lib/module/lib/installReferrer/index.js +189 -0
- package/lib/module/lib/installReferrer/index.js.map +1 -0
- package/lib/module/lib/lifecycle/index.js +14 -5
- package/lib/module/lib/lifecycle/index.js.map +1 -1
- package/lib/module/lib/logger/index.js +2 -0
- package/lib/module/lib/logger/index.js.map +1 -1
- package/lib/module/lib/session/index.js +5 -3
- package/lib/module/lib/session/index.js.map +1 -1
- package/lib/module/lib/storage/AsyncStorageAdapter.js +4 -2
- package/lib/module/lib/storage/AsyncStorageAdapter.js.map +1 -1
- package/lib/module/lib/storage/MemoryStorage.js +3 -1
- package/lib/module/lib/storage/MemoryStorage.js.map +1 -1
- package/lib/module/lib/storage/StorageBlueprint.js +3 -1
- package/lib/module/lib/storage/StorageBlueprint.js.map +1 -1
- package/lib/module/lib/storage/StorageManager.js +5 -3
- package/lib/module/lib/storage/StorageManager.js.map +1 -1
- package/lib/module/lib/storage/index.js +6 -4
- package/lib/module/lib/storage/index.js.map +1 -1
- package/lib/module/lib/storage/types.js +1 -1
- package/lib/module/lib/wagmi/WagmiEventHandler.js +5 -8
- package/lib/module/lib/wagmi/WagmiEventHandler.js.map +1 -1
- package/lib/module/lib/wagmi/index.js +4 -2
- package/lib/module/lib/wagmi/index.js.map +1 -1
- package/lib/module/lib/wagmi/types.js +1 -1
- package/lib/module/package.json +1 -0
- package/lib/module/solana/address.js +102 -0
- package/lib/module/solana/address.js.map +1 -0
- package/lib/module/solana/index.js +5 -0
- package/lib/module/solana/index.js.map +1 -0
- package/lib/module/solana/types.js +42 -0
- package/lib/module/solana/types.js.map +1 -0
- package/lib/module/types/base.js +2 -0
- package/lib/module/types/events.js +2 -0
- package/lib/module/types/events.js.map +1 -1
- package/lib/module/types/index.js +4 -2
- package/lib/module/types/index.js.map +1 -1
- package/lib/module/utils/address.js +60 -6
- package/lib/module/utils/address.js.map +1 -1
- package/lib/module/utils/hash.js +46 -6
- package/lib/module/utils/hash.js.map +1 -1
- package/lib/module/utils/helpers.js +2 -0
- package/lib/module/utils/helpers.js.map +1 -1
- package/lib/module/utils/index.js +7 -5
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/utils/timestamp.js +2 -0
- package/lib/module/utils/timestamp.js.map +1 -1
- package/lib/module/utils/trafficSource.js +64 -3
- package/lib/module/utils/trafficSource.js.map +1 -1
- package/lib/module/version.js +3 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/{FormoAnalytics.d.ts → commonjs/FormoAnalytics.d.ts} +23 -4
- package/lib/typescript/commonjs/FormoAnalytics.d.ts.map +1 -0
- package/lib/typescript/commonjs/FormoAnalyticsProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/constants/config.d.ts.map +1 -0
- package/lib/typescript/{constants → commonjs/constants}/events.d.ts +1 -0
- package/lib/typescript/commonjs/constants/events.d.ts.map +1 -0
- package/lib/typescript/commonjs/constants/index.d.ts.map +1 -0
- package/lib/typescript/{constants → commonjs/constants}/storage.d.ts +3 -0
- package/lib/typescript/commonjs/constants/storage.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/consent/index.d.ts.map +1 -0
- package/lib/typescript/{lib → commonjs/lib}/event/EventFactory.d.ts +36 -1
- package/lib/typescript/commonjs/lib/event/EventFactory.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/event/EventManager.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/event/EventQueue.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/event/index.d.ts.map +1 -0
- package/lib/typescript/{lib → commonjs/lib}/event/types.d.ts +1 -1
- package/lib/typescript/commonjs/lib/event/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/installReferrer/index.d.ts +39 -0
- package/lib/typescript/commonjs/lib/installReferrer/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/lifecycle/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/logger/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/session/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/storage/AsyncStorageAdapter.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/storage/MemoryStorage.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/storage/StorageBlueprint.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/storage/StorageManager.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/storage/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/storage/types.d.ts.map +1 -0
- package/lib/typescript/{lib → commonjs/lib}/wagmi/WagmiEventHandler.d.ts +0 -1
- package/lib/typescript/commonjs/lib/wagmi/WagmiEventHandler.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/wagmi/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/lib/wagmi/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/solana/address.d.ts +42 -0
- package/lib/typescript/commonjs/solana/address.d.ts.map +1 -0
- package/lib/typescript/commonjs/solana/index.d.ts +3 -0
- package/lib/typescript/commonjs/solana/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/solana/types.d.ts +34 -0
- package/lib/typescript/commonjs/solana/types.d.ts.map +1 -0
- package/lib/typescript/{types → commonjs/types}/base.d.ts +39 -1
- package/lib/typescript/commonjs/types/base.d.ts.map +1 -0
- package/lib/typescript/{types → commonjs/types}/events.d.ts +1 -1
- package/lib/typescript/commonjs/types/events.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/address.d.ts +45 -0
- package/lib/typescript/commonjs/utils/address.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/hash.d.ts +18 -0
- package/lib/typescript/commonjs/utils/hash.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/helpers.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/utils/timestamp.d.ts.map +1 -0
- package/lib/typescript/{utils → commonjs/utils}/trafficSource.d.ts +16 -0
- package/lib/typescript/commonjs/utils/trafficSource.d.ts.map +1 -0
- package/lib/typescript/commonjs/version.d.ts +2 -0
- package/lib/typescript/commonjs/version.d.ts.map +1 -0
- package/lib/typescript/module/FormoAnalytics.d.ts +182 -0
- package/lib/typescript/module/FormoAnalytics.d.ts.map +1 -0
- package/lib/typescript/module/FormoAnalyticsProvider.d.ts +29 -0
- package/lib/typescript/module/FormoAnalyticsProvider.d.ts.map +1 -0
- package/lib/typescript/module/constants/config.d.ts +8 -0
- package/lib/typescript/module/constants/config.d.ts.map +1 -0
- package/lib/typescript/module/constants/events.d.ts +24 -0
- package/lib/typescript/module/constants/events.d.ts.map +1 -0
- package/lib/typescript/module/constants/index.d.ts +4 -0
- package/lib/typescript/module/constants/index.d.ts.map +1 -0
- package/lib/typescript/module/constants/storage.d.ts +13 -0
- package/lib/typescript/module/constants/storage.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +44 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/lib/consent/index.d.ts +13 -0
- package/lib/typescript/module/lib/consent/index.d.ts.map +1 -0
- package/lib/typescript/module/lib/event/EventFactory.d.ts +99 -0
- package/lib/typescript/module/lib/event/EventFactory.d.ts.map +1 -0
- package/lib/typescript/module/lib/event/EventManager.d.ts +17 -0
- package/lib/typescript/module/lib/event/EventManager.d.ts.map +1 -0
- package/lib/typescript/module/lib/event/EventQueue.d.ts +74 -0
- package/lib/typescript/module/lib/event/EventQueue.d.ts.map +1 -0
- package/lib/typescript/module/lib/event/index.d.ts +5 -0
- package/lib/typescript/module/lib/event/index.d.ts.map +1 -0
- package/lib/typescript/module/lib/event/types.d.ts +23 -0
- package/lib/typescript/module/lib/event/types.d.ts.map +1 -0
- package/lib/typescript/module/lib/installReferrer/index.d.ts +39 -0
- package/lib/typescript/module/lib/installReferrer/index.d.ts.map +1 -0
- package/lib/typescript/module/lib/lifecycle/index.d.ts +46 -0
- package/lib/typescript/module/lib/lifecycle/index.d.ts.map +1 -0
- package/lib/typescript/module/lib/logger/index.d.ts +19 -0
- package/lib/typescript/module/lib/logger/index.d.ts.map +1 -0
- package/lib/typescript/module/lib/session/index.d.ts +41 -0
- package/lib/typescript/module/lib/session/index.d.ts.map +1 -0
- package/lib/typescript/module/lib/storage/AsyncStorageAdapter.d.ts +48 -0
- package/lib/typescript/module/lib/storage/AsyncStorageAdapter.d.ts.map +1 -0
- package/lib/typescript/module/lib/storage/MemoryStorage.d.ts +18 -0
- package/lib/typescript/module/lib/storage/MemoryStorage.d.ts.map +1 -0
- package/lib/typescript/module/lib/storage/StorageBlueprint.d.ts +21 -0
- package/lib/typescript/module/lib/storage/StorageBlueprint.d.ts.map +1 -0
- package/lib/typescript/module/lib/storage/StorageManager.d.ts +45 -0
- package/lib/typescript/module/lib/storage/StorageManager.d.ts.map +1 -0
- package/lib/typescript/module/lib/storage/index.d.ts +5 -0
- package/lib/typescript/module/lib/storage/index.d.ts.map +1 -0
- package/lib/typescript/module/lib/storage/types.d.ts +22 -0
- package/lib/typescript/module/lib/storage/types.d.ts.map +1 -0
- package/lib/typescript/module/lib/wagmi/WagmiEventHandler.d.ts +103 -0
- package/lib/typescript/module/lib/wagmi/WagmiEventHandler.d.ts.map +1 -0
- package/lib/typescript/module/lib/wagmi/index.d.ts +3 -0
- package/lib/typescript/module/lib/wagmi/index.d.ts.map +1 -0
- package/lib/typescript/module/lib/wagmi/types.d.ts +54 -0
- package/lib/typescript/module/lib/wagmi/types.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/solana/address.d.ts +42 -0
- package/lib/typescript/module/solana/address.d.ts.map +1 -0
- package/lib/typescript/module/solana/index.d.ts +3 -0
- package/lib/typescript/module/solana/index.d.ts.map +1 -0
- package/lib/typescript/module/solana/types.d.ts +34 -0
- package/lib/typescript/module/solana/types.d.ts.map +1 -0
- package/lib/typescript/module/types/base.d.ts +258 -0
- package/lib/typescript/module/types/base.d.ts.map +1 -0
- package/lib/typescript/module/types/events.d.ts +111 -0
- package/lib/typescript/module/types/events.d.ts.map +1 -0
- package/lib/typescript/module/types/index.d.ts +3 -0
- package/lib/typescript/module/types/index.d.ts.map +1 -0
- package/lib/typescript/module/utils/address.d.ts +45 -0
- package/lib/typescript/module/utils/address.d.ts.map +1 -0
- package/lib/typescript/module/utils/hash.d.ts +18 -0
- package/lib/typescript/module/utils/hash.d.ts.map +1 -0
- package/lib/typescript/module/utils/helpers.d.ts +26 -0
- package/lib/typescript/module/utils/helpers.d.ts.map +1 -0
- package/lib/typescript/module/utils/index.d.ts +6 -0
- package/lib/typescript/module/utils/index.d.ts.map +1 -0
- package/lib/typescript/module/utils/timestamp.d.ts +13 -0
- package/lib/typescript/module/utils/timestamp.d.ts.map +1 -0
- package/lib/typescript/module/utils/trafficSource.d.ts +46 -0
- package/lib/typescript/module/utils/trafficSource.d.ts.map +1 -0
- package/lib/typescript/module/version.d.ts +2 -0
- package/lib/typescript/module/version.d.ts.map +1 -0
- package/package.json +44 -49
- package/src/FormoAnalytics.ts +118 -16
- package/src/constants/events.ts +4 -0
- package/src/constants/storage.ts +7 -0
- package/src/lib/event/EventFactory.ts +129 -29
- package/src/lib/event/EventQueue.ts +14 -0
- package/src/lib/event/types.ts +0 -1
- package/src/lib/installReferrer/index.ts +225 -0
- package/src/lib/lifecycle/index.ts +10 -1
- package/src/lib/wagmi/WagmiEventHandler.ts +0 -4
- package/src/solana/address.ts +122 -0
- package/src/solana/index.ts +2 -0
- package/src/solana/types.ts +46 -0
- package/src/types/base.ts +41 -1
- package/src/types/events.ts +1 -1
- package/src/utils/address.ts +72 -6
- package/src/utils/hash.ts +51 -6
- package/src/utils/trafficSource.ts +73 -0
- package/src/version.ts +1 -1
- package/lib/typescript/FormoAnalytics.d.ts.map +0 -1
- package/lib/typescript/FormoAnalyticsProvider.d.ts.map +0 -1
- package/lib/typescript/constants/config.d.ts.map +0 -1
- package/lib/typescript/constants/events.d.ts.map +0 -1
- package/lib/typescript/constants/index.d.ts.map +0 -1
- package/lib/typescript/constants/storage.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/lib/consent/index.d.ts.map +0 -1
- package/lib/typescript/lib/event/EventFactory.d.ts.map +0 -1
- package/lib/typescript/lib/event/EventManager.d.ts.map +0 -1
- package/lib/typescript/lib/event/EventQueue.d.ts.map +0 -1
- package/lib/typescript/lib/event/index.d.ts.map +0 -1
- package/lib/typescript/lib/event/types.d.ts.map +0 -1
- package/lib/typescript/lib/lifecycle/index.d.ts.map +0 -1
- package/lib/typescript/lib/logger/index.d.ts.map +0 -1
- package/lib/typescript/lib/session/index.d.ts.map +0 -1
- package/lib/typescript/lib/storage/AsyncStorageAdapter.d.ts.map +0 -1
- package/lib/typescript/lib/storage/MemoryStorage.d.ts.map +0 -1
- package/lib/typescript/lib/storage/StorageBlueprint.d.ts.map +0 -1
- package/lib/typescript/lib/storage/StorageManager.d.ts.map +0 -1
- package/lib/typescript/lib/storage/index.d.ts.map +0 -1
- package/lib/typescript/lib/storage/types.d.ts.map +0 -1
- package/lib/typescript/lib/wagmi/WagmiEventHandler.d.ts.map +0 -1
- package/lib/typescript/lib/wagmi/index.d.ts.map +0 -1
- package/lib/typescript/lib/wagmi/types.d.ts.map +0 -1
- package/lib/typescript/types/base.d.ts.map +0 -1
- package/lib/typescript/types/events.d.ts.map +0 -1
- package/lib/typescript/types/index.d.ts.map +0 -1
- package/lib/typescript/utils/address.d.ts +0 -25
- package/lib/typescript/utils/address.d.ts.map +0 -1
- package/lib/typescript/utils/hash.d.ts +0 -10
- package/lib/typescript/utils/hash.d.ts.map +0 -1
- package/lib/typescript/utils/helpers.d.ts.map +0 -1
- package/lib/typescript/utils/index.d.ts.map +0 -1
- package/lib/typescript/utils/timestamp.d.ts.map +0 -1
- package/lib/typescript/utils/trafficSource.d.ts.map +0 -1
- package/lib/typescript/version.d.ts +0 -2
- package/lib/typescript/version.d.ts.map +0 -1
- /package/lib/typescript/{FormoAnalyticsProvider.d.ts → commonjs/FormoAnalyticsProvider.d.ts} +0 -0
- /package/lib/typescript/{constants → commonjs/constants}/config.d.ts +0 -0
- /package/lib/typescript/{constants → commonjs/constants}/index.d.ts +0 -0
- /package/lib/typescript/{index.d.ts → commonjs/index.d.ts} +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/consent/index.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/event/EventManager.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/event/EventQueue.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/event/index.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/lifecycle/index.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/logger/index.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/session/index.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/storage/AsyncStorageAdapter.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/storage/MemoryStorage.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/storage/StorageBlueprint.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/storage/StorageManager.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/storage/index.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/storage/types.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/wagmi/index.d.ts +0 -0
- /package/lib/typescript/{lib → commonjs/lib}/wagmi/types.d.ts +0 -0
- /package/lib/typescript/{types → commonjs/types}/index.d.ts +0 -0
- /package/lib/typescript/{utils → commonjs/utils}/helpers.d.ts +0 -0
- /package/lib/typescript/{utils → commonjs/utils}/index.d.ts +0 -0
- /package/lib/typescript/{utils → commonjs/utils}/timestamp.d.ts +0 -0
|
@@ -168,6 +168,20 @@ export class EventQueue implements IEventQueue {
|
|
|
168
168
|
`Event enqueued: ${getActionDescriptor(event.type, event.properties)}`
|
|
169
169
|
);
|
|
170
170
|
|
|
171
|
+
// Per-event detail line for debugging (only prints when debug logging is on).
|
|
172
|
+
const ctx = (event.context ?? {}) as Record<string, unknown>;
|
|
173
|
+
logger.debug(
|
|
174
|
+
"Event detail:",
|
|
175
|
+
JSON.stringify({
|
|
176
|
+
type: event.type,
|
|
177
|
+
event: event.event,
|
|
178
|
+
session_id: event.session_id,
|
|
179
|
+
anonymous_id: event.anonymous_id,
|
|
180
|
+
user_agent: ctx.user_agent,
|
|
181
|
+
page_url: ctx.page_url,
|
|
182
|
+
})
|
|
183
|
+
);
|
|
184
|
+
|
|
171
185
|
const hasReachedFlushAt = this.queue.length >= this.flushAt;
|
|
172
186
|
const hasReachedQueueSize =
|
|
173
187
|
this.queue.reduce(
|
package/src/lib/event/types.ts
CHANGED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install Referrer / attribution capture (Android)
|
|
3
|
+
*
|
|
4
|
+
* Populates the existing traffic source fields (utm_source, utm_medium,
|
|
5
|
+
* utm_campaign, utm_term, utm_content, ref, referrer) from the Google Play
|
|
6
|
+
* Install Referrer on first launch. This is what enables web-to-mobile
|
|
7
|
+
* attribution: a user who tapped a link on example.com before installing shows
|
|
8
|
+
* up with that referrer on their first events (see P-2207).
|
|
9
|
+
*
|
|
10
|
+
* - Android: Google Play Install Referrer API via react-native-play-install-referrer
|
|
11
|
+
* (optional peer dep). Returns a URL-encoded query string like
|
|
12
|
+
* "utm_source=example.com&utm_campaign=spring_sale&..." which we parse with
|
|
13
|
+
* parseTrafficSource.
|
|
14
|
+
*
|
|
15
|
+
* - iOS: NOT supported. Apple exposes no install-referrer API, so an install
|
|
16
|
+
* cannot be attributed to a referring website from the SDK. Doing so requires
|
|
17
|
+
* a third-party attribution service (Branch/AppsFlyer) or fingerprint
|
|
18
|
+
* matching — out of scope. On iOS this capture is a no-op.
|
|
19
|
+
*
|
|
20
|
+
* The native module is lazy-required and capture silently no-ops when it is not
|
|
21
|
+
* installed (keeps Expo Go and minimal integrations working).
|
|
22
|
+
*
|
|
23
|
+
* Result is merged with mergeTrafficSourceFill so a deep link that arrived
|
|
24
|
+
* via Linking.getInitialURL() takes precedence over install-referrer data.
|
|
25
|
+
*
|
|
26
|
+
* The resolution is one-shot: on success we set LOCAL_INSTALL_REFERRER_RESOLVED_KEY
|
|
27
|
+
* so we never call the native API again (Play returns meaningful data only on
|
|
28
|
+
* the first fetch).
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { Platform } from "react-native";
|
|
32
|
+
import { logger } from "../logger";
|
|
33
|
+
import { storage, getStorageManager } from "../storage";
|
|
34
|
+
import { LOCAL_INSTALL_REFERRER_RESOLVED_KEY } from "../../constants/storage";
|
|
35
|
+
import {
|
|
36
|
+
parseTrafficSource,
|
|
37
|
+
mergeTrafficSourceFill,
|
|
38
|
+
} from "../../utils/trafficSource";
|
|
39
|
+
import type { ITrafficSource } from "../../types";
|
|
40
|
+
|
|
41
|
+
// Lazy-load the optional native module. Absence is fine — attribution is best-effort.
|
|
42
|
+
let PlayInstallReferrer: {
|
|
43
|
+
getInstallReferrerInfo: (
|
|
44
|
+
cb: (info: { installReferrer?: string } | null, error?: unknown) => void
|
|
45
|
+
) => void;
|
|
46
|
+
} | null = null;
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
PlayInstallReferrer = require("react-native-play-install-referrer")
|
|
50
|
+
.PlayInstallReferrer;
|
|
51
|
+
} catch {
|
|
52
|
+
// Not installed — Android install referrer capture will no-op.
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Upper bound on the Play Install Referrer native call.
|
|
57
|
+
*
|
|
58
|
+
* SDK init awaits this capture so the referrer is available for the
|
|
59
|
+
* Application Installed event, which means it must never block init
|
|
60
|
+
* indefinitely (a stalled Play Store service connection can leave the callback
|
|
61
|
+
* pending forever). Until init resolves the provider serves its no-op context,
|
|
62
|
+
* so any delay here is a window where startup events are dropped.
|
|
63
|
+
*
|
|
64
|
+
* That cost is paid on the FIRST launch only: the capture is one-shot, and
|
|
65
|
+
* every later launch short-circuits on LOCAL_INSTALL_REFERRER_RESOLVED_KEY
|
|
66
|
+
* before reaching the native call. The bind is normally sub-second, so this is
|
|
67
|
+
* kept tight rather than generous — on timeout we skip and retry next launch.
|
|
68
|
+
*/
|
|
69
|
+
const INSTALL_REFERRER_TIMEOUT_MS = 1500;
|
|
70
|
+
|
|
71
|
+
export interface CaptureOptions {
|
|
72
|
+
customRefParams?: string[];
|
|
73
|
+
pathPattern?: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Capture install-time attribution and merge into the stored traffic source.
|
|
78
|
+
* One-shot: returns immediately if already resolved on a previous launch.
|
|
79
|
+
*/
|
|
80
|
+
export async function captureInstallReferrer(
|
|
81
|
+
options: CaptureOptions = {}
|
|
82
|
+
): Promise<void> {
|
|
83
|
+
try {
|
|
84
|
+
// The one-shot flag is only useful if it can persist across launches.
|
|
85
|
+
// Without AsyncStorage (MemoryStorage fallback) the flag is lost every
|
|
86
|
+
// restart, so we'd re-hit the native API every cold start. Mirror the
|
|
87
|
+
// lifecycle manager's guard and skip capture entirely in that case.
|
|
88
|
+
const hasPersistentStorage =
|
|
89
|
+
getStorageManager()?.hasPersistentStorage() ?? false;
|
|
90
|
+
if (!hasPersistentStorage) {
|
|
91
|
+
logger.debug(
|
|
92
|
+
"InstallReferrer: persistent storage unavailable, skipping capture"
|
|
93
|
+
);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const resolved = storage().get(LOCAL_INSTALL_REFERRER_RESOLVED_KEY);
|
|
98
|
+
if (resolved === "true") {
|
|
99
|
+
logger.debug("InstallReferrer: already resolved, skipping");
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let didResolve = false;
|
|
104
|
+
|
|
105
|
+
if (Platform.OS === "android") {
|
|
106
|
+
didResolve = await captureAndroidReferrer(options);
|
|
107
|
+
} else {
|
|
108
|
+
// iOS (and any non-Android platform): no OS-level install referrer exists.
|
|
109
|
+
// Attributing an install to a referring website requires a third-party
|
|
110
|
+
// attribution SDK (Branch/AppsFlyer) or fingerprint matching. No-op.
|
|
111
|
+
logger.debug(
|
|
112
|
+
`InstallReferrer: no install-referrer source on ${Platform.OS}, skipping`
|
|
113
|
+
);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (didResolve) {
|
|
118
|
+
await storage().setAsync(LOCAL_INSTALL_REFERRER_RESOLVED_KEY, "true");
|
|
119
|
+
}
|
|
120
|
+
} catch (error) {
|
|
121
|
+
// Never let attribution failures break SDK init.
|
|
122
|
+
logger.debug("InstallReferrer: capture failed", error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Android: call Play Install Referrer API once, parse the returned UTM query
|
|
128
|
+
* string, fill in any empty traffic-source fields.
|
|
129
|
+
*/
|
|
130
|
+
async function captureAndroidReferrer(
|
|
131
|
+
options: CaptureOptions
|
|
132
|
+
): Promise<boolean> {
|
|
133
|
+
if (!PlayInstallReferrer) {
|
|
134
|
+
// Warn (not debug) on Android: attribution silently does nothing here, and
|
|
135
|
+
// marking the peer optional suppresses the missing-peer install warning, so
|
|
136
|
+
// this is the only actionable signal the integrator gets.
|
|
137
|
+
logger.warn(
|
|
138
|
+
"InstallReferrer: react-native-play-install-referrer is not installed — " +
|
|
139
|
+
"Android install attribution is disabled. Install it and rebuild the " +
|
|
140
|
+
"native app to enable web-to-mobile attribution."
|
|
141
|
+
);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Distinguish "native API errored" (retry next launch) from "native API
|
|
146
|
+
// succeeded but no referrer data" (organic install — mark resolved so we
|
|
147
|
+
// don't re-call every launch).
|
|
148
|
+
//
|
|
149
|
+
// The native callback is bounded by a timeout: a stalled Play Store service
|
|
150
|
+
// connection would otherwise leave this promise pending forever, and since
|
|
151
|
+
// init() awaits this, that would hang SDK initialization and leave every
|
|
152
|
+
// consumer on the no-op context. On timeout we resolve as "errored" so the
|
|
153
|
+
// capture is retried on the next launch.
|
|
154
|
+
const result = await new Promise<{
|
|
155
|
+
ok: boolean;
|
|
156
|
+
info: { installReferrer?: string } | null;
|
|
157
|
+
}>((resolve) => {
|
|
158
|
+
let settled = false;
|
|
159
|
+
const finish = (value: {
|
|
160
|
+
ok: boolean;
|
|
161
|
+
info: { installReferrer?: string } | null;
|
|
162
|
+
}) => {
|
|
163
|
+
if (settled) return;
|
|
164
|
+
settled = true;
|
|
165
|
+
clearTimeout(timer);
|
|
166
|
+
resolve(value);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const timer = setTimeout(() => {
|
|
170
|
+
logger.debug(
|
|
171
|
+
`InstallReferrer: Play API did not respond within ${INSTALL_REFERRER_TIMEOUT_MS}ms, continuing`
|
|
172
|
+
);
|
|
173
|
+
finish({ ok: false, info: null });
|
|
174
|
+
}, INSTALL_REFERRER_TIMEOUT_MS);
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
PlayInstallReferrer!.getInstallReferrerInfo((info, error) => {
|
|
178
|
+
if (error) {
|
|
179
|
+
logger.debug("InstallReferrer: Play API error", error);
|
|
180
|
+
finish({ ok: false, info: null });
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
finish({ ok: true, info: info ?? null });
|
|
184
|
+
});
|
|
185
|
+
} catch (e) {
|
|
186
|
+
logger.debug("InstallReferrer: Play API threw", e);
|
|
187
|
+
finish({ ok: false, info: null });
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
if (!result.ok) return false; // errored — retry next launch
|
|
192
|
+
|
|
193
|
+
const referrerQuery = result.info?.installReferrer;
|
|
194
|
+
if (!referrerQuery) {
|
|
195
|
+
// Organic install (or untracked). API answered definitively — mark
|
|
196
|
+
// resolved so we don't ask Play again on every launch.
|
|
197
|
+
logger.debug("InstallReferrer: no Play referrer (organic install)");
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// The referrer string is already URL-encoded UTM params, e.g.
|
|
202
|
+
// "utm_source=google&utm_medium=cpc&utm_campaign=spring&utm_term=kw&utm_content=ad1"
|
|
203
|
+
// Wrap in a dummy URL so parseTrafficSource can read it.
|
|
204
|
+
const parsed = parseTrafficSource(
|
|
205
|
+
`https://play.google.com/store/apps?${referrerQuery}`,
|
|
206
|
+
options.customRefParams,
|
|
207
|
+
options.pathPattern
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
// Don't let the dummy play.google.com URL overwrite a real referrer — clear
|
|
211
|
+
// referrer if it's the synthetic one and no deep link was present.
|
|
212
|
+
const toMerge: Partial<ITrafficSource> = { ...parsed };
|
|
213
|
+
if (
|
|
214
|
+
toMerge.referrer &&
|
|
215
|
+
toMerge.referrer.startsWith("https://play.google.com/store/apps?")
|
|
216
|
+
) {
|
|
217
|
+
// Preserve the raw referrer query as-is, useful for debugging campaigns
|
|
218
|
+
// that use non-UTM keys.
|
|
219
|
+
toMerge.referrer = referrerQuery;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
mergeTrafficSourceFill(toMerge);
|
|
223
|
+
logger.info("InstallReferrer: captured Android install referrer");
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
LOCAL_APP_VERSION_KEY,
|
|
18
18
|
LOCAL_APP_BUILD_KEY,
|
|
19
19
|
} from "../../constants/storage";
|
|
20
|
+
import { getStoredTrafficSource } from "../../utils/trafficSource";
|
|
20
21
|
|
|
21
22
|
/** Interface for the analytics instance to avoid circular deps */
|
|
22
23
|
interface IAnalyticsInstance {
|
|
@@ -141,11 +142,19 @@ export class AppLifecycleManager {
|
|
|
141
142
|
const { version, build } = this.appVersionInfo;
|
|
142
143
|
|
|
143
144
|
if (previousVersion === null && previousBuild === null) {
|
|
144
|
-
// No stored version — first install
|
|
145
|
+
// No stored version — first install. Attach the captured web-to-mobile
|
|
146
|
+
// attribution (Android Play Install Referrer / deep link) so the install
|
|
147
|
+
// event reports where the user came from, e.g. referrer=example.com.
|
|
148
|
+
// Only non-empty fields are included to keep properties clean.
|
|
149
|
+
const trafficSource = getStoredTrafficSource() ?? {};
|
|
150
|
+
const attribution = Object.fromEntries(
|
|
151
|
+
Object.entries(trafficSource).filter(([, value]) => Boolean(value))
|
|
152
|
+
);
|
|
145
153
|
logger.info("AppLifecycleManager: Application Installed");
|
|
146
154
|
await this.analytics.track("Application Installed", {
|
|
147
155
|
version,
|
|
148
156
|
build,
|
|
157
|
+
...attribution,
|
|
149
158
|
});
|
|
150
159
|
} else if (previousVersion !== version || previousBuild !== build) {
|
|
151
160
|
// Version or build changed — update
|
|
@@ -33,7 +33,6 @@ interface IFormoAnalyticsInstance {
|
|
|
33
33
|
chainId: number;
|
|
34
34
|
address: string;
|
|
35
35
|
message: string;
|
|
36
|
-
signatureHash?: string;
|
|
37
36
|
}): Promise<void>;
|
|
38
37
|
transaction(params: {
|
|
39
38
|
status: TransactionStatus;
|
|
@@ -362,13 +361,11 @@ export class WagmiEventHandler {
|
|
|
362
361
|
|
|
363
362
|
try {
|
|
364
363
|
let status: SignatureStatus;
|
|
365
|
-
let signatureHash: string | undefined;
|
|
366
364
|
|
|
367
365
|
if (state.status === "pending") {
|
|
368
366
|
status = SignatureStatus.REQUESTED;
|
|
369
367
|
} else if (state.status === "success") {
|
|
370
368
|
status = SignatureStatus.CONFIRMED;
|
|
371
|
-
signatureHash = state.data as string;
|
|
372
369
|
} else if (state.status === "error") {
|
|
373
370
|
status = SignatureStatus.REJECTED;
|
|
374
371
|
} else {
|
|
@@ -394,7 +391,6 @@ export class WagmiEventHandler {
|
|
|
394
391
|
chainId,
|
|
395
392
|
address,
|
|
396
393
|
message,
|
|
397
|
-
...(signatureHash && { signatureHash }),
|
|
398
394
|
}).catch((error) => {
|
|
399
395
|
logger.error("WagmiEventHandler: Error tracking signature:", error);
|
|
400
396
|
});
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solana address validation utilities
|
|
3
|
+
*
|
|
4
|
+
* Solana uses Base58 encoded 32-byte public keys as addresses.
|
|
5
|
+
* Format: FDKJvWcJNe6wecbgDYDFPCfgs14aJnVsUfWQRYWLn4Tn (32-44 characters)
|
|
6
|
+
*
|
|
7
|
+
* @see https://solana.com/developers/courses/intro-to-solana/interact-with-wallets
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { SolanaPublicKey } from "./types";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Base58 alphabet used by Solana (Bitcoin alphabet)
|
|
14
|
+
*/
|
|
15
|
+
const BASE58_ALPHABET =
|
|
16
|
+
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
17
|
+
|
|
18
|
+
const BASE58_CHAR_SET = new Set(BASE58_ALPHABET);
|
|
19
|
+
|
|
20
|
+
const MIN_SOLANA_ADDRESS_LENGTH = 32;
|
|
21
|
+
const MAX_SOLANA_ADDRESS_LENGTH = 44;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* System program addresses and other special Solana addresses
|
|
25
|
+
* These are valid addresses but may not represent user wallets
|
|
26
|
+
*/
|
|
27
|
+
export const SOLANA_SYSTEM_ADDRESSES = {
|
|
28
|
+
SYSTEM_PROGRAM: "11111111111111111111111111111111",
|
|
29
|
+
TOKEN_PROGRAM: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
|
|
30
|
+
TOKEN_2022_PROGRAM: "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
|
|
31
|
+
ASSOCIATED_TOKEN_PROGRAM: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
|
|
32
|
+
RENT_SYSVAR: "SysvarRent111111111111111111111111111111111",
|
|
33
|
+
CLOCK_SYSVAR: "SysvarC1ock11111111111111111111111111111111",
|
|
34
|
+
} as const;
|
|
35
|
+
|
|
36
|
+
function isValidBase58String(str: string): boolean {
|
|
37
|
+
for (const ch of str) {
|
|
38
|
+
if (!BASE58_CHAR_SET.has(ch)) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check if a string is a valid Solana address format
|
|
47
|
+
*
|
|
48
|
+
* Performs format validation only (length and character set). Does not
|
|
49
|
+
* verify that the address is a valid point on the Ed25519 curve.
|
|
50
|
+
*/
|
|
51
|
+
export function isSolanaAddress(value: unknown): value is string {
|
|
52
|
+
if (typeof value !== "string") {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const trimmed = value.trim();
|
|
57
|
+
|
|
58
|
+
if (
|
|
59
|
+
trimmed.length < MIN_SOLANA_ADDRESS_LENGTH ||
|
|
60
|
+
trimmed.length > MAX_SOLANA_ADDRESS_LENGTH
|
|
61
|
+
) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return isValidBase58String(trimmed);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get a valid Solana address from a string or PublicKey
|
|
70
|
+
*/
|
|
71
|
+
export function getValidSolanaAddress(
|
|
72
|
+
address: string | SolanaPublicKey | null | undefined
|
|
73
|
+
): string | null {
|
|
74
|
+
if (!address) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (typeof address === "object" && "toBase58" in address) {
|
|
79
|
+
try {
|
|
80
|
+
const base58 = address.toBase58();
|
|
81
|
+
return isSolanaAddress(base58) ? base58 : null;
|
|
82
|
+
} catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (typeof address === "string") {
|
|
88
|
+
const trimmed = address.trim();
|
|
89
|
+
return isSolanaAddress(trimmed) ? trimmed : null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Check if a Solana address is a system program or well-known program address
|
|
97
|
+
*/
|
|
98
|
+
export function isSolanaSystemAddress(address: string): boolean {
|
|
99
|
+
const validAddress = getValidSolanaAddress(address);
|
|
100
|
+
if (!validAddress) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return Object.values(SOLANA_SYSTEM_ADDRESSES).includes(
|
|
105
|
+
validAddress as (typeof SOLANA_SYSTEM_ADDRESSES)[keyof typeof SOLANA_SYSTEM_ADDRESSES]
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Check if a Solana address is blocked (should not emit events).
|
|
111
|
+
* Blocks system program addresses since they don't represent user wallets.
|
|
112
|
+
*/
|
|
113
|
+
export function isBlockedSolanaAddress(
|
|
114
|
+
address: string | SolanaPublicKey | null | undefined
|
|
115
|
+
): boolean {
|
|
116
|
+
const validAddress = getValidSolanaAddress(address);
|
|
117
|
+
if (!validAddress) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return isSolanaSystemAddress(validAddress);
|
|
122
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solana-specific type definitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Solana cluster/network types
|
|
7
|
+
* Solana doesn't use chainId like EVM, instead it uses cluster names
|
|
8
|
+
*/
|
|
9
|
+
export type SolanaCluster = "mainnet-beta" | "testnet" | "devnet" | "localnet";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Mapping of Solana clusters to numeric chain IDs for consistency with EVM events
|
|
13
|
+
* These IDs are non-standard but provide a way to identify Solana networks in our analytics
|
|
14
|
+
*
|
|
15
|
+
* Using high numbers (900000+) to avoid collision with EVM chain IDs
|
|
16
|
+
*/
|
|
17
|
+
export const SOLANA_CHAIN_IDS: Record<SolanaCluster, number> = {
|
|
18
|
+
"mainnet-beta": 900001,
|
|
19
|
+
testnet: 900002,
|
|
20
|
+
devnet: 900003,
|
|
21
|
+
localnet: 900004,
|
|
22
|
+
} as const;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Default Solana chain ID (mainnet-beta)
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_SOLANA_CHAIN_ID = SOLANA_CHAIN_IDS["mainnet-beta"];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Check if a chain ID belongs to a Solana network.
|
|
31
|
+
*/
|
|
32
|
+
export function isSolanaChainId(chainId: number | undefined | null): boolean {
|
|
33
|
+
if (chainId === undefined || chainId === null) return false;
|
|
34
|
+
return Object.values(SOLANA_CHAIN_IDS).includes(chainId);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Solana PublicKey interface
|
|
39
|
+
* Used by address validation utilities.
|
|
40
|
+
*/
|
|
41
|
+
export interface SolanaPublicKey {
|
|
42
|
+
toBase58(): string;
|
|
43
|
+
toString(): string;
|
|
44
|
+
toBytes(): Uint8Array;
|
|
45
|
+
equals(other: SolanaPublicKey): boolean;
|
|
46
|
+
}
|
package/src/types/base.ts
CHANGED
|
@@ -56,7 +56,6 @@ export interface IFormoAnalytics {
|
|
|
56
56
|
chainId?: ChainID;
|
|
57
57
|
address: Address;
|
|
58
58
|
message: string;
|
|
59
|
-
signatureHash?: string;
|
|
60
59
|
},
|
|
61
60
|
properties?: IFormoEventProperties,
|
|
62
61
|
context?: IFormoEventContext,
|
|
@@ -161,6 +160,37 @@ export interface AutocaptureOptions {
|
|
|
161
160
|
lifecycle?: boolean;
|
|
162
161
|
}
|
|
163
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Configuration options for attribution capture.
|
|
165
|
+
*
|
|
166
|
+
* Attribution is not an event type — it's context enrichment that decorates
|
|
167
|
+
* every tracked event with `utm_*`, `ref`, and `referrer` fields. These
|
|
168
|
+
* options control the SDK's automatic attribution data sources.
|
|
169
|
+
*/
|
|
170
|
+
export interface AttributionOptions {
|
|
171
|
+
/**
|
|
172
|
+
* Capture traffic source from deep links via React Native's Linking API.
|
|
173
|
+
* When enabled, the SDK calls Linking.getInitialURL() on init and subscribes
|
|
174
|
+
* to the `url` event, parsing UTM parameters and referral codes into the
|
|
175
|
+
* event context.
|
|
176
|
+
* @default true
|
|
177
|
+
*/
|
|
178
|
+
deeplinks?: boolean;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Capture install-time attribution on first launch:
|
|
182
|
+
* - Android: Google Play Install Referrer API (requires react-native-play-install-referrer).
|
|
183
|
+
* Enables web-to-mobile attribution, e.g. referrer=example.com.
|
|
184
|
+
* - iOS: not supported — Apple exposes no install-referrer API, so this is a no-op.
|
|
185
|
+
*
|
|
186
|
+
* Resolved once on first successful fetch and cached; subsequent launches
|
|
187
|
+
* skip the native call. Silently no-ops when the optional native module
|
|
188
|
+
* is not installed.
|
|
189
|
+
* @default true
|
|
190
|
+
*/
|
|
191
|
+
installReferrer?: boolean;
|
|
192
|
+
}
|
|
193
|
+
|
|
164
194
|
/**
|
|
165
195
|
* Configuration options for Wagmi integration
|
|
166
196
|
* Allows the SDK to hook into Wagmi v2 wallet events
|
|
@@ -230,6 +260,16 @@ export interface Options {
|
|
|
230
260
|
* @default true
|
|
231
261
|
*/
|
|
232
262
|
autocapture?: boolean | AutocaptureOptions;
|
|
263
|
+
/**
|
|
264
|
+
* Control attribution context capture (deep links and install referrer).
|
|
265
|
+
* Attribution decorates every tracked event with `utm_*`, `ref`, and
|
|
266
|
+
* `referrer` fields — it is not itself an event type.
|
|
267
|
+
* - `false`: Disable all attribution capture
|
|
268
|
+
* - `true`: Enable all attribution sources (default)
|
|
269
|
+
* - `AttributionOptions`: Granular control over specific sources
|
|
270
|
+
* @default true
|
|
271
|
+
*/
|
|
272
|
+
attribution?: boolean | AttributionOptions;
|
|
233
273
|
/**
|
|
234
274
|
* Wagmi integration configuration
|
|
235
275
|
* When provided, the SDK will hook into Wagmi's event system
|
package/src/types/events.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type AnonymousID = string;
|
|
|
5
5
|
|
|
6
6
|
export interface ICommonProperties {
|
|
7
7
|
anonymous_id: AnonymousID;
|
|
8
|
+
session_id: string;
|
|
8
9
|
user_id: Nullable<string>;
|
|
9
10
|
address: Nullable<string>;
|
|
10
11
|
type: TEventType;
|
|
@@ -85,7 +86,6 @@ export interface SignatureAPIEvent {
|
|
|
85
86
|
chainId?: ChainID;
|
|
86
87
|
address: Address;
|
|
87
88
|
message: string;
|
|
88
|
-
signatureHash?: string;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
export interface ConnectAPIEvent {
|
package/src/utils/address.ts
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Address validation and checksum utilities
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Supports both EVM and Solana addresses.
|
|
5
|
+
*
|
|
6
|
+
* Uses ethereum-cryptography for proper EIP-55 checksum computation.
|
|
5
7
|
*/
|
|
6
8
|
|
|
7
9
|
import { keccak256 } from "ethereum-cryptography/keccak.js";
|
|
8
10
|
import { utf8ToBytes } from "ethereum-cryptography/utils.js";
|
|
11
|
+
import {
|
|
12
|
+
isSolanaAddress,
|
|
13
|
+
getValidSolanaAddress,
|
|
14
|
+
isBlockedSolanaAddress,
|
|
15
|
+
} from "../solana/address";
|
|
16
|
+
import { isSolanaChainId } from "../solana/types";
|
|
9
17
|
|
|
10
18
|
/**
|
|
11
19
|
* Convert Uint8Array to hex string
|
|
@@ -17,7 +25,7 @@ function toHex(bytes: Uint8Array): string {
|
|
|
17
25
|
}
|
|
18
26
|
|
|
19
27
|
/**
|
|
20
|
-
* Check if a string is a valid Ethereum address
|
|
28
|
+
* Check if a string is a valid Ethereum (EVM) address
|
|
21
29
|
*/
|
|
22
30
|
export function isValidAddress(address: string): boolean {
|
|
23
31
|
if (!address) return false;
|
|
@@ -56,7 +64,7 @@ export function toChecksumAddress(address: string): string {
|
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
/**
|
|
59
|
-
* Get valid address or null
|
|
67
|
+
* Get a valid (trimmed) EVM address, or null if invalid.
|
|
60
68
|
*/
|
|
61
69
|
export function getValidAddress(
|
|
62
70
|
address: string | undefined | null
|
|
@@ -68,7 +76,52 @@ export function getValidAddress(
|
|
|
68
76
|
}
|
|
69
77
|
|
|
70
78
|
/**
|
|
71
|
-
*
|
|
79
|
+
* Validates an EVM address and returns it in checksummed format.
|
|
80
|
+
*/
|
|
81
|
+
export function validateAndChecksumAddress(
|
|
82
|
+
address: string
|
|
83
|
+
): string | undefined {
|
|
84
|
+
const validAddress = getValidAddress(address);
|
|
85
|
+
return validAddress ? toChecksumAddress(validAddress) : undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Validates an address for both EVM and Solana chains.
|
|
90
|
+
*
|
|
91
|
+
* For EVM addresses, returns checksummed format.
|
|
92
|
+
* For Solana addresses, returns the Base58 address as-is.
|
|
93
|
+
*
|
|
94
|
+
* When chainId is explicitly provided, validation is strict:
|
|
95
|
+
* - Solana chainId → only Solana validation
|
|
96
|
+
* - Non-Solana chainId → only EVM validation
|
|
97
|
+
*
|
|
98
|
+
* When chainId is omitted, EVM is tried first with Solana fallback.
|
|
99
|
+
*/
|
|
100
|
+
export function validateAddress(
|
|
101
|
+
address: string,
|
|
102
|
+
chainId?: number | null
|
|
103
|
+
): string | undefined {
|
|
104
|
+
// Explicit Solana chainId → validate ONLY as Solana
|
|
105
|
+
if (chainId !== undefined && chainId !== null && isSolanaChainId(chainId)) {
|
|
106
|
+
return getValidSolanaAddress(address) || undefined;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Explicit non-Solana chainId → validate ONLY as EVM
|
|
110
|
+
if (chainId !== undefined && chainId !== null) {
|
|
111
|
+
return validateAndChecksumAddress(address);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// No chainId → try EVM first, then Solana fallback
|
|
115
|
+
const validEvmAddress = validateAndChecksumAddress(address);
|
|
116
|
+
if (validEvmAddress) {
|
|
117
|
+
return validEvmAddress;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return getValidSolanaAddress(address) || undefined;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Blocked EVM addresses that should not emit events
|
|
72
125
|
* (zero address, dead address)
|
|
73
126
|
*/
|
|
74
127
|
const BLOCKED_ADDRESSES = new Set<string>([
|
|
@@ -77,8 +130,21 @@ const BLOCKED_ADDRESSES = new Set<string>([
|
|
|
77
130
|
]);
|
|
78
131
|
|
|
79
132
|
/**
|
|
80
|
-
* Check if address is in blocked list
|
|
133
|
+
* Check if an address is in a blocked list.
|
|
134
|
+
* Handles both EVM (zero/dead addresses) and Solana (system program) blocks.
|
|
81
135
|
*/
|
|
82
136
|
export function isBlockedAddress(address: string): boolean {
|
|
83
|
-
|
|
137
|
+
if (!address || typeof address !== "string") return false;
|
|
138
|
+
|
|
139
|
+
const trimmed = address.trim();
|
|
140
|
+
|
|
141
|
+
if (isValidAddress(trimmed)) {
|
|
142
|
+
return BLOCKED_ADDRESSES.has(trimmed.toLowerCase());
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (isSolanaAddress(trimmed)) {
|
|
146
|
+
return isBlockedSolanaAddress(trimmed);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return false;
|
|
84
150
|
}
|