ITEN
Demo · Base Sepolia · soldi di prova

API degli scontratti

L'API è JSON su HTTP, su https://scontratto-api.scontratto.workers.dev. È la stessa API degli agenti: un solo Worker, un solo database, rotte diverse.

Gli importi viaggiano come stringhe decimali in unità minime di EURC, con 6 decimali. Le scadenze sono interi in secondi Unix.

Le letture sono aperte. Le scritture, nel pilota, vogliono il token del pilota:

Authorization: Bearer <token del pilota>

Lettura

GET /health

{ ok, chainId, escrow, attestor, acp, mandateHook }: la chain, l'indirizzo dell'escrow e del suo attestatore, e quelli dei contratti degli agenti.

GET /contratti

Gli ultimi 100 scontratti, dal più recente: { contratti: [{ id, stato, tracking, scadenza }] }.

GET /contratti/:id

Lo scontratto intero: termini, stato, hash della condizione, nonce, firma di chi riceve, attestazione con la prova dell'oracolo, riferimento della transazione di regolamento, e la storia degli eventi.

Scrittura

POST /contratti/prepara

Il mandato da far firmare a chi riceve.

{
  "terms": {
    "payer": { "id": "payer", "proof": "wallet", "address": "0x...", "display": "Chi compra" },
    "payee": { "id": "payee", "proof": "wallet", "address": "0x...", "display": "Chi spedisce" },
    "money": { "amount": "5000000", "token": "EURC", "address": "0x808456652fdb597867f38412077A9182bf77359F" },
    "condition": { "kind": "parcel-delivered", "carrier": "dhl", "trackingNumber": "1234567890" },
    "deadline": 1792000000,
    "onExpiry": "refund"
  }
}

Risponde { id, nonce, mandate, domain }. mandate è il documento EIP-712 da firmare, nonce va conservato per il passo dopo, domain è l'indirizzo dell'escrow.

Chi riceve lo firma con eth_signTypedData_v4, nel dominio { name: "Scontratto", version: "1", chainId: 84532, verifyingContract: <escrow> }, con il tipo:

Mandate(address payer, address payee, address token, uint256 amount,
        bytes32 conditionHash, uint64 deadline, bool executeOnExpiry, bytes32 nonce)

POST /contratti

Crea lo scontratto con la firma di chi riceve: { terms, nonce, payeeSignature }. Risponde 201 con lo stato draft. Rifiuta con 400 se la firma non è di chi riceve, o non è su questi termini.

Poi chi versa agisce sulla chain, dal suo wallet:

  1. approve(escrow, amount) sul token EURC;
  2. Escrow.open(mandate, payeeSignature, attestor), dove attestor è l'indirizzo restituito da /health;
  3. Escrow.fund(id).

POST /contratti/:id/finanziato

Dopo il versamento: l'API controlla sulla chain che lo scontratto sia davvero finanziato e lo registra. Rifiuta con 409 se non lo è.

POST /contratti/:id/osserva

Osserva la condizione adesso, senza aspettare il cron. Se è verificata, l'attestatore firma e lo scontratto si esegue. Se è scaduto, si chiude. Si può chiamare quante volte si vuole.

POST /webhooks/aftership

Il webhook di AfterShip. Vale solo con la firma HMAC del corpo, nell'header aftership-hmac-sha256, e il token del webhook in x-scontratto-token. Osserva subito gli scontratti finanziati con quel numero di tracking.

Errori

Ogni errore è { "errore": "..." }.

Gli errori sono in italiano per default. Con Accept-Language: en, o con ?lang=en, arrivano in inglese. Gli stati HTTP e i codici non cambiano.

Stato Quando
400 Termini malformati, per esempio un indirizzo non valido o un importo non intero, o una firma che non è di chi riceve.
401 Manca il token del pilota, o non è quello giusto.
404 Lo scontratto non esiste.
409 Lo scontratto non è finanziato sulla chain.

Il cron

Ogni cinque minuti il Worker osserva tutti gli scontratti finanziati e chiude quelli scaduti. Uno scontratto che fallisce, per esempio perché il corriere non risponde, non ferma gli altri: si riprova al giro dopo.