@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.
Files changed (345) hide show
  1. package/README.md +25 -0
  2. package/lib/commonjs/FormoAnalytics.js +158 -79
  3. package/lib/commonjs/FormoAnalytics.js.map +1 -1
  4. package/lib/commonjs/FormoAnalyticsProvider.js +32 -26
  5. package/lib/commonjs/FormoAnalyticsProvider.js.map +1 -1
  6. package/lib/commonjs/constants/events.js +5 -1
  7. package/lib/commonjs/constants/events.js.map +1 -1
  8. package/lib/commonjs/constants/index.js +3 -3
  9. package/lib/commonjs/constants/storage.js +8 -1
  10. package/lib/commonjs/constants/storage.js.map +1 -1
  11. package/lib/commonjs/index.js +7 -7
  12. package/lib/commonjs/index.js.map +1 -1
  13. package/lib/commonjs/lib/consent/index.js +8 -8
  14. package/lib/commonjs/lib/consent/index.js.map +1 -1
  15. package/lib/commonjs/lib/event/EventFactory.js +135 -52
  16. package/lib/commonjs/lib/event/EventFactory.js.map +1 -1
  17. package/lib/commonjs/lib/event/EventManager.js +6 -6
  18. package/lib/commonjs/lib/event/EventManager.js.map +1 -1
  19. package/lib/commonjs/lib/event/EventQueue.js +35 -24
  20. package/lib/commonjs/lib/event/EventQueue.js.map +1 -1
  21. package/lib/commonjs/lib/event/index.js +4 -4
  22. package/lib/commonjs/lib/installReferrer/index.js +193 -0
  23. package/lib/commonjs/lib/installReferrer/index.js.map +1 -0
  24. package/lib/commonjs/lib/lifecycle/index.js +24 -17
  25. package/lib/commonjs/lib/lifecycle/index.js.map +1 -1
  26. package/lib/commonjs/lib/session/index.js +13 -13
  27. package/lib/commonjs/lib/session/index.js.map +1 -1
  28. package/lib/commonjs/lib/storage/AsyncStorageAdapter.js +10 -10
  29. package/lib/commonjs/lib/storage/AsyncStorageAdapter.js.map +1 -1
  30. package/lib/commonjs/lib/storage/MemoryStorage.js +1 -1
  31. package/lib/commonjs/lib/storage/StorageBlueprint.js +2 -2
  32. package/lib/commonjs/lib/storage/StorageBlueprint.js.map +1 -1
  33. package/lib/commonjs/lib/storage/StorageManager.js +6 -6
  34. package/lib/commonjs/lib/storage/StorageManager.js.map +1 -1
  35. package/lib/commonjs/lib/storage/index.js +4 -4
  36. package/lib/commonjs/lib/wagmi/WagmiEventHandler.js +31 -36
  37. package/lib/commonjs/lib/wagmi/WagmiEventHandler.js.map +1 -1
  38. package/lib/commonjs/lib/wagmi/index.js +2 -2
  39. package/lib/commonjs/package.json +1 -0
  40. package/lib/commonjs/solana/address.js +110 -0
  41. package/lib/commonjs/solana/address.js.map +1 -0
  42. package/lib/commonjs/solana/index.js +28 -0
  43. package/lib/commonjs/solana/index.js.map +1 -0
  44. package/lib/commonjs/solana/types.js +47 -0
  45. package/lib/commonjs/solana/types.js.map +1 -0
  46. package/lib/commonjs/types/events.js.map +1 -1
  47. package/lib/commonjs/types/index.js +2 -2
  48. package/lib/commonjs/utils/address.js +60 -6
  49. package/lib/commonjs/utils/address.js.map +1 -1
  50. package/lib/commonjs/utils/hash.js +44 -6
  51. package/lib/commonjs/utils/hash.js.map +1 -1
  52. package/lib/commonjs/utils/index.js +5 -5
  53. package/lib/commonjs/utils/trafficSource.js +74 -13
  54. package/lib/commonjs/utils/trafficSource.js.map +1 -1
  55. package/lib/commonjs/version.js +1 -1
  56. package/lib/module/FormoAnalytics.js +107 -26
  57. package/lib/module/FormoAnalytics.js.map +1 -1
  58. package/lib/module/FormoAnalyticsProvider.js +21 -13
  59. package/lib/module/FormoAnalyticsProvider.js.map +1 -1
  60. package/lib/module/constants/config.js +2 -0
  61. package/lib/module/constants/config.js.map +1 -1
  62. package/lib/module/constants/events.js +6 -0
  63. package/lib/module/constants/events.js.map +1 -1
  64. package/lib/module/constants/index.js +5 -3
  65. package/lib/module/constants/index.js.map +1 -1
  66. package/lib/module/constants/storage.js +9 -0
  67. package/lib/module/constants/storage.js.map +1 -1
  68. package/lib/module/index.js +6 -4
  69. package/lib/module/index.js.map +1 -1
  70. package/lib/module/lib/consent/index.js +4 -2
  71. package/lib/module/lib/consent/index.js.map +1 -1
  72. package/lib/module/lib/event/EventFactory.js +116 -33
  73. package/lib/module/lib/event/EventFactory.js.map +1 -1
  74. package/lib/module/lib/event/EventManager.js +5 -3
  75. package/lib/module/lib/event/EventManager.js.map +1 -1
  76. package/lib/module/lib/event/EventQueue.js +18 -5
  77. package/lib/module/lib/event/EventQueue.js.map +1 -1
  78. package/lib/module/lib/event/index.js +6 -4
  79. package/lib/module/lib/event/index.js.map +1 -1
  80. package/lib/module/lib/event/types.js +2 -0
  81. package/lib/module/lib/installReferrer/index.js +189 -0
  82. package/lib/module/lib/installReferrer/index.js.map +1 -0
  83. package/lib/module/lib/lifecycle/index.js +14 -5
  84. package/lib/module/lib/lifecycle/index.js.map +1 -1
  85. package/lib/module/lib/logger/index.js +2 -0
  86. package/lib/module/lib/logger/index.js.map +1 -1
  87. package/lib/module/lib/session/index.js +5 -3
  88. package/lib/module/lib/session/index.js.map +1 -1
  89. package/lib/module/lib/storage/AsyncStorageAdapter.js +4 -2
  90. package/lib/module/lib/storage/AsyncStorageAdapter.js.map +1 -1
  91. package/lib/module/lib/storage/MemoryStorage.js +3 -1
  92. package/lib/module/lib/storage/MemoryStorage.js.map +1 -1
  93. package/lib/module/lib/storage/StorageBlueprint.js +3 -1
  94. package/lib/module/lib/storage/StorageBlueprint.js.map +1 -1
  95. package/lib/module/lib/storage/StorageManager.js +5 -3
  96. package/lib/module/lib/storage/StorageManager.js.map +1 -1
  97. package/lib/module/lib/storage/index.js +6 -4
  98. package/lib/module/lib/storage/index.js.map +1 -1
  99. package/lib/module/lib/storage/types.js +1 -1
  100. package/lib/module/lib/wagmi/WagmiEventHandler.js +5 -8
  101. package/lib/module/lib/wagmi/WagmiEventHandler.js.map +1 -1
  102. package/lib/module/lib/wagmi/index.js +4 -2
  103. package/lib/module/lib/wagmi/index.js.map +1 -1
  104. package/lib/module/lib/wagmi/types.js +1 -1
  105. package/lib/module/package.json +1 -0
  106. package/lib/module/solana/address.js +102 -0
  107. package/lib/module/solana/address.js.map +1 -0
  108. package/lib/module/solana/index.js +5 -0
  109. package/lib/module/solana/index.js.map +1 -0
  110. package/lib/module/solana/types.js +42 -0
  111. package/lib/module/solana/types.js.map +1 -0
  112. package/lib/module/types/base.js +2 -0
  113. package/lib/module/types/events.js +2 -0
  114. package/lib/module/types/events.js.map +1 -1
  115. package/lib/module/types/index.js +4 -2
  116. package/lib/module/types/index.js.map +1 -1
  117. package/lib/module/utils/address.js +60 -6
  118. package/lib/module/utils/address.js.map +1 -1
  119. package/lib/module/utils/hash.js +46 -6
  120. package/lib/module/utils/hash.js.map +1 -1
  121. package/lib/module/utils/helpers.js +2 -0
  122. package/lib/module/utils/helpers.js.map +1 -1
  123. package/lib/module/utils/index.js +7 -5
  124. package/lib/module/utils/index.js.map +1 -1
  125. package/lib/module/utils/timestamp.js +2 -0
  126. package/lib/module/utils/timestamp.js.map +1 -1
  127. package/lib/module/utils/trafficSource.js +64 -3
  128. package/lib/module/utils/trafficSource.js.map +1 -1
  129. package/lib/module/version.js +3 -1
  130. package/lib/module/version.js.map +1 -1
  131. package/lib/typescript/{FormoAnalytics.d.ts → commonjs/FormoAnalytics.d.ts} +23 -4
  132. package/lib/typescript/commonjs/FormoAnalytics.d.ts.map +1 -0
  133. package/lib/typescript/commonjs/FormoAnalyticsProvider.d.ts.map +1 -0
  134. package/lib/typescript/commonjs/constants/config.d.ts.map +1 -0
  135. package/lib/typescript/{constants → commonjs/constants}/events.d.ts +1 -0
  136. package/lib/typescript/commonjs/constants/events.d.ts.map +1 -0
  137. package/lib/typescript/commonjs/constants/index.d.ts.map +1 -0
  138. package/lib/typescript/{constants → commonjs/constants}/storage.d.ts +3 -0
  139. package/lib/typescript/commonjs/constants/storage.d.ts.map +1 -0
  140. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  141. package/lib/typescript/commonjs/lib/consent/index.d.ts.map +1 -0
  142. package/lib/typescript/{lib → commonjs/lib}/event/EventFactory.d.ts +36 -1
  143. package/lib/typescript/commonjs/lib/event/EventFactory.d.ts.map +1 -0
  144. package/lib/typescript/commonjs/lib/event/EventManager.d.ts.map +1 -0
  145. package/lib/typescript/commonjs/lib/event/EventQueue.d.ts.map +1 -0
  146. package/lib/typescript/commonjs/lib/event/index.d.ts.map +1 -0
  147. package/lib/typescript/{lib → commonjs/lib}/event/types.d.ts +1 -1
  148. package/lib/typescript/commonjs/lib/event/types.d.ts.map +1 -0
  149. package/lib/typescript/commonjs/lib/installReferrer/index.d.ts +39 -0
  150. package/lib/typescript/commonjs/lib/installReferrer/index.d.ts.map +1 -0
  151. package/lib/typescript/commonjs/lib/lifecycle/index.d.ts.map +1 -0
  152. package/lib/typescript/commonjs/lib/logger/index.d.ts.map +1 -0
  153. package/lib/typescript/commonjs/lib/session/index.d.ts.map +1 -0
  154. package/lib/typescript/commonjs/lib/storage/AsyncStorageAdapter.d.ts.map +1 -0
  155. package/lib/typescript/commonjs/lib/storage/MemoryStorage.d.ts.map +1 -0
  156. package/lib/typescript/commonjs/lib/storage/StorageBlueprint.d.ts.map +1 -0
  157. package/lib/typescript/commonjs/lib/storage/StorageManager.d.ts.map +1 -0
  158. package/lib/typescript/commonjs/lib/storage/index.d.ts.map +1 -0
  159. package/lib/typescript/commonjs/lib/storage/types.d.ts.map +1 -0
  160. package/lib/typescript/{lib → commonjs/lib}/wagmi/WagmiEventHandler.d.ts +0 -1
  161. package/lib/typescript/commonjs/lib/wagmi/WagmiEventHandler.d.ts.map +1 -0
  162. package/lib/typescript/commonjs/lib/wagmi/index.d.ts.map +1 -0
  163. package/lib/typescript/commonjs/lib/wagmi/types.d.ts.map +1 -0
  164. package/lib/typescript/commonjs/package.json +1 -0
  165. package/lib/typescript/commonjs/solana/address.d.ts +42 -0
  166. package/lib/typescript/commonjs/solana/address.d.ts.map +1 -0
  167. package/lib/typescript/commonjs/solana/index.d.ts +3 -0
  168. package/lib/typescript/commonjs/solana/index.d.ts.map +1 -0
  169. package/lib/typescript/commonjs/solana/types.d.ts +34 -0
  170. package/lib/typescript/commonjs/solana/types.d.ts.map +1 -0
  171. package/lib/typescript/{types → commonjs/types}/base.d.ts +39 -1
  172. package/lib/typescript/commonjs/types/base.d.ts.map +1 -0
  173. package/lib/typescript/{types → commonjs/types}/events.d.ts +1 -1
  174. package/lib/typescript/commonjs/types/events.d.ts.map +1 -0
  175. package/lib/typescript/commonjs/types/index.d.ts.map +1 -0
  176. package/lib/typescript/commonjs/utils/address.d.ts +45 -0
  177. package/lib/typescript/commonjs/utils/address.d.ts.map +1 -0
  178. package/lib/typescript/commonjs/utils/hash.d.ts +18 -0
  179. package/lib/typescript/commonjs/utils/hash.d.ts.map +1 -0
  180. package/lib/typescript/commonjs/utils/helpers.d.ts.map +1 -0
  181. package/lib/typescript/commonjs/utils/index.d.ts.map +1 -0
  182. package/lib/typescript/commonjs/utils/timestamp.d.ts.map +1 -0
  183. package/lib/typescript/{utils → commonjs/utils}/trafficSource.d.ts +16 -0
  184. package/lib/typescript/commonjs/utils/trafficSource.d.ts.map +1 -0
  185. package/lib/typescript/commonjs/version.d.ts +2 -0
  186. package/lib/typescript/commonjs/version.d.ts.map +1 -0
  187. package/lib/typescript/module/FormoAnalytics.d.ts +182 -0
  188. package/lib/typescript/module/FormoAnalytics.d.ts.map +1 -0
  189. package/lib/typescript/module/FormoAnalyticsProvider.d.ts +29 -0
  190. package/lib/typescript/module/FormoAnalyticsProvider.d.ts.map +1 -0
  191. package/lib/typescript/module/constants/config.d.ts +8 -0
  192. package/lib/typescript/module/constants/config.d.ts.map +1 -0
  193. package/lib/typescript/module/constants/events.d.ts +24 -0
  194. package/lib/typescript/module/constants/events.d.ts.map +1 -0
  195. package/lib/typescript/module/constants/index.d.ts +4 -0
  196. package/lib/typescript/module/constants/index.d.ts.map +1 -0
  197. package/lib/typescript/module/constants/storage.d.ts +13 -0
  198. package/lib/typescript/module/constants/storage.d.ts.map +1 -0
  199. package/lib/typescript/module/index.d.ts +44 -0
  200. package/lib/typescript/module/index.d.ts.map +1 -0
  201. package/lib/typescript/module/lib/consent/index.d.ts +13 -0
  202. package/lib/typescript/module/lib/consent/index.d.ts.map +1 -0
  203. package/lib/typescript/module/lib/event/EventFactory.d.ts +99 -0
  204. package/lib/typescript/module/lib/event/EventFactory.d.ts.map +1 -0
  205. package/lib/typescript/module/lib/event/EventManager.d.ts +17 -0
  206. package/lib/typescript/module/lib/event/EventManager.d.ts.map +1 -0
  207. package/lib/typescript/module/lib/event/EventQueue.d.ts +74 -0
  208. package/lib/typescript/module/lib/event/EventQueue.d.ts.map +1 -0
  209. package/lib/typescript/module/lib/event/index.d.ts +5 -0
  210. package/lib/typescript/module/lib/event/index.d.ts.map +1 -0
  211. package/lib/typescript/module/lib/event/types.d.ts +23 -0
  212. package/lib/typescript/module/lib/event/types.d.ts.map +1 -0
  213. package/lib/typescript/module/lib/installReferrer/index.d.ts +39 -0
  214. package/lib/typescript/module/lib/installReferrer/index.d.ts.map +1 -0
  215. package/lib/typescript/module/lib/lifecycle/index.d.ts +46 -0
  216. package/lib/typescript/module/lib/lifecycle/index.d.ts.map +1 -0
  217. package/lib/typescript/module/lib/logger/index.d.ts +19 -0
  218. package/lib/typescript/module/lib/logger/index.d.ts.map +1 -0
  219. package/lib/typescript/module/lib/session/index.d.ts +41 -0
  220. package/lib/typescript/module/lib/session/index.d.ts.map +1 -0
  221. package/lib/typescript/module/lib/storage/AsyncStorageAdapter.d.ts +48 -0
  222. package/lib/typescript/module/lib/storage/AsyncStorageAdapter.d.ts.map +1 -0
  223. package/lib/typescript/module/lib/storage/MemoryStorage.d.ts +18 -0
  224. package/lib/typescript/module/lib/storage/MemoryStorage.d.ts.map +1 -0
  225. package/lib/typescript/module/lib/storage/StorageBlueprint.d.ts +21 -0
  226. package/lib/typescript/module/lib/storage/StorageBlueprint.d.ts.map +1 -0
  227. package/lib/typescript/module/lib/storage/StorageManager.d.ts +45 -0
  228. package/lib/typescript/module/lib/storage/StorageManager.d.ts.map +1 -0
  229. package/lib/typescript/module/lib/storage/index.d.ts +5 -0
  230. package/lib/typescript/module/lib/storage/index.d.ts.map +1 -0
  231. package/lib/typescript/module/lib/storage/types.d.ts +22 -0
  232. package/lib/typescript/module/lib/storage/types.d.ts.map +1 -0
  233. package/lib/typescript/module/lib/wagmi/WagmiEventHandler.d.ts +103 -0
  234. package/lib/typescript/module/lib/wagmi/WagmiEventHandler.d.ts.map +1 -0
  235. package/lib/typescript/module/lib/wagmi/index.d.ts +3 -0
  236. package/lib/typescript/module/lib/wagmi/index.d.ts.map +1 -0
  237. package/lib/typescript/module/lib/wagmi/types.d.ts +54 -0
  238. package/lib/typescript/module/lib/wagmi/types.d.ts.map +1 -0
  239. package/lib/typescript/module/package.json +1 -0
  240. package/lib/typescript/module/solana/address.d.ts +42 -0
  241. package/lib/typescript/module/solana/address.d.ts.map +1 -0
  242. package/lib/typescript/module/solana/index.d.ts +3 -0
  243. package/lib/typescript/module/solana/index.d.ts.map +1 -0
  244. package/lib/typescript/module/solana/types.d.ts +34 -0
  245. package/lib/typescript/module/solana/types.d.ts.map +1 -0
  246. package/lib/typescript/module/types/base.d.ts +258 -0
  247. package/lib/typescript/module/types/base.d.ts.map +1 -0
  248. package/lib/typescript/module/types/events.d.ts +111 -0
  249. package/lib/typescript/module/types/events.d.ts.map +1 -0
  250. package/lib/typescript/module/types/index.d.ts +3 -0
  251. package/lib/typescript/module/types/index.d.ts.map +1 -0
  252. package/lib/typescript/module/utils/address.d.ts +45 -0
  253. package/lib/typescript/module/utils/address.d.ts.map +1 -0
  254. package/lib/typescript/module/utils/hash.d.ts +18 -0
  255. package/lib/typescript/module/utils/hash.d.ts.map +1 -0
  256. package/lib/typescript/module/utils/helpers.d.ts +26 -0
  257. package/lib/typescript/module/utils/helpers.d.ts.map +1 -0
  258. package/lib/typescript/module/utils/index.d.ts +6 -0
  259. package/lib/typescript/module/utils/index.d.ts.map +1 -0
  260. package/lib/typescript/module/utils/timestamp.d.ts +13 -0
  261. package/lib/typescript/module/utils/timestamp.d.ts.map +1 -0
  262. package/lib/typescript/module/utils/trafficSource.d.ts +46 -0
  263. package/lib/typescript/module/utils/trafficSource.d.ts.map +1 -0
  264. package/lib/typescript/module/version.d.ts +2 -0
  265. package/lib/typescript/module/version.d.ts.map +1 -0
  266. package/package.json +44 -49
  267. package/src/FormoAnalytics.ts +118 -16
  268. package/src/constants/events.ts +4 -0
  269. package/src/constants/storage.ts +7 -0
  270. package/src/lib/event/EventFactory.ts +129 -29
  271. package/src/lib/event/EventQueue.ts +14 -0
  272. package/src/lib/event/types.ts +0 -1
  273. package/src/lib/installReferrer/index.ts +225 -0
  274. package/src/lib/lifecycle/index.ts +10 -1
  275. package/src/lib/wagmi/WagmiEventHandler.ts +0 -4
  276. package/src/solana/address.ts +122 -0
  277. package/src/solana/index.ts +2 -0
  278. package/src/solana/types.ts +46 -0
  279. package/src/types/base.ts +41 -1
  280. package/src/types/events.ts +1 -1
  281. package/src/utils/address.ts +72 -6
  282. package/src/utils/hash.ts +51 -6
  283. package/src/utils/trafficSource.ts +73 -0
  284. package/src/version.ts +1 -1
  285. package/lib/typescript/FormoAnalytics.d.ts.map +0 -1
  286. package/lib/typescript/FormoAnalyticsProvider.d.ts.map +0 -1
  287. package/lib/typescript/constants/config.d.ts.map +0 -1
  288. package/lib/typescript/constants/events.d.ts.map +0 -1
  289. package/lib/typescript/constants/index.d.ts.map +0 -1
  290. package/lib/typescript/constants/storage.d.ts.map +0 -1
  291. package/lib/typescript/index.d.ts.map +0 -1
  292. package/lib/typescript/lib/consent/index.d.ts.map +0 -1
  293. package/lib/typescript/lib/event/EventFactory.d.ts.map +0 -1
  294. package/lib/typescript/lib/event/EventManager.d.ts.map +0 -1
  295. package/lib/typescript/lib/event/EventQueue.d.ts.map +0 -1
  296. package/lib/typescript/lib/event/index.d.ts.map +0 -1
  297. package/lib/typescript/lib/event/types.d.ts.map +0 -1
  298. package/lib/typescript/lib/lifecycle/index.d.ts.map +0 -1
  299. package/lib/typescript/lib/logger/index.d.ts.map +0 -1
  300. package/lib/typescript/lib/session/index.d.ts.map +0 -1
  301. package/lib/typescript/lib/storage/AsyncStorageAdapter.d.ts.map +0 -1
  302. package/lib/typescript/lib/storage/MemoryStorage.d.ts.map +0 -1
  303. package/lib/typescript/lib/storage/StorageBlueprint.d.ts.map +0 -1
  304. package/lib/typescript/lib/storage/StorageManager.d.ts.map +0 -1
  305. package/lib/typescript/lib/storage/index.d.ts.map +0 -1
  306. package/lib/typescript/lib/storage/types.d.ts.map +0 -1
  307. package/lib/typescript/lib/wagmi/WagmiEventHandler.d.ts.map +0 -1
  308. package/lib/typescript/lib/wagmi/index.d.ts.map +0 -1
  309. package/lib/typescript/lib/wagmi/types.d.ts.map +0 -1
  310. package/lib/typescript/types/base.d.ts.map +0 -1
  311. package/lib/typescript/types/events.d.ts.map +0 -1
  312. package/lib/typescript/types/index.d.ts.map +0 -1
  313. package/lib/typescript/utils/address.d.ts +0 -25
  314. package/lib/typescript/utils/address.d.ts.map +0 -1
  315. package/lib/typescript/utils/hash.d.ts +0 -10
  316. package/lib/typescript/utils/hash.d.ts.map +0 -1
  317. package/lib/typescript/utils/helpers.d.ts.map +0 -1
  318. package/lib/typescript/utils/index.d.ts.map +0 -1
  319. package/lib/typescript/utils/timestamp.d.ts.map +0 -1
  320. package/lib/typescript/utils/trafficSource.d.ts.map +0 -1
  321. package/lib/typescript/version.d.ts +0 -2
  322. package/lib/typescript/version.d.ts.map +0 -1
  323. /package/lib/typescript/{FormoAnalyticsProvider.d.ts → commonjs/FormoAnalyticsProvider.d.ts} +0 -0
  324. /package/lib/typescript/{constants → commonjs/constants}/config.d.ts +0 -0
  325. /package/lib/typescript/{constants → commonjs/constants}/index.d.ts +0 -0
  326. /package/lib/typescript/{index.d.ts → commonjs/index.d.ts} +0 -0
  327. /package/lib/typescript/{lib → commonjs/lib}/consent/index.d.ts +0 -0
  328. /package/lib/typescript/{lib → commonjs/lib}/event/EventManager.d.ts +0 -0
  329. /package/lib/typescript/{lib → commonjs/lib}/event/EventQueue.d.ts +0 -0
  330. /package/lib/typescript/{lib → commonjs/lib}/event/index.d.ts +0 -0
  331. /package/lib/typescript/{lib → commonjs/lib}/lifecycle/index.d.ts +0 -0
  332. /package/lib/typescript/{lib → commonjs/lib}/logger/index.d.ts +0 -0
  333. /package/lib/typescript/{lib → commonjs/lib}/session/index.d.ts +0 -0
  334. /package/lib/typescript/{lib → commonjs/lib}/storage/AsyncStorageAdapter.d.ts +0 -0
  335. /package/lib/typescript/{lib → commonjs/lib}/storage/MemoryStorage.d.ts +0 -0
  336. /package/lib/typescript/{lib → commonjs/lib}/storage/StorageBlueprint.d.ts +0 -0
  337. /package/lib/typescript/{lib → commonjs/lib}/storage/StorageManager.d.ts +0 -0
  338. /package/lib/typescript/{lib → commonjs/lib}/storage/index.d.ts +0 -0
  339. /package/lib/typescript/{lib → commonjs/lib}/storage/types.d.ts +0 -0
  340. /package/lib/typescript/{lib → commonjs/lib}/wagmi/index.d.ts +0 -0
  341. /package/lib/typescript/{lib → commonjs/lib}/wagmi/types.d.ts +0 -0
  342. /package/lib/typescript/{types → commonjs/types}/index.d.ts +0 -0
  343. /package/lib/typescript/{utils → commonjs/utils}/helpers.d.ts +0 -0
  344. /package/lib/typescript/{utils → commonjs/utils}/index.d.ts +0 -0
  345. /package/lib/typescript/{utils → commonjs/utils}/timestamp.d.ts +0 -0
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@formo/analytics-react-native",
3
- "version": "0.1.4",
3
+ "version": "1.0.0",
4
4
  "description": "Formo Analytics SDK for React Native - Track wallet events and user analytics in mobile dApps",
5
- "packageManager": "pnpm@10.27.0",
5
+ "packageManager": "pnpm@11.1.1",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/getformo/sdk-react-native.git"
9
9
  },
10
10
  "main": "lib/commonjs/index.js",
11
11
  "module": "lib/module/index.js",
12
- "types": "lib/typescript/index.d.ts",
12
+ "types": "lib/typescript/commonjs/index.d.ts",
13
13
  "react-native": "src/index.ts",
14
14
  "source": "src/index.ts",
15
15
  "files": [
@@ -21,9 +21,14 @@
21
21
  ],
22
22
  "exports": {
23
23
  ".": {
24
- "import": "./lib/module/index.js",
25
- "require": "./lib/commonjs/index.js",
26
- "types": "./lib/typescript/index.d.ts"
24
+ "import": {
25
+ "types": "./lib/typescript/module/index.d.ts",
26
+ "default": "./lib/module/index.js"
27
+ },
28
+ "require": {
29
+ "types": "./lib/typescript/commonjs/index.d.ts",
30
+ "default": "./lib/commonjs/index.js"
31
+ }
27
32
  }
28
33
  },
29
34
  "private": false,
@@ -63,6 +68,7 @@
63
68
  "react": ">=18.0.0",
64
69
  "react-native": ">=0.70.0",
65
70
  "react-native-device-info": ">=10.0.0",
71
+ "react-native-play-install-referrer": ">=1.1.8",
66
72
  "wagmi": ">=2.0.0"
67
73
  },
68
74
  "peerDependenciesMeta": {
@@ -81,66 +87,55 @@
81
87
  "react-native-device-info": {
82
88
  "optional": true
83
89
  },
90
+ "react-native-play-install-referrer": {
91
+ "optional": true
92
+ },
84
93
  "wagmi": {
85
94
  "optional": true
86
95
  }
87
96
  },
88
97
  "dependencies": {
89
- "@react-native-community/netinfo": "^11.5.1",
98
+ "@react-native-community/netinfo": "12.0.1",
90
99
  "ethereum-cryptography": "3.2.0"
91
100
  },
92
101
  "devDependencies": {
93
- "@babel/preset-env": "^7.29.0",
102
+ "@babel/preset-env": "^7.29.5",
94
103
  "@babel/preset-react": "^7.28.5",
95
104
  "@babel/preset-typescript": "^7.28.5",
96
105
  "@react-native-async-storage/async-storage": "^1.21.0",
97
- "@react-native/babel-preset": "^0.77.0",
98
- "@types/jest": "^29.5.12",
99
- "@types/react": "^18.0.25",
100
- "@typescript-eslint/eslint-plugin": "^8.57.2",
101
- "@typescript-eslint/parser": "^8.57.2",
102
- "babel-jest": "^29.7.0",
103
- "eslint": "^10.1.0",
104
- "expo-application": "^6.0.0",
105
- "expo-device": "^7.0.0",
106
- "jest": "^29.7.0",
107
- "react": "^18.3.1",
108
- "react-native": "^0.77.0",
109
- "react-native-builder-bob": "^0.23.0",
106
+ "@react-native/babel-preset": "^0.85.3",
107
+ "@types/jest": "^30.0.0",
108
+ "@types/react": "^19.2.14",
109
+ "@typescript-eslint/eslint-plugin": "^8.59.3",
110
+ "@typescript-eslint/parser": "^8.59.3",
111
+ "babel-jest": "^30.4.1",
112
+ "eslint": "^10.3.0",
113
+ "expo-application": "^55.0.15",
114
+ "expo-device": "^55.0.17",
115
+ "jest": "^30.4.1",
116
+ "react": "^19.2.6",
117
+ "react-native": "^0.85.3",
118
+ "react-native-builder-bob": "^0.41.0",
110
119
  "react-native-device-info": "^14.0.0",
111
- "typescript": "^5.7.3",
112
- "typescript-eslint": "^8.57.2"
113
- },
114
- "pnpm": {
115
- "overrides": {
116
- "@react-native-community/cli": ">=17.0.1",
117
- "@react-native-community/cli-server-api": ">=17.0.1",
118
- "@xmldom/xmldom": ">=0.8.12",
119
- "brace-expansion@1": ">=1.1.13 <2",
120
- "brace-expansion@2": ">=2.0.3 <3",
121
- "fast-xml-parser": ">=4.5.5",
122
- "minimatch@3": ">=3.1.5 <4",
123
- "minimatch@5": ">=5.1.9 <6",
124
- "minimatch@9": ">=9.0.9 <10",
125
- "minimatch@10": ">=10.2.4",
126
- "node-forge": ">=1.4.0",
127
- "picomatch@2": ">=2.3.2 <3",
128
- "picomatch@3": ">=3.0.2 <4",
129
- "picomatch@4": ">=4.0.4",
130
- "semver@5": ">=7.7.4",
131
- "semver@6": ">=7.7.4",
132
- "tar": ">=7.5.13",
133
- "undici": ">=6.24.1 <7",
134
- "yaml@1": ">=1.10.3 <2",
135
- "yaml@2": ">=2.8.3 <3"
136
- }
120
+ "typescript": "^6.0.3",
121
+ "typescript-eslint": "^8.59.3"
137
122
  },
138
123
  "react-native-builder-bob": {
139
124
  "source": "src",
140
125
  "output": "lib",
141
126
  "targets": [
142
- "commonjs",
143
- "module",
127
+ [
128
+ "commonjs",
129
+ {
130
+ "esm": true
131
+ }
132
+ ],
133
+ [
134
+ "module",
135
+ {
136
+ "esm": true
137
+ }
138
+ ],
144
139
  [
145
140
  "typescript",
146
141
  {
@@ -8,6 +8,8 @@ import {
8
8
  EVENTS_API_HOST,
9
9
  EventType,
10
10
  LOCAL_ANONYMOUS_ID_KEY,
11
+ LOCAL_SESSION_ID_KEY,
12
+ LOCAL_SESSION_LAST_ACTIVITY_KEY,
11
13
  SESSION_USER_ID_KEY,
12
14
  CONSENT_OPT_OUT_KEY,
13
15
  TEventType,
@@ -35,8 +37,10 @@ import {
35
37
  TrackingOptions,
36
38
  TransactionStatus,
37
39
  } from "./types";
38
- import { toChecksumAddress, getValidAddress } from "./utils";
39
- import { parseTrafficSource, storeTrafficSource } from "./utils/trafficSource";
40
+ import { validateAddress } from "./utils";
41
+ import { parseTrafficSource, updateStoredTrafficSource } from "./utils/trafficSource";
42
+ import { captureInstallReferrer } from "./lib/installReferrer";
43
+ import { Linking, EmitterSubscription } from "react-native";
40
44
 
41
45
  export class FormoAnalytics implements IFormoAnalytics {
42
46
  private session: FormoAnalyticsSession;
@@ -44,6 +48,7 @@ export class FormoAnalytics implements IFormoAnalytics {
44
48
  private eventQueue: EventQueue;
45
49
  private wagmiHandler?: WagmiEventHandler;
46
50
  private lifecycleManager?: AppLifecycleManager;
51
+ private linkingSubscription?: EmitterSubscription;
47
52
 
48
53
  config: Config;
49
54
  currentChainId?: ChainID;
@@ -128,6 +133,34 @@ export class FormoAnalytics implements IFormoAnalytics {
128
133
 
129
134
  const analytics = new FormoAnalytics(writeKey, options);
130
135
 
136
+ // Capture attribution BEFORE lifecycle tracking so the first
137
+ // Application Installed/Opened events carry utm_*/ref/referrer.
138
+ //
139
+ // Both are awaited so the stored traffic source is populated before
140
+ // lifecycle fires — that's what lets Application Installed report the
141
+ // web-to-mobile referrer (e.g. referrer=example.com). Deep-link initial URL
142
+ // is a fast native bridge call; the Android Play Install Referrer is a fast
143
+ // one-shot native call (and no-ops instantly when the native module or the
144
+ // platform isn't Android), so awaiting it does not meaningfully delay init.
145
+ if (analytics.isAttributionEnabled("deeplinks")) {
146
+ try {
147
+ await analytics.startDeepLinkCapture();
148
+ } catch (error) {
149
+ logger.error("FormoAnalytics: Failed to initialize deep link capture", error);
150
+ }
151
+ }
152
+
153
+ if (analytics.isAttributionEnabled("installReferrer")) {
154
+ try {
155
+ await captureInstallReferrer({
156
+ customRefParams: analytics.options.referral?.queryParams,
157
+ pathPattern: analytics.options.referral?.pathPattern,
158
+ });
159
+ } catch (error) {
160
+ logger.debug("FormoAnalytics: install referrer capture failed", error);
161
+ }
162
+ }
163
+
131
164
  // Initialize lifecycle tracking if enabled
132
165
  // Wrapped in try-catch so a transient storage failure doesn't prevent SDK init
133
166
  if (analytics.isAutocaptureEnabled("lifecycle")) {
@@ -147,6 +180,25 @@ export class FormoAnalytics implements IFormoAnalytics {
147
180
  return analytics;
148
181
  }
149
182
 
183
+ /**
184
+ * Hook into React Native's Linking API to auto-capture traffic source from
185
+ * the launch URL and any subsequent deep-link opens. Awaits the initial URL
186
+ * so attribution is in storage before the first lifecycle event fires.
187
+ */
188
+ private async startDeepLinkCapture(): Promise<void> {
189
+ try {
190
+ const url = await Linking.getInitialURL();
191
+ if (url) this.setTrafficSourceFromUrl(url);
192
+ } catch (error) {
193
+ logger.debug("FormoAnalytics: Linking.getInitialURL failed", error);
194
+ }
195
+
196
+ // Runtime deep links (foreground opens, universal links).
197
+ this.linkingSubscription = Linking.addEventListener("url", (event) => {
198
+ if (event?.url) this.setTrafficSourceFromUrl(event.url);
199
+ });
200
+ }
201
+
150
202
  /**
151
203
  * Track a screen view (mobile equivalent of page view)
152
204
  */
@@ -195,7 +247,10 @@ export class FormoAnalytics implements IFormoAnalytics {
195
247
  this.options.referral?.queryParams,
196
248
  this.options.referral?.pathPattern
197
249
  );
198
- storeTrafficSource(trafficSource);
250
+ // Per-field merge: incoming non-empty fields win, empty fields preserve
251
+ // stored values. A non-marketing deep link (e.g. "myapp://home") with only
252
+ // a referrer will not destroy previously captured utm_*/ref attribution.
253
+ updateStoredTrafficSource(trafficSource);
199
254
  logger.debug("Traffic source set from URL:", trafficSource);
200
255
  }
201
256
 
@@ -205,6 +260,8 @@ export class FormoAnalytics implements IFormoAnalytics {
205
260
  public reset(): void {
206
261
  this.currentUserId = undefined;
207
262
  storage().remove(LOCAL_ANONYMOUS_ID_KEY);
263
+ storage().remove(LOCAL_SESSION_ID_KEY);
264
+ storage().remove(LOCAL_SESSION_LAST_ACTIVITY_KEY);
208
265
  storage().remove(SESSION_USER_ID_KEY);
209
266
  this.session.clear();
210
267
  }
@@ -220,6 +277,11 @@ export class FormoAnalytics implements IFormoAnalytics {
220
277
  this.lifecycleManager = undefined;
221
278
  }
222
279
 
280
+ if (this.linkingSubscription) {
281
+ this.linkingSubscription.remove();
282
+ this.linkingSubscription = undefined;
283
+ }
284
+
223
285
  if (this.wagmiHandler) {
224
286
  this.wagmiHandler.cleanup();
225
287
  this.wagmiHandler = undefined;
@@ -250,8 +312,8 @@ export class FormoAnalytics implements IFormoAnalytics {
250
312
  return;
251
313
  }
252
314
 
253
- const checksummedAddress = this.validateAndChecksumAddress(address);
254
- if (!checksummedAddress) {
315
+ const validatedAddress = this.validateAndChecksumAddress(address, chainId);
316
+ if (!validatedAddress) {
255
317
  logger.warn(`Connect: Invalid address provided ("${address}")`);
256
318
  return;
257
319
  }
@@ -259,14 +321,14 @@ export class FormoAnalytics implements IFormoAnalytics {
259
321
  // Track event before updating state so connect events TO excluded chains are tracked
260
322
  await this.trackEvent(
261
323
  EventType.CONNECT,
262
- { chainId, address: checksummedAddress },
324
+ { chainId, address: validatedAddress },
263
325
  properties,
264
326
  context,
265
327
  callback
266
328
  );
267
329
 
268
330
  this.currentChainId = chainId;
269
- this.currentAddress = checksummedAddress;
331
+ this.currentAddress = validatedAddress;
270
332
  }
271
333
 
272
334
  /**
@@ -345,13 +407,11 @@ export class FormoAnalytics implements IFormoAnalytics {
345
407
  chainId,
346
408
  address,
347
409
  message,
348
- signatureHash,
349
410
  }: {
350
411
  status: SignatureStatus;
351
412
  chainId?: ChainID;
352
413
  address: Address;
353
414
  message: string;
354
- signatureHash?: string;
355
415
  },
356
416
  properties?: IFormoEventProperties,
357
417
  context?: IFormoEventContext,
@@ -368,7 +428,6 @@ export class FormoAnalytics implements IFormoAnalytics {
368
428
  ...(chainId !== undefined && chainId !== null && { chainId }),
369
429
  address,
370
430
  message,
371
- ...(signatureHash && { signatureHash }),
372
431
  },
373
432
  properties,
374
433
  context,
@@ -458,6 +517,8 @@ export class FormoAnalytics implements IFormoAnalytics {
458
517
  return;
459
518
  }
460
519
  this.currentAddress = validAddress;
520
+ // Note: validateAddress returns Solana addresses unchanged (Base58, case-sensitive)
521
+ // and EVM addresses checksummed.
461
522
  } else {
462
523
  this.currentAddress = undefined;
463
524
  }
@@ -566,10 +627,19 @@ export class FormoAnalytics implements IFormoAnalytics {
566
627
  }
567
628
 
568
629
  /**
569
- * Check if autocapture is enabled for event type
630
+ * Check if autocapture is enabled for a given event type.
631
+ * Applies only to event-generating behaviors (wallet events, lifecycle
632
+ * events). Attribution is controlled separately via `options.attribution`
633
+ * because it enriches events rather than generating them.
570
634
  */
571
635
  public isAutocaptureEnabled(
572
- eventType: "connect" | "disconnect" | "signature" | "transaction" | "chain" | "lifecycle"
636
+ eventType:
637
+ | "connect"
638
+ | "disconnect"
639
+ | "signature"
640
+ | "transaction"
641
+ | "chain"
642
+ | "lifecycle"
573
643
  ): boolean {
574
644
  if (this.options.autocapture === undefined) {
575
645
  return true;
@@ -590,6 +660,32 @@ export class FormoAnalytics implements IFormoAnalytics {
590
660
  return true;
591
661
  }
592
662
 
663
+ /**
664
+ * Check if an attribution source is enabled. Attribution is not an event
665
+ * type — it decorates every tracked event with `utm_*`, `ref`, and
666
+ * `referrer` context fields.
667
+ */
668
+ public isAttributionEnabled(
669
+ source: "deeplinks" | "installReferrer"
670
+ ): boolean {
671
+ if (this.options.attribution === undefined) {
672
+ return true;
673
+ }
674
+
675
+ if (typeof this.options.attribution === "boolean") {
676
+ return this.options.attribution;
677
+ }
678
+
679
+ if (
680
+ this.options.attribution !== null &&
681
+ typeof this.options.attribution === "object"
682
+ ) {
683
+ return this.options.attribution[source] !== false;
684
+ }
685
+
686
+ return true;
687
+ }
688
+
593
689
  /**
594
690
  * Internal method to track events
595
691
  * This is the single enforcement point for shouldTrack() - all public tracking
@@ -669,11 +765,17 @@ export class FormoAnalytics implements IFormoAnalytics {
669
765
  }
670
766
 
671
767
  /**
672
- * Validate and checksum address
768
+ * Validate and normalize an address for the given chain.
769
+ *
770
+ * EVM addresses are returned in EIP-55 checksum format.
771
+ * Solana addresses are returned as-is (Base58 is case-sensitive).
772
+ * When chainId is omitted, EVM is tried first with Solana as fallback.
673
773
  */
674
- private validateAndChecksumAddress(address: string): Address | undefined {
675
- const validAddress = getValidAddress(address);
676
- return validAddress ? toChecksumAddress(validAddress) : undefined;
774
+ private validateAndChecksumAddress(
775
+ address: string,
776
+ chainId?: ChainID
777
+ ): Address | undefined {
778
+ return validateAddress(address, chainId);
677
779
  }
678
780
 
679
781
  /**
@@ -24,3 +24,7 @@ export type TEventChannel = Lowercase<EventChannel>;
24
24
  // React Native SDK uses mobile channel
25
25
  export const CHANNEL: TEventChannel = "mobile";
26
26
  export const VERSION = "0";
27
+
28
+ // Session inactivity timeout (30 min), matching the GA4/Segment default. A new
29
+ // session_id is minted once the gap since the last tracked event exceeds this.
30
+ export const SESSION_TIMEOUT_MS = 30 * 60 * 1000;
@@ -5,6 +5,13 @@ export const STORAGE_PREFIX = "formo_rn_";
5
5
  export const LOCAL_ANONYMOUS_ID_KEY = "anonymous_id";
6
6
  export const LOCAL_APP_VERSION_KEY = "app_version";
7
7
  export const LOCAL_APP_BUILD_KEY = "app_build";
8
+ // Session identifier + last-activity marker. Persisted so a session survives an
9
+ // app restart, but expires after SESSION_TIMEOUT_MS of inactivity (see EventFactory).
10
+ export const LOCAL_SESSION_ID_KEY = "session_id";
11
+ export const LOCAL_SESSION_LAST_ACTIVITY_KEY = "session_last_activity";
12
+ // One-shot flag: set once the Android Play Install Referrer attribution has
13
+ // been fetched, so we never call the native API again.
14
+ export const LOCAL_INSTALL_REFERRER_RESOLVED_KEY = "install_referrer_resolved";
8
15
 
9
16
  // Session storage keys (cleared on app restart)
10
17
  export const SESSION_USER_ID_KEY = "user_id";
@@ -25,7 +25,15 @@ try {
25
25
  } catch {
26
26
  // Not available
27
27
  }
28
- import { COUNTRY_LIST, LOCAL_ANONYMOUS_ID_KEY, CHANNEL, VERSION } from "../../constants";
28
+ import {
29
+ COUNTRY_LIST,
30
+ LOCAL_ANONYMOUS_ID_KEY,
31
+ LOCAL_SESSION_ID_KEY,
32
+ LOCAL_SESSION_LAST_ACTIVITY_KEY,
33
+ SESSION_TIMEOUT_MS,
34
+ CHANNEL,
35
+ VERSION,
36
+ } from "../../constants";
29
37
  import {
30
38
  Address,
31
39
  APIEvent,
@@ -39,8 +47,7 @@ import {
39
47
  TransactionStatus,
40
48
  } from "../../types";
41
49
  import {
42
- toChecksumAddress,
43
- getValidAddress,
50
+ validateAddress,
44
51
  toSnakeCase,
45
52
  mergeDeepRight,
46
53
  getStoredTrafficSource,
@@ -66,6 +73,73 @@ function generateAnonymousId(key: string): string {
66
73
  return newId;
67
74
  }
68
75
 
76
+ /**
77
+ * Get the current session id, or start a new one.
78
+ *
79
+ * A session persists across app restarts but expires after SESSION_TIMEOUT_MS of
80
+ * inactivity, at which point a fresh id is minted. Every call refreshes the
81
+ * last-activity marker.
82
+ *
83
+ * The mobile SDK owns its session_id rather than letting ingestion derive one.
84
+ * The events-gateway authorizer computes
85
+ * `hash(dailySalt + domain + sourceIp + userAgent)` — a design built for the
86
+ * web, where all three inputs carry real entropy. For a native app they all
87
+ * degenerate at once: there is no Origin header (so `domain` is the constant
88
+ * "unknown"), the HTTP User-Agent is the client library's (`okhttp/…`,
89
+ * `CFNetwork/… Darwin/…`) and is near-identical across users on the same app
90
+ * build, and carrier CGNAT puts many users behind one IP — so unrelated users
91
+ * collapse into a single session. Ingestion honours a body-provided session_id
92
+ * (`obj?.session_id || session_id` in handlerV0), which is the path used here.
93
+ */
94
+ export function getSessionId(): string {
95
+ const now = Date.now();
96
+ const existingId = storage().get(LOCAL_SESSION_ID_KEY);
97
+ const lastActivityRaw = storage().get(LOCAL_SESSION_LAST_ACTIVITY_KEY);
98
+ const lastActivity = lastActivityRaw ? parseInt(lastActivityRaw, 10) : 0;
99
+
100
+ const isExpired =
101
+ !existingId || !lastActivity || now - lastActivity > SESSION_TIMEOUT_MS;
102
+ const sessionId = isExpired ? generateUUID() : existingId;
103
+
104
+ storage().set(LOCAL_SESSION_ID_KEY, sessionId);
105
+ storage().set(LOCAL_SESSION_LAST_ACTIVITY_KEY, String(now));
106
+
107
+ return sessionId;
108
+ }
109
+
110
+ /**
111
+ * Build a representative User-Agent string from structured device info.
112
+ *
113
+ * The ingestion pipeline classifies device / os / browser purely from the
114
+ * user_agent string; a mobile event with an empty UA is bucketed as "unknown".
115
+ * Platforms without a native UA (e.g. Expo, where DeviceInfo.getUserAgent() is
116
+ * unavailable) would otherwise report device=os=unknown. We synthesize a UA
117
+ * containing the tokens the classifier keys off (iphone/ipad/android + version)
118
+ * so mobile device and OS resolve correctly. Returns "" for unknown platforms.
119
+ */
120
+ export function synthesizeUserAgent(info: {
121
+ os_name: string;
122
+ os_version: string;
123
+ device_model: string;
124
+ device_type: string;
125
+ }): string {
126
+ const os = (info.os_name || "").toLowerCase();
127
+ const version = info.os_version || "";
128
+ const model = info.device_model || "";
129
+ const isTablet = info.device_type === "tablet";
130
+
131
+ if (os === "ios" || os === "ipados") {
132
+ const device = isTablet ? "iPad" : "iPhone";
133
+ const osVersion = version.replace(/\./g, "_");
134
+ return `Mozilla/5.0 (${device}; CPU ${device} OS ${osVersion} like Mac OS X) FormoAnalytics/ReactNative`;
135
+ }
136
+ if (os === "android") {
137
+ const formFactor = isTablet ? "Tablet" : "Mobile";
138
+ return `Mozilla/5.0 (Linux; Android ${version}; ${model}) ${formFactor} FormoAnalytics/ReactNative`;
139
+ }
140
+ return "";
141
+ }
142
+
69
143
  /**
70
144
  * Event factory for React Native
71
145
  * Creates event payloads with mobile-specific context
@@ -219,14 +293,24 @@ class EventFactory implements IEventFactory {
219
293
  DeviceInfo.isTablet(),
220
294
  ]);
221
295
 
296
+ const device_type = isTablet ? "tablet" : "mobile";
297
+ const os_version = DeviceInfo.getSystemVersion();
222
298
  return {
223
299
  os_name: Platform.OS,
224
- os_version: DeviceInfo.getSystemVersion(),
300
+ os_version,
225
301
  device_model: model,
226
302
  device_manufacturer: manufacturer,
227
303
  device_name: deviceName,
228
- device_type: isTablet ? "tablet" : "mobile",
229
- user_agent: userAgent,
304
+ device_type,
305
+ // Prefer the native UA; fall back to a synthesized one if unavailable.
306
+ user_agent:
307
+ userAgent ||
308
+ synthesizeUserAgent({
309
+ os_name: Platform.OS,
310
+ os_version,
311
+ device_model: model,
312
+ device_type,
313
+ }),
230
314
  app_name: DeviceInfo.getApplicationName(),
231
315
  app_version: DeviceInfo.getVersion(),
232
316
  app_build: DeviceInfo.getBuildNumber(),
@@ -241,14 +325,25 @@ class EventFactory implements IEventFactory {
241
325
  if (ExpoDevice || ExpoApplication) {
242
326
  try {
243
327
  const isTablet = ExpoDevice?.deviceType === ExpoDevice?.DeviceType?.TABLET;
328
+ const os_name = ExpoDevice?.osName || Platform.OS;
329
+ const os_version = ExpoDevice?.osVersion || String(Platform.Version);
330
+ const device_model = ExpoDevice?.modelName || "Unknown";
331
+ const device_type = isTablet ? "tablet" : "mobile";
244
332
  return {
245
- os_name: ExpoDevice?.osName || Platform.OS,
246
- os_version: ExpoDevice?.osVersion || String(Platform.Version),
247
- device_model: ExpoDevice?.modelName || "Unknown",
333
+ os_name,
334
+ os_version,
335
+ device_model,
248
336
  device_manufacturer: ExpoDevice?.manufacturer || "Unknown",
249
337
  device_name: ExpoDevice?.deviceName || "Unknown Device",
250
- device_type: isTablet ? "tablet" : "mobile",
251
- user_agent: "",
338
+ device_type,
339
+ // Expo exposes no native UA; synthesize one so the pipeline can
340
+ // classify device/os (both are derived from the UA string).
341
+ user_agent: synthesizeUserAgent({
342
+ os_name,
343
+ os_version,
344
+ device_model,
345
+ device_type,
346
+ }),
252
347
  app_name: ExpoApplication?.applicationName || "",
253
348
  app_version: ExpoApplication?.nativeApplicationVersion || "",
254
349
  app_build: ExpoApplication?.nativeBuildVersion || "",
@@ -261,14 +356,21 @@ class EventFactory implements IEventFactory {
261
356
 
262
357
  // Final fallback - minimal info from Platform
263
358
  logger.debug("No device info modules available, using Platform defaults");
359
+ const os_name = Platform.OS;
360
+ const os_version = String(Platform.Version);
264
361
  return {
265
- os_name: Platform.OS,
266
- os_version: String(Platform.Version),
362
+ os_name,
363
+ os_version,
267
364
  device_model: "Unknown",
268
365
  device_manufacturer: "Unknown",
269
366
  device_name: "Unknown Device",
270
367
  device_type: "mobile",
271
- user_agent: "",
368
+ user_agent: synthesizeUserAgent({
369
+ os_name,
370
+ os_version,
371
+ device_model: "Unknown",
372
+ device_type: "mobile",
373
+ }),
272
374
  app_name: "",
273
375
  app_version: "",
274
376
  app_build: "",
@@ -335,14 +437,14 @@ class EventFactory implements IEventFactory {
335
437
  };
336
438
 
337
439
  commonEventData.anonymous_id = generateAnonymousId(LOCAL_ANONYMOUS_ID_KEY);
440
+ commonEventData.session_id = getSessionId();
338
441
 
339
442
  // Handle address - convert undefined to null for consistency
340
- const validAddress = getValidAddress(formoEvent.address);
341
- if (validAddress) {
342
- commonEventData.address = toChecksumAddress(validAddress);
343
- } else {
344
- commonEventData.address = null;
345
- }
443
+ // Try EVM first, then Solana fallback (chainId is not always present here).
444
+ const validAddress = formoEvent.address
445
+ ? validateAddress(formoEvent.address)
446
+ : undefined;
447
+ commonEventData.address = validAddress ?? null;
346
448
 
347
449
  const processedEvent = mergeDeepRight(
348
450
  formoEvent as Record<string, unknown>,
@@ -385,8 +487,12 @@ class EventFactory implements IEventFactory {
385
487
  ): Promise<IFormoEvent> {
386
488
  const props = { ...(properties ?? {}), name, ...(category && { category }) };
387
489
 
388
- // Map screen name to page-equivalent context fields for Tinybird compatibility.
389
- // page_path is omitted Tinybird derives it from page_url via path().
490
+ // Map screen name to page-equivalent context fields so mobile screens flow
491
+ // through the same analytics as web page views. The screen name is emitted
492
+ // as-is in the app:// URL; the ingestion pipeline derives `origin` (from the
493
+ // app identifier in context — app_name / app_bundle_id) and `page_path` (by
494
+ // stripping the app:// scheme), so the SDK deliberately does NOT encode a
495
+ // host here (see backend mobile page-event handling, P-2070).
390
496
  // User-supplied context values take precedence (spread last).
391
497
  const screenContext: IFormoEventContext = {
392
498
  page_title: name,
@@ -501,7 +607,6 @@ class EventFactory implements IEventFactory {
501
607
  chainId: ChainID | undefined,
502
608
  address: Address,
503
609
  message: string,
504
- signatureHash?: string,
505
610
  properties?: IFormoEventProperties,
506
611
  context?: IFormoEventContext
507
612
  ): Promise<IFormoEvent> {
@@ -510,7 +615,6 @@ class EventFactory implements IEventFactory {
510
615
  status,
511
616
  ...(chainId !== undefined && chainId !== null && { chainId }),
512
617
  message,
513
- ...(signatureHash && { signatureHash }),
514
618
  ...properties,
515
619
  },
516
620
  address,
@@ -648,7 +752,6 @@ class EventFactory implements IEventFactory {
648
752
  event.chainId,
649
753
  event.address,
650
754
  event.message,
651
- event.signatureHash,
652
755
  event.properties,
653
756
  event.context
654
757
  );
@@ -680,10 +783,7 @@ class EventFactory implements IEventFactory {
680
783
 
681
784
  // Set address if not already set by the specific event generator
682
785
  if (formoEvent.address === undefined || formoEvent.address === null) {
683
- const validAddress = getValidAddress(address);
684
- formoEvent.address = validAddress
685
- ? toChecksumAddress(validAddress)
686
- : null;
786
+ formoEvent.address = address ? validateAddress(address) ?? null : null;
687
787
  }
688
788
  formoEvent.user_id = userId || null;
689
789