@whanext/core 0.19.2 → 0.19.4
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 +25 -0
- package/MIGRATING_TO_ZAPO.md +1 -1
- package/README.md +2 -0
- package/dist/index.js +145 -64
- package/dist/index.js.map +1 -1
- package/package.json +1 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.4
|
|
4
|
+
### Corrigido
|
|
5
|
+
- Corrigida a normalização de `timestampMs` dos eventos nativos de chamada; removida uma referência inválida ao helper privado `#number`.
|
|
6
|
+
- Chamadas no provider Zapo agora usam o evento nativo `call`, sem depender do plugin completo de VoIP.
|
|
7
|
+
- `rejectCall()` envia diretamente a sinalização mínima `<call><reject/></call>` pelo `client.lowlevel.sendNode()`, preservando `callId` e `callCreatorJid`.
|
|
8
|
+
- Removidas as dependências `@zapo-js/voip`, `@roamhq/wrtc` e `libmlow-wasm` do WhaNext Core; detectar/rejeitar chamadas não exige WebRTC nem binário nativo.
|
|
9
|
+
- O `callCreatorJid` técnico é mantido em cache limitado para que a rejeição use o endereço de protocolo correto mesmo quando o evento público expõe o `callerPnJid`.
|
|
10
|
+
|
|
11
|
+
### Compatibilidade
|
|
12
|
+
- A API pública permanece igual: `app.on('call')`, `CallEvent` e `rejectCall(callId, from)` não mudam para consumidores.
|
|
13
|
+
- O suporte completo a aceitar/realizar chamadas VoIP não faz parte da API pública do WhaNext.
|
|
14
|
+
|
|
15
|
+
## 0.19.3
|
|
16
|
+
### Corrigido
|
|
17
|
+
- Carregamento lazy do plugin VoIP do Zapo para evitar importar o runtime WebRTC em consumidores e testes que não inicializam o provider.
|
|
18
|
+
- Ajustes de tipagem dos testes com `exactOptionalPropertyTypes`.
|
|
19
|
+
- Provider Zapo agora usa `@zapo-js/voip` como único caminho de chamadas: eventos `voip_*` e `client.voip.rejectCall()`, sem fallback silencioso.
|
|
20
|
+
- `messageEdited` também reconhece edições criptografadas descriptografadas pelo Zapo em `message_addon`, além de `message_protocol`.
|
|
21
|
+
- `messageDeleted` e `messageEdited` ignoram protocolo de backlog durante bootstrap quando `processOfflineMessages` está desativado.
|
|
22
|
+
- Mensagens recebidas antes de `connection: open` deixam de ser publicadas como mensagens ao vivo; ainda entram no cache limitado para permitir recuperação posterior.
|
|
23
|
+
- Eventos `message` duplicados no mesmo runtime são descartados antes de chegar aos consumidores, evitando downloads repetidos de mídia/ViewOnce.
|
|
24
|
+
|
|
25
|
+
### Compatibilidade
|
|
26
|
+
- Mudança corretiva e aditiva; a API pública de `CallEvent`, `messageDeleted` e `messageEdited` permanece inalterada.
|
|
27
|
+
|
|
3
28
|
## 0.19.2
|
|
4
29
|
|
|
5
30
|
- Corrigido o download real de mídias citadas no provider Zapo: `downloadMedia()` agora entrega o `Proto.IMessage` bruto diretamente ao `downloadBytes()`, como suportado pela API do Zapo.
|
package/MIGRATING_TO_ZAPO.md
CHANGED
|
@@ -58,7 +58,7 @@ O provider usa `@zapo-js/media-utils`. Para processamento completo de imagem, v
|
|
|
58
58
|
|
|
59
59
|
## Chamadas
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
A partir da v0.19.4, `app.on('call')` usa o evento `call` nativo do Zapo e `rejectCall()` envia somente a sinalização de rejeição pelo `client.lowlevel`. O WhaNext não carrega o stack completo de VoIP/WebRTC para detectar ou rejeitar chamadas.
|
|
62
62
|
|
|
63
63
|
## Checklist de atualização
|
|
64
64
|
|
package/README.md
CHANGED
|
@@ -994,6 +994,8 @@ app.on('call', async (call) => {
|
|
|
994
994
|
|
|
995
995
|
`call.status` reflete o ciclo da chamada (`offer`, `ringing`, `preaccept`, `timeout`, `reject`, `accept`). `call.isVideo` e `call.isGroup` indicam o tipo. Somente chamadas em `offer` podem ser rejeitadas.
|
|
996
996
|
|
|
997
|
+
No provider Zapo, detecção e rejeição usam apenas a sinalização nativa de chamadas e `client.lowlevel.sendNode()`. O WhaNext não carrega o stack completo de VoIP/WebRTC para esse fluxo.
|
|
998
|
+
|
|
997
999
|
## Erros
|
|
998
1000
|
|
|
999
1001
|
```ts
|
package/dist/index.js
CHANGED
|
@@ -2708,9 +2708,11 @@ var ZapoProvider = class {
|
|
|
2708
2708
|
#logger;
|
|
2709
2709
|
#messageStore = /* @__PURE__ */ new Map();
|
|
2710
2710
|
#messageKeyStore = /* @__PURE__ */ new WeakMap();
|
|
2711
|
+
#deliveredMessageStore = /* @__PURE__ */ new Set();
|
|
2712
|
+
#handledProtocolStore = /* @__PURE__ */ new Set();
|
|
2713
|
+
#callCreatorStore = /* @__PURE__ */ new Map();
|
|
2711
2714
|
#messageCacheSize;
|
|
2712
2715
|
#client;
|
|
2713
|
-
#voip;
|
|
2714
2716
|
#intentionalClose = false;
|
|
2715
2717
|
#reconnectAttempt = 0;
|
|
2716
2718
|
#reconnectTimer;
|
|
@@ -2964,16 +2966,26 @@ var ZapoProvider = class {
|
|
|
2964
2966
|
const presence = this.#requireClient().presence;
|
|
2965
2967
|
await presence.sendChatstate(chatId, { state: value });
|
|
2966
2968
|
}
|
|
2967
|
-
async rejectCall(callId,
|
|
2968
|
-
this.#requireClient();
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2969
|
+
async rejectCall(callId, from) {
|
|
2970
|
+
const client = this.#requireClient();
|
|
2971
|
+
const creator = this.#callCreatorStore.get(callId) ?? from;
|
|
2972
|
+
if (!creator) {
|
|
2973
|
+
throw new WhaNextError("ARGUMENT_INVALID", "Call creator is required to reject a call.");
|
|
2974
|
+
}
|
|
2975
|
+
const lowlevel = client.lowlevel;
|
|
2976
|
+
await lowlevel.sendNode({
|
|
2977
|
+
tag: "call",
|
|
2978
|
+
attrs: { to: creator },
|
|
2979
|
+
content: [
|
|
2980
|
+
{
|
|
2981
|
+
tag: "reject",
|
|
2982
|
+
attrs: {
|
|
2983
|
+
"call-id": callId,
|
|
2984
|
+
"call-creator": creator
|
|
2985
|
+
}
|
|
2986
|
+
}
|
|
2987
|
+
]
|
|
2988
|
+
});
|
|
2977
2989
|
}
|
|
2978
2990
|
async #ensureClient() {
|
|
2979
2991
|
if (this.#client) return this.#client;
|
|
@@ -3002,15 +3014,6 @@ var ZapoProvider = class {
|
|
|
3002
3014
|
messageSecret: "sqlite"
|
|
3003
3015
|
}
|
|
3004
3016
|
});
|
|
3005
|
-
const plugins = [];
|
|
3006
|
-
try {
|
|
3007
|
-
const { voipPlugin } = await import("@zapo-js/voip");
|
|
3008
|
-
plugins.push(voipPlugin({ logLevel: "warn" }));
|
|
3009
|
-
} catch (error) {
|
|
3010
|
-
this.#logger.warn("Zapo VoIP support is unavailable; call events and rejection are disabled.", {
|
|
3011
|
-
error: error instanceof Error ? error.message : String(error)
|
|
3012
|
-
});
|
|
3013
|
-
}
|
|
3014
3017
|
const client = new WaClient({
|
|
3015
3018
|
store,
|
|
3016
3019
|
sessionId: this.#options.sessionId ?? "default",
|
|
@@ -3022,11 +3025,9 @@ var ZapoProvider = class {
|
|
|
3022
3025
|
autoDecrypt: true,
|
|
3023
3026
|
persistAllSecrets: true
|
|
3024
3027
|
},
|
|
3025
|
-
media: { processor: createMediaProcessor() }
|
|
3026
|
-
plugins
|
|
3028
|
+
media: { processor: createMediaProcessor() }
|
|
3027
3029
|
}, new WhaNextZapoLogger(this.#logger));
|
|
3028
3030
|
this.#client = client;
|
|
3029
|
-
this.#voip = client.voip;
|
|
3030
3031
|
this.#bind(client);
|
|
3031
3032
|
return client;
|
|
3032
3033
|
}
|
|
@@ -3058,49 +3059,46 @@ var ZapoProvider = class {
|
|
|
3058
3059
|
client.on("message_protocol", (event) => {
|
|
3059
3060
|
this.#handleProtocolEvent(event);
|
|
3060
3061
|
});
|
|
3062
|
+
client.on("message_addon", (event) => {
|
|
3063
|
+
this.#handleAddonEvent(event);
|
|
3064
|
+
});
|
|
3061
3065
|
client.on("group", (event) => {
|
|
3062
3066
|
this.#handleGroupEvent(event);
|
|
3063
3067
|
});
|
|
3064
|
-
|
|
3065
|
-
const
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
if (call) void this.#events.emit("call", call);
|
|
3069
|
-
});
|
|
3070
|
-
voipClient.on("voip_call_state", (event) => {
|
|
3071
|
-
if (event.stateData?.state === "ended") return;
|
|
3072
|
-
const call = this.#normalizeVoipCall(event);
|
|
3073
|
-
if (call && call.status !== "offer") void this.#events.emit("call", call);
|
|
3074
|
-
});
|
|
3075
|
-
voipClient.on("voip_call_ended", (event) => {
|
|
3076
|
-
const call = this.#normalizeVoipCall(
|
|
3077
|
-
event,
|
|
3078
|
-
this.#callEndStatus(event.stateData?.endReason)
|
|
3079
|
-
);
|
|
3080
|
-
if (call) void this.#events.emit("call", call);
|
|
3081
|
-
});
|
|
3082
|
-
}
|
|
3068
|
+
client.on("call", (event) => {
|
|
3069
|
+
const call = this.#normalizeCall(event);
|
|
3070
|
+
if (call) void this.#events.emit("call", call);
|
|
3071
|
+
});
|
|
3083
3072
|
client.on("connection", (event) => {
|
|
3084
3073
|
void this.#handleConnectionEvent(client, event);
|
|
3085
3074
|
});
|
|
3086
3075
|
}
|
|
3087
3076
|
#handleMessage(event) {
|
|
3088
3077
|
const stored = event;
|
|
3078
|
+
if (stored.key?.id && stored.message) this.#remember(stored);
|
|
3079
|
+
const quoted = extractQuotedZapoMessage(event);
|
|
3080
|
+
if (quoted?.key.id && quoted.message) {
|
|
3081
|
+
this.#remember(quoted);
|
|
3082
|
+
}
|
|
3089
3083
|
if (this.#isOfflineMessage(stored)) {
|
|
3090
|
-
this.#logger.debug("Ignored message queued before the current connection.", {
|
|
3084
|
+
this.#logger.debug("Ignored message queued before the current live connection.", {
|
|
3091
3085
|
messageId: stored.key.id ?? void 0,
|
|
3092
3086
|
chatId: stored.key.remoteJid ?? void 0,
|
|
3093
3087
|
timestampSeconds: stored.timestampSeconds ?? void 0
|
|
3094
3088
|
});
|
|
3095
3089
|
return;
|
|
3096
3090
|
}
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3091
|
+
const deliveryKey = this.#messageDeliveryKey(stored.key);
|
|
3092
|
+
if (stored.key.id && this.#deliveredMessageStore.has(deliveryKey)) {
|
|
3093
|
+
this.#logger.debug("Ignored duplicate Zapo message event.", {
|
|
3094
|
+
messageId: stored.key.id,
|
|
3095
|
+
chatId: stored.key.remoteJid ?? void 0
|
|
3096
|
+
});
|
|
3097
|
+
return;
|
|
3101
3098
|
}
|
|
3102
3099
|
const message = normalizeZapoMessage(event);
|
|
3103
3100
|
if (!message) return;
|
|
3101
|
+
if (stored.key.id) this.#rememberDeliveredMessage(deliveryKey);
|
|
3104
3102
|
this.#messageKeyStore.set(message.keys, stored);
|
|
3105
3103
|
if (message.quoted && quoted?.message) {
|
|
3106
3104
|
this.#messageKeyStore.set(
|
|
@@ -3110,7 +3108,50 @@ var ZapoProvider = class {
|
|
|
3110
3108
|
}
|
|
3111
3109
|
void this.#events.emit("message", message);
|
|
3112
3110
|
}
|
|
3111
|
+
#handleAddonEvent(event) {
|
|
3112
|
+
if (event.kind !== "message_edit" || !event.targetMessageId) return;
|
|
3113
|
+
const editedMessage = this.#addonEditedMessage(event.decrypted);
|
|
3114
|
+
if (!editedMessage) return;
|
|
3115
|
+
const target = {
|
|
3116
|
+
id: event.targetMessageId,
|
|
3117
|
+
...event.key.remoteJid !== void 0 ? { remoteJid: event.key.remoteJid } : {},
|
|
3118
|
+
...event.key.fromMe !== void 0 ? { fromMe: event.key.fromMe } : {},
|
|
3119
|
+
...event.key.participant !== void 0 ? { participant: event.key.participant } : {},
|
|
3120
|
+
...event.key.participantAlt !== void 0 ? { participantAlt: event.key.participantAlt } : {}
|
|
3121
|
+
};
|
|
3122
|
+
this.#handleProtocolEvent({
|
|
3123
|
+
key: event.key,
|
|
3124
|
+
...event.offline !== void 0 ? { offline: event.offline } : {},
|
|
3125
|
+
protocolMessage: {
|
|
3126
|
+
type: proto.Message.ProtocolMessage.Type.MESSAGE_EDIT,
|
|
3127
|
+
key: target,
|
|
3128
|
+
editedMessage
|
|
3129
|
+
}
|
|
3130
|
+
});
|
|
3131
|
+
}
|
|
3132
|
+
#addonEditedMessage(value) {
|
|
3133
|
+
if (!value || typeof value !== "object") return void 0;
|
|
3134
|
+
const record = value;
|
|
3135
|
+
const protocol = record.protocolMessage;
|
|
3136
|
+
if (protocol && typeof protocol === "object") {
|
|
3137
|
+
const edited2 = protocol.editedMessage;
|
|
3138
|
+
if (edited2 && typeof edited2 === "object") return edited2;
|
|
3139
|
+
}
|
|
3140
|
+
const edited = record.editedMessage;
|
|
3141
|
+
if (edited && typeof edited === "object") return edited;
|
|
3142
|
+
const message = record.message;
|
|
3143
|
+
if (message && typeof message === "object") return message;
|
|
3144
|
+
return value;
|
|
3145
|
+
}
|
|
3113
3146
|
#handleProtocolEvent(event) {
|
|
3147
|
+
if (this.#isOfflineMessage(event)) {
|
|
3148
|
+
this.#logger.debug("Ignored protocol event queued before the current live connection.", {
|
|
3149
|
+
messageId: event.key.id ?? void 0,
|
|
3150
|
+
chatId: event.key.remoteJid ?? void 0,
|
|
3151
|
+
timestampSeconds: event.timestampSeconds ?? void 0
|
|
3152
|
+
});
|
|
3153
|
+
return;
|
|
3154
|
+
}
|
|
3114
3155
|
const protocol = event.protocolMessage ?? event.message?.protocolMessage;
|
|
3115
3156
|
if (!protocol) return;
|
|
3116
3157
|
const protocolKey = protocol.key;
|
|
@@ -3127,7 +3168,16 @@ var ZapoProvider = class {
|
|
|
3127
3168
|
if (!target.remoteJid) return;
|
|
3128
3169
|
const stored = this.#findStoredMessage(target);
|
|
3129
3170
|
const type = protocol?.type;
|
|
3171
|
+
const mutationKey = this.#protocolDeliveryKey(event, target, type);
|
|
3172
|
+
if (mutationKey && this.#handledProtocolStore.has(mutationKey)) {
|
|
3173
|
+
this.#logger.debug("Ignored duplicate Zapo protocol event.", {
|
|
3174
|
+
messageId: event.key.id ?? void 0,
|
|
3175
|
+
targetMessageId: target.id ?? void 0
|
|
3176
|
+
});
|
|
3177
|
+
return;
|
|
3178
|
+
}
|
|
3130
3179
|
if (type === proto.Message.ProtocolMessage.Type.REVOKE) {
|
|
3180
|
+
if (mutationKey) this.#rememberHandledProtocol(mutationKey);
|
|
3131
3181
|
const previous2 = stored ? normalizeZapoMessage(stored) : void 0;
|
|
3132
3182
|
const deletedByMe = event.key.fromMe === true;
|
|
3133
3183
|
const deletedById = event.key.participant ?? event.key.participantAlt ?? (deletedByMe ? this.getCurrentUserIds()[0] : event.key.remoteJid ?? void 0);
|
|
@@ -3157,6 +3207,7 @@ var ZapoProvider = class {
|
|
|
3157
3207
|
const message = normalizeZapoMessage(edited);
|
|
3158
3208
|
if (!message) return;
|
|
3159
3209
|
const previous = stored ? normalizeZapoMessage(stored) : void 0;
|
|
3210
|
+
if (mutationKey) this.#rememberHandledProtocol(mutationKey);
|
|
3160
3211
|
this.#remember(edited);
|
|
3161
3212
|
const editedByMe = event.key.fromMe === true;
|
|
3162
3213
|
const editedById = event.key.participant ?? event.key.participantAlt ?? (editedByMe ? this.getCurrentUserIds()[0] : event.key.remoteJid ?? void 0);
|
|
@@ -3521,49 +3572,49 @@ var ZapoProvider = class {
|
|
|
3521
3572
|
timestamp: /* @__PURE__ */ new Date()
|
|
3522
3573
|
};
|
|
3523
3574
|
}
|
|
3524
|
-
#
|
|
3575
|
+
#normalizeCall(event) {
|
|
3525
3576
|
const id = event.callId;
|
|
3526
|
-
const
|
|
3527
|
-
const
|
|
3577
|
+
const creator = event.callCreatorJid ?? void 0;
|
|
3578
|
+
const from = event.callerPnJid ?? creator;
|
|
3579
|
+
const chatId = event.groupJid ?? from;
|
|
3528
3580
|
if (!id || !from || !chatId) return void 0;
|
|
3581
|
+
if (creator) {
|
|
3582
|
+
this.#callCreatorStore.delete(id);
|
|
3583
|
+
this.#callCreatorStore.set(id, creator);
|
|
3584
|
+
while (this.#callCreatorStore.size > 256) {
|
|
3585
|
+
const oldest = this.#callCreatorStore.keys().next().value;
|
|
3586
|
+
if (!oldest) break;
|
|
3587
|
+
this.#callCreatorStore.delete(oldest);
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3590
|
+
const timestampMs = toNumber2(event.timestampMs);
|
|
3529
3591
|
return {
|
|
3530
3592
|
id,
|
|
3531
3593
|
chatId,
|
|
3532
3594
|
from,
|
|
3533
|
-
status:
|
|
3534
|
-
isVideo: event.
|
|
3595
|
+
status: this.#callStatus(event.type),
|
|
3596
|
+
isVideo: event.isVideo === true,
|
|
3535
3597
|
isGroup: Boolean(event.groupJid),
|
|
3536
|
-
date:
|
|
3598
|
+
date: timestampMs && timestampMs > 0 ? new Date(timestampMs) : /* @__PURE__ */ new Date()
|
|
3537
3599
|
};
|
|
3538
3600
|
}
|
|
3539
3601
|
#callStatus(status) {
|
|
3540
3602
|
switch (status?.toLowerCase()) {
|
|
3541
3603
|
case "offer":
|
|
3542
|
-
case "initiating":
|
|
3543
3604
|
return "offer";
|
|
3544
3605
|
case "ringing":
|
|
3545
|
-
case "incoming_ringing":
|
|
3546
3606
|
return "ringing";
|
|
3547
3607
|
case "preaccept":
|
|
3548
|
-
case "connecting":
|
|
3549
3608
|
return "preaccept";
|
|
3550
3609
|
case "accept":
|
|
3551
|
-
case "accepted":
|
|
3552
|
-
case "active":
|
|
3553
3610
|
return "accept";
|
|
3554
3611
|
case "reject":
|
|
3555
|
-
case "rejected":
|
|
3556
3612
|
case "terminate":
|
|
3557
|
-
case "terminated":
|
|
3558
|
-
case "ended":
|
|
3559
3613
|
return "reject";
|
|
3560
3614
|
default:
|
|
3561
3615
|
return "timeout";
|
|
3562
3616
|
}
|
|
3563
3617
|
}
|
|
3564
|
-
#callEndStatus(reason) {
|
|
3565
|
-
return reason?.toLowerCase() === "timeout" ? "timeout" : "reject";
|
|
3566
|
-
}
|
|
3567
3618
|
#groupAction(action) {
|
|
3568
3619
|
const value = action?.toLowerCase() ?? "";
|
|
3569
3620
|
if (value.includes("promote")) return "promote";
|
|
@@ -3607,9 +3658,33 @@ var ZapoProvider = class {
|
|
|
3607
3658
|
#messageStoreKey(key) {
|
|
3608
3659
|
return `${key.remoteJid ?? ""}:${key.id ?? ""}:${key.participant ?? key.participantAlt ?? ""}`;
|
|
3609
3660
|
}
|
|
3661
|
+
#messageDeliveryKey(key) {
|
|
3662
|
+
return `${key.remoteJid ?? ""}:${key.id ?? ""}`;
|
|
3663
|
+
}
|
|
3664
|
+
#protocolDeliveryKey(event, target, type) {
|
|
3665
|
+
if (type == null || !event.key.id || !target.id) return void 0;
|
|
3666
|
+
return `${type}:${event.key.remoteJid ?? target.remoteJid ?? ""}:${event.key.id}:${target.id}`;
|
|
3667
|
+
}
|
|
3668
|
+
#rememberHandledProtocol(key) {
|
|
3669
|
+
this.#handledProtocolStore.delete(key);
|
|
3670
|
+
this.#handledProtocolStore.add(key);
|
|
3671
|
+
while (this.#handledProtocolStore.size > this.#messageCacheSize) {
|
|
3672
|
+
const oldest = this.#handledProtocolStore.values().next().value;
|
|
3673
|
+
if (oldest) this.#handledProtocolStore.delete(oldest);
|
|
3674
|
+
}
|
|
3675
|
+
}
|
|
3676
|
+
#rememberDeliveredMessage(key) {
|
|
3677
|
+
this.#deliveredMessageStore.delete(key);
|
|
3678
|
+
this.#deliveredMessageStore.add(key);
|
|
3679
|
+
while (this.#deliveredMessageStore.size > this.#messageCacheSize) {
|
|
3680
|
+
const oldest = this.#deliveredMessageStore.values().next().value;
|
|
3681
|
+
if (oldest) this.#deliveredMessageStore.delete(oldest);
|
|
3682
|
+
}
|
|
3683
|
+
}
|
|
3610
3684
|
#isOfflineMessage(message) {
|
|
3611
3685
|
if (this.#options.processOfflineMessages === true) return false;
|
|
3612
3686
|
if (message.offline === true) return true;
|
|
3687
|
+
if (!this.#connected) return true;
|
|
3613
3688
|
if (!this.#connectedAtSeconds || message.timestampSeconds == null) return false;
|
|
3614
3689
|
const timestamp = toSeconds(message.timestampSeconds);
|
|
3615
3690
|
if (timestamp === void 0) return false;
|
|
@@ -3699,6 +3774,12 @@ var WhaNextZapoLogger = class _WhaNextZapoLogger {
|
|
|
3699
3774
|
return context ? { ...this.#context, ...context } : this.#context;
|
|
3700
3775
|
}
|
|
3701
3776
|
};
|
|
3777
|
+
function toNumber2(value) {
|
|
3778
|
+
if (typeof value === "number") return value;
|
|
3779
|
+
if (value?.toNumber) return value.toNumber();
|
|
3780
|
+
if (typeof value?.low === "number") return value.low;
|
|
3781
|
+
return void 0;
|
|
3782
|
+
}
|
|
3702
3783
|
function toSeconds(value) {
|
|
3703
3784
|
const raw = typeof value === "number" ? value : value?.toNumber ? value.toNumber() : value?.low;
|
|
3704
3785
|
if (raw === void 0) return void 0;
|