@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.
- package/CHANGELOG.md +32 -0
- package/LICENSE +21 -0
- package/README.md +226 -0
- package/SECURITY.md +67 -0
- package/dist/builders.d.ts +19 -0
- package/dist/builders.d.ts.map +1 -0
- package/dist/builders.js +180 -0
- package/dist/builders.js.map +1 -0
- package/dist/clarity.d.ts +11 -0
- package/dist/clarity.d.ts.map +1 -0
- package/dist/clarity.js +80 -0
- package/dist/clarity.js.map +1 -0
- package/dist/client.d.ts +39 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +290 -0
- package/dist/client.js.map +1 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +72 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/policy.d.ts +14 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +75 -0
- package/dist/policy.js.map +1 -0
- package/dist/signers.d.ts +51 -0
- package/dist/signers.d.ts.map +1 -0
- package/dist/signers.js +145 -0
- package/dist/signers.js.map +1 -0
- package/dist/tracker.d.ts +21 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/tracker.js +175 -0
- package/dist/tracker.js.map +1 -0
- package/dist/txid.d.ts +2 -0
- package/dist/txid.d.ts.map +1 -0
- package/dist/txid.js +13 -0
- package/dist/txid.js.map +1 -0
- package/dist/types.d.ts +204 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +17 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +124 -0
- package/dist/validation.js.map +1 -0
- package/docs/ARCHITECTURE.md +111 -0
- package/examples/quickstart.ts +19 -0
- package/examples/testnet-api.ts +23 -0
- package/examples/testnet-lifecycle.ts +305 -0
- package/examples/testnet.env.example +14 -0
- package/package.json +69 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ClarityValue, PostCondition, PostConditionModeName } from "@stacks/transactions";
|
|
2
|
+
import type { ContractCallPlan, ContractId, PerkOSNetwork, PerkOSSigner, SignerResult } from "./types.js";
|
|
3
|
+
export type PrivateKeyMaterial = string | Uint8Array;
|
|
4
|
+
export type PrivateKeyProvider = () => PrivateKeyMaterial | Promise<PrivateKeyMaterial>;
|
|
5
|
+
export interface HeadlessTransactionRequest {
|
|
6
|
+
readonly plan: ContractCallPlan;
|
|
7
|
+
readonly privateKey: PrivateKeyMaterial;
|
|
8
|
+
readonly apiUrl?: string;
|
|
9
|
+
}
|
|
10
|
+
export type HeadlessTransactionExecutor = (request: HeadlessTransactionRequest) => Promise<SignerResult>;
|
|
11
|
+
export interface HeadlessSignerOptions {
|
|
12
|
+
readonly network: PerkOSNetwork;
|
|
13
|
+
readonly privateKeyProvider: PrivateKeyProvider;
|
|
14
|
+
readonly apiUrl?: string;
|
|
15
|
+
readonly transactionExecutor?: HeadlessTransactionExecutor;
|
|
16
|
+
}
|
|
17
|
+
export declare class HeadlessSigner implements PerkOSSigner {
|
|
18
|
+
private readonly network;
|
|
19
|
+
private readonly privateKeyProvider;
|
|
20
|
+
private readonly apiUrl;
|
|
21
|
+
private readonly transactionExecutor;
|
|
22
|
+
private address;
|
|
23
|
+
constructor(options: HeadlessSignerOptions);
|
|
24
|
+
getAddress(): Promise<string>;
|
|
25
|
+
signAndBroadcast(plan: ContractCallPlan): Promise<SignerResult>;
|
|
26
|
+
private withPrivateKey;
|
|
27
|
+
}
|
|
28
|
+
export interface StacksConnectContractCallParams {
|
|
29
|
+
readonly contract: ContractId;
|
|
30
|
+
readonly functionName: string;
|
|
31
|
+
readonly functionArgs: readonly ClarityValue[];
|
|
32
|
+
readonly network: PerkOSNetwork;
|
|
33
|
+
readonly postConditions: readonly PostCondition[];
|
|
34
|
+
readonly postConditionMode: PostConditionModeName;
|
|
35
|
+
readonly sponsored: boolean;
|
|
36
|
+
}
|
|
37
|
+
export type StacksConnectRequest = (method: "stx_callContract", params: StacksConnectContractCallParams) => Promise<unknown>;
|
|
38
|
+
export interface StacksConnectSignerOptions {
|
|
39
|
+
readonly network: PerkOSNetwork;
|
|
40
|
+
readonly address: string;
|
|
41
|
+
readonly request: StacksConnectRequest;
|
|
42
|
+
}
|
|
43
|
+
export declare class StacksConnectSigner implements PerkOSSigner {
|
|
44
|
+
private readonly network;
|
|
45
|
+
private readonly address;
|
|
46
|
+
private readonly request;
|
|
47
|
+
constructor(options: StacksConnectSignerOptions);
|
|
48
|
+
getAddress(): Promise<string>;
|
|
49
|
+
signAndBroadcast(plan: ContractCallPlan): Promise<SignerResult>;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=signers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signers.d.ts","sourceRoot":"","sources":["../src/signers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,YAAY,EACZ,YAAY,EACb,MAAM,YAAY,CAAC;AAOpB,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,UAAU,CAAC;AACrD,MAAM,MAAM,kBAAkB,GAAG,MAC7B,kBAAkB,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAEhC,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,2BAA2B,GAAG,CACxC,OAAO,EAAE,0BAA0B,KAChC,OAAO,CAAC,YAAY,CAAC,CAAC;AAE3B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;CAC5D;AAuCD,qBAAa,cAAe,YAAW,YAAY;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA8B;IAClE,OAAO,CAAC,OAAO,CAAqB;gBAExB,OAAO,EAAE,qBAAqB;IAgBpC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAU7B,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;YAiBvD,cAAc;CA4B7B;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,CAAC;IAClD,QAAQ,CAAC,iBAAiB,EAAE,qBAAqB,CAAC;IAClD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,oBAAoB,GAAG,CACjC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,+BAA+B,KACpC,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;CACxC;AA0BD,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;gBAEnC,OAAO,EAAE,0BAA0B;IAazC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAI7B,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,CAAC;CA2BtE"}
|
package/dist/signers.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { broadcastTransaction, getAddressFromPrivateKey, makeContractCall, } from "@stacks/transactions";
|
|
2
|
+
import { PerkOSError } from "./errors.js";
|
|
3
|
+
import { normalizeTxid } from "./txid.js";
|
|
4
|
+
import { assertPrincipal, normalizeApiUrl, parseContractId, } from "./validation.js";
|
|
5
|
+
async function defaultHeadlessExecutor(request) {
|
|
6
|
+
const { address, name } = parseContractId(request.plan.contract, "plan.contract", request.plan.network);
|
|
7
|
+
const client = request.apiUrl
|
|
8
|
+
? { client: { baseUrl: request.apiUrl } }
|
|
9
|
+
: {};
|
|
10
|
+
const transaction = await makeContractCall({
|
|
11
|
+
contractAddress: address,
|
|
12
|
+
contractName: name,
|
|
13
|
+
functionName: request.plan.functionName,
|
|
14
|
+
functionArgs: [...request.plan.functionArgs],
|
|
15
|
+
senderKey: request.privateKey,
|
|
16
|
+
network: request.plan.network,
|
|
17
|
+
postConditions: [...request.plan.postConditions],
|
|
18
|
+
postConditionMode: request.plan.postConditionMode,
|
|
19
|
+
...client,
|
|
20
|
+
});
|
|
21
|
+
const result = await broadcastTransaction({
|
|
22
|
+
transaction,
|
|
23
|
+
network: request.plan.network,
|
|
24
|
+
...client,
|
|
25
|
+
});
|
|
26
|
+
if ("error" in result) {
|
|
27
|
+
throw new PerkOSError("BROADCAST_REJECTED", `Stacks rejected the transaction: ${result.reason}.`, { raw: result, reason: result.reason });
|
|
28
|
+
}
|
|
29
|
+
return { txid: normalizeTxid(result.txid), raw: result };
|
|
30
|
+
}
|
|
31
|
+
export class HeadlessSigner {
|
|
32
|
+
network;
|
|
33
|
+
privateKeyProvider;
|
|
34
|
+
apiUrl;
|
|
35
|
+
transactionExecutor;
|
|
36
|
+
address;
|
|
37
|
+
constructor(options) {
|
|
38
|
+
if (typeof options.privateKeyProvider !== "function") {
|
|
39
|
+
throw new PerkOSError("CONFIG_INVALID", "HeadlessSigner requires a privateKeyProvider callback.");
|
|
40
|
+
}
|
|
41
|
+
this.network = options.network;
|
|
42
|
+
this.privateKeyProvider = options.privateKeyProvider;
|
|
43
|
+
this.apiUrl = options.apiUrl
|
|
44
|
+
? normalizeApiUrl(options.apiUrl, "HeadlessSigner apiUrl")
|
|
45
|
+
: undefined;
|
|
46
|
+
this.transactionExecutor =
|
|
47
|
+
options.transactionExecutor ?? defaultHeadlessExecutor;
|
|
48
|
+
}
|
|
49
|
+
async getAddress() {
|
|
50
|
+
if (this.address)
|
|
51
|
+
return this.address;
|
|
52
|
+
const address = await this.withPrivateKey((privateKey) => getAddressFromPrivateKey(privateKey, this.network));
|
|
53
|
+
assertPrincipal(address, "headless signer address", this.network);
|
|
54
|
+
this.address = address;
|
|
55
|
+
return address;
|
|
56
|
+
}
|
|
57
|
+
async signAndBroadcast(plan) {
|
|
58
|
+
if (plan.network !== this.network) {
|
|
59
|
+
throw new PerkOSError("SIGNER_MISMATCH", `HeadlessSigner is configured for ${this.network}, not ${plan.network}.`);
|
|
60
|
+
}
|
|
61
|
+
const result = await this.withPrivateKey((privateKey) => this.transactionExecutor({
|
|
62
|
+
plan,
|
|
63
|
+
privateKey,
|
|
64
|
+
...(this.apiUrl ? { apiUrl: this.apiUrl } : {}),
|
|
65
|
+
}));
|
|
66
|
+
return { ...result, txid: normalizeTxid(result.txid) };
|
|
67
|
+
}
|
|
68
|
+
async withPrivateKey(operation) {
|
|
69
|
+
let privateKey;
|
|
70
|
+
try {
|
|
71
|
+
const supplied = await this.privateKeyProvider();
|
|
72
|
+
privateKey =
|
|
73
|
+
typeof supplied === "string"
|
|
74
|
+
? supplied.trim()
|
|
75
|
+
: Uint8Array.from(supplied);
|
|
76
|
+
if (privateKey.length === 0) {
|
|
77
|
+
throw new PerkOSError("SIGNING_FAILED", "privateKeyProvider returned empty key material.");
|
|
78
|
+
}
|
|
79
|
+
return await operation(privateKey);
|
|
80
|
+
}
|
|
81
|
+
catch (cause) {
|
|
82
|
+
if (cause instanceof PerkOSError)
|
|
83
|
+
throw cause;
|
|
84
|
+
throw new PerkOSError("SIGNING_FAILED", "HeadlessSigner could not use the supplied key material.", { cause });
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
if (privateKey instanceof Uint8Array)
|
|
88
|
+
privateKey.fill(0);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function extractConnectTxid(result) {
|
|
93
|
+
if (!result || typeof result !== "object") {
|
|
94
|
+
throw new PerkOSError("BROADCAST_REJECTED", "Stacks Connect returned an invalid transaction result.", { raw: result });
|
|
95
|
+
}
|
|
96
|
+
const record = result;
|
|
97
|
+
const nested = record.result && typeof record.result === "object"
|
|
98
|
+
? record.result
|
|
99
|
+
: undefined;
|
|
100
|
+
const candidate = record.txid ?? record.txId ?? nested?.txid ?? nested?.txId;
|
|
101
|
+
if (typeof candidate !== "string") {
|
|
102
|
+
throw new PerkOSError("BROADCAST_REJECTED", "Stacks Connect did not return a transaction ID.", { raw: result });
|
|
103
|
+
}
|
|
104
|
+
return normalizeTxid(candidate);
|
|
105
|
+
}
|
|
106
|
+
export class StacksConnectSigner {
|
|
107
|
+
network;
|
|
108
|
+
address;
|
|
109
|
+
request;
|
|
110
|
+
constructor(options) {
|
|
111
|
+
assertPrincipal(options.address, "Stacks Connect address", options.network);
|
|
112
|
+
if (typeof options.request !== "function") {
|
|
113
|
+
throw new PerkOSError("CONFIG_INVALID", "StacksConnectSigner requires the Stacks Connect request function.");
|
|
114
|
+
}
|
|
115
|
+
this.network = options.network;
|
|
116
|
+
this.address = options.address;
|
|
117
|
+
this.request = options.request;
|
|
118
|
+
}
|
|
119
|
+
async getAddress() {
|
|
120
|
+
return this.address;
|
|
121
|
+
}
|
|
122
|
+
async signAndBroadcast(plan) {
|
|
123
|
+
if (plan.network !== this.network) {
|
|
124
|
+
throw new PerkOSError("SIGNER_MISMATCH", `StacksConnectSigner is configured for ${this.network}, not ${plan.network}.`);
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const result = await this.request("stx_callContract", {
|
|
128
|
+
contract: plan.contract,
|
|
129
|
+
functionName: plan.functionName,
|
|
130
|
+
functionArgs: [...plan.functionArgs],
|
|
131
|
+
network: plan.network,
|
|
132
|
+
postConditions: [...plan.postConditions],
|
|
133
|
+
postConditionMode: plan.postConditionMode,
|
|
134
|
+
sponsored: false,
|
|
135
|
+
});
|
|
136
|
+
return { txid: extractConnectTxid(result), raw: result };
|
|
137
|
+
}
|
|
138
|
+
catch (cause) {
|
|
139
|
+
if (cause instanceof PerkOSError)
|
|
140
|
+
throw cause;
|
|
141
|
+
throw new PerkOSError("SIGNING_FAILED", "Stacks Connect rejected or cancelled the contract call.", { cause, contract: plan.contract, functionName: plan.functionName });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=signers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signers.js","sourceRoot":"","sources":["../src/signers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ConfirmationOptions, PerkOSNetwork, TransactionConfirmation, TransactionTrackerLike } from "./types.js";
|
|
2
|
+
export type TrackerFetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
3
|
+
export interface TransactionTrackerOptions {
|
|
4
|
+
readonly network: PerkOSNetwork;
|
|
5
|
+
readonly apiUrl?: string;
|
|
6
|
+
readonly fetch?: TrackerFetch;
|
|
7
|
+
readonly sleep?: (milliseconds: number, signal?: AbortSignal) => Promise<void>;
|
|
8
|
+
readonly now?: () => number;
|
|
9
|
+
}
|
|
10
|
+
export declare class TransactionTracker implements TransactionTrackerLike {
|
|
11
|
+
private readonly network;
|
|
12
|
+
private readonly apiUrl;
|
|
13
|
+
private readonly fetch;
|
|
14
|
+
private readonly sleep;
|
|
15
|
+
private readonly now;
|
|
16
|
+
constructor(options: TransactionTrackerOptions);
|
|
17
|
+
getStatus(txidInput: string): Promise<TransactionConfirmation>;
|
|
18
|
+
private getExecutionResult;
|
|
19
|
+
waitForConfirmation(txidInput: string, options?: ConfirmationOptions): Promise<TransactionConfirmation>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../src/tracker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,mBAAmB,EACnB,aAAa,EACb,uBAAuB,EAGvB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAGpB,MAAM,MAAM,YAAY,GAAG,CACzB,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,IAAI,CAAC,EAAE,WAAW,KACf,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAuED,qBAAa,kBAAmB,YAAW,sBAAsB;IAC/D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAGH;IACnB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEvB,OAAO,EAAE,yBAAyB;IAWxC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;YA2EtD,kBAAkB;IAkB1B,mBAAmB,CACvB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,uBAAuB,CAAC;CAuCpC"}
|
package/dist/tracker.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { PerkOSError } from "./errors.js";
|
|
2
|
+
import { normalizeTxid } from "./txid.js";
|
|
3
|
+
import { normalizeApiUrl } from "./validation.js";
|
|
4
|
+
const DEFAULT_API_URL = {
|
|
5
|
+
mainnet: "https://api.hiro.so",
|
|
6
|
+
testnet: "https://api.testnet.hiro.so",
|
|
7
|
+
};
|
|
8
|
+
function statusFromApi(value) {
|
|
9
|
+
if (typeof value !== "string") {
|
|
10
|
+
throw new PerkOSError("CONFIRMATION_FAILED", "The transaction API returned no status.");
|
|
11
|
+
}
|
|
12
|
+
const status = value.toLowerCase();
|
|
13
|
+
if (status === "success")
|
|
14
|
+
return "success";
|
|
15
|
+
if (status === "pending" || status === "mempool")
|
|
16
|
+
return "pending";
|
|
17
|
+
if (status.startsWith("abort"))
|
|
18
|
+
return "abort";
|
|
19
|
+
if (status.startsWith("drop"))
|
|
20
|
+
return "dropped";
|
|
21
|
+
throw new PerkOSError("CONFIRMATION_FAILED", `The transaction API returned an unknown status: ${value}.`);
|
|
22
|
+
}
|
|
23
|
+
function optionalNumber(value) {
|
|
24
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
25
|
+
return undefined;
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
function optionalString(value) {
|
|
29
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
30
|
+
}
|
|
31
|
+
function resultFromApi(value) {
|
|
32
|
+
if (!value || typeof value !== "object")
|
|
33
|
+
return undefined;
|
|
34
|
+
const record = value;
|
|
35
|
+
const hex = optionalString(record.hex);
|
|
36
|
+
const repr = optionalString(record.repr);
|
|
37
|
+
if (!hex && !repr)
|
|
38
|
+
return undefined;
|
|
39
|
+
return { ...(hex ? { hex } : {}), ...(repr ? { repr } : {}) };
|
|
40
|
+
}
|
|
41
|
+
function abortError() {
|
|
42
|
+
return new PerkOSError("CONFIRMATION_FAILED", "Transaction confirmation was cancelled.");
|
|
43
|
+
}
|
|
44
|
+
async function defaultSleep(milliseconds, signal) {
|
|
45
|
+
if (signal?.aborted)
|
|
46
|
+
throw abortError();
|
|
47
|
+
await new Promise((resolve, reject) => {
|
|
48
|
+
const cleanup = () => signal?.removeEventListener("abort", onAbort);
|
|
49
|
+
const finish = () => {
|
|
50
|
+
cleanup();
|
|
51
|
+
resolve();
|
|
52
|
+
};
|
|
53
|
+
const timer = setTimeout(finish, milliseconds);
|
|
54
|
+
const onAbort = () => {
|
|
55
|
+
clearTimeout(timer);
|
|
56
|
+
cleanup();
|
|
57
|
+
reject(abortError());
|
|
58
|
+
};
|
|
59
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
export class TransactionTracker {
|
|
63
|
+
network;
|
|
64
|
+
apiUrl;
|
|
65
|
+
fetch;
|
|
66
|
+
sleep;
|
|
67
|
+
now;
|
|
68
|
+
constructor(options) {
|
|
69
|
+
this.network = options.network;
|
|
70
|
+
this.apiUrl = normalizeApiUrl(options.apiUrl ?? DEFAULT_API_URL[options.network], "TransactionTracker apiUrl");
|
|
71
|
+
this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
72
|
+
this.sleep = options.sleep ?? defaultSleep;
|
|
73
|
+
this.now = options.now ?? Date.now;
|
|
74
|
+
}
|
|
75
|
+
async getStatus(txidInput) {
|
|
76
|
+
const txid = normalizeTxid(txidInput);
|
|
77
|
+
let response;
|
|
78
|
+
try {
|
|
79
|
+
response = await this.fetch(`${this.apiUrl}/extended/v3/transactions/${encodeURIComponent(txid)}`, { headers: { accept: "application/json" } });
|
|
80
|
+
}
|
|
81
|
+
catch (cause) {
|
|
82
|
+
throw new PerkOSError("CONFIRMATION_FAILED", "Could not reach the Stacks transaction API.", { cause, txid });
|
|
83
|
+
}
|
|
84
|
+
const observedAt = new Date(this.now()).toISOString();
|
|
85
|
+
if (response.status === 404) {
|
|
86
|
+
return {
|
|
87
|
+
txid,
|
|
88
|
+
network: this.network,
|
|
89
|
+
status: "pending",
|
|
90
|
+
observedAt,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
const body = await response.text().catch(() => "");
|
|
95
|
+
throw new PerkOSError("CONFIRMATION_FAILED", `Transaction API returned HTTP ${response.status}.`, { txid, status: response.status, body: body.slice(0, 500) });
|
|
96
|
+
}
|
|
97
|
+
let raw;
|
|
98
|
+
try {
|
|
99
|
+
raw = await response.json();
|
|
100
|
+
}
|
|
101
|
+
catch (cause) {
|
|
102
|
+
throw new PerkOSError("CONFIRMATION_FAILED", "Transaction API returned invalid JSON.", { cause, txid });
|
|
103
|
+
}
|
|
104
|
+
if (!raw || typeof raw !== "object") {
|
|
105
|
+
throw new PerkOSError("CONFIRMATION_FAILED", "Transaction API returned an invalid response.", { txid, raw });
|
|
106
|
+
}
|
|
107
|
+
const record = raw;
|
|
108
|
+
const block = record.block && typeof record.block === "object"
|
|
109
|
+
? record.block
|
|
110
|
+
: undefined;
|
|
111
|
+
const status = statusFromApi(record.status ?? record.tx_status);
|
|
112
|
+
let result = resultFromApi(record.result ?? record.tx_result);
|
|
113
|
+
if (!result && status !== "pending") {
|
|
114
|
+
result = await this.getExecutionResult(txid);
|
|
115
|
+
}
|
|
116
|
+
const blockHeight = optionalNumber(block?.height ?? record.block_height);
|
|
117
|
+
const blockHash = optionalString(block?.hash ?? record.block_hash);
|
|
118
|
+
return {
|
|
119
|
+
txid,
|
|
120
|
+
network: this.network,
|
|
121
|
+
status,
|
|
122
|
+
observedAt,
|
|
123
|
+
...(blockHeight !== undefined ? { blockHeight } : {}),
|
|
124
|
+
...(blockHash ? { blockHash } : {}),
|
|
125
|
+
...(result ? { result } : {}),
|
|
126
|
+
raw,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
async getExecutionResult(txid) {
|
|
130
|
+
try {
|
|
131
|
+
const response = await this.fetch(`${this.apiUrl}/extended/v1/tx/${encodeURIComponent(txid)}`, { headers: { accept: "application/json" } });
|
|
132
|
+
if (!response.ok)
|
|
133
|
+
return undefined;
|
|
134
|
+
const raw = await response.json();
|
|
135
|
+
if (!raw || typeof raw !== "object")
|
|
136
|
+
return undefined;
|
|
137
|
+
const record = raw;
|
|
138
|
+
return resultFromApi(record.tx_result ?? record.result);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async waitForConfirmation(txidInput, options = {}) {
|
|
145
|
+
const txid = normalizeTxid(txidInput);
|
|
146
|
+
const pollIntervalMs = options.pollIntervalMs ?? 5_000;
|
|
147
|
+
const timeoutMs = options.timeoutMs ?? 10 * 60_000;
|
|
148
|
+
if (!Number.isFinite(pollIntervalMs) || pollIntervalMs < 1) {
|
|
149
|
+
throw new PerkOSError("CONFIG_INVALID", "pollIntervalMs must be at least 1 millisecond.");
|
|
150
|
+
}
|
|
151
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 1) {
|
|
152
|
+
throw new PerkOSError("CONFIG_INVALID", "timeoutMs must be at least 1 millisecond.");
|
|
153
|
+
}
|
|
154
|
+
const startedAt = this.now();
|
|
155
|
+
let last;
|
|
156
|
+
while (true) {
|
|
157
|
+
if (options.signal?.aborted)
|
|
158
|
+
throw abortError();
|
|
159
|
+
last = await this.getStatus(txid);
|
|
160
|
+
await options.onStatus?.(last);
|
|
161
|
+
if (last.status !== "pending")
|
|
162
|
+
return last;
|
|
163
|
+
const elapsed = this.now() - startedAt;
|
|
164
|
+
if (elapsed >= timeoutMs) {
|
|
165
|
+
return {
|
|
166
|
+
...last,
|
|
167
|
+
status: "timeout",
|
|
168
|
+
observedAt: new Date(this.now()).toISOString(),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
await this.sleep(Math.min(pollIntervalMs, Math.max(1, timeoutMs - elapsed)), options.signal);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.js","sourceRoot":"","sources":["../src/tracker.ts"],"names":[],"mappings":"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"}
|
package/dist/txid.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txid.d.ts","sourceRoot":"","sources":["../src/txid.ts"],"names":[],"mappings":"AAIA,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiBnD"}
|
package/dist/txid.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PerkOSError } from "./errors.js";
|
|
2
|
+
const TXID = /^[0-9a-f]{64}$/i;
|
|
3
|
+
export function normalizeTxid(value) {
|
|
4
|
+
if (typeof value !== "string") {
|
|
5
|
+
throw new PerkOSError("BROADCAST_REJECTED", "The signer returned no Stacks transaction ID.", { txid: value });
|
|
6
|
+
}
|
|
7
|
+
const hex = value.trim().replace(/^0x/i, "");
|
|
8
|
+
if (!TXID.test(hex)) {
|
|
9
|
+
throw new PerkOSError("BROADCAST_REJECTED", "The signer returned an invalid Stacks transaction ID.", { txid: value });
|
|
10
|
+
}
|
|
11
|
+
return `0x${hex.toLowerCase()}`;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=txid.js.map
|
package/dist/txid.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"txid.js","sourceRoot":"","sources":["../src/txid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,IAAI,GAAG,iBAAiB,CAAC;AAE/B,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,WAAW,CACnB,oBAAoB,EACpB,+CAA+C,EAC/C,EAAE,IAAI,EAAE,KAAK,EAAE,CAChB,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,WAAW,CACnB,oBAAoB,EACpB,uDAAuD,EACvD,EAAE,IAAI,EAAE,KAAK,EAAE,CAChB,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;AAClC,CAAC"}
|