@panal/sdk 0.7.0 → 0.9.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/dist/abis.d.ts +9 -0
- package/dist/abis.js +10 -0
- package/dist/client.d.ts +29 -0
- package/dist/client.js +82 -0
- package/dist/types.d.ts +30 -0
- package/package.json +1 -1
package/dist/abis.d.ts
CHANGED
|
@@ -240,6 +240,15 @@ export declare const escrowAbi: readonly [{
|
|
|
240
240
|
readonly type: "uint256";
|
|
241
241
|
}];
|
|
242
242
|
readonly outputs: readonly [];
|
|
243
|
+
}, {
|
|
244
|
+
readonly type: "function";
|
|
245
|
+
readonly name: "openDispute";
|
|
246
|
+
readonly stateMutability: "nonpayable";
|
|
247
|
+
readonly inputs: readonly [{
|
|
248
|
+
readonly name: "taskId";
|
|
249
|
+
readonly type: "uint256";
|
|
250
|
+
}];
|
|
251
|
+
readonly outputs: readonly [];
|
|
243
252
|
}];
|
|
244
253
|
export declare const erc20Abi: readonly [{
|
|
245
254
|
readonly type: "function";
|
package/dist/abis.js
CHANGED
|
@@ -172,6 +172,16 @@ export const escrowAbi = [
|
|
|
172
172
|
inputs: [{ name: 'taskId', type: 'uint256' }],
|
|
173
173
|
outputs: [],
|
|
174
174
|
},
|
|
175
|
+
// Lo unico que detiene el autoRelease de 3 dias. Faltaba en este ABI, asi
|
|
176
|
+
// que desde el SDK no habia forma de disputar una entrega: tocaba ir al
|
|
177
|
+
// contrato a mano justo cuando corre el reloj.
|
|
178
|
+
{
|
|
179
|
+
type: 'function',
|
|
180
|
+
name: 'openDispute',
|
|
181
|
+
stateMutability: 'nonpayable',
|
|
182
|
+
inputs: [{ name: 'taskId', type: 'uint256' }],
|
|
183
|
+
outputs: [],
|
|
184
|
+
},
|
|
175
185
|
];
|
|
176
186
|
export const erc20Abi = [
|
|
177
187
|
{
|
package/dist/client.d.ts
CHANGED
|
@@ -130,6 +130,35 @@ export declare class PanalClient {
|
|
|
130
130
|
* registrada: sin ella el agente no construye reputación.
|
|
131
131
|
*/
|
|
132
132
|
approveTask(taskId: bigint, rating: number): Promise<Hex>;
|
|
133
|
+
/**
|
|
134
|
+
* Cancela una tarea que nunca arrancó y recupera lo bloqueado.
|
|
135
|
+
*
|
|
136
|
+
* El escrow solo lo permite al cliente, con la tarea todavía `Open` —o sea
|
|
137
|
+
* sin entrega— y además vencido el plazo o sin worker asignado. Con worker
|
|
138
|
+
* asignado hay que esperar al deadline: si no, el cliente podría retirarle
|
|
139
|
+
* el encargo a alguien que ya está trabajando.
|
|
140
|
+
*
|
|
141
|
+
* Hace falta cuando el encargo no llegó a su destino y el pago sí: el brief
|
|
142
|
+
* se entrega después de crear la tarea, así que un endpoint caído o un texto
|
|
143
|
+
* que el agente rechaza dejan dinero parado hasta el plazo. Sin esto, la
|
|
144
|
+
* única salida era llamar al contrato a mano.
|
|
145
|
+
*
|
|
146
|
+
* OJO: el escrow es pull payment. Esto ACREDITA el reembolso, no lo envía.
|
|
147
|
+
* Para tenerlo en la wallet hay que llamar después a `withdraw()`.
|
|
148
|
+
*/
|
|
149
|
+
cancelTask(taskId: bigint): Promise<Hex>;
|
|
150
|
+
/**
|
|
151
|
+
* Abre una disputa sobre una entrega, y con ello para el reloj.
|
|
152
|
+
*
|
|
153
|
+
* Urge más de lo que parece: si no apruebas ni disputas, el escrow libera el
|
|
154
|
+
* pago solo a los 3 días de la entrega, con un 5/5 implícito. O sea que ante
|
|
155
|
+
* una entrega mala, no hacer nada NO es neutral: es pagar y además regalar la
|
|
156
|
+
* mejor valoración. Disputar es lo único que detiene esa cuenta atrás.
|
|
157
|
+
*
|
|
158
|
+
* La resuelve el arbitrator repartiendo el importe. Si no lo hace en 14 días,
|
|
159
|
+
* cualquiera puede llamar a `resolveStuckDispute` y el cliente recupera todo.
|
|
160
|
+
*/
|
|
161
|
+
openDispute(taskId: bigint): Promise<Hex>;
|
|
133
162
|
/**
|
|
134
163
|
* Registra tu agente en el marketplace. Lo llama la wallet que trabajará y
|
|
135
164
|
* cobrará: en Panal el agente ES una dirección, no una fila en una base de
|
package/dist/client.js
CHANGED
|
@@ -26,6 +26,22 @@ import { TaskStatus, formatAgentMetadata, parseAgentMetadata, } from './types.js
|
|
|
26
26
|
const REGISTRY_PAGE = 50n;
|
|
27
27
|
/** Tope duro de agentes recorridos, por si el registro crece mucho. */
|
|
28
28
|
const REGISTRY_MAX = 500;
|
|
29
|
+
/**
|
|
30
|
+
* ¿Esto que manda el indexador es un nombre de PanalNames?
|
|
31
|
+
*
|
|
32
|
+
* Se valida como todo lo que llega de un servicio: si viene a medias se
|
|
33
|
+
* descarta, porque un `origen` inventado haria que la web avisara de una venta
|
|
34
|
+
* que no existio, o peor, que callara una que si.
|
|
35
|
+
*/
|
|
36
|
+
function esNombre(v) {
|
|
37
|
+
if (v === null || typeof v !== 'object')
|
|
38
|
+
return false;
|
|
39
|
+
const n = v;
|
|
40
|
+
return (typeof n.nombre === 'string' &&
|
|
41
|
+
n.nombre.length > 0 &&
|
|
42
|
+
typeof n.desdeTs === 'number' &&
|
|
43
|
+
(n.origen === 'reclamado' || n.origen === 'comprado' || n.origen === 'recibido'));
|
|
44
|
+
}
|
|
29
45
|
export class PanalClient {
|
|
30
46
|
network;
|
|
31
47
|
addresses;
|
|
@@ -153,6 +169,11 @@ export class PanalClient {
|
|
|
153
169
|
registeredAt,
|
|
154
170
|
metadataURI: formatAgentMetadata(metadata),
|
|
155
171
|
metadata,
|
|
172
|
+
// Solo `true` cuenta como verificado. Un indexador viejo no manda el
|
|
173
|
+
// campo, y tratar «no lo sé» como «sí» es justo al revés de lo que
|
|
174
|
+
// hay que hacer con una insignia de confianza.
|
|
175
|
+
verificado: raw.verificado === true,
|
|
176
|
+
...(esNombre(raw.nombre) ? { nombre: raw.nombre } : {}),
|
|
156
177
|
});
|
|
157
178
|
}
|
|
158
179
|
return out;
|
|
@@ -320,6 +341,67 @@ export class PanalClient {
|
|
|
320
341
|
await this.publicClient.waitForTransactionReceipt({ hash });
|
|
321
342
|
return hash;
|
|
322
343
|
}
|
|
344
|
+
/**
|
|
345
|
+
* Cancela una tarea que nunca arrancó y recupera lo bloqueado.
|
|
346
|
+
*
|
|
347
|
+
* El escrow solo lo permite al cliente, con la tarea todavía `Open` —o sea
|
|
348
|
+
* sin entrega— y además vencido el plazo o sin worker asignado. Con worker
|
|
349
|
+
* asignado hay que esperar al deadline: si no, el cliente podría retirarle
|
|
350
|
+
* el encargo a alguien que ya está trabajando.
|
|
351
|
+
*
|
|
352
|
+
* Hace falta cuando el encargo no llegó a su destino y el pago sí: el brief
|
|
353
|
+
* se entrega después de crear la tarea, así que un endpoint caído o un texto
|
|
354
|
+
* que el agente rechaza dejan dinero parado hasta el plazo. Sin esto, la
|
|
355
|
+
* única salida era llamar al contrato a mano.
|
|
356
|
+
*
|
|
357
|
+
* OJO: el escrow es pull payment. Esto ACREDITA el reembolso, no lo envía.
|
|
358
|
+
* Para tenerlo en la wallet hay que llamar después a `withdraw()`.
|
|
359
|
+
*/
|
|
360
|
+
async cancelTask(taskId) {
|
|
361
|
+
const wallet = this.wallet();
|
|
362
|
+
const task = await this.getTask(taskId);
|
|
363
|
+
if (task.status !== TaskStatus.Open) {
|
|
364
|
+
throw new Error(`La tarea #${taskId} está "${TaskStatus[task.status]}": solo se cancela lo que sigue abierto.`);
|
|
365
|
+
}
|
|
366
|
+
const hash = await wallet.writeContract({
|
|
367
|
+
address: this.addresses.escrow,
|
|
368
|
+
abi: escrowAbi,
|
|
369
|
+
functionName: 'cancelTask',
|
|
370
|
+
args: [taskId],
|
|
371
|
+
chain: chainFor(this.network),
|
|
372
|
+
account: this.account,
|
|
373
|
+
});
|
|
374
|
+
await this.publicClient.waitForTransactionReceipt({ hash });
|
|
375
|
+
return hash;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Abre una disputa sobre una entrega, y con ello para el reloj.
|
|
379
|
+
*
|
|
380
|
+
* Urge más de lo que parece: si no apruebas ni disputas, el escrow libera el
|
|
381
|
+
* pago solo a los 3 días de la entrega, con un 5/5 implícito. O sea que ante
|
|
382
|
+
* una entrega mala, no hacer nada NO es neutral: es pagar y además regalar la
|
|
383
|
+
* mejor valoración. Disputar es lo único que detiene esa cuenta atrás.
|
|
384
|
+
*
|
|
385
|
+
* La resuelve el arbitrator repartiendo el importe. Si no lo hace en 14 días,
|
|
386
|
+
* cualquiera puede llamar a `resolveStuckDispute` y el cliente recupera todo.
|
|
387
|
+
*/
|
|
388
|
+
async openDispute(taskId) {
|
|
389
|
+
const wallet = this.wallet();
|
|
390
|
+
const task = await this.getTask(taskId);
|
|
391
|
+
if (task.status !== TaskStatus.Delivered) {
|
|
392
|
+
throw new Error(`La tarea #${taskId} está "${TaskStatus[task.status]}": solo se disputa lo entregado.`);
|
|
393
|
+
}
|
|
394
|
+
const hash = await wallet.writeContract({
|
|
395
|
+
address: this.addresses.escrow,
|
|
396
|
+
abi: escrowAbi,
|
|
397
|
+
functionName: 'openDispute',
|
|
398
|
+
args: [taskId],
|
|
399
|
+
chain: chainFor(this.network),
|
|
400
|
+
account: this.account,
|
|
401
|
+
});
|
|
402
|
+
await this.publicClient.waitForTransactionReceipt({ hash });
|
|
403
|
+
return hash;
|
|
404
|
+
}
|
|
323
405
|
// -------------------------------------------------------------------------
|
|
324
406
|
// Lado del AGENTE — darse de alta, trabajar y entregar.
|
|
325
407
|
// -------------------------------------------------------------------------
|
package/dist/types.d.ts
CHANGED
|
@@ -56,6 +56,36 @@ export interface Agent {
|
|
|
56
56
|
metadata: AgentMetadata;
|
|
57
57
|
/** La cadena cruda, por si quieres interpretarla tú. */
|
|
58
58
|
metadataURI: string;
|
|
59
|
+
/**
|
|
60
|
+
* Si su dominio confirma que esta dirección es suya.
|
|
61
|
+
*
|
|
62
|
+
* El nombre lo escribe el propio agente y no es único: cualquiera puede
|
|
63
|
+
* registrarse como "Lint". Lo que sí es de alguien es su dominio, y el
|
|
64
|
+
* `agent.json` que sirve declara su dirección, así que el indexador va a
|
|
65
|
+
* buscarla y la compara.
|
|
66
|
+
*
|
|
67
|
+
* **Elegir un agente sin mirar esto es el fallo que más caro sale**: un
|
|
68
|
+
* suplantador con el nombre y la descripción del original cuesta una
|
|
69
|
+
* transacción. `undefined` = no se sabe (sin indexador, o aún sin mirar);
|
|
70
|
+
* trátalo como «no verificado», nunca como «verificado».
|
|
71
|
+
*/
|
|
72
|
+
verificado?: boolean;
|
|
73
|
+
/** Su nombre único en PanalNames, si lo tiene. */
|
|
74
|
+
nombre?: NombreDeAgente;
|
|
75
|
+
}
|
|
76
|
+
/** El nombre de un agente en PanalNames, y cómo llegó a tenerlo. */
|
|
77
|
+
export interface NombreDeAgente {
|
|
78
|
+
nombre: string;
|
|
79
|
+
/** Cuándo pasó a ser de esta dirección (segundos epoch). */
|
|
80
|
+
desdeTs: number;
|
|
81
|
+
/**
|
|
82
|
+
* Reclamado de cero, comprado a otro, o recibido.
|
|
83
|
+
*
|
|
84
|
+
* Importa tanto como el nombre: en una venta lo único que viaja es el
|
|
85
|
+
* nombre, y la reputación se queda con el vendedor. Un `lint` comprado la
|
|
86
|
+
* semana pasada no hizo las tareas que hicieron valer ese nombre.
|
|
87
|
+
*/
|
|
88
|
+
origen: 'reclamado' | 'comprado' | 'recibido';
|
|
59
89
|
}
|
|
60
90
|
/** Una tarea del escrow. */
|
|
61
91
|
export interface Task {
|