@pincerpay/agent 0.1.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/LICENSE +21 -0
- package/README.md +186 -0
- package/dist/client.d.ts +74 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +217 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/solana-agent.d.ts +95 -0
- package/dist/solana-agent.d.ts.map +1 -0
- package/dist/solana-agent.js +190 -0
- package/dist/solana-agent.js.map +1 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PincerPay
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# @pincerpay/agent
|
|
2
|
+
|
|
3
|
+
Agent SDK for AI agents to pay for APIs using on-chain USDC via the x402 protocol.
|
|
4
|
+
|
|
5
|
+
> **ESM Required:** Your project must have `"type": "module"` in package.json. This package is ESM-only.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @pincerpay/agent
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { PincerPayAgent } from "@pincerpay/agent";
|
|
17
|
+
|
|
18
|
+
const agent = await PincerPayAgent.create({
|
|
19
|
+
chains: ["solana"],
|
|
20
|
+
solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Automatic 402 handling — pays and retries transparently
|
|
24
|
+
const response = await agent.fetch("https://api.example.com/weather");
|
|
25
|
+
const data = await response.json();
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## API Reference
|
|
29
|
+
|
|
30
|
+
### `PincerPayAgent`
|
|
31
|
+
|
|
32
|
+
Wraps `fetch` with automatic x402 payment handling. When a request returns HTTP 402, the agent signs a USDC transfer and retries.
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
class PincerPayAgent {
|
|
36
|
+
static async create(config: AgentConfig): Promise<PincerPayAgent>;
|
|
37
|
+
|
|
38
|
+
fetch(url: string | URL, init?: RequestInit): Promise<Response>;
|
|
39
|
+
|
|
40
|
+
checkPolicy(amountBaseUnits: string): { allowed: boolean; reason?: string };
|
|
41
|
+
setPolicy(policy: Partial<SpendingPolicy>): void;
|
|
42
|
+
getDailySpend(): { date: string; amount: string };
|
|
43
|
+
recordSpend(amountBaseUnits: string): void;
|
|
44
|
+
|
|
45
|
+
get evmAddress(): string | undefined;
|
|
46
|
+
get solanaAddress(): string | undefined;
|
|
47
|
+
get chains(): string[];
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### `SolanaSmartAgent`
|
|
52
|
+
|
|
53
|
+
Extended agent with Squads SPN smart account support and on-chain spending policies.
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
class SolanaSmartAgent extends PincerPayAgent {
|
|
57
|
+
static override async create(
|
|
58
|
+
config: SolanaSmartAgentConfig
|
|
59
|
+
): Promise<SolanaSmartAgent>;
|
|
60
|
+
|
|
61
|
+
get smartAccountPda(): string | undefined;
|
|
62
|
+
get settingsPda(): string | undefined;
|
|
63
|
+
get spendingLimitPda(): string | undefined;
|
|
64
|
+
|
|
65
|
+
async settleDirectly(
|
|
66
|
+
merchantId: string,
|
|
67
|
+
amountBaseUnits: string,
|
|
68
|
+
options?: { facilitatorUrl?: string; apiKey?: string; network?: string }
|
|
69
|
+
): Promise<{ success: boolean; transactionId?: string; error?: string }>;
|
|
70
|
+
|
|
71
|
+
async checkOnChainPolicy(
|
|
72
|
+
amountBaseUnits: string,
|
|
73
|
+
rpcUrl?: string
|
|
74
|
+
): Promise<{ allowed: boolean; reason?: string; remainingAmount?: bigint }>;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Config
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
interface AgentConfig {
|
|
82
|
+
chains: string[]; // ["solana", "base", "polygon"]
|
|
83
|
+
evmPrivateKey?: string; // Hex-encoded EVM key
|
|
84
|
+
solanaPrivateKey?: string; // Base58-encoded Solana keypair
|
|
85
|
+
policies?: SpendingPolicy[]; // Client-side spending limits
|
|
86
|
+
facilitatorUrl?: string; // Default: https://facilitator.pincerpay.com
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface SpendingPolicy {
|
|
90
|
+
maxPerTransaction?: string; // Max USDC per transaction (base units)
|
|
91
|
+
maxPerDay?: string; // Max USDC per day (base units)
|
|
92
|
+
allowedMerchants?: string[]; // Whitelist merchant addresses
|
|
93
|
+
allowedChains?: string[]; // Whitelist chain shorthands
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 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" — BigInt("0.10") throws at runtime.
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Common Patterns
|
|
101
|
+
|
|
102
|
+
### Solana agent with spending limits
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
const agent = await PincerPayAgent.create({
|
|
106
|
+
chains: ["solana"],
|
|
107
|
+
solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
108
|
+
policies: [
|
|
109
|
+
{
|
|
110
|
+
maxPerTransaction: "1000000", // 1 USDC max per tx
|
|
111
|
+
maxPerDay: "10000000", // 10 USDC max per day
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Multi-chain agent (Solana + EVM)
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
const agent = await PincerPayAgent.create({
|
|
121
|
+
chains: ["solana", "base"],
|
|
122
|
+
solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
123
|
+
evmPrivateKey: process.env.AGENT_EVM_KEY!,
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Direct settlement via Anchor program
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { SolanaSmartAgent } from "@pincerpay/agent";
|
|
131
|
+
|
|
132
|
+
const agent = await SolanaSmartAgent.create({
|
|
133
|
+
chains: ["solana"],
|
|
134
|
+
solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
135
|
+
smartAccountIndex: 0,
|
|
136
|
+
spendingLimitIndex: 0,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const result = await agent.settleDirectly("merchant-uuid", "500000", {
|
|
140
|
+
apiKey: process.env.PINCERPAY_API_KEY!,
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Runtime policy management
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// Pre-check if a payment would be allowed
|
|
148
|
+
const check = agent.checkPolicy("500000"); // 0.50 USDC
|
|
149
|
+
if (!check.allowed) console.log(check.reason);
|
|
150
|
+
|
|
151
|
+
// Update spending limits dynamically
|
|
152
|
+
agent.setPolicy({ maxPerTransaction: "5000000", maxPerDay: "50000000" });
|
|
153
|
+
|
|
154
|
+
// Monitor daily spending
|
|
155
|
+
const { date, amount } = agent.getDailySpend();
|
|
156
|
+
console.log(`Spent ${amount} base units on ${date}`);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Anti-Patterns
|
|
160
|
+
|
|
161
|
+
### Don't expose agent private keys in client-side code
|
|
162
|
+
|
|
163
|
+
Agent keys should only be used in server-side or backend agent processes, never in browser environments.
|
|
164
|
+
|
|
165
|
+
### Don't skip spending policies in production
|
|
166
|
+
|
|
167
|
+
Without policies, an agent can spend unlimited USDC. Always set `maxPerDay` at minimum.
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
// Bad — no limits
|
|
171
|
+
const agent = await PincerPayAgent.create({
|
|
172
|
+
chains: ["solana"],
|
|
173
|
+
solanaPrivateKey: key,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Good — bounded spending
|
|
177
|
+
const agent = await PincerPayAgent.create({
|
|
178
|
+
chains: ["solana"],
|
|
179
|
+
solanaPrivateKey: key,
|
|
180
|
+
policies: [{ maxPerDay: "10000000" }], // 10 USDC/day
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Don't use `PincerPayAgent` for merchant-side logic
|
|
185
|
+
|
|
186
|
+
The agent SDK is for making payments. Use `@pincerpay/merchant` for accepting payments.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { x402Client } from "@x402/core/client";
|
|
2
|
+
import type { AgentConfig, SpendingPolicy } from "@pincerpay/core";
|
|
3
|
+
/**
|
|
4
|
+
* PincerPayAgent — wraps x402/fetch with EVM + Solana wallet support and spending policies.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* const agent = await PincerPayAgent.create({
|
|
8
|
+
* chains: ["base-sepolia"],
|
|
9
|
+
* evmPrivateKey: process.env.AGENT_EVM_KEY!,
|
|
10
|
+
* });
|
|
11
|
+
*
|
|
12
|
+
* const response = await agent.fetch("https://api.example.com/weather");
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare class PincerPayAgent {
|
|
16
|
+
private config;
|
|
17
|
+
private x402Fetch;
|
|
18
|
+
private dailySpend;
|
|
19
|
+
private dailyResetAt;
|
|
20
|
+
private _solanaAddress?;
|
|
21
|
+
/**
|
|
22
|
+
* Create a new PincerPayAgent. Use `PincerPayAgent.create()` for async initialization
|
|
23
|
+
* (required when using Solana wallets).
|
|
24
|
+
*/
|
|
25
|
+
constructor(config: AgentConfig, client?: x402Client);
|
|
26
|
+
/**
|
|
27
|
+
* Async factory — use this when Solana wallets are needed.
|
|
28
|
+
* Also works for EVM-only agents.
|
|
29
|
+
*/
|
|
30
|
+
static create(config: AgentConfig): Promise<PincerPayAgent>;
|
|
31
|
+
/**
|
|
32
|
+
* Payment-enabled fetch — automatically handles 402 challenges.
|
|
33
|
+
*/
|
|
34
|
+
fetch(url: string | URL, init?: RequestInit): Promise<Response>;
|
|
35
|
+
/**
|
|
36
|
+
* Check if a transaction amount is within spending policy limits.
|
|
37
|
+
*/
|
|
38
|
+
checkPolicy(amountBaseUnits: string): {
|
|
39
|
+
allowed: boolean;
|
|
40
|
+
reason?: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Record a successful spend for daily tracking.
|
|
44
|
+
*/
|
|
45
|
+
recordSpend(amountBaseUnits: string): void;
|
|
46
|
+
/** Get the agent's EVM address */
|
|
47
|
+
get evmAddress(): string | undefined;
|
|
48
|
+
/** Get the agent's Solana address (only available via PincerPayAgent.create()) */
|
|
49
|
+
get solanaAddress(): string | undefined;
|
|
50
|
+
/** Get configured chain shorthands */
|
|
51
|
+
get chains(): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Replace the agent's spending policies and reset daily tracking.
|
|
54
|
+
*/
|
|
55
|
+
setPolicy(policy: SpendingPolicy): void;
|
|
56
|
+
/**
|
|
57
|
+
* Get the first active spending policy, if any.
|
|
58
|
+
*/
|
|
59
|
+
getPolicy(): SpendingPolicy | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Get today's tracked spend total and date.
|
|
62
|
+
*/
|
|
63
|
+
getDailySpend(): {
|
|
64
|
+
date: string;
|
|
65
|
+
amount: bigint;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Register x402 hooks to enforce spending policies before payment
|
|
69
|
+
* and record spend after successful payment creation.
|
|
70
|
+
*/
|
|
71
|
+
private registerPolicyHooks;
|
|
72
|
+
private resetDailyIfNeeded;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAK/C,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEnE;;;;;;;;;;;GAWG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,cAAc,CAAC,CAAS;IAEhC;;;OAGG;gBACS,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,UAAU;IAsBpD;;;OAGG;WACU,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAuBjE;;OAEG;IACG,KAAK,CACT,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,IAAI,CAAC,EAAE,WAAW,GACjB,OAAO,CAAC,QAAQ,CAAC;IAIpB;;OAEG;IACH,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAuC3E;;OAEG;IACH,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI;IAO1C,kCAAkC;IAClC,IAAI,UAAU,IAAI,MAAM,GAAG,SAAS,CAGnC;IAED,kFAAkF;IAClF,IAAI,aAAa,IAAI,MAAM,GAAG,SAAS,CAEtC;IAED,sCAAsC;IACtC,IAAI,MAAM,IAAI,MAAM,EAAE,CAErB;IAED;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAMvC;;OAEG;IACH,SAAS,IAAI,cAAc,GAAG,SAAS;IAIvC;;OAEG;IACH,aAAa,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IASjD;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAmB3B,OAAO,CAAC,kBAAkB;CAU3B"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
2
|
+
import { x402Client } from "@x402/core/client";
|
|
3
|
+
import { wrapFetchWithPayment } from "@x402/fetch";
|
|
4
|
+
import { registerExactEvmScheme } from "@x402/evm/exact/client";
|
|
5
|
+
import { registerExactSvmScheme } from "@x402/svm/exact/client";
|
|
6
|
+
import { createKeyPairSignerFromBytes } from "@solana/kit";
|
|
7
|
+
/**
|
|
8
|
+
* PincerPayAgent — wraps x402/fetch with EVM + Solana wallet support and spending policies.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* const agent = await PincerPayAgent.create({
|
|
12
|
+
* chains: ["base-sepolia"],
|
|
13
|
+
* evmPrivateKey: process.env.AGENT_EVM_KEY!,
|
|
14
|
+
* });
|
|
15
|
+
*
|
|
16
|
+
* const response = await agent.fetch("https://api.example.com/weather");
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export class PincerPayAgent {
|
|
20
|
+
config;
|
|
21
|
+
x402Fetch;
|
|
22
|
+
dailySpend = new Map();
|
|
23
|
+
dailyResetAt = 0;
|
|
24
|
+
_solanaAddress;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new PincerPayAgent. Use `PincerPayAgent.create()` for async initialization
|
|
27
|
+
* (required when using Solana wallets).
|
|
28
|
+
*/
|
|
29
|
+
constructor(config, client) {
|
|
30
|
+
this.config = config;
|
|
31
|
+
if (!config.evmPrivateKey && !config.solanaPrivateKey) {
|
|
32
|
+
throw new Error("At least one wallet key (evmPrivateKey or solanaPrivateKey) is required");
|
|
33
|
+
}
|
|
34
|
+
const x402 = client ?? new x402Client();
|
|
35
|
+
// Register EVM scheme synchronously
|
|
36
|
+
if (config.evmPrivateKey && !client) {
|
|
37
|
+
const account = privateKeyToAccount(config.evmPrivateKey);
|
|
38
|
+
registerExactEvmScheme(x402, { signer: account });
|
|
39
|
+
}
|
|
40
|
+
// Register spending policy hooks
|
|
41
|
+
this.registerPolicyHooks(x402);
|
|
42
|
+
// Wrap global fetch with x402 payment handling
|
|
43
|
+
this.x402Fetch = wrapFetchWithPayment(globalThis.fetch, x402);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Async factory — use this when Solana wallets are needed.
|
|
47
|
+
* Also works for EVM-only agents.
|
|
48
|
+
*/
|
|
49
|
+
static async create(config) {
|
|
50
|
+
const client = new x402Client();
|
|
51
|
+
// Register EVM scheme
|
|
52
|
+
if (config.evmPrivateKey) {
|
|
53
|
+
const account = privateKeyToAccount(config.evmPrivateKey);
|
|
54
|
+
registerExactEvmScheme(client, { signer: account });
|
|
55
|
+
}
|
|
56
|
+
// Register Solana scheme (async — needs key derivation)
|
|
57
|
+
let solanaAddress;
|
|
58
|
+
if (config.solanaPrivateKey) {
|
|
59
|
+
const keyBytes = base58Decode(config.solanaPrivateKey);
|
|
60
|
+
const keypairSigner = await createKeyPairSignerFromBytes(keyBytes);
|
|
61
|
+
registerExactSvmScheme(client, { signer: keypairSigner });
|
|
62
|
+
solanaAddress = keypairSigner.address;
|
|
63
|
+
}
|
|
64
|
+
const agent = new PincerPayAgent(config, client);
|
|
65
|
+
agent._solanaAddress = solanaAddress;
|
|
66
|
+
return agent;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Payment-enabled fetch — automatically handles 402 challenges.
|
|
70
|
+
*/
|
|
71
|
+
async fetch(url, init) {
|
|
72
|
+
return this.x402Fetch(url.toString(), init);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if a transaction amount is within spending policy limits.
|
|
76
|
+
*/
|
|
77
|
+
checkPolicy(amountBaseUnits) {
|
|
78
|
+
const policies = this.config.policies;
|
|
79
|
+
if (!policies || policies.length === 0) {
|
|
80
|
+
return { allowed: true };
|
|
81
|
+
}
|
|
82
|
+
const amount = BigInt(amountBaseUnits);
|
|
83
|
+
for (const policy of policies) {
|
|
84
|
+
// Per-transaction limit
|
|
85
|
+
if (policy.maxPerTransaction) {
|
|
86
|
+
const max = BigInt(policy.maxPerTransaction);
|
|
87
|
+
if (amount > max) {
|
|
88
|
+
return {
|
|
89
|
+
allowed: false,
|
|
90
|
+
reason: `Exceeds per-transaction limit: ${amountBaseUnits} > ${policy.maxPerTransaction}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Daily limit
|
|
95
|
+
if (policy.maxPerDay) {
|
|
96
|
+
this.resetDailyIfNeeded();
|
|
97
|
+
const todayKey = new Date().toISOString().slice(0, 10);
|
|
98
|
+
const currentSpend = this.dailySpend.get(todayKey) ?? 0n;
|
|
99
|
+
const max = BigInt(policy.maxPerDay);
|
|
100
|
+
if (currentSpend + amount > max) {
|
|
101
|
+
return {
|
|
102
|
+
allowed: false,
|
|
103
|
+
reason: `Exceeds daily limit: ${currentSpend + amount} > ${policy.maxPerDay}`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { allowed: true };
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Record a successful spend for daily tracking.
|
|
112
|
+
*/
|
|
113
|
+
recordSpend(amountBaseUnits) {
|
|
114
|
+
this.resetDailyIfNeeded();
|
|
115
|
+
const todayKey = new Date().toISOString().slice(0, 10);
|
|
116
|
+
const current = this.dailySpend.get(todayKey) ?? 0n;
|
|
117
|
+
this.dailySpend.set(todayKey, current + BigInt(amountBaseUnits));
|
|
118
|
+
}
|
|
119
|
+
/** Get the agent's EVM address */
|
|
120
|
+
get evmAddress() {
|
|
121
|
+
if (!this.config.evmPrivateKey)
|
|
122
|
+
return undefined;
|
|
123
|
+
return privateKeyToAccount(this.config.evmPrivateKey).address;
|
|
124
|
+
}
|
|
125
|
+
/** Get the agent's Solana address (only available via PincerPayAgent.create()) */
|
|
126
|
+
get solanaAddress() {
|
|
127
|
+
return this._solanaAddress;
|
|
128
|
+
}
|
|
129
|
+
/** Get configured chain shorthands */
|
|
130
|
+
get chains() {
|
|
131
|
+
return this.config.chains;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Replace the agent's spending policies and reset daily tracking.
|
|
135
|
+
*/
|
|
136
|
+
setPolicy(policy) {
|
|
137
|
+
this.config.policies = [policy];
|
|
138
|
+
this.dailySpend.clear();
|
|
139
|
+
this.dailyResetAt = 0;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get the first active spending policy, if any.
|
|
143
|
+
*/
|
|
144
|
+
getPolicy() {
|
|
145
|
+
return this.config.policies?.[0];
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Get today's tracked spend total and date.
|
|
149
|
+
*/
|
|
150
|
+
getDailySpend() {
|
|
151
|
+
this.resetDailyIfNeeded();
|
|
152
|
+
const todayKey = new Date().toISOString().slice(0, 10);
|
|
153
|
+
return {
|
|
154
|
+
date: todayKey,
|
|
155
|
+
amount: this.dailySpend.get(todayKey) ?? 0n,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Register x402 hooks to enforce spending policies before payment
|
|
160
|
+
* and record spend after successful payment creation.
|
|
161
|
+
*/
|
|
162
|
+
registerPolicyHooks(client) {
|
|
163
|
+
if (!this.config.policies || this.config.policies.length === 0)
|
|
164
|
+
return;
|
|
165
|
+
// Before payment: enforce spending limits
|
|
166
|
+
client.onBeforePaymentCreation(async (ctx) => {
|
|
167
|
+
const amount = String(ctx.selectedRequirements.maxAmountRequired ?? ctx.selectedRequirements.amount ?? "0");
|
|
168
|
+
const check = this.checkPolicy(amount);
|
|
169
|
+
if (!check.allowed) {
|
|
170
|
+
return { abort: true, reason: check.reason };
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
// After payment: track spend for daily limits
|
|
174
|
+
client.onAfterPaymentCreation(async (ctx) => {
|
|
175
|
+
const amount = String(ctx.selectedRequirements.maxAmountRequired ?? ctx.selectedRequirements.amount ?? "0");
|
|
176
|
+
this.recordSpend(amount);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
resetDailyIfNeeded() {
|
|
180
|
+
const now = Date.now();
|
|
181
|
+
if (now > this.dailyResetAt) {
|
|
182
|
+
this.dailySpend.clear();
|
|
183
|
+
// Reset at midnight UTC
|
|
184
|
+
const tomorrow = new Date();
|
|
185
|
+
tomorrow.setUTCHours(24, 0, 0, 0);
|
|
186
|
+
this.dailyResetAt = tomorrow.getTime();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Minimal base58 decoder for Solana private keys.
|
|
192
|
+
* Avoids pulling in @scure/base as a dependency for the agent SDK.
|
|
193
|
+
*/
|
|
194
|
+
function base58Decode(input) {
|
|
195
|
+
const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
196
|
+
const BASE = BigInt(58);
|
|
197
|
+
let num = 0n;
|
|
198
|
+
for (const char of input) {
|
|
199
|
+
const idx = ALPHABET.indexOf(char);
|
|
200
|
+
if (idx === -1)
|
|
201
|
+
throw new Error(`Invalid base58 character: ${char}`);
|
|
202
|
+
num = num * BASE + BigInt(idx);
|
|
203
|
+
}
|
|
204
|
+
// Count leading zeros
|
|
205
|
+
let leadingZeros = 0;
|
|
206
|
+
for (const char of input) {
|
|
207
|
+
if (char !== "1")
|
|
208
|
+
break;
|
|
209
|
+
leadingZeros++;
|
|
210
|
+
}
|
|
211
|
+
// Convert to bytes (pad hex to even length so .match(/.{2}/g) doesn't drop a nibble)
|
|
212
|
+
const rawHex = num.toString(16);
|
|
213
|
+
const hex = rawHex.length % 2 ? "0" + rawHex : rawHex;
|
|
214
|
+
const bytes = hex.match(/.{2}/g)?.map((b) => parseInt(b, 16)) ?? [];
|
|
215
|
+
return new Uint8Array([...new Array(leadingZeros).fill(0), ...bytes]);
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,sBAAsB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Instruction } from "@solana/kit";
|
|
2
|
+
import { type SolanaSmartAgentConfig } from "@pincerpay/core";
|
|
3
|
+
import { SpendingLimitPeriod } from "@pincerpay/solana/squads";
|
|
4
|
+
import { PincerPayAgent } from "./client.js";
|
|
5
|
+
/**
|
|
6
|
+
* SolanaSmartAgent — extends PincerPayAgent with Squads Smart Account support.
|
|
7
|
+
*
|
|
8
|
+
* Spending limits are enforced on-chain via the Squads program, not in-memory.
|
|
9
|
+
* This agent performs an optimistic pre-check against the on-chain spending limit
|
|
10
|
+
* before each payment, but the real enforcement happens at the transaction level.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const agent = await SolanaSmartAgent.create({
|
|
14
|
+
* chains: ["solana"],
|
|
15
|
+
* solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
16
|
+
* smartAccountIndex: 0,
|
|
17
|
+
* spendingLimitIndex: 0,
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* const response = await agent.fetch("https://api.example.com/weather");
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare class SolanaSmartAgent extends PincerPayAgent {
|
|
24
|
+
private smartConfig;
|
|
25
|
+
private _smartAccountPda?;
|
|
26
|
+
private _settingsPda?;
|
|
27
|
+
private _spendingLimitPda?;
|
|
28
|
+
private constructor();
|
|
29
|
+
/**
|
|
30
|
+
* Async factory — initializes the Solana wallet, derives Squads PDAs,
|
|
31
|
+
* and optionally validates on-chain state.
|
|
32
|
+
*/
|
|
33
|
+
static create(config: SolanaSmartAgentConfig): Promise<SolanaSmartAgent>;
|
|
34
|
+
/** Get the Squads Smart Account PDA */
|
|
35
|
+
get smartAccountPda(): string | undefined;
|
|
36
|
+
/** Get the Squads Settings PDA */
|
|
37
|
+
get settingsPda(): string | undefined;
|
|
38
|
+
/** Get the Squads Spending Limit PDA */
|
|
39
|
+
get spendingLimitPda(): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Settle a payment directly via the Anchor program (bypassing x402).
|
|
42
|
+
* Calls POST /v1/settle-direct on the facilitator.
|
|
43
|
+
*
|
|
44
|
+
* Returns the settlement response including the on-chain accounts needed
|
|
45
|
+
* for the agent to construct and sign the settle_payment instruction.
|
|
46
|
+
*/
|
|
47
|
+
settleDirectly(merchantId: string, amountBaseUnits: string, options?: {
|
|
48
|
+
facilitatorUrl?: string;
|
|
49
|
+
apiKey?: string;
|
|
50
|
+
network?: string;
|
|
51
|
+
}): Promise<{
|
|
52
|
+
success: boolean;
|
|
53
|
+
transactionId?: string;
|
|
54
|
+
accounts?: Record<string, string>;
|
|
55
|
+
error?: string;
|
|
56
|
+
}>;
|
|
57
|
+
/**
|
|
58
|
+
* Build a createSmartAccount instruction using this agent's config.
|
|
59
|
+
* The caller is responsible for signing and sending.
|
|
60
|
+
*/
|
|
61
|
+
buildCreateSmartAccountInstruction(params?: {
|
|
62
|
+
members?: string[];
|
|
63
|
+
threshold?: number;
|
|
64
|
+
}): Promise<Instruction>;
|
|
65
|
+
/**
|
|
66
|
+
* Build an addSpendingLimit instruction for this agent's Smart Account.
|
|
67
|
+
* Requires a Smart Account to be configured.
|
|
68
|
+
*/
|
|
69
|
+
buildAddSpendingLimitInstruction(params: {
|
|
70
|
+
mint: string;
|
|
71
|
+
amount: bigint;
|
|
72
|
+
period: SpendingLimitPeriod;
|
|
73
|
+
members?: string[];
|
|
74
|
+
destinations?: string[];
|
|
75
|
+
authority: string;
|
|
76
|
+
}): Promise<Instruction>;
|
|
77
|
+
/**
|
|
78
|
+
* Build a removeSpendingLimit instruction for this agent's Smart Account.
|
|
79
|
+
* Requires a Smart Account to be configured.
|
|
80
|
+
*/
|
|
81
|
+
buildRevokeSpendingLimitInstruction(params: {
|
|
82
|
+
authority: string;
|
|
83
|
+
rentCollector?: string;
|
|
84
|
+
}): Promise<Instruction>;
|
|
85
|
+
/**
|
|
86
|
+
* Check on-chain spending limit before payment.
|
|
87
|
+
* This is an optimistic pre-check — the real enforcement is on-chain.
|
|
88
|
+
*/
|
|
89
|
+
checkOnChainPolicy(amountBaseUnits: string, rpcUrl?: string): Promise<{
|
|
90
|
+
allowed: boolean;
|
|
91
|
+
reason?: string;
|
|
92
|
+
remainingAmount?: bigint;
|
|
93
|
+
}>;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=solana-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solana-agent.d.ts","sourceRoot":"","sources":["../src/solana-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,WAAW,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAA2B,KAAK,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAQL,mBAAmB,EACpB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,gBAAiB,SAAQ,cAAc;IAClD,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAClC,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,iBAAiB,CAAC,CAAS;IAEnC,OAAO;IAKP;;;OAGG;WACmB,MAAM,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAoCvF,uCAAuC;IACvC,IAAI,eAAe,IAAI,MAAM,GAAG,SAAS,CAExC;IAED,kCAAkC;IAClC,IAAI,WAAW,IAAI,MAAM,GAAG,SAAS,CAEpC;IAED,wCAAwC;IACxC,IAAI,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAEzC;IAED;;;;;;OAMG;IACG,cAAc,CAClB,UAAU,EAAE,MAAM,EAClB,eAAe,EAAE,MAAM,EACvB,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACvE,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAmCF;;;OAGG;IACG,kCAAkC,CAAC,MAAM,CAAC,EAAE;QAChD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,WAAW,CAAC;IAgBxB;;;OAGG;IACG,gCAAgC,CAAC,MAAM,EAAE;QAC7C,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,mBAAmB,CAAC;QAC5B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,WAAW,CAAC;IAqBxB;;;OAGG;IACG,mCAAmC,CAAC,MAAM,EAAE;QAChD,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,WAAW,CAAC;IAaxB;;;OAGG;IACG,kBAAkB,CACtB,eAAe,EAAE,MAAM,EACvB,MAAM,SAAkC,GACvC,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CA8B5E"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { createSolanaRpc } from "@solana/kit";
|
|
2
|
+
import { DEFAULT_FACILITATOR_URL } from "@pincerpay/core";
|
|
3
|
+
import { deriveSmartAccountPda, deriveSettingsPda, deriveSpendingLimitPda, checkSpendingLimit, createSmartAccountInstruction, addSpendingLimitInstruction, removeSpendingLimitInstruction, SpendingLimitPeriod, } from "@pincerpay/solana/squads";
|
|
4
|
+
import { PincerPayAgent } from "./client.js";
|
|
5
|
+
/**
|
|
6
|
+
* SolanaSmartAgent — extends PincerPayAgent with Squads Smart Account support.
|
|
7
|
+
*
|
|
8
|
+
* Spending limits are enforced on-chain via the Squads program, not in-memory.
|
|
9
|
+
* This agent performs an optimistic pre-check against the on-chain spending limit
|
|
10
|
+
* before each payment, but the real enforcement happens at the transaction level.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const agent = await SolanaSmartAgent.create({
|
|
14
|
+
* chains: ["solana"],
|
|
15
|
+
* solanaPrivateKey: process.env.AGENT_SOLANA_KEY!,
|
|
16
|
+
* smartAccountIndex: 0,
|
|
17
|
+
* spendingLimitIndex: 0,
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* const response = await agent.fetch("https://api.example.com/weather");
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export class SolanaSmartAgent extends PincerPayAgent {
|
|
24
|
+
smartConfig;
|
|
25
|
+
_smartAccountPda;
|
|
26
|
+
_settingsPda;
|
|
27
|
+
_spendingLimitPda;
|
|
28
|
+
constructor(config) {
|
|
29
|
+
super(config);
|
|
30
|
+
this.smartConfig = config;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Async factory — initializes the Solana wallet, derives Squads PDAs,
|
|
34
|
+
* and optionally validates on-chain state.
|
|
35
|
+
*/
|
|
36
|
+
static async create(config) {
|
|
37
|
+
// Create the base agent (registers Solana x402 scheme)
|
|
38
|
+
const baseAgent = await PincerPayAgent.create(config);
|
|
39
|
+
// Create SolanaSmartAgent and transfer state
|
|
40
|
+
const agent = new SolanaSmartAgent(config);
|
|
41
|
+
// Copy over the Solana address from base agent
|
|
42
|
+
Object.defineProperty(agent, "_solanaAddress", {
|
|
43
|
+
value: baseAgent.solanaAddress,
|
|
44
|
+
writable: true,
|
|
45
|
+
});
|
|
46
|
+
// Derive Squads PDAs if configured
|
|
47
|
+
const solanaAddr = baseAgent.solanaAddress;
|
|
48
|
+
if (solanaAddr && config.smartAccountIndex !== undefined) {
|
|
49
|
+
const [smartPda] = await deriveSmartAccountPda(solanaAddr, config.smartAccountIndex);
|
|
50
|
+
agent._smartAccountPda = smartPda;
|
|
51
|
+
const [settingsPda] = await deriveSettingsPda(smartPda);
|
|
52
|
+
agent._settingsPda = config.settingsPda ?? settingsPda;
|
|
53
|
+
if (config.spendingLimitIndex !== undefined) {
|
|
54
|
+
const [limitPda] = await deriveSpendingLimitPda(smartPda, config.spendingLimitIndex);
|
|
55
|
+
agent._spendingLimitPda = limitPda;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return agent;
|
|
59
|
+
}
|
|
60
|
+
/** Get the Squads Smart Account PDA */
|
|
61
|
+
get smartAccountPda() {
|
|
62
|
+
return this._smartAccountPda;
|
|
63
|
+
}
|
|
64
|
+
/** Get the Squads Settings PDA */
|
|
65
|
+
get settingsPda() {
|
|
66
|
+
return this._settingsPda;
|
|
67
|
+
}
|
|
68
|
+
/** Get the Squads Spending Limit PDA */
|
|
69
|
+
get spendingLimitPda() {
|
|
70
|
+
return this._spendingLimitPda;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Settle a payment directly via the Anchor program (bypassing x402).
|
|
74
|
+
* Calls POST /v1/settle-direct on the facilitator.
|
|
75
|
+
*
|
|
76
|
+
* Returns the settlement response including the on-chain accounts needed
|
|
77
|
+
* for the agent to construct and sign the settle_payment instruction.
|
|
78
|
+
*/
|
|
79
|
+
async settleDirectly(merchantId, amountBaseUnits, options) {
|
|
80
|
+
const facilitatorUrl = options?.facilitatorUrl
|
|
81
|
+
?? this.smartConfig.facilitatorUrl
|
|
82
|
+
?? DEFAULT_FACILITATOR_URL;
|
|
83
|
+
const solanaAddr = this.solanaAddress;
|
|
84
|
+
if (!solanaAddr) {
|
|
85
|
+
return { success: false, error: "No Solana address configured" };
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const response = await globalThis.fetch(`${facilitatorUrl}/v1/settle-direct`, {
|
|
89
|
+
method: "POST",
|
|
90
|
+
headers: {
|
|
91
|
+
"Content-Type": "application/json",
|
|
92
|
+
...(options?.apiKey ? { "x-pincerpay-api-key": options.apiKey } : {}),
|
|
93
|
+
},
|
|
94
|
+
body: JSON.stringify({
|
|
95
|
+
agentAddress: solanaAddr,
|
|
96
|
+
merchantId,
|
|
97
|
+
amount: amountBaseUnits,
|
|
98
|
+
network: options?.network ?? "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
|
|
99
|
+
}),
|
|
100
|
+
});
|
|
101
|
+
const result = await response.json();
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
error: err instanceof Error ? err.message : String(err),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Build a createSmartAccount instruction using this agent's config.
|
|
113
|
+
* The caller is responsible for signing and sending.
|
|
114
|
+
*/
|
|
115
|
+
async buildCreateSmartAccountInstruction(params) {
|
|
116
|
+
const solanaAddr = this.solanaAddress;
|
|
117
|
+
if (!solanaAddr)
|
|
118
|
+
throw new Error("No Solana address configured");
|
|
119
|
+
const accountIndex = this.smartConfig.smartAccountIndex ?? 0;
|
|
120
|
+
const members = params?.members?.map((m) => m) ?? [solanaAddr];
|
|
121
|
+
const threshold = params?.threshold ?? 1;
|
|
122
|
+
return createSmartAccountInstruction({
|
|
123
|
+
creator: solanaAddr,
|
|
124
|
+
accountIndex,
|
|
125
|
+
members,
|
|
126
|
+
threshold,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Build an addSpendingLimit instruction for this agent's Smart Account.
|
|
131
|
+
* Requires a Smart Account to be configured.
|
|
132
|
+
*/
|
|
133
|
+
async buildAddSpendingLimitInstruction(params) {
|
|
134
|
+
if (!this._smartAccountPda)
|
|
135
|
+
throw new Error("No Smart Account PDA configured");
|
|
136
|
+
const solanaAddr = this.solanaAddress;
|
|
137
|
+
const spendingLimitIndex = this.smartConfig.spendingLimitIndex ?? 0;
|
|
138
|
+
const members = params.members?.map((m) => m) ?? (solanaAddr ? [solanaAddr] : []);
|
|
139
|
+
return addSpendingLimitInstruction({
|
|
140
|
+
smartAccountPda: this._smartAccountPda,
|
|
141
|
+
mint: params.mint,
|
|
142
|
+
amount: params.amount,
|
|
143
|
+
period: params.period,
|
|
144
|
+
members,
|
|
145
|
+
destinations: params.destinations?.map((d) => d) ?? [],
|
|
146
|
+
}, spendingLimitIndex, params.authority);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Build a removeSpendingLimit instruction for this agent's Smart Account.
|
|
150
|
+
* Requires a Smart Account to be configured.
|
|
151
|
+
*/
|
|
152
|
+
async buildRevokeSpendingLimitInstruction(params) {
|
|
153
|
+
if (!this._smartAccountPda)
|
|
154
|
+
throw new Error("No Smart Account PDA configured");
|
|
155
|
+
const spendingLimitIndex = this.smartConfig.spendingLimitIndex ?? 0;
|
|
156
|
+
return removeSpendingLimitInstruction({
|
|
157
|
+
smartAccountPda: this._smartAccountPda,
|
|
158
|
+
spendingLimitIndex,
|
|
159
|
+
authority: params.authority,
|
|
160
|
+
rentCollector: (params.rentCollector ?? params.authority),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Check on-chain spending limit before payment.
|
|
165
|
+
* This is an optimistic pre-check — the real enforcement is on-chain.
|
|
166
|
+
*/
|
|
167
|
+
async checkOnChainPolicy(amountBaseUnits, rpcUrl = "https://api.devnet.solana.com") {
|
|
168
|
+
if (!this._smartAccountPda || this.smartConfig.spendingLimitIndex === undefined) {
|
|
169
|
+
// No Squads spending limit configured — fall back to in-memory policy
|
|
170
|
+
return this.checkPolicy(amountBaseUnits);
|
|
171
|
+
}
|
|
172
|
+
const result = await checkSpendingLimit(this._smartAccountPda, this.smartConfig.spendingLimitIndex, rpcUrl);
|
|
173
|
+
if (!result) {
|
|
174
|
+
return {
|
|
175
|
+
allowed: false,
|
|
176
|
+
reason: "Spending limit account not found on-chain",
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
const amount = BigInt(amountBaseUnits);
|
|
180
|
+
if (result.remainingAmount !== undefined && amount > result.remainingAmount) {
|
|
181
|
+
return {
|
|
182
|
+
allowed: false,
|
|
183
|
+
reason: `Exceeds on-chain spending limit: ${amountBaseUnits} > ${result.remainingAmount}`,
|
|
184
|
+
remainingAmount: result.remainingAmount,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
return { allowed: true, remainingAmount: result.remainingAmount };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=solana-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solana-agent.js","sourceRoot":"","sources":["../src/solana-agent.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pincerpay/agent",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Agent SDK for PincerPay. Drop-in fetch wrapper that handles x402 payment flows automatically.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://pincerpay.com",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/ds1/pincerpay.git",
|
|
14
|
+
"directory": "packages/agent"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/ds1/pincerpay/issues"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"pincerpay",
|
|
21
|
+
"x402",
|
|
22
|
+
"usdc",
|
|
23
|
+
"payments",
|
|
24
|
+
"ai-agents",
|
|
25
|
+
"solana",
|
|
26
|
+
"agent-sdk",
|
|
27
|
+
"payment-gateway",
|
|
28
|
+
"stablecoin"
|
|
29
|
+
],
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE"
|
|
34
|
+
],
|
|
35
|
+
"main": "dist/index.js",
|
|
36
|
+
"types": "dist/index.d.ts",
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"import": "./dist/index.js"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@solana/kit": "^5.5.1",
|
|
45
|
+
"@x402/core": "^2.3",
|
|
46
|
+
"@x402/evm": "^2.3",
|
|
47
|
+
"@x402/fetch": "^2.3",
|
|
48
|
+
"@x402/svm": "^2.3.0",
|
|
49
|
+
"viem": "^2",
|
|
50
|
+
"zod": "^3.24",
|
|
51
|
+
"@pincerpay/core": "0.1.0",
|
|
52
|
+
"@pincerpay/solana": "0.1.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@scure/base": "^1.2.6",
|
|
56
|
+
"typescript": "^5.7"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc",
|
|
60
|
+
"test": "vitest run",
|
|
61
|
+
"typecheck": "tsc --noEmit",
|
|
62
|
+
"clean": "rm -rf dist"
|
|
63
|
+
}
|
|
64
|
+
}
|