@panal/sdk 0.18.0 → 0.18.1

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/dist/client.d.ts CHANGED
@@ -129,6 +129,30 @@ export declare class PanalClient {
129
129
  constructor(options?: PanalClientOptions);
130
130
  /** El wallet client, o un error que dice exactamente qué falta. */
131
131
  private wallet;
132
+ /**
133
+ * Comprueba ANTES de firmar que la wallet cubre lo que Monad va a reservar.
134
+ *
135
+ * Monad bloquea `gas_limit × maxFeePerGas` antes de ejecutar, aunque luego
136
+ * cobre bastante menos: darse de alta estima ~264.000 de gas, que a 122 gwei
137
+ * son 0,032 MON de reserva (medido el 2026-09-14). Con menos, el nodo
138
+ * rechaza la transacción con «Signer had insufficient balance» y viem lo
139
+ * presenta como un revert del contrato, que no llegó a ejecutarse. Y hay una
140
+ * segunda trampa: reintentar tras recargar con el mismo nonce y las mismas
141
+ * comisiones firma una transacción idéntica, y el nodo repite el rechazo sin
142
+ * volver a mirar el saldo.
143
+ *
144
+ * Si no se puede estimar —RPC caído, o una llamada que el contrato rechazaría
145
+ * por otro motivo— no se bloquea nada: que hable el error de verdad.
146
+ */
147
+ private comprobarReserva;
148
+ /**
149
+ * Espera el recibo y comprueba que la transacción SALIÓ BIEN.
150
+ *
151
+ * Esperar el recibo no basta: un revert también llega con recibo. Sin mirar
152
+ * `status`, una transacción que gastó gas y no cambió nada volvía como si
153
+ * todo hubiera ido bien.
154
+ */
155
+ private esperarExito;
132
156
  /** Todos los agentes del registry, activos e inactivos. */
133
157
  listAgents(): Promise<Agent[]>;
134
158
  /**
package/dist/client.js CHANGED
@@ -126,6 +126,55 @@ export class PanalClient {
126
126
  }
127
127
  return this.walletClient;
128
128
  }
129
+ /**
130
+ * Comprueba ANTES de firmar que la wallet cubre lo que Monad va a reservar.
131
+ *
132
+ * Monad bloquea `gas_limit × maxFeePerGas` antes de ejecutar, aunque luego
133
+ * cobre bastante menos: darse de alta estima ~264.000 de gas, que a 122 gwei
134
+ * son 0,032 MON de reserva (medido el 2026-09-14). Con menos, el nodo
135
+ * rechaza la transacción con «Signer had insufficient balance» y viem lo
136
+ * presenta como un revert del contrato, que no llegó a ejecutarse. Y hay una
137
+ * segunda trampa: reintentar tras recargar con el mismo nonce y las mismas
138
+ * comisiones firma una transacción idéntica, y el nodo repite el rechazo sin
139
+ * volver a mirar el saldo.
140
+ *
141
+ * Si no se puede estimar —RPC caído, o una llamada que el contrato rechazaría
142
+ * por otro motivo— no se bloquea nada: que hable el error de verdad.
143
+ */
144
+ async comprobarReserva(que, llamada) {
145
+ let gas;
146
+ let maxFeePerGas;
147
+ let saldo;
148
+ try {
149
+ [gas, { maxFeePerGas }, saldo] = await Promise.all([
150
+ this.publicClient.estimateContractGas({ ...llamada, account: this.account }),
151
+ this.publicClient.estimateFeesPerGas(),
152
+ this.publicClient.getBalance({ address: this.account.address }),
153
+ ]);
154
+ }
155
+ catch {
156
+ return;
157
+ }
158
+ const reserva = gas * maxFeePerGas + (llamada.value ?? 0n);
159
+ if (saldo < reserva) {
160
+ throw new Error(`${que}: Monad reserva ${formatEther(reserva)} MON por adelantado (límite de gas × precio máximo), ` +
161
+ `aunque luego cobre menos. ${this.account.address} tiene ${formatEther(saldo)} MON: ` +
162
+ `faltan ${formatEther(reserva - saldo)} MON. No se ha enviado nada.`);
163
+ }
164
+ }
165
+ /**
166
+ * Espera el recibo y comprueba que la transacción SALIÓ BIEN.
167
+ *
168
+ * Esperar el recibo no basta: un revert también llega con recibo. Sin mirar
169
+ * `status`, una transacción que gastó gas y no cambió nada volvía como si
170
+ * todo hubiera ido bien.
171
+ */
172
+ async esperarExito(hash, que) {
173
+ const recibo = await this.publicClient.waitForTransactionReceipt({ hash });
174
+ if (recibo.status !== 'success') {
175
+ throw new Error(`${que} revirtió (tx ${hash}): se cobró el gas y no cambió nada.`);
176
+ }
177
+ }
129
178
  // -------------------------------------------------------------------------
130
179
  // Lectura
131
180
  // -------------------------------------------------------------------------
@@ -526,15 +575,21 @@ export class PanalClient {
526
575
  */
527
576
  async registerAgent(params) {
528
577
  const wallet = this.wallet();
529
- const hash = await wallet.writeContract({
578
+ const llamada = {
530
579
  address: this.addresses.registry,
531
580
  abi: registryAbi,
532
581
  functionName: 'registerAgent',
533
582
  args: [formatAgentMetadata(params.metadata), params.pricePerTask, params.currency ?? NATIVE_CURRENCY],
583
+ };
584
+ await this.comprobarReserva('No se puede dar de alta', llamada);
585
+ const hash = await wallet.writeContract({
586
+ ...llamada,
587
+ abi: registryAbi,
588
+ functionName: 'registerAgent',
534
589
  chain: chainFor(this.network),
535
590
  account: this.account,
536
591
  });
537
- await this.publicClient.waitForTransactionReceipt({ hash });
592
+ await this.esperarExito(hash, 'El alta');
538
593
  return hash;
539
594
  }
540
595
  /** Cambia el nombre, la descripción, las skills o el endpoint publicados. */
@@ -608,7 +663,7 @@ export class PanalClient {
608
663
  chain: chainFor(this.network),
609
664
  account: this.account,
610
665
  });
611
- await this.publicClient.waitForTransactionReceipt({ hash: txHash });
666
+ await this.esperarExito(txHash, `La entrega de #${taskId}`);
612
667
  return { txHash, resultHash };
613
668
  }
614
669
  /**
@@ -747,7 +802,7 @@ export class PanalClient {
747
802
  chain: chainFor(this.network),
748
803
  account: this.account,
749
804
  });
750
- await this.publicClient.waitForTransactionReceipt({ hash: txHash });
805
+ await this.esperarExito(txHash, `Coger la tarea #${taskId}`);
751
806
  return { txHash };
752
807
  }
753
808
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@panal/sdk",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "SDK de Panal: contrata agentes de IA autonomos on-chain en Monad",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -45,7 +45,7 @@
45
45
  "scripts": {
46
46
  "build": "tsc -p tsconfig.json",
47
47
  "typecheck": "tsc -p tsconfig.json --noEmit",
48
- "test": "tsx test/sdk.test.ts && tsx test/x402.test.ts && tsx test/x402-server.test.ts && tsx test/envelope.test.ts && tsx test/files.test.ts && tsx test/attachments.test.ts && tsx test/llm.test.ts && tsx test/skill.test.ts && tsx test/agent-card.test.ts && tsx test/niveles.test.ts && tsx test/tablon.test.ts",
48
+ "test": "tsx test/sdk.test.ts && tsx test/x402.test.ts && tsx test/x402-server.test.ts && tsx test/envelope.test.ts && tsx test/files.test.ts && tsx test/attachments.test.ts && tsx test/llm.test.ts && tsx test/skill.test.ts && tsx test/agent-card.test.ts && tsx test/niveles.test.ts && tsx test/tablon.test.ts && tsx test/reserva.test.ts",
49
49
  "test:nombres": "tsx test/nombres.test.ts"
50
50
  }
51
51
  }