paytaca-cli 0.2.0 → 0.3.1

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 (41) hide show
  1. package/README.md +63 -2
  2. package/dist/commands/check.d.ts +14 -0
  3. package/dist/commands/check.d.ts.map +1 -0
  4. package/dist/commands/check.js +162 -0
  5. package/dist/commands/check.js.map +1 -0
  6. package/dist/commands/claude.d.ts +9 -0
  7. package/dist/commands/claude.d.ts.map +1 -0
  8. package/dist/commands/claude.js +20 -0
  9. package/dist/commands/claude.js.map +1 -0
  10. package/dist/commands/opencode.d.ts +9 -0
  11. package/dist/commands/opencode.d.ts.map +1 -0
  12. package/dist/commands/opencode.js +20 -0
  13. package/dist/commands/opencode.js.map +1 -0
  14. package/dist/commands/pay.d.ts +17 -0
  15. package/dist/commands/pay.d.ts.map +1 -0
  16. package/dist/commands/pay.js +350 -0
  17. package/dist/commands/pay.js.map +1 -0
  18. package/dist/index.js +8 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/types/x402.d.ts +72 -0
  21. package/dist/types/x402.d.ts.map +1 -0
  22. package/dist/types/x402.js +9 -0
  23. package/dist/types/x402.js.map +1 -0
  24. package/dist/utils/skill.d.ts +17 -0
  25. package/dist/utils/skill.d.ts.map +1 -0
  26. package/dist/utils/skill.js +100 -0
  27. package/dist/utils/skill.js.map +1 -0
  28. package/dist/utils/x402.d.ts +17 -0
  29. package/dist/utils/x402.d.ts.map +1 -0
  30. package/dist/utils/x402.js +119 -0
  31. package/dist/utils/x402.js.map +1 -0
  32. package/dist/utils/x402.test.d.ts +2 -0
  33. package/dist/utils/x402.test.d.ts.map +1 -0
  34. package/dist/utils/x402.test.js +216 -0
  35. package/dist/utils/x402.test.js.map +1 -0
  36. package/dist/wallet/x402.d.ts +29 -0
  37. package/dist/wallet/x402.d.ts.map +1 -0
  38. package/dist/wallet/x402.js +45 -0
  39. package/dist/wallet/x402.js.map +1 -0
  40. package/package.json +7 -2
  41. package/skills/paytaca/SKILL.md +130 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402.d.ts","sourceRoot":"","sources":["../../src/utils/x402.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,aAAa,EAEb,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,YAAY,EAAE,CAAA;AAEjE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,GAAG,GAAG,eAAe,GAAG,IAAI,CA6B1E;AAED,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,eAAe,EAC7B,aAAa,EAAE,SAAS,GAAG,SAAS,GACnC,mBAAmB,GAAG,IAAI,CAQ5B;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,mBAAmB,EAC7B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,cAAc,CAwBhB;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,mBAAmB,EAC7B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,aAAa,CASf;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,UAAU,GAAE,OAAc,GACzB,MAAM,CAUR;AAED,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAChD,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,GAAG,GAAG,cAAc,CAiB9D"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * x402 utility functions for BCH payments
3
+ * Implements x402-bch v2.2 specification
4
+ * https://github.com/x402-bch/x402-bch/blob/master/specs/x402-bch-specification-v2.2.md
5
+ */
6
+ import crypto from 'crypto';
7
+ import { BCH_ASSET_ID, BCH_MAINNET_NETWORK, BCH_CHIPNET_NETWORK, } from '../types/x402.js';
8
+ import { secp256k1 } from '@bitauth/libauth';
9
+ export { BCH_MAINNET_NETWORK, BCH_CHIPNET_NETWORK, BCH_ASSET_ID };
10
+ export function isBchNetwork(network) {
11
+ return network === BCH_MAINNET_NETWORK || network === BCH_CHIPNET_NETWORK;
12
+ }
13
+ export function isChipnetNetwork(network) {
14
+ return network === BCH_CHIPNET_NETWORK;
15
+ }
16
+ export function parsePaymentRequiredJson(body) {
17
+ if (!body || typeof body !== 'object')
18
+ return null;
19
+ if (body.x402Version !== 2)
20
+ return null;
21
+ const pr = {
22
+ x402Version: body.x402Version,
23
+ error: body.error,
24
+ resource: body.resource || { url: '' },
25
+ accepts: [],
26
+ extensions: body.extensions || {},
27
+ };
28
+ if (Array.isArray(body.accepts)) {
29
+ for (const accept of body.accepts) {
30
+ if (accept.scheme && accept.network && accept.payTo) {
31
+ pr.accepts.push({
32
+ scheme: accept.scheme,
33
+ network: accept.network,
34
+ amount: accept.amount,
35
+ asset: accept.asset || BCH_ASSET_ID,
36
+ payTo: accept.payTo,
37
+ maxTimeoutSeconds: accept.maxTimeoutSeconds || 60,
38
+ extra: accept.extra || {},
39
+ });
40
+ }
41
+ }
42
+ }
43
+ return pr;
44
+ }
45
+ export function selectBchPaymentRequirements(requirements, clientNetwork) {
46
+ const clientNetworkId = clientNetwork === 'chipnet' ? BCH_CHIPNET_NETWORK : BCH_MAINNET_NETWORK;
47
+ for (const accept of requirements.accepts) {
48
+ if (accept.scheme === 'utxo' && accept.network === clientNetworkId) {
49
+ return accept;
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+ export function buildPaymentPayload(accepted, resourceUrl, payer, txid, vout, amount) {
55
+ const resource = {
56
+ url: resourceUrl,
57
+ description: '',
58
+ mimeType: 'application/json',
59
+ };
60
+ return {
61
+ x402Version: 2,
62
+ resource,
63
+ accepted,
64
+ payload: {
65
+ signature: '',
66
+ authorization: {
67
+ from: payer,
68
+ to: accepted.payTo,
69
+ value: accepted.amount,
70
+ txid,
71
+ vout,
72
+ amount,
73
+ },
74
+ },
75
+ extensions: {},
76
+ };
77
+ }
78
+ export function buildAuthorization(accepted, resourceUrl, payer, txid, vout, amount) {
79
+ return {
80
+ from: payer,
81
+ to: accepted.payTo,
82
+ value: accepted.amount,
83
+ txid,
84
+ vout,
85
+ amount,
86
+ };
87
+ }
88
+ export function signMessageBCH(message, privateKeyHex, compressed = true) {
89
+ const prefix = '\x18Bitcoin Signed Message:\n';
90
+ const messageBytes = Buffer.from(message, 'utf8');
91
+ const prefixBytes = Buffer.from(prefix, 'utf8');
92
+ const lengthByte = Buffer.from([messageBytes.length]);
93
+ const prefixedMessage = Buffer.concat([prefixBytes, lengthByte, messageBytes]);
94
+ const hash = crypto.createHash('sha256').update(crypto.createHash('sha256').update(prefixedMessage).digest()).digest();
95
+ const privateKey = Buffer.from(privateKeyHex, 'hex');
96
+ const signature = secp256k1.signMessageHashDER(hash, privateKey);
97
+ return Buffer.from(signature).toString('base64');
98
+ }
99
+ export async function signAuthorization(authorization, signMessage) {
100
+ const message = JSON.stringify(authorization);
101
+ return signMessage(message);
102
+ }
103
+ export function parsePaymentResponse(data) {
104
+ if (!data)
105
+ return { isValid: false, invalidReason: 'no_response_data' };
106
+ if (typeof data.isValid === 'boolean') {
107
+ return {
108
+ isValid: data.isValid,
109
+ payer: data.payer,
110
+ invalidReason: data.invalidReason,
111
+ remainingBalanceSat: data.remainingBalanceSat,
112
+ };
113
+ }
114
+ if (data.error) {
115
+ return { isValid: false, invalidReason: data.error };
116
+ }
117
+ return { isValid: false, invalidReason: 'unknown_response_format' };
118
+ }
119
+ //# sourceMappingURL=x402.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402.js","sourceRoot":"","sources":["../../src/utils/x402.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=x402.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402.test.d.ts","sourceRoot":"","sources":["../../src/utils/x402.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,216 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { parsePaymentRequiredJson, selectBchPaymentRequirements, buildPaymentPayload, buildAuthorization, parsePaymentResponse, isBchNetwork, isChipnetNetwork, BCH_MAINNET_NETWORK, BCH_CHIPNET_NETWORK, BCH_ASSET_ID, } from './x402.js';
3
+ describe('x402 parsing', () => {
4
+ describe('parsePaymentRequiredJson', () => {
5
+ it('should parse valid PaymentRequired JSON', () => {
6
+ const input = {
7
+ x402Version: 2,
8
+ error: 'Payment required',
9
+ resource: { url: 'https://api.example.com/data' },
10
+ accepts: [
11
+ {
12
+ scheme: 'utxo',
13
+ network: BCH_MAINNET_NETWORK,
14
+ amount: '1000',
15
+ asset: BCH_ASSET_ID,
16
+ payTo: 'bitcoincash:qp2f5j6q3fj5gjwgk8rkq8xrk8q8q8q8q8q8q8q8q',
17
+ maxTimeoutSeconds: 300,
18
+ extra: {},
19
+ },
20
+ ],
21
+ extensions: {},
22
+ };
23
+ const result = parsePaymentRequiredJson(input);
24
+ expect(result).not.toBeNull();
25
+ expect(result.x402Version).toBe(2);
26
+ expect(result.error).toBe('Payment required');
27
+ expect(result.resource.url).toBe('https://api.example.com/data');
28
+ expect(result.accepts).toHaveLength(1);
29
+ expect(result.accepts[0].scheme).toBe('utxo');
30
+ expect(result.accepts[0].amount).toBe('1000');
31
+ });
32
+ it('should return null for null input', () => {
33
+ expect(parsePaymentRequiredJson(null)).toBeNull();
34
+ });
35
+ it('should return null for non-object input', () => {
36
+ expect(parsePaymentRequiredJson('string')).toBeNull();
37
+ expect(parsePaymentRequiredJson(123)).toBeNull();
38
+ });
39
+ it('should return null for wrong x402Version', () => {
40
+ const input = { x402Version: 1, accepts: [] };
41
+ expect(parsePaymentRequiredJson(input)).toBeNull();
42
+ });
43
+ it('should use default values for missing optional fields', () => {
44
+ const input = {
45
+ x402Version: 2,
46
+ resource: {},
47
+ accepts: [
48
+ {
49
+ scheme: 'utxo',
50
+ network: BCH_MAINNET_NETWORK,
51
+ payTo: 'bitcoincash:qp2f5j6q3fj5gjwgk8rkq8xrk8q8q8q8q8q8q8q8',
52
+ },
53
+ ],
54
+ };
55
+ const result = parsePaymentRequiredJson(input);
56
+ expect(result).not.toBeNull();
57
+ expect(result.accepts[0].asset).toBe(BCH_ASSET_ID);
58
+ expect(result.accepts[0].maxTimeoutSeconds).toBe(60);
59
+ });
60
+ it('should filter out invalid accepts entries', () => {
61
+ const input = {
62
+ x402Version: 2,
63
+ resource: { url: 'https://api.example.com' },
64
+ accepts: [
65
+ { scheme: 'utxo', network: BCH_MAINNET_NETWORK, payTo: 'valid1' },
66
+ { scheme: 'invalid' },
67
+ { network: BCH_MAINNET_NETWORK, payTo: 'missing-scheme' },
68
+ { scheme: 'utxo', payTo: 'missing-network' },
69
+ { scheme: 'utxo', network: BCH_MAINNET_NETWORK },
70
+ ],
71
+ };
72
+ const result = parsePaymentRequiredJson(input);
73
+ expect(result.accepts).toHaveLength(1);
74
+ expect(result.accepts[0].payTo).toBe('valid1');
75
+ });
76
+ });
77
+ describe('selectBchPaymentRequirements', () => {
78
+ const paymentRequired = {
79
+ x402Version: 2,
80
+ resource: { url: 'https://api.example.com' },
81
+ accepts: [
82
+ {
83
+ scheme: 'utxo',
84
+ network: BCH_MAINNET_NETWORK,
85
+ amount: '1000',
86
+ asset: BCH_ASSET_ID,
87
+ payTo: 'bitcoincash:mainnet-address',
88
+ maxTimeoutSeconds: 300,
89
+ extra: {},
90
+ },
91
+ {
92
+ scheme: 'utxo',
93
+ network: BCH_CHIPNET_NETWORK,
94
+ amount: '1000',
95
+ asset: BCH_ASSET_ID,
96
+ payTo: 'bitcoincash:chipnet-address',
97
+ maxTimeoutSeconds: 300,
98
+ extra: {},
99
+ },
100
+ ],
101
+ extensions: {},
102
+ };
103
+ it('should select mainnet requirements for mainnet client', () => {
104
+ const result = selectBchPaymentRequirements(paymentRequired, 'mainnet');
105
+ expect(result).not.toBeNull();
106
+ expect(result.network).toBe(BCH_MAINNET_NETWORK);
107
+ expect(result.payTo).toBe('bitcoincash:mainnet-address');
108
+ });
109
+ it('should select chipnet requirements for chipnet client', () => {
110
+ const result = selectBchPaymentRequirements(paymentRequired, 'chipnet');
111
+ expect(result).not.toBeNull();
112
+ expect(result.network).toBe(BCH_CHIPNET_NETWORK);
113
+ expect(result.payTo).toBe('bitcoincash:chipnet-address');
114
+ });
115
+ it('should return null when no matching network', () => {
116
+ const emptyAccepts = { ...paymentRequired, accepts: [paymentRequired.accepts[0]] };
117
+ const result = selectBchPaymentRequirements(emptyAccepts, 'chipnet');
118
+ expect(result).toBeNull();
119
+ });
120
+ });
121
+ });
122
+ describe('x402 building', () => {
123
+ describe('buildPaymentPayload', () => {
124
+ it('should build a valid PaymentPayload', () => {
125
+ const accepted = {
126
+ scheme: 'utxo',
127
+ network: BCH_MAINNET_NETWORK,
128
+ amount: '1000',
129
+ asset: BCH_ASSET_ID,
130
+ payTo: 'bitcoincash:qp2f5j6q3fj5gjwgk8rkq8xrk8q8q8q8q8q8q8q8',
131
+ maxTimeoutSeconds: 300,
132
+ extra: {},
133
+ };
134
+ const result = buildPaymentPayload(accepted, 'https://api.example.com/data', 'bitcoincash:payer-address', 'abc123txid', 0, '1000');
135
+ expect(result.x402Version).toBe(2);
136
+ expect(result.resource.url).toBe('https://api.example.com/data');
137
+ expect(result.accepted).toBe(accepted);
138
+ expect(result.payload.authorization.from).toBe('bitcoincash:payer-address');
139
+ expect(result.payload.authorization.to).toBe(accepted.payTo);
140
+ expect(result.payload.authorization.txid).toBe('abc123txid');
141
+ expect(result.payload.signature).toBe('');
142
+ });
143
+ });
144
+ describe('buildAuthorization', () => {
145
+ it('should build a valid Authorization', () => {
146
+ const accepted = {
147
+ scheme: 'utxo',
148
+ network: BCH_MAINNET_NETWORK,
149
+ amount: '1000',
150
+ asset: BCH_ASSET_ID,
151
+ payTo: 'bitcoincash:qp2f5j6q3fj5gjwgk8rkq8xrk8q8q8q8q8q8q8q8',
152
+ maxTimeoutSeconds: 300,
153
+ extra: {},
154
+ };
155
+ const result = buildAuthorization(accepted, 'https://api.example.com/data', 'bitcoincash:payer-address', 'abc123txid', 0, '1000');
156
+ expect(result.from).toBe('bitcoincash:payer-address');
157
+ expect(result.to).toBe(accepted.payTo);
158
+ expect(result.txid).toBe('abc123txid');
159
+ expect(result.vout).toBe(0);
160
+ expect(result.amount).toBe('1000');
161
+ });
162
+ });
163
+ });
164
+ describe('parsePaymentResponse', () => {
165
+ it('should parse valid isValid response', () => {
166
+ const data = {
167
+ isValid: true,
168
+ payer: 'bitcoincash:abc123',
169
+ remainingBalanceSat: '1000000',
170
+ };
171
+ const result = parsePaymentResponse(data);
172
+ expect(result.isValid).toBe(true);
173
+ expect(result.payer).toBe('bitcoincash:abc123');
174
+ expect(result.remainingBalanceSat).toBe('1000000');
175
+ });
176
+ it('should parse error response', () => {
177
+ const data = { error: 'Invalid signature' };
178
+ const result = parsePaymentResponse(data);
179
+ expect(result.isValid).toBe(false);
180
+ expect(result.invalidReason).toBe('Invalid signature');
181
+ });
182
+ it('should return no_response_data for null input', () => {
183
+ const result = parsePaymentResponse(null);
184
+ expect(result.isValid).toBe(false);
185
+ expect(result.invalidReason).toBe('no_response_data');
186
+ });
187
+ it('should return unknown_response_format for unrecognized data', () => {
188
+ const data = { some: 'unknown', format: true };
189
+ const result = parsePaymentResponse(data);
190
+ expect(result.isValid).toBe(false);
191
+ expect(result.invalidReason).toBe('unknown_response_format');
192
+ });
193
+ });
194
+ describe('network helpers', () => {
195
+ describe('isBchNetwork', () => {
196
+ it('should return true for mainnet', () => {
197
+ expect(isBchNetwork(BCH_MAINNET_NETWORK)).toBe(true);
198
+ });
199
+ it('should return true for chipnet', () => {
200
+ expect(isBchNetwork(BCH_CHIPNET_NETWORK)).toBe(true);
201
+ });
202
+ it('should return false for other networks', () => {
203
+ expect(isBchNetwork('bitcoin')).toBe(false);
204
+ expect(isBchNetwork('litecoin')).toBe(false);
205
+ });
206
+ });
207
+ describe('isChipnetNetwork', () => {
208
+ it('should return true for chipnet', () => {
209
+ expect(isChipnetNetwork(BCH_CHIPNET_NETWORK)).toBe(true);
210
+ });
211
+ it('should return false for mainnet', () => {
212
+ expect(isChipnetNetwork(BCH_MAINNET_NETWORK)).toBe(false);
213
+ });
214
+ });
215
+ });
216
+ //# sourceMappingURL=x402.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402.test.js","sourceRoot":"","sources":["../../src/utils/x402.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * x402 payment handler for BCH
3
+ * Implements x402-bch v2.2 specification
4
+ * https://github.com/x402-bch/x402-bch/blob/master/specs/x402-bch-specification-v2.2.md
5
+ */
6
+ import { LibauthHDWallet } from './keys.js';
7
+ import { PaymentRequirements, PaymentPayload } from '../types/x402.js';
8
+ export interface X402Signer {
9
+ address: string;
10
+ signMessage: (message: string) => Promise<string>;
11
+ }
12
+ export interface X402PayerConfig {
13
+ hdWallet: LibauthHDWallet;
14
+ addressIndex?: number;
15
+ }
16
+ export declare class X402Payer {
17
+ private signer;
18
+ private isChipnet;
19
+ constructor(config: X402PayerConfig);
20
+ private createSigner;
21
+ getPayerAddress(): string;
22
+ createPaymentPayload(requirements: PaymentRequirements, resourceUrl: string, txid: string, vout: number | null, amount: string | null): Promise<PaymentPayload>;
23
+ makePaymentRequest(requirements: PaymentRequirements, resourceUrl: string, txid: string, vout: number | null, amount: string | null): Promise<{
24
+ paymentPayload: PaymentPayload;
25
+ paymentUrl: string;
26
+ }>;
27
+ }
28
+ export declare function createX402Payer(hdWallet: LibauthHDWallet, addressIndex?: number): X402Payer;
29
+ //# sourceMappingURL=x402.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402.d.ts","sourceRoot":"","sources":["../../src/wallet/x402.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAS3C,OAAO,EAEL,mBAAmB,EACnB,cAAc,EAGf,MAAM,kBAAkB,CAAA;AAEzB,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CAClD;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,eAAe,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,eAAe;IAKnC,OAAO,CAAC,YAAY;IAYpB,eAAe,IAAI,MAAM;IAInB,oBAAoB,CACxB,YAAY,EAAE,mBAAmB,EACjC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,OAAO,CAAC,cAAc,CAAC;IAgBpB,kBAAkB,CACtB,YAAY,EAAE,mBAAmB,EACjC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,OAAO,CAAC;QAAE,cAAc,EAAE,cAAc,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAQnE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAE3F"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * x402 payment handler for BCH
3
+ * Implements x402-bch v2.2 specification
4
+ * https://github.com/x402-bch/x402-bch/blob/master/specs/x402-bch-specification-v2.2.md
5
+ */
6
+ import { buildPaymentPayload, signAuthorization, signMessageBCH, } from '../utils/x402.js';
7
+ export class X402Payer {
8
+ signer;
9
+ isChipnet;
10
+ constructor(config) {
11
+ this.isChipnet = config.hdWallet.isChipnet;
12
+ this.signer = this.createSigner(config.hdWallet, config.addressIndex || 0);
13
+ }
14
+ createSigner(hdWallet, index) {
15
+ const addressSet = hdWallet.getAddressSetAt(index);
16
+ return {
17
+ address: addressSet.receiving,
18
+ signMessage: async (message) => {
19
+ const node = hdWallet.getNodeAt(`0/${index}`);
20
+ const privKeyHex = Buffer.from(node.privateKey).toString('hex');
21
+ return signMessageBCH(message, privKeyHex, true);
22
+ },
23
+ };
24
+ }
25
+ getPayerAddress() {
26
+ return this.signer.address;
27
+ }
28
+ async createPaymentPayload(requirements, resourceUrl, txid, vout, amount) {
29
+ const payload = buildPaymentPayload(requirements, resourceUrl, this.signer.address, txid, vout, amount);
30
+ const signature = await signAuthorization(payload.payload.authorization, this.signer.signMessage.bind(this.signer));
31
+ payload.payload.signature = signature;
32
+ return payload;
33
+ }
34
+ async makePaymentRequest(requirements, resourceUrl, txid, vout, amount) {
35
+ const paymentPayload = await this.createPaymentPayload(requirements, resourceUrl, txid, vout, amount);
36
+ return {
37
+ paymentPayload,
38
+ paymentUrl: requirements.payTo,
39
+ };
40
+ }
41
+ }
42
+ export function createX402Payer(hdWallet, addressIndex) {
43
+ return new X402Payer({ hdWallet, addressIndex });
44
+ }
45
+ //# sourceMappingURL=x402.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402.js","sourceRoot":"","sources":["../../src/wallet/x402.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAGL,mBAAmB,EAEnB,iBAAiB,EACjB,cAAc,GACf,MAAM,kBAAkB,CAAA;AAmBzB,MAAM,OAAO,SAAS;IACZ,MAAM,CAAY;IAClB,SAAS,CAAS;IAE1B,YAAY,MAAuB;QACjC,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAA;QAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC,CAAA;IAC5E,CAAC;IAEO,YAAY,CAAC,QAAyB,EAAE,KAAa;QAC3D,MAAM,UAAU,GAAG,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,CAAA;QAClD,OAAO;YACL,OAAO,EAAE,UAAU,CAAC,SAAS;YAC7B,WAAW,EAAE,KAAK,EAAE,OAAe,EAAE,EAAE;gBACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,KAAK,EAAE,CAAC,CAAA;gBAC7C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;gBAC/D,OAAO,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,CAAA;YAClD,CAAC;SACF,CAAA;IACH,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,oBAAoB,CACxB,YAAiC,EACjC,WAAmB,EACnB,IAAY,EACZ,IAAmB,EACnB,MAAqB;QAErB,MAAM,OAAO,GAAG,mBAAmB,CACjC,YAAY,EACZ,WAAW,EACX,IAAI,CAAC,MAAM,CAAC,OAAO,EACnB,IAAI,EACJ,IAAI,EACJ,MAAM,CACP,CAAA;QAED,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;QACnH,OAAO,CAAC,OAAO,CAAC,SAAS,GAAG,SAAS,CAAA;QAErC,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,YAAiC,EACjC,WAAmB,EACnB,IAAY,EACZ,IAAmB,EACnB,MAAqB;QAErB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QAErG,OAAO;YACL,cAAc;YACd,UAAU,EAAE,YAAY,CAAC,KAAK;SAC/B,CAAA;IACH,CAAC;CACF;AAED,MAAM,UAAU,eAAe,CAAC,QAAyB,EAAE,YAAqB;IAC9E,OAAO,IAAI,SAAS,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAA;AAClD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paytaca-cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Command-line interface for the Paytaca Bitcoin Cash wallet",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,6 +11,7 @@
11
11
  "files": [
12
12
  "bin/",
13
13
  "dist/",
14
+ "skills/",
14
15
  "LICENSE",
15
16
  "README.md"
16
17
  ],
@@ -19,6 +20,8 @@
19
20
  "dev": "tsc --watch",
20
21
  "start": "node bin/paytaca.js",
21
22
  "clean": "rm -rf dist",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest",
22
25
  "prepublishOnly": "npm run clean && npm run build"
23
26
  },
24
27
  "keywords": [
@@ -49,7 +52,9 @@
49
52
  "devDependencies": {
50
53
  "@types/node": "^22.0.0",
51
54
  "@types/qrcode-terminal": "^0.12.2",
52
- "typescript": "^5.9.3"
55
+ "@vitest/ui": "^4.1.2",
56
+ "typescript": "^5.9.3",
57
+ "vitest": "^4.1.2"
53
58
  },
54
59
  "engines": {
55
60
  "node": ">=20.0.0"
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: paytaca-x402
3
+ description: Handles x402 HTTP payment requests using Paytaca BCH wallet. Use when encountering HTTP 402 responses or when calling APIs that may require payment via the x402 protocol.
4
+ ---
5
+
6
+ # Paytaca x402 Payment Handler
7
+
8
+ This skill teaches the agent how to handle x402-based HTTP payments using the Paytaca CLI wallet.
9
+
10
+ ## Overview
11
+
12
+ Some APIs (like nanogpt, etc.) use the x402 protocol for HTTP payments. When you call these APIs:
13
+ - Server returns **HTTP 402 PAYMENT REQUIRED**
14
+ - You must pay with BCH to access the resource
15
+ - After payment, the server returns the actual response
16
+
17
+ ## Commands
18
+
19
+ ### Check if a URL requires payment (recommended first step)
20
+
21
+ ```bash
22
+ paytaca check <url> --json
23
+ # Returns: acceptsX402, acceptsBch, estimatedCostSats, etc.
24
+ ```
25
+
26
+ Example output:
27
+ ```json
28
+ {
29
+ "url": "https://api.nanogpt.com/v1/complete",
30
+ "acceptsX402": true,
31
+ "acceptsBch": true,
32
+ "paymentRequired": true,
33
+ "estimatedCostSats": "100",
34
+ "costInBch": "0.00000100"
35
+ }
36
+ ```
37
+
38
+ ### Preview payment without executing (dry-run)
39
+
40
+ ```bash
41
+ paytaca pay <url> --dry-run --json
42
+ # Shows what would happen without actually paying
43
+ ```
44
+
45
+ ### Make a paid request
46
+
47
+ ```bash
48
+ # Basic (will prompt for confirmation)
49
+ paytaca pay <url>
50
+
51
+ # With JSON output (preferred for AI agents)
52
+ paytaca pay <url> --json
53
+
54
+ # Skip confirmation prompt (only use after user has already approved via paytaca check)
55
+ paytaca pay <url> --confirmed
56
+
57
+ # POST request
58
+ paytaca pay <url> --method POST --body '{"prompt":"hello"}'
59
+
60
+ # Custom headers
61
+ paytaca pay <url> -H "Authorization: Bearer token123"
62
+ ```
63
+
64
+ ### Check wallet balance
65
+
66
+ ```bash
67
+ paytaca balance
68
+ ```
69
+
70
+ ## Decision Flow
71
+
72
+ When preparing to call an unfamiliar API that might require payment:
73
+
74
+ 1. **First check**: `paytaca check <url> --json`
75
+ - If `paymentRequired: false` → proceed normally
76
+ - If `paymentRequired: true` and `acceptsBch: true` → inform user of cost and **seek explicit approval** before paying
77
+ - If `paymentRequired: true` but `acceptsBch: false` → inform user
78
+
79
+ 2. **When encountering HTTP 402**:
80
+ - Parse the `PAYMENT-REQUIRED` headers
81
+ - **Seek explicit user approval** before spending any BCH
82
+ - Once approved, use `paytaca pay <url> --json` to handle payment
83
+ - The command handles: parse headers → build BCH tx → broadcast → retry with signature
84
+
85
+ 3. **For known paid APIs**:
86
+ - **Always seek user approval first**, then use `paytaca pay <url>` - it handles 402 automatically
87
+
88
+ ## ⚠️ User Approval Required Before Any Payment
89
+
90
+ **CRITICAL**: The agent MUST NOT execute `paytaca pay` without explicit user approval. Since `paytaca pay` spends real BCH from the user's wallet, always:
91
+
92
+ 1. Run `paytaca check <url> --json` first to determine the cost
93
+ 2. Inform the user of the cost (e.g., "This API costs ~1000 sats")
94
+ 3. Wait for explicit user confirmation (e.g., "yes", "go ahead", "pay")
95
+ 4. Only then execute the payment using `paytaca pay <url> --confirmed --json`
96
+
97
+ The `--confirmed` flag skips the interactive confirmation prompt since the user has already approved the transaction. Do NOT use `--confirmed` without first obtaining explicit user approval.
98
+
99
+ Do NOT assume the user wants to pay - even if the cost seems small.
100
+
101
+ ## AI Agent Workflow
102
+
103
+ ```
104
+ Task: Call nanogpt API
105
+ Agent: paytaca check https://api.nanogpt.com/v1/complete --json
106
+ → {"acceptsBch": true, "estimatedCostSats": "100"}
107
+
108
+ Agent: Informs user "This API costs 100 sats (0.00000100 BCH). Approve to proceed?"
109
+ User: "yes"
110
+
111
+ Agent: paytaca pay https://api.nanogpt.com/v1/complete --method POST --body '{"prompt":"hello"}' --confirmed --json
112
+ → Handles 402 → pays 100 sats → returns response with txid
113
+ ```
114
+
115
+ ## Key Options
116
+
117
+ | Option | Description |
118
+ |--------|-------------|
119
+ | `--json` | Machine-readable output (recommended for AI) |
120
+ | `--dry-run` | Preview payment without executing |
121
+ | `--confirmed` | Skip confirmation prompt (prior approval obtained) |
122
+ | `--chipnet` | Use chipnet (testnet) instead of mainnet |
123
+ | `--max-amount` | Override max payment amount in sats |
124
+
125
+ ## Notes
126
+
127
+ - Payment is per-request (no batching)
128
+ - Each request = separate BCH transaction
129
+ - Only BCH payments are supported (no stablecoins)
130
+ - Uses local wallet from OS keychain (credentials never leave the machine)