@escro/sdk 0.4.1 → 0.5.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/README.md +69 -4
- package/dist/index.cjs +5754 -461
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1455 -184
- package/dist/index.d.ts +1455 -184
- package/dist/index.js +5680 -462
- package/dist/index.js.map +1 -1
- package/package.json +13 -6
package/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# @escro/sdk
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for the [escro.ai](https://escro.ai) on-chain escrow protocol on Solana
|
|
3
|
+
TypeScript SDK for the [escro.ai](https://escro.ai) on-chain escrow protocol on Solana: escrow for
|
|
4
|
+
bots. A Buyer Bot locks USDC, a Worker Bot delivers, and the contract enforces the state machine
|
|
5
|
+
and defaults to refund. The SDK builds and signs the transactions and talks to the API; Escro never
|
|
6
|
+
judges quality, the Buyer releases or disputes.
|
|
7
|
+
|
|
8
|
+
Source: [github.com/escro-ai/escro.ai](https://github.com/escro-ai/escro.ai/tree/main/packages/sdk).
|
|
4
9
|
|
|
5
10
|
## Install
|
|
6
11
|
|
|
@@ -23,8 +28,10 @@ const client = new Escro({
|
|
|
23
28
|
|
|
24
29
|
// Buyer: create and fund an escrow
|
|
25
30
|
const { escrowPda, signature } = await client.createEscrow({
|
|
26
|
-
taskSpec: {
|
|
27
|
-
|
|
31
|
+
taskSpec: {
|
|
32
|
+
/* ... */
|
|
33
|
+
},
|
|
34
|
+
amountUsdc: 10_000_000, // 10 USDC
|
|
28
35
|
deadlineUnix: Math.floor(Date.now() / 1000) + 3600,
|
|
29
36
|
assignedWorker: "WorkerPubkeyBase58...",
|
|
30
37
|
});
|
|
@@ -39,9 +46,67 @@ await client.submitDeliverable(items[0].address, {
|
|
|
39
46
|
|
|
40
47
|
// Buyer: release payment or cancel
|
|
41
48
|
await client.releasePayment(escrowPda);
|
|
42
|
-
await client.cancelEscrow(escrowPda);
|
|
49
|
+
await client.cancelEscrow(escrowPda); // only if FUNDED, before worker claims
|
|
43
50
|
```
|
|
44
51
|
|
|
52
|
+
## Spend cap
|
|
53
|
+
|
|
54
|
+
A buyer sets `spendCap` when it constructs the client: the most micro-USDC its wallet may hold
|
|
55
|
+
in open escrows, each counted as its deposit (amount plus fee).
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { Escro, parseUsdc } from "@escro/sdk";
|
|
59
|
+
|
|
60
|
+
const buyer = new Escro({
|
|
61
|
+
cluster: "mainnet",
|
|
62
|
+
rpcUrl: "https://api.mainnet-beta.solana.com",
|
|
63
|
+
apiUrl: "https://api.escro.ai",
|
|
64
|
+
wallet,
|
|
65
|
+
spendCap: { maxOutstandingMicroUsdc: parseUsdc("50") }, // 50 USDC
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Before the create is sent, `createEscrow` reads the on-chain fee rate and the wallet's open
|
|
70
|
+
deposits (one `GET /v1/escrows/outstanding`: FUNDED, IN_PROGRESS, SUBMITTED and DISPUTED escrows),
|
|
71
|
+
adds this process's creates still in flight, and throws `SPEND_CAP_EXCEEDED` for a create that
|
|
72
|
+
would pass the cap. An outstanding read that fails, answers something malformed or takes longer
|
|
73
|
+
than 15 s refuses the create with `SPEND_CAP_UNREADABLE` (a failed or timed-out read as its
|
|
74
|
+
`cause`); a PlatformConfig read that fails or takes longer than 15 s throws its own error, with no
|
|
75
|
+
code. On `"mainnet"` a client without `spendCap` cannot create (`SPEND_CAP_REQUIRED`); a
|
|
76
|
+
worker-only client needs none. `spendCap.outstanding` replaces the API read under the same 15 s
|
|
77
|
+
bound (one that has not answered is abandoned, not cancelled), and the in-flight creates are
|
|
78
|
+
added to its answer. The error codes are exported as `SPEND_CAP_ERROR_CODES`. `createEscrow`
|
|
79
|
+
also refuses an `assignedWorker` that is not a base-58 public key, or an
|
|
80
|
+
`amountUsdc` that is not a positive whole number (`VALIDATION_ERROR`). The create request
|
|
81
|
+
(`POST /v1/escrows`) is abandoned after 15 s with `API_TIMEOUT`.
|
|
82
|
+
|
|
83
|
+
The cap holds per process. Every capped client for one wallet and cluster in the process shares one
|
|
84
|
+
queue: creates are checked one at a time, and each holds its deposit as in flight from the API's
|
|
85
|
+
answer to its POST. A create that throws before its transaction is sent (the SDK's refusal of the
|
|
86
|
+
server's transaction as not the create it asked for, `UNEXPECTED_TRANSACTION`; an undecodable server
|
|
87
|
+
transaction; a failed blockhash read) holds nothing. Once sent, the hold lasts until a successful
|
|
88
|
+
`confirm(address, signature)`, or until evidence shows the transaction never took effect: the RPC
|
|
89
|
+
rejected it other than as already processed, or it failed at execution (`TX_FAILED`). A create that
|
|
90
|
+
throws after its transaction is sent for any other reason (a network error, a confirmation timeout,
|
|
91
|
+
an `EscroConfirmError`) keeps counting, and shrinks the cap's room, until `confirm(address,
|
|
92
|
+
signature)` succeeds or the process exits. An "already processed" rejection carries no signature to
|
|
93
|
+
confirm with, so its hold lasts until the process exits. Two processes or hosts on one wallet each
|
|
94
|
+
enforce the cap and together can pass it by the other's in-flight deposits: run one buyer process
|
|
95
|
+
per wallet, or give each its share.
|
|
96
|
+
|
|
97
|
+
## Paying a 402
|
|
98
|
+
|
|
99
|
+
A `pay()` given an address rule (`admitAddress`) needs direct egress and local DNS: it resolves each
|
|
100
|
+
host with this machine's resolver and connects directly to the addresses the rule admitted, ignoring
|
|
101
|
+
any HTTP or HTTPS proxy set in the environment. With `url`, on a network reachable only through a
|
|
102
|
+
proxy the pay fails at its first request, before anything is funded or signed. With
|
|
103
|
+
`paymentRequired`, a `resource.url` whose host resolves here but cannot be reached directly fails at
|
|
104
|
+
the paid request, after the escrow is funded or the `exact` payment signed.
|
|
105
|
+
|
|
106
|
+
`pay()` refuses a `url`, or with `paymentRequired` the 402's `resource.url`, on a port `fetch` blocks
|
|
107
|
+
(25, 6667 and the rest of the Fetch standard's bad-port list) before any lookup or request, and the default job-specification read refuses a
|
|
108
|
+
`specUri` that carries a username or password or names such a port.
|
|
109
|
+
|
|
45
110
|
## API
|
|
46
111
|
|
|
47
112
|
Every method, its parameters and its errors are in the generated
|