@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.
@@ -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.1.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://stacks.perkos.xyz",
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",