@pincerpay/agent 0.1.0 → 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 +101 -26
- package/package.json +13 -4
package/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# @pincerpay/agent
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@pincerpay/agent)
|
|
4
|
+
[](https://www.npmjs.com/package/@pincerpay/agent)
|
|
5
|
+
[](https://github.com/ds1/pincerpay/blob/master/LICENSE)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
|
|
8
|
+
Agent SDK for AI agents to pay for APIs using on-chain USDC via the [x402 protocol](https://x402.org).
|
|
4
9
|
|
|
5
10
|
> **ESM Required:** Your project must have `"type": "module"` in package.json. This package is ESM-only.
|
|
6
11
|
|
|
@@ -20,7 +25,7 @@ const agent = await PincerPayAgent.create({
|
|
|
20
25
|
solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
21
26
|
});
|
|
22
27
|
|
|
23
|
-
// Automatic 402 handling
|
|
28
|
+
// Automatic 402 handling -- pays and retries transparently
|
|
24
29
|
const response = await agent.fetch("https://api.example.com/weather");
|
|
25
30
|
const data = await response.json();
|
|
26
31
|
```
|
|
@@ -29,7 +34,7 @@ const data = await response.json();
|
|
|
29
34
|
|
|
30
35
|
### `PincerPayAgent`
|
|
31
36
|
|
|
32
|
-
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.
|
|
33
38
|
|
|
34
39
|
```typescript
|
|
35
40
|
class PincerPayAgent {
|
|
@@ -37,11 +42,14 @@ class PincerPayAgent {
|
|
|
37
42
|
|
|
38
43
|
fetch(url: string | URL, init?: RequestInit): Promise<Response>;
|
|
39
44
|
|
|
45
|
+
// Policy enforcement
|
|
40
46
|
checkPolicy(amountBaseUnits: string): { allowed: boolean; reason?: string };
|
|
41
|
-
setPolicy(policy:
|
|
42
|
-
|
|
47
|
+
setPolicy(policy: SpendingPolicy): void;
|
|
48
|
+
getPolicy(): SpendingPolicy | undefined;
|
|
43
49
|
recordSpend(amountBaseUnits: string): void;
|
|
50
|
+
getDailySpend(): { date: string; amount: bigint };
|
|
44
51
|
|
|
52
|
+
// Wallet info
|
|
45
53
|
get evmAddress(): string | undefined;
|
|
46
54
|
get solanaAddress(): string | undefined;
|
|
47
55
|
get chains(): string[];
|
|
@@ -50,28 +58,49 @@ class PincerPayAgent {
|
|
|
50
58
|
|
|
51
59
|
### `SolanaSmartAgent`
|
|
52
60
|
|
|
53
|
-
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.
|
|
54
62
|
|
|
55
63
|
```typescript
|
|
56
64
|
class SolanaSmartAgent extends PincerPayAgent {
|
|
57
|
-
static override async create(
|
|
58
|
-
config: SolanaSmartAgentConfig
|
|
59
|
-
): Promise<SolanaSmartAgent>;
|
|
65
|
+
static override async create(config: SolanaSmartAgentConfig): Promise<SolanaSmartAgent>;
|
|
60
66
|
|
|
67
|
+
// Squads PDAs (derived automatically from config)
|
|
61
68
|
get smartAccountPda(): string | undefined;
|
|
62
69
|
get settingsPda(): string | undefined;
|
|
63
70
|
get spendingLimitPda(): string | undefined;
|
|
64
71
|
|
|
72
|
+
// Direct settlement (bypasses x402, settles via Anchor program)
|
|
65
73
|
async settleDirectly(
|
|
66
74
|
merchantId: string,
|
|
67
75
|
amountBaseUnits: string,
|
|
68
76
|
options?: { facilitatorUrl?: string; apiKey?: string; network?: string }
|
|
69
|
-
): Promise<{ success: boolean; transactionId?: string; error?: string }>;
|
|
77
|
+
): Promise<{ success: boolean; transactionId?: string; accounts?: Record<string, string>; error?: string }>;
|
|
70
78
|
|
|
79
|
+
// On-chain policy check (optimistic pre-check against Squads spending limit)
|
|
71
80
|
async checkOnChainPolicy(
|
|
72
81
|
amountBaseUnits: string,
|
|
73
82
|
rpcUrl?: string
|
|
74
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>;
|
|
75
104
|
}
|
|
76
105
|
```
|
|
77
106
|
|
|
@@ -86,6 +115,12 @@ interface AgentConfig {
|
|
|
86
115
|
facilitatorUrl?: string; // Default: https://facilitator.pincerpay.com
|
|
87
116
|
}
|
|
88
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
|
+
|
|
89
124
|
interface SpendingPolicy {
|
|
90
125
|
maxPerTransaction?: string; // Max USDC per transaction (base units)
|
|
91
126
|
maxPerDay?: string; // Max USDC per day (base units)
|
|
@@ -94,7 +129,7 @@ interface SpendingPolicy {
|
|
|
94
129
|
}
|
|
95
130
|
|
|
96
131
|
// USDC base units (6 decimals): $0.01 = "10000", $0.10 = "100000", $1.00 = "1000000"
|
|
97
|
-
// 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.
|
|
98
133
|
```
|
|
99
134
|
|
|
100
135
|
## Common Patterns
|
|
@@ -124,6 +159,25 @@ const agent = await PincerPayAgent.create({
|
|
|
124
159
|
});
|
|
125
160
|
```
|
|
126
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
|
+
|
|
127
181
|
### Direct settlement via Anchor program
|
|
128
182
|
|
|
129
183
|
```typescript
|
|
@@ -136,24 +190,35 @@ const agent = await SolanaSmartAgent.create({
|
|
|
136
190
|
spendingLimitIndex: 0,
|
|
137
191
|
});
|
|
138
192
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
+
}
|
|
142
200
|
```
|
|
143
201
|
|
|
144
|
-
###
|
|
202
|
+
### Build Squads instructions for wallet signing
|
|
145
203
|
|
|
146
204
|
```typescript
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
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
|
+
});
|
|
153
210
|
|
|
154
|
-
//
|
|
155
|
-
const
|
|
156
|
-
|
|
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
|
+
});
|
|
157
222
|
```
|
|
158
223
|
|
|
159
224
|
## Anti-Patterns
|
|
@@ -167,13 +232,13 @@ Agent keys should only be used in server-side or backend agent processes, never
|
|
|
167
232
|
Without policies, an agent can spend unlimited USDC. Always set `maxPerDay` at minimum.
|
|
168
233
|
|
|
169
234
|
```typescript
|
|
170
|
-
// Bad
|
|
235
|
+
// Bad -- no limits
|
|
171
236
|
const agent = await PincerPayAgent.create({
|
|
172
237
|
chains: ["solana"],
|
|
173
238
|
solanaPrivateKey: key,
|
|
174
239
|
});
|
|
175
240
|
|
|
176
|
-
// Good
|
|
241
|
+
// Good -- bounded spending
|
|
177
242
|
const agent = await PincerPayAgent.create({
|
|
178
243
|
chains: ["solana"],
|
|
179
244
|
solanaPrivateKey: key,
|
|
@@ -184,3 +249,13 @@ const agent = await PincerPayAgent.create({
|
|
|
184
249
|
### Don't use `PincerPayAgent` for merchant-side logic
|
|
185
250
|
|
|
186
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",
|
|
@@ -25,7 +25,16 @@
|
|
|
25
25
|
"solana",
|
|
26
26
|
"agent-sdk",
|
|
27
27
|
"payment-gateway",
|
|
28
|
-
"stablecoin"
|
|
28
|
+
"stablecoin",
|
|
29
|
+
"typescript",
|
|
30
|
+
"web3",
|
|
31
|
+
"crypto",
|
|
32
|
+
"on-chain",
|
|
33
|
+
"http-402",
|
|
34
|
+
"fetch-wrapper",
|
|
35
|
+
"autonomous",
|
|
36
|
+
"spending-policy",
|
|
37
|
+
"agentic"
|
|
29
38
|
],
|
|
30
39
|
"files": [
|
|
31
40
|
"dist",
|
|
@@ -48,8 +57,8 @@
|
|
|
48
57
|
"@x402/svm": "^2.3.0",
|
|
49
58
|
"viem": "^2",
|
|
50
59
|
"zod": "^3.24",
|
|
51
|
-
"@pincerpay/
|
|
52
|
-
"@pincerpay/
|
|
60
|
+
"@pincerpay/solana": "0.2.0",
|
|
61
|
+
"@pincerpay/core": "0.2.0"
|
|
53
62
|
},
|
|
54
63
|
"devDependencies": {
|
|
55
64
|
"@scure/base": "^1.2.6",
|