@perkos/agent-sdk 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/CHANGELOG.md +48 -0
- package/README.md +175 -5
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/x402-direct.d.ts +100 -0
- package/dist/x402-direct.d.ts.map +1 -0
- package/dist/x402-direct.js +576 -0
- package/dist/x402-direct.js.map +1 -0
- package/dist/x402-facilitator.d.ts +86 -0
- package/dist/x402-facilitator.d.ts.map +1 -0
- package/dist/x402-facilitator.js +480 -0
- package/dist/x402-facilitator.js.map +1 -0
- package/dist/x402.d.ts +60 -0
- package/dist/x402.d.ts.map +1 -0
- package/dist/x402.js +306 -0
- package/dist/x402.js.map +1 -0
- package/docs/ARCHITECTURE.md +25 -1
- package/docs/plans/2026-08-25-stacks-x402-direct-profile-design.md +68 -0
- package/docs/plans/2026-08-25-stacks-x402-facilitator-design.md +143 -0
- package/docs/plans/2026-08-25-stacks-x402-v2-design.md +139 -0
- package/examples/x402-facilitator.ts +69 -0
- package/examples/x402-foundation.ts +30 -0
- package/package.json +10 -5
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Stacks x402 v2 foundation
|
|
2
|
+
|
|
3
|
+
Date: 2026-08-25
|
|
4
|
+
Status: approved foundation for implementation
|
|
5
|
+
|
|
6
|
+
## Milestone 2 alignment
|
|
7
|
+
|
|
8
|
+
Milestone 1 is approved and closed. This work must not redeploy, replace, or add fee behavior to
|
|
9
|
+
the M1 mainnet contracts. It is an additive SDK adapter intended to make the existing STX and sBTC
|
|
10
|
+
job lifecycle easier for external developers and agent frameworks to adopt during Milestone 2.
|
|
11
|
+
|
|
12
|
+
The authoritative M2 acceptance work remains the public SDK, working documentation and example,
|
|
13
|
+
external security review, recorded SDK demo, mainnet adoption, non-team participation, and external
|
|
14
|
+
technical feedback. This x402 foundation can support the SDK/example/adoption portions, but does
|
|
15
|
+
not by itself complete M2 and must not delay the security review or adoption outreach.
|
|
16
|
+
|
|
17
|
+
## Decision
|
|
18
|
+
|
|
19
|
+
Use the official `@x402/core` v2 envelope and HTTP header codecs, then implement a narrow Stacks
|
|
20
|
+
escrow adapter around the existing `PerkOSClient`. The first version represents a confirmed
|
|
21
|
+
`fund-job` transaction as the scheme-specific payment proof. It does not implement a hosted
|
|
22
|
+
facilitator, protocol revenue, metering, or a new smart contract.
|
|
23
|
+
|
|
24
|
+
The wire contract uses:
|
|
25
|
+
|
|
26
|
+
- x402 version `2`;
|
|
27
|
+
- `PAYMENT-REQUIRED`, `PAYMENT-SIGNATURE`, and `PAYMENT-RESPONSE` header formats from
|
|
28
|
+
`@x402/core/http`;
|
|
29
|
+
- CAIP-2 network identifiers `stacks:1` for mainnet and `stacks:2147483648` for testnet;
|
|
30
|
+
- scheme `exact` because the job budget is an exact atomic amount;
|
|
31
|
+
- asset transfer method `perkos-escrow-v1` to prevent a direct-transfer facilitator from
|
|
32
|
+
misinterpreting an escrow requirement;
|
|
33
|
+
- payment flow `upfront` for the HTTP resource because the escrow must be confirmed before the
|
|
34
|
+
protected endpoint proceeds. The later job completion remains governed by the existing neutral
|
|
35
|
+
evaluator and escrow contract.
|
|
36
|
+
|
|
37
|
+
## Alternatives considered
|
|
38
|
+
|
|
39
|
+
### Keep the existing custom `X-X402-*` headers
|
|
40
|
+
|
|
41
|
+
This is the smallest code change, but it is not the current x402 v2 transport and makes ecosystem
|
|
42
|
+
integration harder. It is rejected for new SDK work. The application migration will happen only
|
|
43
|
+
after this SDK foundation is merged and tested.
|
|
44
|
+
|
|
45
|
+
### Adopt a third-party Stacks x402 package directly
|
|
46
|
+
|
|
47
|
+
`@t402/stacks` and `x402-stacks` provide useful reference implementations. Their transfer and
|
|
48
|
+
signer assumptions do not match the PerkOS job escrow lifecycle or the SDK's injected signer and
|
|
49
|
+
fail-closed spending policy. A direct dependency would create two signing/policy stacks. They are
|
|
50
|
+
not used in the foundation.
|
|
51
|
+
|
|
52
|
+
### Official x402 core plus a PerkOS Stacks adapter
|
|
53
|
+
|
|
54
|
+
This keeps the rapidly evolving transport and schemas with the x402 Foundation while retaining
|
|
55
|
+
PerkOS-specific escrow validation, exact post-conditions, Leather support, confirmation tracking,
|
|
56
|
+
and spending limits. This is the selected approach.
|
|
57
|
+
|
|
58
|
+
## Components
|
|
59
|
+
|
|
60
|
+
`src/x402.ts` will provide:
|
|
61
|
+
|
|
62
|
+
1. Network conversion between the SDK network names and Stacks CAIP-2 identifiers.
|
|
63
|
+
2. A payment-requirement builder derived from a resolved `PerkOSClient` configuration.
|
|
64
|
+
3. Strict parsing of PerkOS escrow requirements and confirmed-funding proofs.
|
|
65
|
+
4. `PerkOSX402SchemeClient`, an `@x402/core` scheme client that uses the existing SDK to inspect
|
|
66
|
+
the job, enforce an exact budget, fund it through the configured signer, wait for terminal
|
|
67
|
+
confirmation, and return a proof containing the transaction ID.
|
|
68
|
+
5. Re-exported x402 v2 header codecs so consumers do not recreate base64 JSON handling.
|
|
69
|
+
|
|
70
|
+
The adapter accepts a small structural client interface rather than a private key or wallet
|
|
71
|
+
implementation. The production `PerkOSClient` satisfies the interface; tests can provide a
|
|
72
|
+
deterministic in-memory client.
|
|
73
|
+
|
|
74
|
+
## Data flow
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
Buyer agent Resource server Stacks
|
|
78
|
+
| GET/POST resource | |
|
|
79
|
+
|--------------------------->| |
|
|
80
|
+
| 402 + PAYMENT-REQUIRED | |
|
|
81
|
+
|<---------------------------| |
|
|
82
|
+
| validate requirement | |
|
|
83
|
+
| inspect job/budget | |
|
|
84
|
+
| fundJob via SDK signer --------------------------->|
|
|
85
|
+
| wait for confirmation ---------------------------->|
|
|
86
|
+
| PAYMENT-SIGNATURE | |
|
|
87
|
+
| (confirmed tx proof) | |
|
|
88
|
+
|--------------------------->| |
|
|
89
|
+
| | facilitator/verification is a later PR
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The `PAYMENT-SIGNATURE` name is the x402 transport field for a scheme-specific payment payload.
|
|
93
|
+
For this foundation, its Stacks payload is a confirmed transaction proof rather than an EVM
|
|
94
|
+
EIP-3009 signature.
|
|
95
|
+
|
|
96
|
+
## Validation and failure handling
|
|
97
|
+
|
|
98
|
+
- Reject protocol versions other than v2.
|
|
99
|
+
- Reject non-Stacks or cross-network requirements.
|
|
100
|
+
- Require positive decimal atomic amounts and job IDs.
|
|
101
|
+
- Require the configured commerce contract as `payTo`.
|
|
102
|
+
- Require the configured sBTC asset identifier for sBTC and `STX` for STX.
|
|
103
|
+
- Require the on-chain job to exist, remain open, and have exactly the quoted budget.
|
|
104
|
+
- Reuse the SDK spending policy, signer/network checks, post-conditions, and confirmation tracker.
|
|
105
|
+
- Return a payload only after a `success` confirmation. Pending, abort, dropped, and timeout states
|
|
106
|
+
are payment failures.
|
|
107
|
+
- Never accept a transaction ID as proof of payment without a later facilitator/server verifying
|
|
108
|
+
the transaction, contract call, sender, amount, job, and replay status.
|
|
109
|
+
|
|
110
|
+
## Security boundary and known limitation
|
|
111
|
+
|
|
112
|
+
This PR creates and serializes payment proofs; it does not make an HTTP resource safe to monetize.
|
|
113
|
+
A production resource server still needs an independent Stacks facilitator/verifier and replay
|
|
114
|
+
store. The verifier must hydrate the transaction, match it to the accepted requirement, confirm
|
|
115
|
+
successful escrow funding, and prevent the same transaction from authorizing multiple purchases.
|
|
116
|
+
|
|
117
|
+
No secret, private key, treasury address, protocol fee, or production endpoint is introduced.
|
|
118
|
+
|
|
119
|
+
## Testing
|
|
120
|
+
|
|
121
|
+
The implementation will cover:
|
|
122
|
+
|
|
123
|
+
- CAIP-2 network mapping;
|
|
124
|
+
- STX and sBTC payment-requirement construction;
|
|
125
|
+
- official x402 header encode/decode round trips;
|
|
126
|
+
- invalid version, network, amount, asset, payee, metadata, and proof rejection;
|
|
127
|
+
- exact job-budget validation;
|
|
128
|
+
- successful confirmed funding through a fake client;
|
|
129
|
+
- failure on non-success terminal confirmations;
|
|
130
|
+
- compatibility with `@x402/core`'s `x402Client` registration and payload creation.
|
|
131
|
+
|
|
132
|
+
## Follow-up sequence
|
|
133
|
+
|
|
134
|
+
1. Merge this SDK foundation.
|
|
135
|
+
2. Build a read-only Stacks verifier/facilitator with replay protection and testnet evidence.
|
|
136
|
+
3. Replace the application's custom `X-X402-*` middleware with the SDK v2 adapter.
|
|
137
|
+
4. Add an M2 example/demo and use it for external developer feedback and adoption outreach.
|
|
138
|
+
5. Consider metering and protocol revenue only as a separate, reviewed product phase that does
|
|
139
|
+
not alter the approved M1 contracts or block M2 acceptance.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HiroX402TransactionSource,
|
|
3
|
+
InMemoryX402ReplayStore,
|
|
4
|
+
PerkOSX402Facilitator,
|
|
5
|
+
createPerkOSX402PaymentRequired,
|
|
6
|
+
resolveConfig,
|
|
7
|
+
type PaymentPayload,
|
|
8
|
+
} from "@perkos/agent-sdk";
|
|
9
|
+
|
|
10
|
+
const transaction =
|
|
11
|
+
"0xaf4129fe46fc913fda7b9fa87543f05fc5f4430b9b5f26a46f9c3032ea0fcbd4";
|
|
12
|
+
const payer = "SP2K7PV5NXBNRV510S6DCA6RFMTFHAF3ZPK6ZSXPH";
|
|
13
|
+
const blockHeight = 8_650_821;
|
|
14
|
+
const blockHash =
|
|
15
|
+
"0x46786964695d632ce40d54e5a94f5e74bcaf4fc995ff45c9ae913be0020e402d";
|
|
16
|
+
const config = resolveConfig({ network: "mainnet" });
|
|
17
|
+
const paymentRequired = createPerkOSX402PaymentRequired(config, {
|
|
18
|
+
resource: {
|
|
19
|
+
url: "https://nayori.example/evidence/m1-job-1",
|
|
20
|
+
description: "Read-only x402 verifier evidence",
|
|
21
|
+
mimeType: "application/json",
|
|
22
|
+
serviceName: "Nayori",
|
|
23
|
+
},
|
|
24
|
+
asset: "sbtc",
|
|
25
|
+
jobId: 1n,
|
|
26
|
+
amount: 10_000n,
|
|
27
|
+
maxTimeoutSeconds: 3_600,
|
|
28
|
+
});
|
|
29
|
+
const paymentPayload: PaymentPayload = {
|
|
30
|
+
x402Version: 2,
|
|
31
|
+
resource: paymentRequired.resource,
|
|
32
|
+
accepted: paymentRequired.accepts[0]!,
|
|
33
|
+
payload: {
|
|
34
|
+
transaction,
|
|
35
|
+
payer,
|
|
36
|
+
jobId: "1",
|
|
37
|
+
amount: "10000",
|
|
38
|
+
asset: "sbtc",
|
|
39
|
+
commerceContract: config.contracts.sbtcCommerce,
|
|
40
|
+
blockHeight,
|
|
41
|
+
blockHash,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
const transactionSource = new HiroX402TransactionSource({ network: "mainnet" });
|
|
45
|
+
const facilitator = new PerkOSX402Facilitator({
|
|
46
|
+
config,
|
|
47
|
+
transactionSource,
|
|
48
|
+
replayStore: new InMemoryX402ReplayStore(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const verification = await facilitator.verify(
|
|
52
|
+
paymentPayload,
|
|
53
|
+
paymentRequired.accepts[0]!
|
|
54
|
+
);
|
|
55
|
+
if (verification.isValid || verification.invalidReason !== "payment_expired") {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Expected the historical proof to be rejected as expired, received ${JSON.stringify(verification)}`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log({
|
|
62
|
+
transaction,
|
|
63
|
+
observedContract: config.contracts.sbtcCommerce,
|
|
64
|
+
observedAsset: paymentRequired.accepts[0]!.asset,
|
|
65
|
+
observedAmount: paymentRequired.accepts[0]!.amount,
|
|
66
|
+
verification,
|
|
67
|
+
note:
|
|
68
|
+
"The facilitator matched the public funding call and transfer events, then failed closed because this historical transaction is outside the x402 payment window. No state was changed.",
|
|
69
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPerkOSX402PaymentRequired,
|
|
3
|
+
decodePaymentRequiredHeader,
|
|
4
|
+
encodePaymentRequiredHeader,
|
|
5
|
+
resolveConfig,
|
|
6
|
+
} from "@perkos/agent-sdk";
|
|
7
|
+
|
|
8
|
+
const config = resolveConfig({ network: "mainnet" });
|
|
9
|
+
const paymentRequired = createPerkOSX402PaymentRequired(config, {
|
|
10
|
+
resource: {
|
|
11
|
+
url: "https://agent.example/jobs/7/fund",
|
|
12
|
+
description: "Fund an existing PerkOS agent job escrow",
|
|
13
|
+
mimeType: "application/json",
|
|
14
|
+
serviceName: "Nayori",
|
|
15
|
+
tags: ["agents", "escrow"],
|
|
16
|
+
},
|
|
17
|
+
asset: "sbtc",
|
|
18
|
+
jobId: 7n,
|
|
19
|
+
amount: 25_000n,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const header = encodePaymentRequiredHeader(paymentRequired);
|
|
23
|
+
const decoded = decodePaymentRequiredHeader(header);
|
|
24
|
+
|
|
25
|
+
console.log({
|
|
26
|
+
headerName: "PAYMENT-REQUIRED",
|
|
27
|
+
header,
|
|
28
|
+
decoded,
|
|
29
|
+
note: "Envelope-only example: no wallet, transaction, or facilitator is used.",
|
|
30
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@perkos/agent-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "TypeScript SDK for agent identity, escrow settlement, and reputation on Stacks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -29,17 +29,21 @@
|
|
|
29
29
|
"prepublishOnly": "npm run verify",
|
|
30
30
|
"prequickstart": "npm run build",
|
|
31
31
|
"quickstart": "node --import tsx examples/quickstart.ts",
|
|
32
|
+
"prequickstart:x402": "npm run build",
|
|
33
|
+
"quickstart:x402": "node --import tsx examples/x402-foundation.ts",
|
|
34
|
+
"prequickstart:x402:facilitator": "npm run build",
|
|
35
|
+
"quickstart:x402:facilitator": "node --import tsx examples/x402-facilitator.ts",
|
|
32
36
|
"prequickstart:testnet": "npm run build",
|
|
33
37
|
"quickstart:testnet": "node --import tsx examples/testnet-lifecycle.ts"
|
|
34
38
|
},
|
|
35
39
|
"repository": {
|
|
36
40
|
"type": "git",
|
|
37
|
-
"url": "git+https://github.com/PerkOS-xyz/PerkOS-Agent-SDK.git"
|
|
41
|
+
"url": "git+https://github.com/PerkOS-xyz/PerkOS-Nayori-Agent-SDK.git"
|
|
38
42
|
},
|
|
39
43
|
"bugs": {
|
|
40
|
-
"url": "https://github.com/PerkOS-xyz/PerkOS-Agent-SDK/issues"
|
|
44
|
+
"url": "https://github.com/PerkOS-xyz/PerkOS-Nayori-Agent-SDK/issues"
|
|
41
45
|
},
|
|
42
|
-
"homepage": "https://
|
|
46
|
+
"homepage": "https://nayori.ai",
|
|
43
47
|
"keywords": [
|
|
44
48
|
"ai-agents",
|
|
45
49
|
"agentic-commerce",
|
|
@@ -58,7 +62,8 @@
|
|
|
58
62
|
"node": ">=20"
|
|
59
63
|
},
|
|
60
64
|
"dependencies": {
|
|
61
|
-
"@stacks/transactions": "^7.6.0"
|
|
65
|
+
"@stacks/transactions": "^7.6.0",
|
|
66
|
+
"@x402/core": "^2.23.0"
|
|
62
67
|
},
|
|
63
68
|
"devDependencies": {
|
|
64
69
|
"@types/node": "^22.15.0",
|