@pincerpay/agent 0.1.1 → 0.2.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 +96 -26
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/ds1/pincerpay/blob/master/LICENSE)
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
7
7
|
|
|
8
|
-
Agent SDK for AI agents to pay for APIs using on-chain USDC via the x402 protocol.
|
|
8
|
+
Agent SDK for AI agents to pay for APIs using on-chain USDC via the [x402 protocol](https://x402.org).
|
|
9
9
|
|
|
10
10
|
> **ESM Required:** Your project must have `"type": "module"` in package.json. This package is ESM-only.
|
|
11
11
|
|
|
@@ -25,7 +25,7 @@ const agent = await PincerPayAgent.create({
|
|
|
25
25
|
solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
// Automatic 402 handling
|
|
28
|
+
// Automatic 402 handling -- pays and retries transparently
|
|
29
29
|
const response = await agent.fetch("https://api.example.com/weather");
|
|
30
30
|
const data = await response.json();
|
|
31
31
|
```
|
|
@@ -34,7 +34,7 @@ const data = await response.json();
|
|
|
34
34
|
|
|
35
35
|
### `PincerPayAgent`
|
|
36
36
|
|
|
37
|
-
Wraps `fetch` with automatic x402 payment handling. When a request returns HTTP 402, the agent signs a USDC transfer and retries.
|
|
37
|
+
Wraps `fetch` with automatic x402 payment handling. When a request returns HTTP 402, the agent signs a USDC transfer and retries. Spending policies are enforced at the x402 protocol layer via `onBeforePaymentCreation` and `onAfterPaymentCreation` hooks.
|
|
38
38
|
|
|
39
39
|
```typescript
|
|
40
40
|
class PincerPayAgent {
|
|
@@ -42,11 +42,14 @@ class PincerPayAgent {
|
|
|
42
42
|
|
|
43
43
|
fetch(url: string | URL, init?: RequestInit): Promise<Response>;
|
|
44
44
|
|
|
45
|
+
// Policy enforcement
|
|
45
46
|
checkPolicy(amountBaseUnits: string): { allowed: boolean; reason?: string };
|
|
46
|
-
setPolicy(policy:
|
|
47
|
-
|
|
47
|
+
setPolicy(policy: SpendingPolicy): void;
|
|
48
|
+
getPolicy(): SpendingPolicy | undefined;
|
|
48
49
|
recordSpend(amountBaseUnits: string): void;
|
|
50
|
+
getDailySpend(): { date: string; amount: bigint };
|
|
49
51
|
|
|
52
|
+
// Wallet info
|
|
50
53
|
get evmAddress(): string | undefined;
|
|
51
54
|
get solanaAddress(): string | undefined;
|
|
52
55
|
get chains(): string[];
|
|
@@ -55,28 +58,49 @@ class PincerPayAgent {
|
|
|
55
58
|
|
|
56
59
|
### `SolanaSmartAgent`
|
|
57
60
|
|
|
58
|
-
Extended agent with Squads SPN smart account support
|
|
61
|
+
Extended agent with Squads SPN smart account support, on-chain spending policies, and direct settlement via the Anchor program.
|
|
59
62
|
|
|
60
63
|
```typescript
|
|
61
64
|
class SolanaSmartAgent extends PincerPayAgent {
|
|
62
|
-
static override async create(
|
|
63
|
-
config: SolanaSmartAgentConfig
|
|
64
|
-
): Promise<SolanaSmartAgent>;
|
|
65
|
+
static override async create(config: SolanaSmartAgentConfig): Promise<SolanaSmartAgent>;
|
|
65
66
|
|
|
67
|
+
// Squads PDAs (derived automatically from config)
|
|
66
68
|
get smartAccountPda(): string | undefined;
|
|
67
69
|
get settingsPda(): string | undefined;
|
|
68
70
|
get spendingLimitPda(): string | undefined;
|
|
69
71
|
|
|
72
|
+
// Direct settlement (bypasses x402, settles via Anchor program)
|
|
70
73
|
async settleDirectly(
|
|
71
74
|
merchantId: string,
|
|
72
75
|
amountBaseUnits: string,
|
|
73
76
|
options?: { facilitatorUrl?: string; apiKey?: string; network?: string }
|
|
74
|
-
): Promise<{ success: boolean; transactionId?: string; error?: string }>;
|
|
77
|
+
): Promise<{ success: boolean; transactionId?: string; accounts?: Record<string, string>; error?: string }>;
|
|
75
78
|
|
|
79
|
+
// On-chain policy check (optimistic pre-check against Squads spending limit)
|
|
76
80
|
async checkOnChainPolicy(
|
|
77
81
|
amountBaseUnits: string,
|
|
78
82
|
rpcUrl?: string
|
|
79
83
|
): Promise<{ allowed: boolean; reason?: string; remainingAmount?: bigint }>;
|
|
84
|
+
|
|
85
|
+
// Instruction builders (returns Instruction, caller signs and sends)
|
|
86
|
+
async buildCreateSmartAccountInstruction(params?: {
|
|
87
|
+
members?: string[];
|
|
88
|
+
threshold?: number;
|
|
89
|
+
}): Promise<Instruction>;
|
|
90
|
+
|
|
91
|
+
async buildAddSpendingLimitInstruction(params: {
|
|
92
|
+
mint: string;
|
|
93
|
+
amount: bigint;
|
|
94
|
+
period: SpendingLimitPeriod;
|
|
95
|
+
members?: string[];
|
|
96
|
+
destinations?: string[];
|
|
97
|
+
authority: string;
|
|
98
|
+
}): Promise<Instruction>;
|
|
99
|
+
|
|
100
|
+
async buildRevokeSpendingLimitInstruction(params: {
|
|
101
|
+
authority: string;
|
|
102
|
+
rentCollector?: string;
|
|
103
|
+
}): Promise<Instruction>;
|
|
80
104
|
}
|
|
81
105
|
```
|
|
82
106
|
|
|
@@ -91,6 +115,12 @@ interface AgentConfig {
|
|
|
91
115
|
facilitatorUrl?: string; // Default: https://facilitator.pincerpay.com
|
|
92
116
|
}
|
|
93
117
|
|
|
118
|
+
interface SolanaSmartAgentConfig extends AgentConfig {
|
|
119
|
+
settingsPda?: string; // Override Squads Settings PDA
|
|
120
|
+
smartAccountIndex?: number; // For PDA derivation (default: 0)
|
|
121
|
+
spendingLimitIndex?: number; // For PDA derivation (default: 0)
|
|
122
|
+
}
|
|
123
|
+
|
|
94
124
|
interface SpendingPolicy {
|
|
95
125
|
maxPerTransaction?: string; // Max USDC per transaction (base units)
|
|
96
126
|
maxPerDay?: string; // Max USDC per day (base units)
|
|
@@ -99,7 +129,7 @@ interface SpendingPolicy {
|
|
|
99
129
|
}
|
|
100
130
|
|
|
101
131
|
// USDC base units (6 decimals): $0.01 = "10000", $0.10 = "100000", $1.00 = "1000000"
|
|
102
|
-
// WARNING: Do NOT use human-readable amounts like "0.10"
|
|
132
|
+
// WARNING: Do NOT use human-readable amounts like "0.10" -- BigInt("0.10") throws at runtime.
|
|
103
133
|
```
|
|
104
134
|
|
|
105
135
|
## Common Patterns
|
|
@@ -129,6 +159,25 @@ const agent = await PincerPayAgent.create({
|
|
|
129
159
|
});
|
|
130
160
|
```
|
|
131
161
|
|
|
162
|
+
### Runtime policy management
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// Pre-check if a payment would be allowed
|
|
166
|
+
const check = agent.checkPolicy("500000"); // 0.50 USDC
|
|
167
|
+
if (!check.allowed) console.log(check.reason);
|
|
168
|
+
|
|
169
|
+
// Get current policy
|
|
170
|
+
const policy = agent.getPolicy();
|
|
171
|
+
// { maxPerTransaction: "1000000", maxPerDay: "10000000" }
|
|
172
|
+
|
|
173
|
+
// Update spending limits dynamically (resets daily tracking)
|
|
174
|
+
agent.setPolicy({ maxPerTransaction: "5000000", maxPerDay: "50000000" });
|
|
175
|
+
|
|
176
|
+
// Monitor daily spending
|
|
177
|
+
const { date, amount } = agent.getDailySpend();
|
|
178
|
+
console.log(`Spent ${amount} base units on ${date}`); // amount is bigint
|
|
179
|
+
```
|
|
180
|
+
|
|
132
181
|
### Direct settlement via Anchor program
|
|
133
182
|
|
|
134
183
|
```typescript
|
|
@@ -141,24 +190,35 @@ const agent = await SolanaSmartAgent.create({
|
|
|
141
190
|
spendingLimitIndex: 0,
|
|
142
191
|
});
|
|
143
192
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
193
|
+
// Check on-chain spending limit before payment
|
|
194
|
+
const check = await agent.checkOnChainPolicy("500000");
|
|
195
|
+
if (check.allowed) {
|
|
196
|
+
const result = await agent.settleDirectly("merchant-uuid", "500000", {
|
|
197
|
+
apiKey: process.env.PINCERPAY_API_KEY!,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
147
200
|
```
|
|
148
201
|
|
|
149
|
-
###
|
|
202
|
+
### Build Squads instructions for wallet signing
|
|
150
203
|
|
|
151
204
|
```typescript
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
agent.setPolicy({ maxPerTransaction: "5000000", maxPerDay: "50000000" });
|
|
205
|
+
const agent = await SolanaSmartAgent.create({
|
|
206
|
+
chains: ["solana"],
|
|
207
|
+
solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
208
|
+
smartAccountIndex: 0,
|
|
209
|
+
});
|
|
158
210
|
|
|
159
|
-
//
|
|
160
|
-
const
|
|
161
|
-
|
|
211
|
+
// Build instructions -- sign and send with your wallet adapter
|
|
212
|
+
const createIx = await agent.buildCreateSmartAccountInstruction({ threshold: 1 });
|
|
213
|
+
const limitIx = await agent.buildAddSpendingLimitInstruction({
|
|
214
|
+
mint: usdcMintAddress,
|
|
215
|
+
amount: 10_000_000n, // 10 USDC
|
|
216
|
+
period: SpendingLimitPeriod.Day,
|
|
217
|
+
authority: walletAddress,
|
|
218
|
+
});
|
|
219
|
+
const revokeIx = await agent.buildRevokeSpendingLimitInstruction({
|
|
220
|
+
authority: walletAddress,
|
|
221
|
+
});
|
|
162
222
|
```
|
|
163
223
|
|
|
164
224
|
## Anti-Patterns
|
|
@@ -172,13 +232,13 @@ Agent keys should only be used in server-side or backend agent processes, never
|
|
|
172
232
|
Without policies, an agent can spend unlimited USDC. Always set `maxPerDay` at minimum.
|
|
173
233
|
|
|
174
234
|
```typescript
|
|
175
|
-
// Bad
|
|
235
|
+
// Bad -- no limits
|
|
176
236
|
const agent = await PincerPayAgent.create({
|
|
177
237
|
chains: ["solana"],
|
|
178
238
|
solanaPrivateKey: key,
|
|
179
239
|
});
|
|
180
240
|
|
|
181
|
-
// Good
|
|
241
|
+
// Good -- bounded spending
|
|
182
242
|
const agent = await PincerPayAgent.create({
|
|
183
243
|
chains: ["solana"],
|
|
184
244
|
solanaPrivateKey: key,
|
|
@@ -189,3 +249,13 @@ const agent = await PincerPayAgent.create({
|
|
|
189
249
|
### Don't use `PincerPayAgent` for merchant-side logic
|
|
190
250
|
|
|
191
251
|
The agent SDK is for making payments. Use `@pincerpay/merchant` for accepting payments.
|
|
252
|
+
|
|
253
|
+
### Don't use human-readable amounts in policies
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
// Bad -- BigInt("0.10") throws SyntaxError at runtime
|
|
257
|
+
policies: [{ maxPerTransaction: "0.10" }]
|
|
258
|
+
|
|
259
|
+
// Good -- use base units (6 decimals)
|
|
260
|
+
policies: [{ maxPerTransaction: "100000" }] // 0.10 USDC
|
|
261
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pincerpay/agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent SDK for PincerPay. Drop-in fetch wrapper that handles x402 payment flows automatically.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"@x402/svm": "^2.3.0",
|
|
58
58
|
"viem": "^2",
|
|
59
59
|
"zod": "^3.24",
|
|
60
|
-
"@pincerpay/
|
|
61
|
-
"@pincerpay/
|
|
60
|
+
"@pincerpay/solana": "0.2.0",
|
|
61
|
+
"@pincerpay/core": "0.2.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@scure/base": "^1.2.6",
|