@gabagool-sdk/react-native 0.2.0 → 0.3.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/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.3.0
2
+
3
+ * **Funciona sem polyfill de crypto**: o core não exige mais `crypto.getRandomValues` (ver `@gabagool-sdk/core` 0.3.0); `react-native-get-random-values` passa de obrigatório (0.2.x) a recomendado: se o app tiver, é usado e os ids ganham aleatoriedade criptográfica; sem ele os ids saem de `Math.random`. Requer `@gabagool-sdk/core` ^0.3.0.
4
+ * **Fix do Metro**: o campo `"react-native"` do `package.json` apontava para `src/index.ts`, e o Metro resolvia o fonte TS com imports `./x.js` e quebrava. Agora aponta para o JS compilado (`dist/index.js`, o mesmo do `main`), que já vai no pacote (`files`).
5
+
6
+ ## 0.2.1
7
+
8
+ * `GabagoolAds.setRewardedSsv({ userId?, customData? })`: SSV do rewarded, mesma semântica do Dart e do core (antes ou depois do `init`; `userId` > `identify`; `customData` ≤ 1024). O adapter aplica `serverSideVerificationOptions` (`react-native-google-mobile-ads` 17.x) no `RewardedAd.createForAdRequest`. Não testado em aparelho. Requer `@gabagool-sdk/core` ^0.2.1.
9
+
1
10
  ## 0.2.0
2
11
 
3
12
  * `GabagoolAds.onPaidEvent` (e opção `onPaidEvent` no `init`): receita de toda impressão, repassada do core. O lado nativo do RN continua parcial (API presente; emissão coberta pelos testes do core). Requer `@gabagool-sdk/core` ^0.2.0.
package/README.md CHANGED
@@ -5,7 +5,7 @@ O servidor Gabagool decide segmento, ad units e pisos a cada `init`; o piso vai
5
5
  **key-value de targeting** (a key de piso é configurada no painel Gabagool, com a grafia exata do
6
6
  valor do piso). Sem configuração do servidor, o SDK não exibe anúncios.
7
7
 
8
- **Limitação da versão 0.2.0:** o formato **native** ainda não é suportado neste pacote
8
+ **Limitação da versão 0.2.x:** o formato **native** ainda não é suportado neste pacote
9
9
  (interstitial, rewarded, banner e app open já funcionam). Android é o alvo testado;
10
10
  no iOS, passe `installInfoProvider` no `init` (o plugin de Play Install Referrer é Android-only).
11
11
 
@@ -15,6 +15,27 @@ Mais detalhes: https://gabagool.com.br
15
15
 
16
16
  ```bash
17
17
  npm install @gabagool-sdk/react-native react-native-google-mobile-ads @react-native-async-storage/async-storage react-native-play-install-referrer
18
+ # recomendado (opcional a partir da 0.3.0):
19
+ npm install react-native-get-random-values
20
+ ```
21
+
22
+ **Polyfill de `crypto.getRandomValues`: recomendado a partir da 0.3.0, obrigatório na 0.2.x.**
23
+ - **0.3.0 ou mais nova**: o SDK funciona sem o polyfill. Se faltar `crypto.getRandomValues`, os ids de evento e de
24
+ instalação saem de `Math.random` (servem como id, não como segredo). Com o polyfill instalado, ele é usado sozinho e
25
+ os ids ganham aleatoriedade criptográfica, por isso é o recomendado.
26
+ - **0.2.x**: sem o polyfill o `init` falha com `crypto.getRandomValues() not supported` e nenhum anúncio aparece
27
+ (confirmado em aparelho em 14/11/2026). Atualize para a 0.3.0 ou instale o polyfill.
28
+
29
+ Se instalar, importe na **primeira linha do arquivo de entrada** do app, antes de qualquer import do SDK:
30
+
31
+ ```js
32
+ // index.js — primeira linha, antes de qualquer import do @gabagool-sdk
33
+ import 'react-native-get-random-values';
34
+ import { AppRegistry } from 'react-native';
35
+ import App from './App';
36
+ import { name as appName } from './app.json';
37
+
38
+ AppRegistry.registerComponent(appName, () => App);
18
39
  ```
19
40
 
20
41
  Você precisa de uma **chave de API** (`x-api-key`) do seu app, gerada no painel Gabagool.
@@ -36,6 +57,7 @@ no `Info.plist` conforme a documentação do `react-native-google-mobile-ads`.
36
57
  ## 3. Init
37
58
 
38
59
  ```tsx
60
+ // se instalou o polyfill recomendado, ele já foi importado na 1ª linha do index.js (seção 1)
39
61
  import { GabagoolAds } from '@gabagool-sdk/react-native';
40
62
 
41
63
  await GabagoolAds.init('SUA_API_KEY', 'https://apps.gabagool.com.br', 'com.seu.app', {
@@ -62,6 +84,14 @@ const result = await GabagoolAds.showInterstitial('home');
62
84
  const reward = await GabagoolAds.showRewarded('bonus');
63
85
  ```
64
86
 
87
+ **SSV (Server-Side Verification)**: para validar a recompensa no seu backend, defina `userId`/`customData` (antes ou depois do `init`; sem `userId`, vale o do `identify`):
88
+
89
+ ```tsx
90
+ GabagoolAds.setRewardedSsv({ userId: 'user-123', customData: '{"pack":"coins_50"}' });
91
+ ```
92
+
93
+ Vira `serverSideVerificationOptions` do `react-native-google-mobile-ads` no load do rewarded (`customData` até 1024 chars). Callback, assinatura e limites: `docs/SSV-REWARDED.md`. Não testado em aparelho nem contra o callback real do Google.
94
+
65
95
  ### Banner
66
96
 
67
97
  ```tsx
package/dist/adapter.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type AdHandle, type AdNetworkAdapter, type FloorKV, type LoadResult, type ShowResult } from '@gabagool-sdk/core';
1
+ import { type AdHandle, type AdNetworkAdapter, type FloorKV, type LoadResult, type RewardedLoadOptions, type ShowResult } from '@gabagool-sdk/core';
2
2
  /** Adapter do core para a API estável do Invertase 17.x. */
3
3
  export declare class ReactNativeGmaAdapter implements AdNetworkAdapter {
4
4
  private sequence;
@@ -9,7 +9,7 @@ export declare class ReactNativeGmaAdapter implements AdNetworkAdapter {
9
9
  /** Falha do initialize() não trava o app (como a Dart): segue e os loads reportam seus próprios erros. */
10
10
  initialize(): Promise<void>;
11
11
  loadInterstitial(adUnit: string, floorKV?: FloorKV): Promise<LoadResult>;
12
- loadRewarded(adUnit: string, floorKV?: FloorKV): Promise<LoadResult>;
12
+ loadRewarded(adUnit: string, floorKV?: FloorKV, opts?: RewardedLoadOptions): Promise<LoadResult>;
13
13
  loadAppOpen(adUnit: string, floorKV?: FloorKV): Promise<LoadResult>;
14
14
  loadBanner(adUnit: string, _floorKV?: FloorKV): Promise<LoadResult>;
15
15
  /** Native ainda não portado para RN (Invertase NativeAd): reporta erro explícito, nunca fill falso. */
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AA4B5B,4DAA4D;AAC5D,qBAAa,qBAAsB,YAAW,gBAAgB;IAC5D,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAE5D,0GAA0G;IAC1G,QAAQ,CAAC,6BAA6B,QAAQ;IAE9C,0GAA0G;IACpG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAGxE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAGpE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAI7D,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAWzE,uGAAuG;IACjG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAI1E,gBAAgB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI;IAI9B,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD,OAAO,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI;IAM3B,IAAI,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAuCvC,OAAO,CAAC,cAAc;IAyCtB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,MAAM;CAGf"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACrB,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,KAAK,mBAAmB,EAExB,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AA+B5B,4DAA4D;AAC5D,qBAAa,qBAAsB,YAAW,gBAAgB;IAC5D,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAE5D,0GAA0G;IAC1G,QAAQ,CAAC,6BAA6B,QAAQ;IAE9C,0GAA0G;IACpG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAGxE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC;IAGhG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAI7D,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAWzE,uGAAuG;IACjG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAI1E,gBAAgB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI;IAI9B,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD,OAAO,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI;IAM3B,IAAI,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAuCvC,OAAO,CAAC,cAAc;IAyCtB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,MAAM;CAGf"}
package/dist/adapter.js CHANGED
@@ -24,8 +24,8 @@ export class ReactNativeGmaAdapter {
24
24
  loadInterstitial(adUnit, floorKV) {
25
25
  return this.loadFullscreen('interstitial', adUnit, floorKV);
26
26
  }
27
- loadRewarded(adUnit, floorKV) {
28
- return this.loadFullscreen('rewarded', adUnit, floorKV);
27
+ loadRewarded(adUnit, floorKV, opts) {
28
+ return this.loadFullscreen('rewarded', adUnit, floorKV, opts?.ssv);
29
29
  }
30
30
  loadAppOpen(adUnit, floorKV) {
31
31
  return this.loadFullscreen('app_open', adUnit, floorKV);
@@ -99,11 +99,11 @@ export class ReactNativeGmaAdapter {
99
99
  }
100
100
  });
101
101
  }
102
- loadFullscreen(format, adUnit, floorKV) {
102
+ loadFullscreen(format, adUnit, floorKV, ssv) {
103
103
  return new Promise((resolve) => {
104
104
  let native;
105
105
  try {
106
- const request = this.requestOptions(adUnit, floorKV);
106
+ const request = this.requestOptions(adUnit, floorKV, format === 'rewarded' ? ssv : undefined);
107
107
  const created = format === 'app_open'
108
108
  ? AppOpenAd.createForAdRequest(adUnit, request)
109
109
  : format === 'rewarded'
@@ -149,9 +149,13 @@ export class ReactNativeGmaAdapter {
149
149
  }
150
150
  });
151
151
  }
152
- requestOptions(adUnit, floorKV) {
152
+ requestOptions(adUnit, floorKV, ssv) {
153
153
  const kv = this.requestFloor(adUnit, floorKV);
154
- return kv ? { customTargeting: kv } : undefined;
154
+ // Invertase: RequestOptions.serverSideVerificationOptions { userId, customData } (só no RewardedAd; vazio => omitido)
155
+ const ssvOptions = ssv && (ssv.userId !== undefined || ssv.customData !== undefined)
156
+ ? { serverSideVerificationOptions: { ...(ssv.userId !== undefined ? { userId: ssv.userId } : {}), ...(ssv.customData !== undefined ? { customData: ssv.customData } : {}) } }
157
+ : {};
158
+ return kv || ssvOptions.serverSideVerificationOptions ? { ...(kv ? { customTargeting: kv } : {}), ...ssvOptions } : undefined;
155
159
  }
156
160
  requestFloor(adUnit, floorKV) {
157
161
  return networkOf(adUnit) === 'gam' && floorKV && Object.keys(floorKV).length > 0 ? { ...floorKV } : undefined;
package/dist/facade.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type AdHandle, type AdNetworkAdapter, type BootAdResult, type FetchLike, type Gabagool, type GateResult, type InterstitialShowResult, type KVStorage, type OnPaidEvent, type RewardedResult, type TelemetryTransport, type WrapperConfig } from '@gabagool-sdk/core';
1
+ import { type AdHandle, type AdNetworkAdapter, type BootAdResult, type FetchLike, type Gabagool, type GateResult, type InterstitialShowResult, type KVStorage, type OnPaidEvent, type RewardedResult, type RewardedSsv, type TelemetryTransport, type WrapperConfig } from '@gabagool-sdk/core';
2
2
  import { ReactNativeGmaAdapter } from './adapter.js';
3
3
  import { type InstallInfoProvider } from './installInfo.js';
4
4
  export interface GabagoolInitOptions {
@@ -38,6 +38,14 @@ export declare class GabagoolAds {
38
38
  * telemetria; exceção do callback é engolida. Pode ser atribuído antes ou depois do `init`.
39
39
  */
40
40
  static onPaidEvent: OnPaidEvent | null;
41
+ /** SSV guardado aqui: setRewardedSsv antes do init sobrevive à recriação do core. */
42
+ private static ssv;
43
+ /**
44
+ * SSV do rewarded (Server-Side Verification): `userId`/`customData` chegam no callback do Google ao seu backend.
45
+ * Vale antes ou depois do `init` (próximos loads; um rewarded já carregado mantém o que tinha). Sem `userId`, usa o do
46
+ * `identify`. Sem argumentos limpa. `customData` acima de 1024 chars é cortado (com aviso). Ver docs/SSV-REWARDED.md.
47
+ */
48
+ static setRewardedSsv(ssv?: RewardedSsv): void;
41
49
  static get core(): Gabagool;
42
50
  static init(apiKey: string, baseUrl: string, appId: string, options?: GabagoolInitOptions): Promise<void>;
43
51
  static showInterstitial(screen?: string): Promise<InterstitialShowResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"facade.d.ts","sourceRoot":"","sources":["../src/facade.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"facade.d.ts","sourceRoot":"","sources":["../src/facade.ts"],"names":[],"mappings":"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"}
package/dist/facade.js CHANGED
@@ -28,6 +28,17 @@ export class GabagoolAds {
28
28
  * telemetria; exceção do callback é engolida. Pode ser atribuído antes ou depois do `init`.
29
29
  */
30
30
  static onPaidEvent = null;
31
+ /** SSV guardado aqui: setRewardedSsv antes do init sobrevive à recriação do core. */
32
+ static ssv;
33
+ /**
34
+ * SSV do rewarded (Server-Side Verification): `userId`/`customData` chegam no callback do Google ao seu backend.
35
+ * Vale antes ou depois do `init` (próximos loads; um rewarded já carregado mantém o que tinha). Sem `userId`, usa o do
36
+ * `identify`. Sem argumentos limpa. `customData` acima de 1024 chars é cortado (com aviso). Ver docs/SSV-REWARDED.md.
37
+ */
38
+ static setRewardedSsv(ssv) {
39
+ this.ssv = ssv;
40
+ this.instance.setRewardedSsv(ssv);
41
+ }
31
42
  static get core() { return this.instance; }
32
43
  static async init(apiKey, baseUrl, appId, options = {}) {
33
44
  if (options.onPaidEvent)
@@ -36,6 +47,7 @@ export class GabagoolAds {
36
47
  this.instance.dispose();
37
48
  this.resetReady();
38
49
  this.instance = createGabagool();
50
+ this.instance.setRewardedSsv(this.ssv);
39
51
  const adapter = options.adapter ?? new ReactNativeGmaAdapter();
40
52
  this.gmaAdapter = adapter instanceof ReactNativeGmaAdapter ? adapter : null;
41
53
  if (this.gmaAdapter)
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@gabagool-sdk/react-native",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "React Native SDK for Gabagool Apps monetization: interstitial, rewarded and banner ads with server-side config, price floors and gating, on top of Google Mobile Ads (Ad Manager / AdMob).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
- "react-native": "src/index.ts",
8
+ "react-native": "dist/index.js",
9
9
  "files": [
10
10
  "dist",
11
11
  "src",
@@ -23,7 +23,7 @@
23
23
  "prepack": "npm run build"
24
24
  },
25
25
  "dependencies": {
26
- "@gabagool-sdk/core": "^0.2.0"
26
+ "@gabagool-sdk/core": "^0.3.0"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "@react-native-async-storage/async-storage": "^3.1.1",
package/src/adapter.ts CHANGED
@@ -15,9 +15,14 @@ import {
15
15
  type AdNetworkAdapter,
16
16
  type FloorKV,
17
17
  type LoadResult,
18
+ type RewardedLoadOptions,
19
+ type RewardedSsv,
18
20
  type ShowResult,
19
21
  } from '@gabagool-sdk/core';
20
- type RequestOptions = { customTargeting?: Record<string, string | number | (string | number)[]> };
22
+ type RequestOptions = {
23
+ customTargeting?: Record<string, string | number | (string | number)[]>;
24
+ serverSideVerificationOptions?: { userId?: string; customData?: string };
25
+ };
21
26
 
22
27
  type Remove = () => void;
23
28
  type EventPayload = Error & { code?: string; reason?: string; phase?: 'load' | 'show' };
@@ -61,8 +66,8 @@ export class ReactNativeGmaAdapter implements AdNetworkAdapter {
61
66
  loadInterstitial(adUnit: string, floorKV?: FloorKV): Promise<LoadResult> {
62
67
  return this.loadFullscreen('interstitial', adUnit, floorKV);
63
68
  }
64
- loadRewarded(adUnit: string, floorKV?: FloorKV): Promise<LoadResult> {
65
- return this.loadFullscreen('rewarded', adUnit, floorKV);
69
+ loadRewarded(adUnit: string, floorKV?: FloorKV, opts?: RewardedLoadOptions): Promise<LoadResult> {
70
+ return this.loadFullscreen('rewarded', adUnit, floorKV, opts?.ssv);
66
71
  }
67
72
  loadAppOpen(adUnit: string, floorKV?: FloorKV): Promise<LoadResult> {
68
73
  return this.loadFullscreen('app_open', adUnit, floorKV);
@@ -137,11 +142,11 @@ export class ReactNativeGmaAdapter implements AdNetworkAdapter {
137
142
  });
138
143
  }
139
144
 
140
- private loadFullscreen(format: Exclude<AdFormat, 'banner'>, adUnit: string, floorKV?: FloorKV): Promise<LoadResult> {
145
+ private loadFullscreen(format: Exclude<AdFormat, 'banner'>, adUnit: string, floorKV?: FloorKV, ssv?: RewardedSsv): Promise<LoadResult> {
141
146
  return new Promise((resolve) => {
142
147
  let native: NativeFullscreen;
143
148
  try {
144
- const request = this.requestOptions(adUnit, floorKV);
149
+ const request = this.requestOptions(adUnit, floorKV, format === 'rewarded' ? ssv : undefined);
145
150
  const created = format === 'app_open'
146
151
  ? AppOpenAd.createForAdRequest(adUnit, request)
147
152
  : format === 'rewarded'
@@ -178,9 +183,13 @@ export class ReactNativeGmaAdapter implements AdNetworkAdapter {
178
183
  });
179
184
  }
180
185
 
181
- private requestOptions(adUnit: string, floorKV?: FloorKV): RequestOptions | undefined {
186
+ private requestOptions(adUnit: string, floorKV?: FloorKV, ssv?: RewardedSsv): RequestOptions | undefined {
182
187
  const kv = this.requestFloor(adUnit, floorKV);
183
- return kv ? { customTargeting: kv } : undefined;
188
+ // Invertase: RequestOptions.serverSideVerificationOptions { userId, customData } (só no RewardedAd; vazio => omitido)
189
+ const ssvOptions = ssv && (ssv.userId !== undefined || ssv.customData !== undefined)
190
+ ? { serverSideVerificationOptions: { ...(ssv.userId !== undefined ? { userId: ssv.userId } : {}), ...(ssv.customData !== undefined ? { customData: ssv.customData } : {}) } }
191
+ : {};
192
+ return kv || ssvOptions.serverSideVerificationOptions ? { ...(kv ? { customTargeting: kv } : {}), ...ssvOptions } : undefined;
184
193
  }
185
194
 
186
195
  private requestFloor(adUnit: string, floorKV?: FloorKV): FloorKV | undefined {
package/src/facade.ts CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  type KVStorage,
14
14
  type OnPaidEvent,
15
15
  type RewardedResult,
16
+ type RewardedSsv,
16
17
  type TelemetryTransport,
17
18
  type WrapperConfig,
18
19
  } from '@gabagool-sdk/core';
@@ -71,6 +72,19 @@ export class GabagoolAds {
71
72
  */
72
73
  static onPaidEvent: OnPaidEvent | null = null;
73
74
 
75
+ /** SSV guardado aqui: setRewardedSsv antes do init sobrevive à recriação do core. */
76
+ private static ssv: RewardedSsv | undefined;
77
+
78
+ /**
79
+ * SSV do rewarded (Server-Side Verification): `userId`/`customData` chegam no callback do Google ao seu backend.
80
+ * Vale antes ou depois do `init` (próximos loads; um rewarded já carregado mantém o que tinha). Sem `userId`, usa o do
81
+ * `identify`. Sem argumentos limpa. `customData` acima de 1024 chars é cortado (com aviso). Ver docs/SSV-REWARDED.md.
82
+ */
83
+ static setRewardedSsv(ssv?: RewardedSsv): void {
84
+ this.ssv = ssv;
85
+ this.instance.setRewardedSsv(ssv);
86
+ }
87
+
74
88
  static get core(): Gabagool { return this.instance; }
75
89
 
76
90
  static async init(apiKey: string, baseUrl: string, appId: string, options: GabagoolInitOptions = {}): Promise<void> {
@@ -79,6 +93,7 @@ export class GabagoolAds {
79
93
  this.instance.dispose();
80
94
  this.resetReady();
81
95
  this.instance = createGabagool();
96
+ this.instance.setRewardedSsv(this.ssv);
82
97
 
83
98
  const adapter = options.adapter ?? new ReactNativeGmaAdapter();
84
99
  this.gmaAdapter = adapter instanceof ReactNativeGmaAdapter ? adapter : null;