arispay 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/.turbo/turbo-build.log +4 -0
- package/dist/chunk-4ON4ZXR3.js +953 -0
- package/dist/cli-b.js +277 -0
- package/dist/cli.js +426 -0
- package/dist/index.d.ts +216 -0
- package/dist/index.js +406 -0
- package/package.json +31 -0
- package/src/agents.ts +117 -0
- package/src/cli-b.ts +373 -0
- package/src/cli-shared.ts +650 -0
- package/src/cli.ts +439 -0
- package/src/client.ts +65 -0
- package/src/index.ts +98 -0
- package/src/payments.ts +22 -0
- package/src/transactions.ts +19 -0
- package/src/users.ts +67 -0
- package/src/webhooks.ts +81 -0
- package/tsconfig.json +8 -0
- package/tsup.config.ts +18 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { RegisterAgentRequest, AgentResponse, AgentListResponse, SetCircuitBreakerRequest, CircuitBreakerResponse, RotateKeysResponse, AgentBalanceResponse, AgentTopupRequest, AgentTopupResponse, AgentSweepRequest, AgentSweepResponse, LedgerHistoryResponse, AgentEarningRequest, CreateUserRequest, UserResponse, WalletStatusResponse, SetupPaymentMethodResponse, WalletPaymentMethodResponse, SetLimitsRequest, SpendLimitsResponse, CreatePaymentRequest, PaymentResponse, Complete3dsRequest, ListTransactionsQuery, TransactionListResponse, RegisterWebhookRequest, WebhookResponse } from '@arispay/shared';
|
|
2
|
+
export { AgentBalanceResponse, AgentEarningRequest, AgentModeMismatchError, AgentSweepRequest, AgentSweepResponse, AgentTopupRequest, AgentTopupResponse, ArisPayError, InsufficientBalanceError, InsufficientFundsError, LedgerEntryResponse, LedgerHistoryResponse, SpendLimitExceededError } from '@arispay/shared';
|
|
3
|
+
|
|
4
|
+
declare class HttpClient {
|
|
5
|
+
private baseUrl;
|
|
6
|
+
private apiKey;
|
|
7
|
+
constructor(baseUrl: string, apiKey: string);
|
|
8
|
+
private request;
|
|
9
|
+
get<T>(path: string): Promise<T>;
|
|
10
|
+
post<T>(path: string, body?: unknown): Promise<T>;
|
|
11
|
+
put<T>(path: string, body?: unknown): Promise<T>;
|
|
12
|
+
delete<T>(path: string): Promise<T>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ChildAgentSummary {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
status: string;
|
|
19
|
+
permissions: string[];
|
|
20
|
+
delegatedBudget: number | null;
|
|
21
|
+
delegatedBudgetDay: number | null;
|
|
22
|
+
delegatedBudgetMo: number | null;
|
|
23
|
+
createdAt: string;
|
|
24
|
+
}
|
|
25
|
+
declare class AgentService {
|
|
26
|
+
private client;
|
|
27
|
+
constructor(client: HttpClient);
|
|
28
|
+
register(params: RegisterAgentRequest): Promise<AgentResponse>;
|
|
29
|
+
get(agentId: string): Promise<AgentResponse>;
|
|
30
|
+
list(params?: {
|
|
31
|
+
name?: string;
|
|
32
|
+
status?: string;
|
|
33
|
+
limit?: number;
|
|
34
|
+
offset?: number;
|
|
35
|
+
}): Promise<AgentListResponse>;
|
|
36
|
+
listChildren(agentId: string): Promise<ChildAgentSummary[]>;
|
|
37
|
+
resume(agentId: string): Promise<{
|
|
38
|
+
status: string;
|
|
39
|
+
resumedAt: string;
|
|
40
|
+
}>;
|
|
41
|
+
setCircuitBreaker(agentId: string, params: SetCircuitBreakerRequest): Promise<CircuitBreakerResponse>;
|
|
42
|
+
getCircuitBreaker(agentId: string): Promise<CircuitBreakerResponse>;
|
|
43
|
+
rotateKeys(agentId: string): Promise<RotateKeysResponse>;
|
|
44
|
+
/**
|
|
45
|
+
* Get the current balance for an autonomous agent.
|
|
46
|
+
*/
|
|
47
|
+
getBalance(agentId: string): Promise<AgentBalanceResponse>;
|
|
48
|
+
/**
|
|
49
|
+
* Fund an autonomous agent's balance (topup).
|
|
50
|
+
*/
|
|
51
|
+
topup(agentId: string, params: AgentTopupRequest): Promise<AgentTopupResponse>;
|
|
52
|
+
/**
|
|
53
|
+
* Withdraw from an autonomous agent's balance (sweep).
|
|
54
|
+
* Omit `amount` to sweep everything above the sweep threshold.
|
|
55
|
+
*/
|
|
56
|
+
sweep(agentId: string, params?: AgentSweepRequest): Promise<AgentSweepResponse>;
|
|
57
|
+
/**
|
|
58
|
+
* Get paginated ledger history for an autonomous agent.
|
|
59
|
+
*/
|
|
60
|
+
getLedger(agentId: string, params?: {
|
|
61
|
+
limit?: number;
|
|
62
|
+
offset?: number;
|
|
63
|
+
type?: string;
|
|
64
|
+
from?: string;
|
|
65
|
+
to?: string;
|
|
66
|
+
}): Promise<LedgerHistoryResponse>;
|
|
67
|
+
/**
|
|
68
|
+
* Record an earning (inbound money) for an autonomous agent.
|
|
69
|
+
*/
|
|
70
|
+
recordEarning(agentId: string, params: AgentEarningRequest): Promise<AgentTopupResponse>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
declare class UserService {
|
|
74
|
+
private client;
|
|
75
|
+
constructor(client: HttpClient);
|
|
76
|
+
create(params: CreateUserRequest): Promise<UserResponse>;
|
|
77
|
+
get(userId: string): Promise<UserResponse>;
|
|
78
|
+
getByExternalId(externalId: string): Promise<UserResponse>;
|
|
79
|
+
getWalletStatus(userId: string): Promise<WalletStatusResponse>;
|
|
80
|
+
/** Hosted card flow — returns setupUrl for redirect */
|
|
81
|
+
addPaymentMethod(params: {
|
|
82
|
+
userId: string;
|
|
83
|
+
type: 'card';
|
|
84
|
+
returnUrl: string;
|
|
85
|
+
}): Promise<SetupPaymentMethodResponse>;
|
|
86
|
+
/** Direct card tokenization — returns user with card attached */
|
|
87
|
+
addPaymentMethod(params: {
|
|
88
|
+
userId: string;
|
|
89
|
+
type: 'card';
|
|
90
|
+
cardNumber: string;
|
|
91
|
+
expiryMonth: string;
|
|
92
|
+
expiryYear: string;
|
|
93
|
+
securityCode: string;
|
|
94
|
+
}): Promise<UserResponse>;
|
|
95
|
+
addPaymentMethod(params: {
|
|
96
|
+
userId: string;
|
|
97
|
+
type: 'wallet';
|
|
98
|
+
walletAddress: string;
|
|
99
|
+
chain: string;
|
|
100
|
+
}): Promise<WalletPaymentMethodResponse>;
|
|
101
|
+
completePaymentMethod(params: {
|
|
102
|
+
userId: string;
|
|
103
|
+
sessionId: string;
|
|
104
|
+
}): Promise<UserResponse>;
|
|
105
|
+
setLimits(params: {
|
|
106
|
+
userId: string;
|
|
107
|
+
} & SetLimitsRequest): Promise<SpendLimitsResponse>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
declare class PaymentService {
|
|
111
|
+
private client;
|
|
112
|
+
constructor(client: HttpClient);
|
|
113
|
+
create(params: CreatePaymentRequest): Promise<PaymentResponse>;
|
|
114
|
+
get(paymentId: string): Promise<PaymentResponse>;
|
|
115
|
+
/** Complete a 3D Secure authentication step (method or challenge) */
|
|
116
|
+
complete3ds(paymentId: string, params: Complete3dsRequest): Promise<PaymentResponse>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
declare class TransactionService {
|
|
120
|
+
private client;
|
|
121
|
+
constructor(client: HttpClient);
|
|
122
|
+
list(params?: ListTransactionsQuery): Promise<TransactionListResponse>;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
declare class WebhookService {
|
|
126
|
+
private client;
|
|
127
|
+
constructor(client: HttpClient);
|
|
128
|
+
register(params: RegisterWebhookRequest): Promise<WebhookResponse & {
|
|
129
|
+
secret: string;
|
|
130
|
+
}>;
|
|
131
|
+
list(): Promise<WebhookResponse[]>;
|
|
132
|
+
delete(webhookId: string): Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* Verify a webhook signature from an incoming request.
|
|
135
|
+
*
|
|
136
|
+
* ArisPay signs every webhook delivery with HMAC-SHA256 using the secret
|
|
137
|
+
* returned when you registered the webhook. The signature is sent in the
|
|
138
|
+
* `X-ArisPay-Signature` header and the unix timestamp in `X-ArisPay-Timestamp`.
|
|
139
|
+
*
|
|
140
|
+
* @param body - The raw request body string (do NOT parse it first)
|
|
141
|
+
* @param signature - Value of the `X-ArisPay-Signature` header
|
|
142
|
+
* @param timestamp - Value of the `X-ArisPay-Timestamp` header
|
|
143
|
+
* @param secret - Your webhook secret (`whsec_...`)
|
|
144
|
+
* @param toleranceSec - Maximum allowed age in seconds (default: 300 = 5 min)
|
|
145
|
+
* @returns `true` if the signature is valid and the timestamp is within tolerance
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* import { WebhookService } from 'arispay';
|
|
150
|
+
*
|
|
151
|
+
* app.post('/webhooks', (req, res) => {
|
|
152
|
+
* const isValid = WebhookService.verifyWebhookSignature(
|
|
153
|
+
* req.body, // raw body string
|
|
154
|
+
* req.headers['x-arispay-signature'],
|
|
155
|
+
* req.headers['x-arispay-timestamp'],
|
|
156
|
+
* process.env.WEBHOOK_SECRET!,
|
|
157
|
+
* );
|
|
158
|
+
* if (!isValid) return res.status(401).send('Invalid signature');
|
|
159
|
+
* // Process the webhook event...
|
|
160
|
+
* });
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
static verifyWebhookSignature(body: string, signature: string, timestamp: string, secret: string, toleranceSec?: number): boolean;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
interface ArisPayConfig {
|
|
167
|
+
apiKey: string;
|
|
168
|
+
environment?: 'sandbox' | 'production';
|
|
169
|
+
baseUrl?: string;
|
|
170
|
+
}
|
|
171
|
+
interface ArisPayClient {
|
|
172
|
+
agents: AgentService;
|
|
173
|
+
users: UserService;
|
|
174
|
+
payments: PaymentService;
|
|
175
|
+
transactions: TransactionService;
|
|
176
|
+
webhooks: WebhookService;
|
|
177
|
+
}
|
|
178
|
+
declare class ArisPay {
|
|
179
|
+
/**
|
|
180
|
+
* Initialize the ArisPay SDK.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* import ArisPay from 'arispay';
|
|
185
|
+
*
|
|
186
|
+
* const arispay = ArisPay.init({
|
|
187
|
+
* apiKey: 'ap_test_abc123',
|
|
188
|
+
* environment: 'sandbox',
|
|
189
|
+
* });
|
|
190
|
+
*
|
|
191
|
+
* const agent = await arispay.agents.register({
|
|
192
|
+
* name: 'TableClaw',
|
|
193
|
+
* description: 'AI restaurant booking agent',
|
|
194
|
+
* permissions: ['browse', 'payment'],
|
|
195
|
+
* });
|
|
196
|
+
*
|
|
197
|
+
* const user = await arispay.users.create({
|
|
198
|
+
* externalId: 'user_123',
|
|
199
|
+
* email: 'jane@example.com',
|
|
200
|
+
* });
|
|
201
|
+
*
|
|
202
|
+
* const payment = await arispay.payments.create({
|
|
203
|
+
* agentId: agent.id,
|
|
204
|
+
* userId: user.id,
|
|
205
|
+
* amount: 20000,
|
|
206
|
+
* currency: 'USD',
|
|
207
|
+
* merchantUrl: 'https://nobu.com',
|
|
208
|
+
* memo: 'Table for 2',
|
|
209
|
+
* idempotencyKey: 'booking_123',
|
|
210
|
+
* });
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
static init(config: ArisPayConfig): ArisPayClient;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export { AgentService, ArisPay, type ArisPayClient, type ArisPayConfig, PaymentService, TransactionService, UserService, WebhookService, ArisPay as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
// ../shared/dist/constants.js
|
|
2
|
+
var CRYPTO_CHAINS = {
|
|
3
|
+
ETHEREUM: "ethereum",
|
|
4
|
+
BASE: "base",
|
|
5
|
+
POLYGON: "polygon",
|
|
6
|
+
SOLANA: "solana"
|
|
7
|
+
};
|
|
8
|
+
var SUPPORTED_CHAINS = Object.values(CRYPTO_CHAINS);
|
|
9
|
+
var ERROR_CODES = {
|
|
10
|
+
INSUFFICIENT_FUNDS: "INSUFFICIENT_FUNDS",
|
|
11
|
+
SPEND_LIMIT_EXCEEDED: "SPEND_LIMIT_EXCEEDED",
|
|
12
|
+
MERCHANT_REJECTED: "MERCHANT_REJECTED",
|
|
13
|
+
TAP_VERIFICATION_FAILED: "TAP_VERIFICATION_FAILED",
|
|
14
|
+
CARD_DECLINED: "CARD_DECLINED",
|
|
15
|
+
INVALID_API_KEY: "INVALID_API_KEY",
|
|
16
|
+
RATE_LIMITED: "RATE_LIMITED",
|
|
17
|
+
IDEMPOTENCY_CONFLICT: "IDEMPOTENCY_CONFLICT",
|
|
18
|
+
AGENT_NOT_FOUND: "AGENT_NOT_FOUND",
|
|
19
|
+
USER_NOT_FOUND: "USER_NOT_FOUND",
|
|
20
|
+
PAYMENT_NOT_FOUND: "PAYMENT_NOT_FOUND",
|
|
21
|
+
INVALID_REQUEST: "INVALID_REQUEST",
|
|
22
|
+
INTERNAL_ERROR: "INTERNAL_ERROR",
|
|
23
|
+
CIRCUIT_BREAKER_TRIPPED: "CIRCUIT_BREAKER_TRIPPED",
|
|
24
|
+
AGENT_SUSPENDED: "AGENT_SUSPENDED",
|
|
25
|
+
WALLET_NOT_FOUND: "WALLET_NOT_FOUND",
|
|
26
|
+
INSUFFICIENT_ALLOWANCE: "INSUFFICIENT_ALLOWANCE",
|
|
27
|
+
INSUFFICIENT_TOKEN_BALANCE: "INSUFFICIENT_TOKEN_BALANCE",
|
|
28
|
+
CRYPTO_TRANSFER_FAILED: "CRYPTO_TRANSFER_FAILED",
|
|
29
|
+
INVALID_WALLET_ADDRESS: "INVALID_WALLET_ADDRESS",
|
|
30
|
+
UNSUPPORTED_CHAIN: "UNSUPPORTED_CHAIN",
|
|
31
|
+
UNSUPPORTED_TOKEN: "UNSUPPORTED_TOKEN",
|
|
32
|
+
UNSUPPORTED_CARD_NETWORK: "UNSUPPORTED_CARD_NETWORK",
|
|
33
|
+
NETWORK_REGISTRY_ERROR: "NETWORK_REGISTRY_ERROR",
|
|
34
|
+
INSUFFICIENT_BALANCE: "INSUFFICIENT_BALANCE",
|
|
35
|
+
AGENT_MODE_MISMATCH: "AGENT_MODE_MISMATCH",
|
|
36
|
+
THREE_DS_FAILED: "THREE_DS_FAILED",
|
|
37
|
+
MERCHANT_NOT_FOUND: "MERCHANT_NOT_FOUND",
|
|
38
|
+
INVALID_MERCHANT_API_KEY: "INVALID_MERCHANT_API_KEY"
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// ../shared/dist/errors.js
|
|
42
|
+
var ArisPayError = class extends Error {
|
|
43
|
+
code;
|
|
44
|
+
statusCode;
|
|
45
|
+
constructor(code, message, statusCode = 400) {
|
|
46
|
+
super(message);
|
|
47
|
+
this.code = code;
|
|
48
|
+
this.statusCode = statusCode;
|
|
49
|
+
this.name = "ArisPayError";
|
|
50
|
+
}
|
|
51
|
+
toJSON() {
|
|
52
|
+
return {
|
|
53
|
+
error: {
|
|
54
|
+
code: this.code,
|
|
55
|
+
message: this.message
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var SpendLimitExceededError = class extends ArisPayError {
|
|
61
|
+
constructor(limit, requested) {
|
|
62
|
+
super("SPEND_LIMIT_EXCEEDED", `Spend limit exceeded: max ${limit} cents per transaction, requested ${requested} cents`, 403);
|
|
63
|
+
this.name = "SpendLimitExceededError";
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var InsufficientFundsError = class extends ArisPayError {
|
|
67
|
+
constructor(message = "Insufficient funds for this transaction") {
|
|
68
|
+
super("INSUFFICIENT_FUNDS", message, 402);
|
|
69
|
+
this.name = "InsufficientFundsError";
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var InsufficientBalanceError = class extends ArisPayError {
|
|
73
|
+
constructor(available, requested) {
|
|
74
|
+
super("INSUFFICIENT_BALANCE", `Insufficient agent balance: available ${available} cents, requested ${requested} cents`, 402);
|
|
75
|
+
this.name = "InsufficientBalanceError";
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
var AgentModeMismatchError = class extends ArisPayError {
|
|
79
|
+
constructor(expected, actual) {
|
|
80
|
+
super("AGENT_MODE_MISMATCH", `Agent mode mismatch: expected '${expected}', got '${actual}'`, 400);
|
|
81
|
+
this.name = "AgentModeMismatchError";
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/client.ts
|
|
86
|
+
var SDK_REQUEST_TIMEOUT_MS = 3e4;
|
|
87
|
+
var VALID_ERROR_CODES = new Set(Object.values(ERROR_CODES));
|
|
88
|
+
function toErrorCode(code) {
|
|
89
|
+
if (typeof code === "string" && VALID_ERROR_CODES.has(code)) {
|
|
90
|
+
return code;
|
|
91
|
+
}
|
|
92
|
+
return "INTERNAL_ERROR";
|
|
93
|
+
}
|
|
94
|
+
var HttpClient = class {
|
|
95
|
+
constructor(baseUrl, apiKey) {
|
|
96
|
+
this.baseUrl = baseUrl;
|
|
97
|
+
this.apiKey = apiKey;
|
|
98
|
+
}
|
|
99
|
+
async request(method, path, body) {
|
|
100
|
+
const url = `${this.baseUrl}${path}`;
|
|
101
|
+
const headers = {
|
|
102
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
103
|
+
"Content-Type": "application/json"
|
|
104
|
+
};
|
|
105
|
+
const res = await fetch(url, {
|
|
106
|
+
method,
|
|
107
|
+
headers,
|
|
108
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
109
|
+
signal: AbortSignal.timeout(SDK_REQUEST_TIMEOUT_MS)
|
|
110
|
+
});
|
|
111
|
+
const data = await res.json();
|
|
112
|
+
if (!res.ok) {
|
|
113
|
+
const err = data;
|
|
114
|
+
throw new ArisPayError(
|
|
115
|
+
toErrorCode(err.error?.code),
|
|
116
|
+
err.error?.message ?? "Request failed",
|
|
117
|
+
res.status
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
return data;
|
|
121
|
+
}
|
|
122
|
+
get(path) {
|
|
123
|
+
return this.request("GET", path);
|
|
124
|
+
}
|
|
125
|
+
post(path, body) {
|
|
126
|
+
return this.request("POST", path, body);
|
|
127
|
+
}
|
|
128
|
+
put(path, body) {
|
|
129
|
+
return this.request("PUT", path, body);
|
|
130
|
+
}
|
|
131
|
+
delete(path) {
|
|
132
|
+
return this.request("DELETE", path);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// src/agents.ts
|
|
137
|
+
var AgentService = class {
|
|
138
|
+
constructor(client) {
|
|
139
|
+
this.client = client;
|
|
140
|
+
}
|
|
141
|
+
async register(params) {
|
|
142
|
+
return this.client.post("/v1/agents", params);
|
|
143
|
+
}
|
|
144
|
+
async get(agentId) {
|
|
145
|
+
return this.client.get(`/v1/agents/${agentId}`);
|
|
146
|
+
}
|
|
147
|
+
async list(params) {
|
|
148
|
+
const query = new URLSearchParams();
|
|
149
|
+
if (params?.name) query.set("name", params.name);
|
|
150
|
+
if (params?.status) query.set("status", params.status);
|
|
151
|
+
if (params?.limit) query.set("limit", String(params.limit));
|
|
152
|
+
if (params?.offset) query.set("offset", String(params.offset));
|
|
153
|
+
const qs = query.toString();
|
|
154
|
+
return this.client.get(`/v1/agents${qs ? `?${qs}` : ""}`);
|
|
155
|
+
}
|
|
156
|
+
async listChildren(agentId) {
|
|
157
|
+
return this.client.get(`/v1/agents/${agentId}/children`);
|
|
158
|
+
}
|
|
159
|
+
async resume(agentId) {
|
|
160
|
+
return this.client.post(`/v1/agents/${agentId}/resume`);
|
|
161
|
+
}
|
|
162
|
+
async setCircuitBreaker(agentId, params) {
|
|
163
|
+
return this.client.put(`/v1/agents/${agentId}/circuit-breaker`, params);
|
|
164
|
+
}
|
|
165
|
+
async getCircuitBreaker(agentId) {
|
|
166
|
+
return this.client.get(`/v1/agents/${agentId}/circuit-breaker`);
|
|
167
|
+
}
|
|
168
|
+
async rotateKeys(agentId) {
|
|
169
|
+
return this.client.post(`/v1/agents/${agentId}/rotate-keys`);
|
|
170
|
+
}
|
|
171
|
+
// ── Autonomous Agent Methods ──────────────────────────
|
|
172
|
+
/**
|
|
173
|
+
* Get the current balance for an autonomous agent.
|
|
174
|
+
*/
|
|
175
|
+
async getBalance(agentId) {
|
|
176
|
+
return this.client.get(`/v1/agents/${agentId}/balance`);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Fund an autonomous agent's balance (topup).
|
|
180
|
+
*/
|
|
181
|
+
async topup(agentId, params) {
|
|
182
|
+
return this.client.post(`/v1/agents/${agentId}/topup`, params);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Withdraw from an autonomous agent's balance (sweep).
|
|
186
|
+
* Omit `amount` to sweep everything above the sweep threshold.
|
|
187
|
+
*/
|
|
188
|
+
async sweep(agentId, params) {
|
|
189
|
+
return this.client.post(`/v1/agents/${agentId}/sweep`, params ?? {});
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get paginated ledger history for an autonomous agent.
|
|
193
|
+
*/
|
|
194
|
+
async getLedger(agentId, params) {
|
|
195
|
+
const query = new URLSearchParams();
|
|
196
|
+
if (params?.limit) query.set("limit", String(params.limit));
|
|
197
|
+
if (params?.offset) query.set("offset", String(params.offset));
|
|
198
|
+
if (params?.type) query.set("type", params.type);
|
|
199
|
+
if (params?.from) query.set("from", params.from);
|
|
200
|
+
if (params?.to) query.set("to", params.to);
|
|
201
|
+
const qs = query.toString();
|
|
202
|
+
return this.client.get(`/v1/agents/${agentId}/ledger${qs ? `?${qs}` : ""}`);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Record an earning (inbound money) for an autonomous agent.
|
|
206
|
+
*/
|
|
207
|
+
async recordEarning(agentId, params) {
|
|
208
|
+
return this.client.post(`/v1/agents/${agentId}/earn`, params);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// src/users.ts
|
|
213
|
+
var UserService = class {
|
|
214
|
+
constructor(client) {
|
|
215
|
+
this.client = client;
|
|
216
|
+
}
|
|
217
|
+
async create(params) {
|
|
218
|
+
return this.client.post("/v1/users", params);
|
|
219
|
+
}
|
|
220
|
+
async get(userId) {
|
|
221
|
+
return this.client.get(`/v1/users/${userId}`);
|
|
222
|
+
}
|
|
223
|
+
async getByExternalId(externalId) {
|
|
224
|
+
return this.client.get(`/v1/users/by-external/${encodeURIComponent(externalId)}`);
|
|
225
|
+
}
|
|
226
|
+
async getWalletStatus(userId) {
|
|
227
|
+
return this.client.get(`/v1/users/${userId}/wallet-status`);
|
|
228
|
+
}
|
|
229
|
+
async addPaymentMethod(params) {
|
|
230
|
+
const { userId, ...body } = params;
|
|
231
|
+
return this.client.post(`/v1/users/${userId}/payment-methods`, body);
|
|
232
|
+
}
|
|
233
|
+
async completePaymentMethod(params) {
|
|
234
|
+
const { userId, ...body } = params;
|
|
235
|
+
return this.client.post(`/v1/users/${userId}/payment-methods/complete`, body);
|
|
236
|
+
}
|
|
237
|
+
async setLimits(params) {
|
|
238
|
+
const { userId, ...body } = params;
|
|
239
|
+
return this.client.put(`/v1/users/${userId}/limits`, body);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
// src/payments.ts
|
|
244
|
+
var PaymentService = class {
|
|
245
|
+
constructor(client) {
|
|
246
|
+
this.client = client;
|
|
247
|
+
}
|
|
248
|
+
async create(params) {
|
|
249
|
+
return this.client.post("/v1/payments", params);
|
|
250
|
+
}
|
|
251
|
+
async get(paymentId) {
|
|
252
|
+
return this.client.get(`/v1/payments/${paymentId}`);
|
|
253
|
+
}
|
|
254
|
+
/** Complete a 3D Secure authentication step (method or challenge) */
|
|
255
|
+
async complete3ds(paymentId, params) {
|
|
256
|
+
return this.client.post(
|
|
257
|
+
`/v1/payments/${paymentId}/3ds/complete`,
|
|
258
|
+
params
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
// src/transactions.ts
|
|
264
|
+
var TransactionService = class {
|
|
265
|
+
constructor(client) {
|
|
266
|
+
this.client = client;
|
|
267
|
+
}
|
|
268
|
+
async list(params) {
|
|
269
|
+
const searchParams = new URLSearchParams();
|
|
270
|
+
if (params?.userId) searchParams.set("userId", params.userId);
|
|
271
|
+
if (params?.agentId) searchParams.set("agentId", params.agentId);
|
|
272
|
+
if (params?.from) searchParams.set("from", params.from);
|
|
273
|
+
if (params?.to) searchParams.set("to", params.to);
|
|
274
|
+
if (params?.limit) searchParams.set("limit", String(params.limit));
|
|
275
|
+
if (params?.offset) searchParams.set("offset", String(params.offset));
|
|
276
|
+
const qs = searchParams.toString();
|
|
277
|
+
return this.client.get(`/v1/transactions${qs ? `?${qs}` : ""}`);
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
// src/webhooks.ts
|
|
282
|
+
import { createHmac, timingSafeEqual } from "crypto";
|
|
283
|
+
var WEBHOOK_TOLERANCE_SECONDS = 300;
|
|
284
|
+
var WebhookService = class {
|
|
285
|
+
constructor(client) {
|
|
286
|
+
this.client = client;
|
|
287
|
+
}
|
|
288
|
+
async register(params) {
|
|
289
|
+
return this.client.post("/v1/webhooks", params);
|
|
290
|
+
}
|
|
291
|
+
async list() {
|
|
292
|
+
return this.client.get("/v1/webhooks");
|
|
293
|
+
}
|
|
294
|
+
async delete(webhookId) {
|
|
295
|
+
await this.client.delete(`/v1/webhooks/${webhookId}`);
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Verify a webhook signature from an incoming request.
|
|
299
|
+
*
|
|
300
|
+
* ArisPay signs every webhook delivery with HMAC-SHA256 using the secret
|
|
301
|
+
* returned when you registered the webhook. The signature is sent in the
|
|
302
|
+
* `X-ArisPay-Signature` header and the unix timestamp in `X-ArisPay-Timestamp`.
|
|
303
|
+
*
|
|
304
|
+
* @param body - The raw request body string (do NOT parse it first)
|
|
305
|
+
* @param signature - Value of the `X-ArisPay-Signature` header
|
|
306
|
+
* @param timestamp - Value of the `X-ArisPay-Timestamp` header
|
|
307
|
+
* @param secret - Your webhook secret (`whsec_...`)
|
|
308
|
+
* @param toleranceSec - Maximum allowed age in seconds (default: 300 = 5 min)
|
|
309
|
+
* @returns `true` if the signature is valid and the timestamp is within tolerance
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* import { WebhookService } from 'arispay';
|
|
314
|
+
*
|
|
315
|
+
* app.post('/webhooks', (req, res) => {
|
|
316
|
+
* const isValid = WebhookService.verifyWebhookSignature(
|
|
317
|
+
* req.body, // raw body string
|
|
318
|
+
* req.headers['x-arispay-signature'],
|
|
319
|
+
* req.headers['x-arispay-timestamp'],
|
|
320
|
+
* process.env.WEBHOOK_SECRET!,
|
|
321
|
+
* );
|
|
322
|
+
* if (!isValid) return res.status(401).send('Invalid signature');
|
|
323
|
+
* // Process the webhook event...
|
|
324
|
+
* });
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
static verifyWebhookSignature(body, signature, timestamp, secret, toleranceSec = WEBHOOK_TOLERANCE_SECONDS) {
|
|
328
|
+
if (!body || !signature || !timestamp || !secret) return false;
|
|
329
|
+
const ts = parseInt(timestamp, 10);
|
|
330
|
+
if (isNaN(ts)) return false;
|
|
331
|
+
const age = Math.abs(Math.floor(Date.now() / 1e3) - ts);
|
|
332
|
+
if (age > toleranceSec) return false;
|
|
333
|
+
const signaturePayload = `${timestamp}.${body}`;
|
|
334
|
+
const expected = createHmac("sha256", secret).update(signaturePayload).digest("hex");
|
|
335
|
+
try {
|
|
336
|
+
return timingSafeEqual(Buffer.from(signature, "hex"), Buffer.from(expected, "hex"));
|
|
337
|
+
} catch {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
// src/index.ts
|
|
344
|
+
var ArisPay = class {
|
|
345
|
+
/**
|
|
346
|
+
* Initialize the ArisPay SDK.
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```ts
|
|
350
|
+
* import ArisPay from 'arispay';
|
|
351
|
+
*
|
|
352
|
+
* const arispay = ArisPay.init({
|
|
353
|
+
* apiKey: 'ap_test_abc123',
|
|
354
|
+
* environment: 'sandbox',
|
|
355
|
+
* });
|
|
356
|
+
*
|
|
357
|
+
* const agent = await arispay.agents.register({
|
|
358
|
+
* name: 'TableClaw',
|
|
359
|
+
* description: 'AI restaurant booking agent',
|
|
360
|
+
* permissions: ['browse', 'payment'],
|
|
361
|
+
* });
|
|
362
|
+
*
|
|
363
|
+
* const user = await arispay.users.create({
|
|
364
|
+
* externalId: 'user_123',
|
|
365
|
+
* email: 'jane@example.com',
|
|
366
|
+
* });
|
|
367
|
+
*
|
|
368
|
+
* const payment = await arispay.payments.create({
|
|
369
|
+
* agentId: agent.id,
|
|
370
|
+
* userId: user.id,
|
|
371
|
+
* amount: 20000,
|
|
372
|
+
* currency: 'USD',
|
|
373
|
+
* merchantUrl: 'https://nobu.com',
|
|
374
|
+
* memo: 'Table for 2',
|
|
375
|
+
* idempotencyKey: 'booking_123',
|
|
376
|
+
* });
|
|
377
|
+
* ```
|
|
378
|
+
*/
|
|
379
|
+
static init(config) {
|
|
380
|
+
const defaultUrl = config.environment === "production" ? "https://api.arispay.app" : "https://api-production-79ea.up.railway.app";
|
|
381
|
+
const baseUrl = config.baseUrl || defaultUrl;
|
|
382
|
+
const client = new HttpClient(baseUrl, config.apiKey);
|
|
383
|
+
return {
|
|
384
|
+
agents: new AgentService(client),
|
|
385
|
+
users: new UserService(client),
|
|
386
|
+
payments: new PaymentService(client),
|
|
387
|
+
transactions: new TransactionService(client),
|
|
388
|
+
webhooks: new WebhookService(client)
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
var index_default = ArisPay;
|
|
393
|
+
export {
|
|
394
|
+
AgentModeMismatchError,
|
|
395
|
+
AgentService,
|
|
396
|
+
ArisPay,
|
|
397
|
+
ArisPayError,
|
|
398
|
+
InsufficientBalanceError,
|
|
399
|
+
InsufficientFundsError,
|
|
400
|
+
PaymentService,
|
|
401
|
+
SpendLimitExceededError,
|
|
402
|
+
TransactionService,
|
|
403
|
+
UserService,
|
|
404
|
+
WebhookService,
|
|
405
|
+
index_default as default
|
|
406
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "arispay",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "SDK and CLI for enabling agent-initiated payments via Visa TAP + Fiserv",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"arispay": "./dist/cli.js",
|
|
10
|
+
"payagent": "./dist/cli-b.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"build:tsc": "tsc",
|
|
21
|
+
"dev": "tsc --watch"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@arispay/shared": "workspace:*",
|
|
25
|
+
"@types/node": "^22.0.0",
|
|
26
|
+
"tsup": "^8.5.1",
|
|
27
|
+
"typescript": "^5.7.0"
|
|
28
|
+
},
|
|
29
|
+
"keywords": ["ai", "agents", "payments", "visa", "tap", "fiserv", "openclaw", "agentic-commerce"],
|
|
30
|
+
"license": "MIT"
|
|
31
|
+
}
|