facinet 1.0.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/README.md +318 -0
- package/dist/commands/connect.d.ts +7 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +80 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/facilitator.d.ts +40 -0
- package/dist/commands/facilitator.d.ts.map +1 -0
- package/dist/commands/facilitator.js +208 -0
- package/dist/commands/facilitator.js.map +1 -0
- package/dist/commands/pay.d.ts +14 -0
- package/dist/commands/pay.d.ts.map +1 -0
- package/dist/commands/pay.js +155 -0
- package/dist/commands/pay.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +99 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/api.d.ts +42 -0
- package/dist/utils/api.d.ts.map +1 -0
- package/dist/utils/api.js +145 -0
- package/dist/utils/api.js.map +1 -0
- package/dist/utils/config.d.ts +25 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +64 -0
- package/dist/utils/config.js.map +1 -0
- package/package.json +43 -0
- package/src/commands/connect.ts +84 -0
- package/src/commands/facilitator.ts +256 -0
- package/src/commands/pay.ts +179 -0
- package/src/index.ts +108 -0
- package/src/utils/api.ts +164 -0
- package/src/utils/config.ts +67 -0
- package/tsconfig.json +20 -0
package/src/utils/api.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Client
|
|
3
|
+
*
|
|
4
|
+
* Interact with x402 backend APIs
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import axios from 'axios';
|
|
8
|
+
|
|
9
|
+
interface FacilitatorCreatePayload {
|
|
10
|
+
name: string;
|
|
11
|
+
facilitatorWallet: string;
|
|
12
|
+
facilitatorPrivateKey: string;
|
|
13
|
+
paymentRecipient: string;
|
|
14
|
+
createdBy: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get all active facilitators
|
|
19
|
+
*/
|
|
20
|
+
export async function listFacilitators(apiUrl: string): Promise<any[]> {
|
|
21
|
+
try {
|
|
22
|
+
const response = await axios.get(`${apiUrl}/api/facilitator/list`);
|
|
23
|
+
|
|
24
|
+
if (response.data.success) {
|
|
25
|
+
// Filter only active facilitators
|
|
26
|
+
return response.data.facilitators.filter((f: any) => f.status === 'active');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return [];
|
|
30
|
+
} catch (error: any) {
|
|
31
|
+
throw new Error(`Failed to fetch facilitators: ${error.message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Select a random active facilitator
|
|
37
|
+
*/
|
|
38
|
+
export async function selectRandomFacilitator(apiUrl: string): Promise<any> {
|
|
39
|
+
const facilitators = await listFacilitators(apiUrl);
|
|
40
|
+
|
|
41
|
+
if (facilitators.length === 0) {
|
|
42
|
+
throw new Error('No active facilitators available');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const randomIndex = Math.floor(Math.random() * facilitators.length);
|
|
46
|
+
return facilitators[randomIndex];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get facilitator by ID
|
|
51
|
+
*/
|
|
52
|
+
export async function getFacilitatorById(apiUrl: string, id: string): Promise<any> {
|
|
53
|
+
try {
|
|
54
|
+
const response = await axios.get(`${apiUrl}/api/facilitator/list`);
|
|
55
|
+
|
|
56
|
+
if (response.data.success) {
|
|
57
|
+
const facilitator = response.data.facilitators.find((f: any) => f.id === id);
|
|
58
|
+
if (!facilitator) {
|
|
59
|
+
throw new Error('Facilitator not found');
|
|
60
|
+
}
|
|
61
|
+
return facilitator;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
throw new Error('Failed to fetch facilitator');
|
|
65
|
+
} catch (error: any) {
|
|
66
|
+
throw new Error(`Failed to get facilitator: ${error.message}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get facilitator status
|
|
72
|
+
*/
|
|
73
|
+
export async function getFacilitatorStatus(apiUrl: string, id: string): Promise<any> {
|
|
74
|
+
return getFacilitatorById(apiUrl, id);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get facilitator balance
|
|
79
|
+
*/
|
|
80
|
+
export async function getFacilitatorBalance(apiUrl: string, id: string): Promise<any> {
|
|
81
|
+
try {
|
|
82
|
+
const response = await axios.post(`${apiUrl}/api/facilitator/balance`, {
|
|
83
|
+
facilitatorId: id,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (response.data.success) {
|
|
87
|
+
return {
|
|
88
|
+
name: response.data.name,
|
|
89
|
+
wallet: response.data.wallet,
|
|
90
|
+
balance: response.data.balance,
|
|
91
|
+
status: response.data.status,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
throw new Error('Failed to fetch balance');
|
|
96
|
+
} catch (error: any) {
|
|
97
|
+
throw new Error(`Failed to get balance: ${error.message}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Create a new facilitator
|
|
103
|
+
*/
|
|
104
|
+
export async function createFacilitator(
|
|
105
|
+
apiUrl: string,
|
|
106
|
+
payload: FacilitatorCreatePayload
|
|
107
|
+
): Promise<any> {
|
|
108
|
+
try {
|
|
109
|
+
// Note: In real implementation, this would:
|
|
110
|
+
// 1. Encrypt private key with user password
|
|
111
|
+
// 2. Call payment API to pay registration fee
|
|
112
|
+
// 3. Submit facilitator creation request
|
|
113
|
+
|
|
114
|
+
// For CLI demo, we'll just show what would happen
|
|
115
|
+
throw new Error(
|
|
116
|
+
'Facilitator creation requires payment flow. Please use the web interface at ' + apiUrl
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// Actual implementation would be:
|
|
120
|
+
/*
|
|
121
|
+
const response = await axios.post(`${apiUrl}/api/facilitator/create`, {
|
|
122
|
+
name: payload.name,
|
|
123
|
+
encryptedPrivateKey: 'encrypted_key',
|
|
124
|
+
systemEncryptedKey: 'system_encrypted_key',
|
|
125
|
+
facilitatorWallet: payload.facilitatorWallet,
|
|
126
|
+
paymentRecipient: payload.paymentRecipient,
|
|
127
|
+
createdBy: payload.createdBy,
|
|
128
|
+
registrationTxHash: 'tx_hash_from_payment',
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
return response.data;
|
|
132
|
+
*/
|
|
133
|
+
} catch (error: any) {
|
|
134
|
+
throw new Error(`Failed to create facilitator: ${error.message}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Submit payment to facilitator
|
|
140
|
+
*/
|
|
141
|
+
export async function submitPayment(
|
|
142
|
+
apiUrl: string,
|
|
143
|
+
facilitatorId: string,
|
|
144
|
+
paymentPayload: any
|
|
145
|
+
): Promise<any> {
|
|
146
|
+
try {
|
|
147
|
+
const response = await axios.post(`${apiUrl}/api/x402/settle-custom`, {
|
|
148
|
+
facilitatorId,
|
|
149
|
+
paymentPayload,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (response.data.success) {
|
|
153
|
+
return {
|
|
154
|
+
txHash: response.data.txHash,
|
|
155
|
+
facilitatorWallet: response.data.facilitatorWallet,
|
|
156
|
+
facilitatorName: response.data.facilitatorName,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
throw new Error('Payment submission failed');
|
|
161
|
+
} catch (error: any) {
|
|
162
|
+
throw new Error(`Failed to submit payment: ${error.message}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Management
|
|
3
|
+
*
|
|
4
|
+
* Save and load user configuration
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import os from 'os';
|
|
10
|
+
|
|
11
|
+
interface Config {
|
|
12
|
+
privateKey?: string;
|
|
13
|
+
address?: string;
|
|
14
|
+
network?: string;
|
|
15
|
+
apiUrl?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const CONFIG_DIR = path.join(os.homedir(), '.facinet');
|
|
19
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get configuration
|
|
23
|
+
*/
|
|
24
|
+
export function getConfig(): Config {
|
|
25
|
+
try {
|
|
26
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const data = fs.readFileSync(CONFIG_FILE, 'utf8');
|
|
31
|
+
return JSON.parse(data);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Save configuration
|
|
39
|
+
*/
|
|
40
|
+
export function saveConfig(config: Partial<Config>): void {
|
|
41
|
+
try {
|
|
42
|
+
// Create config directory if it doesn't exist
|
|
43
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
44
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const existingConfig = getConfig();
|
|
48
|
+
const newConfig = { ...existingConfig, ...config };
|
|
49
|
+
|
|
50
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(newConfig, null, 2), 'utf8');
|
|
51
|
+
} catch (error: any) {
|
|
52
|
+
throw new Error(`Failed to save configuration: ${error.message}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Clear configuration
|
|
58
|
+
*/
|
|
59
|
+
export function clearConfig(): void {
|
|
60
|
+
try {
|
|
61
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
62
|
+
fs.unlinkSync(CONFIG_FILE);
|
|
63
|
+
}
|
|
64
|
+
} catch (error: any) {
|
|
65
|
+
throw new Error(`Failed to clear configuration: ${error.message}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"declaration": true,
|
|
14
|
+
"declarationMap": true,
|
|
15
|
+
"sourceMap": true,
|
|
16
|
+
"moduleResolution": "node"
|
|
17
|
+
},
|
|
18
|
+
"include": ["src/**/*"],
|
|
19
|
+
"exclude": ["node_modules", "dist"]
|
|
20
|
+
}
|