@perkos/agent-sdk 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.
Files changed (58) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/LICENSE +21 -0
  3. package/README.md +226 -0
  4. package/SECURITY.md +67 -0
  5. package/dist/builders.d.ts +19 -0
  6. package/dist/builders.d.ts.map +1 -0
  7. package/dist/builders.js +180 -0
  8. package/dist/builders.js.map +1 -0
  9. package/dist/clarity.d.ts +11 -0
  10. package/dist/clarity.d.ts.map +1 -0
  11. package/dist/clarity.js +80 -0
  12. package/dist/clarity.js.map +1 -0
  13. package/dist/client.d.ts +39 -0
  14. package/dist/client.d.ts.map +1 -0
  15. package/dist/client.js +290 -0
  16. package/dist/client.js.map +1 -0
  17. package/dist/constants.d.ts +12 -0
  18. package/dist/constants.d.ts.map +1 -0
  19. package/dist/constants.js +72 -0
  20. package/dist/constants.js.map +1 -0
  21. package/dist/errors.d.ts +14 -0
  22. package/dist/errors.d.ts.map +1 -0
  23. package/dist/errors.js +11 -0
  24. package/dist/errors.js.map +1 -0
  25. package/dist/index.d.ts +14 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +10 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/policy.d.ts +14 -0
  30. package/dist/policy.d.ts.map +1 -0
  31. package/dist/policy.js +75 -0
  32. package/dist/policy.js.map +1 -0
  33. package/dist/signers.d.ts +51 -0
  34. package/dist/signers.d.ts.map +1 -0
  35. package/dist/signers.js +145 -0
  36. package/dist/signers.js.map +1 -0
  37. package/dist/tracker.d.ts +21 -0
  38. package/dist/tracker.d.ts.map +1 -0
  39. package/dist/tracker.js +175 -0
  40. package/dist/tracker.js.map +1 -0
  41. package/dist/txid.d.ts +2 -0
  42. package/dist/txid.d.ts.map +1 -0
  43. package/dist/txid.js +13 -0
  44. package/dist/txid.js.map +1 -0
  45. package/dist/types.d.ts +204 -0
  46. package/dist/types.d.ts.map +1 -0
  47. package/dist/types.js +2 -0
  48. package/dist/types.js.map +1 -0
  49. package/dist/validation.d.ts +17 -0
  50. package/dist/validation.d.ts.map +1 -0
  51. package/dist/validation.js +124 -0
  52. package/dist/validation.js.map +1 -0
  53. package/docs/ARCHITECTURE.md +111 -0
  54. package/examples/quickstart.ts +19 -0
  55. package/examples/testnet-api.ts +23 -0
  56. package/examples/testnet-lifecycle.ts +305 -0
  57. package/examples/testnet.env.example +14 -0
  58. package/package.json +69 -0
@@ -0,0 +1,204 @@
1
+ import type { ClarityValue, ContractIdString, PostCondition, PostConditionModeName } from "@stacks/transactions";
2
+ export type PerkOSNetwork = "mainnet" | "testnet";
3
+ export type PaymentAsset = "sbtc" | "stx";
4
+ export type ContractId = ContractIdString;
5
+ export type Amount = bigint;
6
+ export type AmountLike = bigint | number | string;
7
+ export interface PerkOSContracts {
8
+ readonly agentRegistry: ContractId;
9
+ readonly stxCommerce: ContractId;
10
+ readonly sbtcCommerce: ContractId;
11
+ readonly reputationRegistry: ContractId;
12
+ readonly sbtcToken: ContractId;
13
+ readonly sbtcAssetName: string;
14
+ }
15
+ export interface PerkOSConfig {
16
+ readonly network: PerkOSNetwork;
17
+ readonly apiUrl?: string;
18
+ readonly contracts?: Partial<PerkOSContracts>;
19
+ readonly signer?: PerkOSSigner;
20
+ readonly spendingPolicy?: SpendingPolicyInput;
21
+ readonly readOnlyTransport?: ReadOnlyTransport;
22
+ readonly transactionTracker?: TransactionTrackerLike;
23
+ }
24
+ export interface ResolvedPerkOSConfig {
25
+ readonly network: PerkOSNetwork;
26
+ readonly apiUrl?: string;
27
+ readonly contracts: PerkOSContracts;
28
+ }
29
+ export interface AgentEndpoint {
30
+ readonly name: string;
31
+ readonly url: string;
32
+ }
33
+ export interface AgentRecord {
34
+ readonly id: bigint;
35
+ readonly name: string;
36
+ readonly description: string;
37
+ readonly creator: string;
38
+ readonly wallet: string;
39
+ readonly active: boolean;
40
+ readonly endpoints: readonly AgentEndpoint[];
41
+ }
42
+ export type JobStatus = "open" | "funded" | "submitted" | "completed" | "rejected" | "expired";
43
+ export interface JobRecord {
44
+ readonly id: bigint;
45
+ readonly asset: PaymentAsset;
46
+ readonly client: string;
47
+ readonly provider?: string;
48
+ readonly evaluator: string;
49
+ readonly description: string;
50
+ readonly budget: bigint;
51
+ readonly expiredAt: bigint;
52
+ readonly status: JobStatus;
53
+ readonly statusCode: bigint;
54
+ readonly deliverable?: string;
55
+ }
56
+ export interface ReputationRecord {
57
+ readonly agent: string;
58
+ readonly totalScore: bigint;
59
+ readonly ratingCount: bigint;
60
+ readonly averageScoreX100: bigint;
61
+ readonly completedJobs: bigint;
62
+ readonly disputedJobs: bigint;
63
+ }
64
+ export type PerkOSOperation = "register-agent" | "update-agent" | "deactivate-agent" | "create-job" | "set-budget" | "fund-job" | "assign-provider" | "submit-work" | "complete-job" | "reject-job" | "expire-job" | "rate-provider";
65
+ export interface TransactionIntent {
66
+ readonly operation: PerkOSOperation;
67
+ readonly asset?: PaymentAsset;
68
+ readonly amount?: bigint;
69
+ readonly jobId?: bigint;
70
+ readonly sender?: string;
71
+ readonly recipient?: string;
72
+ }
73
+ export interface ContractCallPlan {
74
+ readonly type: "contract-call";
75
+ readonly network: PerkOSNetwork;
76
+ readonly contract: ContractId;
77
+ readonly functionName: string;
78
+ readonly functionArgs: readonly ClarityValue[];
79
+ readonly postConditions: readonly PostCondition[];
80
+ readonly postConditionMode: PostConditionModeName;
81
+ readonly intent: TransactionIntent;
82
+ }
83
+ export interface SignerResult {
84
+ readonly txid: string;
85
+ readonly raw?: unknown;
86
+ }
87
+ export interface PerkOSSigner {
88
+ getAddress(): Promise<string>;
89
+ signAndBroadcast(plan: ContractCallPlan): Promise<SignerResult>;
90
+ }
91
+ export interface TransactionReceipt {
92
+ readonly txid: string;
93
+ readonly status: "broadcast";
94
+ readonly network: PerkOSNetwork;
95
+ readonly contract: ContractId;
96
+ readonly operation: PerkOSOperation;
97
+ readonly asset?: PaymentAsset;
98
+ readonly amount?: bigint;
99
+ readonly jobId?: bigint;
100
+ readonly explorerUrl: string;
101
+ readonly raw?: unknown;
102
+ }
103
+ export type TransactionConfirmationStatus = "pending" | "success" | "abort" | "dropped" | "timeout";
104
+ export interface TransactionResultValue {
105
+ readonly hex?: string;
106
+ readonly repr?: string;
107
+ }
108
+ export interface TransactionConfirmation {
109
+ readonly txid: string;
110
+ readonly network: PerkOSNetwork;
111
+ readonly status: TransactionConfirmationStatus;
112
+ readonly observedAt: string;
113
+ readonly blockHeight?: number;
114
+ readonly blockHash?: string;
115
+ readonly result?: TransactionResultValue;
116
+ readonly raw?: unknown;
117
+ }
118
+ export interface ConfirmationOptions {
119
+ readonly pollIntervalMs?: number;
120
+ readonly timeoutMs?: number;
121
+ readonly signal?: AbortSignal;
122
+ readonly onStatus?: (confirmation: TransactionConfirmation) => void | Promise<void>;
123
+ }
124
+ export interface TransactionTrackerLike {
125
+ getStatus(txid: string): Promise<TransactionConfirmation>;
126
+ waitForConfirmation(txid: string, options?: ConfirmationOptions): Promise<TransactionConfirmation>;
127
+ }
128
+ export interface ConfirmedTransactionReceipt {
129
+ readonly broadcast: TransactionReceipt;
130
+ readonly confirmation: TransactionConfirmation;
131
+ }
132
+ export interface ReadOnlyCall {
133
+ readonly network: PerkOSNetwork;
134
+ readonly apiUrl?: string;
135
+ readonly contract: ContractId;
136
+ readonly functionName: string;
137
+ readonly functionArgs: readonly ClarityValue[];
138
+ readonly senderAddress: string;
139
+ }
140
+ export type ReadOnlyTransport = (call: ReadOnlyCall) => Promise<ClarityValue>;
141
+ export interface SpendingPolicyInput {
142
+ readonly allowedNetworks?: readonly PerkOSNetwork[];
143
+ readonly allowedContracts?: readonly ContractId[];
144
+ readonly allowedAssets?: readonly PaymentAsset[];
145
+ readonly maxPerTransaction?: Partial<Record<PaymentAsset, AmountLike>>;
146
+ readonly maxPerSession?: Partial<Record<PaymentAsset, AmountLike>>;
147
+ }
148
+ export interface SpendingApproval {
149
+ readonly operation: PerkOSOperation;
150
+ readonly asset?: PaymentAsset;
151
+ readonly amount?: bigint;
152
+ readonly spentThisSession?: bigint;
153
+ readonly remainingThisSession?: bigint;
154
+ }
155
+ export interface RegisterAgentInput {
156
+ readonly name: string;
157
+ readonly description: string;
158
+ readonly wallet: string;
159
+ readonly endpoints?: readonly AgentEndpoint[];
160
+ }
161
+ export interface UpdateAgentInput {
162
+ readonly agentId: AmountLike;
163
+ readonly name?: string;
164
+ readonly description?: string;
165
+ readonly wallet?: string;
166
+ }
167
+ export interface CreateJobInput {
168
+ readonly asset: PaymentAsset;
169
+ readonly provider?: string;
170
+ readonly evaluator: string;
171
+ readonly expiredAt: AmountLike;
172
+ readonly description: string;
173
+ }
174
+ export interface JobAmountInput {
175
+ readonly asset: PaymentAsset;
176
+ readonly jobId: AmountLike;
177
+ readonly amount: AmountLike;
178
+ }
179
+ export interface FundJobInput extends JobAmountInput {
180
+ readonly sender?: string;
181
+ }
182
+ export interface AssignProviderInput {
183
+ readonly asset: PaymentAsset;
184
+ readonly jobId: AmountLike;
185
+ readonly provider: string;
186
+ }
187
+ export interface SubmitWorkInput {
188
+ readonly asset: PaymentAsset;
189
+ readonly jobId: AmountLike;
190
+ readonly deliverable: string | Uint8Array;
191
+ }
192
+ export interface SettleJobInput {
193
+ readonly asset: PaymentAsset;
194
+ readonly jobId: AmountLike;
195
+ readonly amount: AmountLike;
196
+ readonly recipient: string;
197
+ }
198
+ export interface RateProviderInput {
199
+ readonly asset: PaymentAsset;
200
+ readonly jobId: AmountLike;
201
+ readonly score: AmountLike;
202
+ readonly comment: string;
203
+ }
204
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import type { AmountLike, ContractId, PerkOSContracts, PerkOSNetwork, ResolvedPerkOSConfig } from "./types.js";
2
+ export declare function toUint(value: AmountLike, field: string, allowZero?: boolean): bigint;
3
+ export declare function assertAscii(value: string, field: string, maxBytes: number, allowEmpty?: boolean): void;
4
+ export declare function assertPrincipal(principal: string, field: string, network?: PerkOSNetwork): void;
5
+ export declare function parseContractId(contract: string, field: string, network?: PerkOSNetwork): {
6
+ address: string;
7
+ name: string;
8
+ };
9
+ export declare function principalMatchesNetwork(principal: string, network: PerkOSNetwork): boolean;
10
+ export declare function normalizeApiUrl(value: string, field?: string): string;
11
+ export declare function resolveConfig(input: {
12
+ network: PerkOSNetwork;
13
+ apiUrl?: string;
14
+ contracts?: Partial<PerkOSContracts>;
15
+ }): ResolvedPerkOSConfig;
16
+ export declare function asContractId(value: string): ContractId;
17
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,eAAe,EACf,aAAa,EACb,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAKpB,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,MAAM,CAyBlF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,IAAI,CAepG;AAED,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,aAAa,GACtB,IAAI,CAcN;AAED,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,aAAa,GACtB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAuBnC;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAI1F;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAW,GAAG,MAAM,CAcvE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;CACtC,GAAG,oBAAoB,CA4BvB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAEtD"}
@@ -0,0 +1,124 @@
1
+ import { validateStacksAddress } from "@stacks/transactions";
2
+ import { PerkOSError } from "./errors.js";
3
+ import { DEFAULT_DEPLOYMENTS } from "./constants.js";
4
+ const CONTRACT_NAME = /^[a-z][a-z0-9-]{0,39}$/;
5
+ export function toUint(value, field, allowZero = false) {
6
+ let parsed;
7
+ try {
8
+ if (typeof value === "number" && (!Number.isSafeInteger(value) || value < 0)) {
9
+ throw new Error("number must be a non-negative safe integer");
10
+ }
11
+ if (typeof value === "string" && !/^\d+$/.test(value)) {
12
+ throw new Error("string must contain only decimal digits");
13
+ }
14
+ parsed = BigInt(value);
15
+ }
16
+ catch (cause) {
17
+ throw new PerkOSError("INPUT_INVALID", `${field} must be an unsigned integer.`, {
18
+ field,
19
+ value,
20
+ cause,
21
+ });
22
+ }
23
+ if (parsed < 0n || (!allowZero && parsed === 0n)) {
24
+ throw new PerkOSError("INPUT_INVALID", `${field} must be ${allowZero ? "zero or greater" : "greater than zero"}.`, { field, value });
25
+ }
26
+ return parsed;
27
+ }
28
+ export function assertAscii(value, field, maxBytes, allowEmpty = false) {
29
+ if ((!allowEmpty && value.length === 0) || value.length > maxBytes) {
30
+ throw new PerkOSError("INPUT_INVALID", `${field} must be ${allowEmpty ? "at most" : "between 1 and"} ${maxBytes} ASCII bytes.`, { field, maxBytes });
31
+ }
32
+ for (const character of value) {
33
+ if (character.codePointAt(0) > 0x7f) {
34
+ throw new PerkOSError("INPUT_INVALID", `${field} must contain ASCII characters only.`, {
35
+ field,
36
+ });
37
+ }
38
+ }
39
+ }
40
+ export function assertPrincipal(principal, field, network) {
41
+ if (!validateStacksAddress(principal)) {
42
+ throw new PerkOSError("INPUT_INVALID", `${field} is not a valid Stacks principal.`, {
43
+ field,
44
+ principal,
45
+ });
46
+ }
47
+ if (network && !principalMatchesNetwork(principal, network)) {
48
+ throw new PerkOSError("INPUT_INVALID", `${field} does not belong to Stacks ${network}.`, { field, principal, network });
49
+ }
50
+ }
51
+ export function parseContractId(contract, field, network) {
52
+ const pieces = contract.split(".");
53
+ if (pieces.length !== 2) {
54
+ throw new PerkOSError("CONFIG_INVALID", `${field} must use <address>.<contract-name>.`, {
55
+ field,
56
+ contract,
57
+ });
58
+ }
59
+ const [address, name] = pieces;
60
+ if (!address || !name || !validateStacksAddress(address) || !CONTRACT_NAME.test(name)) {
61
+ throw new PerkOSError("CONFIG_INVALID", `${field} is not a valid contract identifier.`, {
62
+ field,
63
+ contract,
64
+ });
65
+ }
66
+ if (network && !principalMatchesNetwork(address, network)) {
67
+ throw new PerkOSError("CONFIG_INVALID", `${field} does not belong to Stacks ${network}.`, {
68
+ field,
69
+ contract,
70
+ network,
71
+ });
72
+ }
73
+ return { address, name };
74
+ }
75
+ export function principalMatchesNetwork(principal, network) {
76
+ return network === "mainnet"
77
+ ? principal.startsWith("SP") || principal.startsWith("SM")
78
+ : principal.startsWith("ST") || principal.startsWith("SN");
79
+ }
80
+ export function normalizeApiUrl(value, field = "apiUrl") {
81
+ const normalized = value.trim();
82
+ let parsed;
83
+ try {
84
+ parsed = new URL(normalized);
85
+ }
86
+ catch (cause) {
87
+ throw new PerkOSError("CONFIG_INVALID", `${field} must be a valid URL.`, {
88
+ cause,
89
+ });
90
+ }
91
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
92
+ throw new PerkOSError("CONFIG_INVALID", `${field} must use HTTP or HTTPS.`);
93
+ }
94
+ return normalized.replace(/\/+$/, "");
95
+ }
96
+ export function resolveConfig(input) {
97
+ if (input.network !== "mainnet" && input.network !== "testnet") {
98
+ throw new PerkOSError("CONFIG_INVALID", 'network must be "mainnet" or "testnet".');
99
+ }
100
+ const apiUrl = input.apiUrl ? normalizeApiUrl(input.apiUrl) : undefined;
101
+ const contracts = {
102
+ ...DEFAULT_DEPLOYMENTS[input.network],
103
+ ...input.contracts,
104
+ };
105
+ for (const field of [
106
+ "agentRegistry",
107
+ "stxCommerce",
108
+ "sbtcCommerce",
109
+ "reputationRegistry",
110
+ "sbtcToken",
111
+ ]) {
112
+ parseContractId(contracts[field], `contracts.${field}`, input.network);
113
+ }
114
+ assertAscii(contracts.sbtcAssetName, "contracts.sbtcAssetName", 128);
115
+ return {
116
+ network: input.network,
117
+ ...(apiUrl ? { apiUrl } : {}),
118
+ contracts,
119
+ };
120
+ }
121
+ export function asContractId(value) {
122
+ return value;
123
+ }
124
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ # Architecture
2
+
3
+ ## Scope
4
+
5
+ The SDK is a typed boundary between agent frameworks and the existing PerkOS contracts. The core
6
+ package contains no LLM, HTTP-paywall, MCP server, wallet extension, or private-key store. Those
7
+ systems integrate through explicit interfaces so that transaction policy remains reusable and
8
+ auditable.
9
+
10
+ ## Flow
11
+
12
+ ```text
13
+ Agent or application
14
+ |
15
+ v
16
+ PerkOSClient ---- read-only transport ---- Stacks API
17
+ |
18
+ +---- PerkOSTransactionBuilder
19
+ | |
20
+ | v
21
+ | ContractCallPlan
22
+ | |
23
+ +---- SpendingPolicy
24
+ | |
25
+ | v
26
+ | StacksConnectSigner ---- browser wallet
27
+ | or
28
+ | HeadlessSigner ------ external key provider
29
+ | |
30
+ | v
31
+ | Stacks transaction broadcast
32
+ |
33
+ +---- TransactionTracker ---- Stacks API v3
34
+ |
35
+ v
36
+ normalized confirmation
37
+ ```
38
+
39
+ ## Read path
40
+
41
+ `PerkOSClient` resolves a known deployment or validated override and invokes a replaceable
42
+ read-only transport. Responses are decoded from Clarity values into records that use `bigint` for
43
+ all on-chain integers. Known missing-record errors return `null`; malformed responses and other
44
+ contract errors remain explicit.
45
+
46
+ ## Write path
47
+
48
+ Builders produce a `ContractCallPlan` containing:
49
+
50
+ - the selected network and exact contract ID;
51
+ - function name and serialized Clarity arguments;
52
+ - post-condition mode and post-conditions;
53
+ - semantic intent such as operation, asset, job ID, sender, recipient, and amount.
54
+
55
+ Plans are inert. `execute` checks the plan against `SpendingPolicy` before invoking the signer.
56
+ The SDK only records session spend after the signer returns a valid Stacks transaction ID.
57
+ The high-level `fundJob` helper also validates its amount and funding limits before requesting a
58
+ signer address, so a denied spend does not cause headless key-provider access.
59
+
60
+ ## Signer adapters
61
+
62
+ `StacksConnectSigner` is an injected adapter around the Stacks Connect `stx_callContract` request.
63
+ The host application owns wallet discovery, account selection, and the user approval surface. The
64
+ adapter forwards the contract, function, arguments, network, and post-conditions without receiving
65
+ a private key.
66
+
67
+ `HeadlessSigner` uses `makeContractCall` and `broadcastTransaction`. It obtains key material from an
68
+ application callback at the last responsible moment, caches only the public address, and clears its
69
+ local `Uint8Array` copy after use. The callback is the integration point for a secret manager, HSM,
70
+ KMS, or isolated signing service. It is intentionally not an environment-variable loader or key
71
+ store.
72
+
73
+ Both adapters reject plans from a network other than the network fixed at construction.
74
+
75
+ ## Confirmation path
76
+
77
+ `TransactionTracker` queries the Hiro Stacks API v3 transaction endpoint and maps API states into
78
+ `pending`, `success`, `abort`, `dropped`, or `timeout`. A not-yet-indexed transaction is pending,
79
+ not failed. Waiting is bounded, cancellable, and emits status observations through an optional
80
+ callback. Because the v3 endpoint may return `result: null` for successful contract calls, terminal
81
+ receipts make a best-effort transaction-detail lookup to hydrate the Clarity result without
82
+ replacing v3 as the status and block-metadata source.
83
+
84
+ `PerkOSClient.executeAndConfirm` keeps broadcast information and confirmation evidence separate in
85
+ one receipt. API-reported success is evidence of transaction execution, but applications may still
86
+ require additional confirmations before treating high-value settlement as irreversible.
87
+
88
+ ## Asset adapters
89
+
90
+ STX and sBTC share the same public job lifecycle but have different contract signatures and
91
+ post-conditions:
92
+
93
+ - STX funding calls `fund-job(job-id)` and constrains micro-STX.
94
+ - sBTC funding calls `fund-job(job-id, token)` and constrains the canonical SIP-010 asset.
95
+ - sBTC settlement functions also receive the configured token trait argument.
96
+
97
+ This difference stays inside the builder so frameworks do not duplicate asset-specific Clarity
98
+ logic.
99
+
100
+ ## Settlement safety
101
+
102
+ Completion, rejection, and expiry may transfer funds held by the escrow contract rather than by
103
+ the transaction origin. High-level client methods read the current job and escrow balance before
104
+ building the plan. The resulting post-condition identifies the escrow contract principal and the
105
+ exact amount expected to leave it.
106
+
107
+ ## Future adapters
108
+
109
+ - x402 v2 resource-server and client adapters.
110
+ - MCP tools with typed inputs, allowlists, and the same spending policy.
111
+ - Optional framework-specific integrations and higher-confirmation settlement policies.
@@ -0,0 +1,19 @@
1
+ import { PerkOSClient } from "@perkos/agent-sdk";
2
+
3
+ const network = process.env.PERKOS_NETWORK === "testnet" ? "testnet" : "mainnet";
4
+ const client = new PerkOSClient({ network });
5
+
6
+ const [agents, stxJobs, sbtcJobs, configuredSbtc] = await Promise.all([
7
+ client.getAgentCount(),
8
+ client.getJobCount("stx"),
9
+ client.getJobCount("sbtc"),
10
+ client.getConfiguredSbtcToken(),
11
+ ]);
12
+
13
+ console.log({
14
+ network,
15
+ agents: agents.toString(),
16
+ stxJobs: stxJobs.toString(),
17
+ sbtcJobs: sbtcJobs.toString(),
18
+ configuredSbtc,
19
+ });
@@ -0,0 +1,23 @@
1
+ export type ExampleFetch = (
2
+ input: string | URL | Request,
3
+ init?: RequestInit
4
+ ) => Promise<Response>;
5
+
6
+ export async function fetchChainTip(
7
+ apiUrl: string,
8
+ fetchImpl: ExampleFetch = globalThis.fetch.bind(globalThis)
9
+ ): Promise<bigint> {
10
+ const response = await fetchImpl(`${apiUrl.replace(/\/+$/, "")}/v2/info`, {
11
+ headers: { accept: "application/json" },
12
+ });
13
+ if (!response.ok) throw new Error(`Stacks API returned HTTP ${response.status}.`);
14
+ const body: unknown = await response.json();
15
+ if (!body || typeof body !== "object") {
16
+ throw new Error("Invalid Stacks API info response.");
17
+ }
18
+ const height = (body as Record<string, unknown>).stacks_tip_height;
19
+ if (typeof height !== "number" || !Number.isSafeInteger(height) || height < 0) {
20
+ throw new Error("Stacks API did not return a valid stacks_tip_height.");
21
+ }
22
+ return BigInt(height);
23
+ }