@tallion/sdk 0.1.3 → 0.1.4
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/dist/index.d.mts +79 -1
- package/dist/index.d.ts +79 -1
- package/dist/index.js +108 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +107 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.d.mts
CHANGED
|
@@ -99,6 +99,59 @@ interface WebhookEvent {
|
|
|
99
99
|
timestamp: string;
|
|
100
100
|
data: Record<string, unknown>;
|
|
101
101
|
}
|
|
102
|
+
interface CreateIntentOptions {
|
|
103
|
+
customerToken: string;
|
|
104
|
+
amount: number;
|
|
105
|
+
currency?: string;
|
|
106
|
+
merchant?: {
|
|
107
|
+
name: string;
|
|
108
|
+
url?: string;
|
|
109
|
+
mcc?: string;
|
|
110
|
+
};
|
|
111
|
+
product?: {
|
|
112
|
+
description: string;
|
|
113
|
+
url?: string;
|
|
114
|
+
};
|
|
115
|
+
walletId?: string;
|
|
116
|
+
amountTolerancePct?: number;
|
|
117
|
+
}
|
|
118
|
+
interface IntentCardDetails {
|
|
119
|
+
pan: string;
|
|
120
|
+
cvv: string;
|
|
121
|
+
expMonth: number;
|
|
122
|
+
expYear: number;
|
|
123
|
+
lastFour: string;
|
|
124
|
+
}
|
|
125
|
+
interface IntentResult {
|
|
126
|
+
intentId: string;
|
|
127
|
+
status: 'card_issued' | 'awaiting_approval' | 'declined';
|
|
128
|
+
amount: number;
|
|
129
|
+
currency: string;
|
|
130
|
+
merchantName?: string;
|
|
131
|
+
expiresAt?: string;
|
|
132
|
+
transactionId?: string;
|
|
133
|
+
/** Card details — only present when status is "card_issued". */
|
|
134
|
+
card?: IntentCardDetails;
|
|
135
|
+
}
|
|
136
|
+
interface IntentStatusResult {
|
|
137
|
+
intentId: string;
|
|
138
|
+
status: string;
|
|
139
|
+
amount: number;
|
|
140
|
+
currency: string;
|
|
141
|
+
merchantName?: string;
|
|
142
|
+
cardLastFour?: string;
|
|
143
|
+
asaVerified: boolean;
|
|
144
|
+
asaAmount?: number;
|
|
145
|
+
asaMerchantDescriptor?: string;
|
|
146
|
+
asaMismatchReason?: string;
|
|
147
|
+
transactionId?: string;
|
|
148
|
+
expiresAt?: string;
|
|
149
|
+
createdAt: string;
|
|
150
|
+
}
|
|
151
|
+
interface ListIntentsOptions {
|
|
152
|
+
limit?: number;
|
|
153
|
+
offset?: number;
|
|
154
|
+
}
|
|
102
155
|
|
|
103
156
|
declare class AuthorizeModule {
|
|
104
157
|
private baseUrl;
|
|
@@ -133,6 +186,29 @@ declare class BalanceModule {
|
|
|
133
186
|
get(customerToken: string, walletId?: string): Promise<BalanceResult>;
|
|
134
187
|
}
|
|
135
188
|
|
|
189
|
+
declare class IntentsModule {
|
|
190
|
+
private baseUrl;
|
|
191
|
+
private apiKey;
|
|
192
|
+
constructor(baseUrl: string, apiKey: string);
|
|
193
|
+
/**
|
|
194
|
+
* Create a purchase intent (Buy Anywhere).
|
|
195
|
+
* Returns a virtual card for the customer to use at the merchant.
|
|
196
|
+
*/
|
|
197
|
+
create(options: CreateIntentOptions): Promise<IntentResult>;
|
|
198
|
+
/**
|
|
199
|
+
* Get the current status of a purchase intent.
|
|
200
|
+
*/
|
|
201
|
+
get(customerToken: string, intentId: string): Promise<IntentStatusResult>;
|
|
202
|
+
/**
|
|
203
|
+
* Cancel an active purchase intent.
|
|
204
|
+
*/
|
|
205
|
+
cancel(customerToken: string, intentId: string): Promise<IntentStatusResult>;
|
|
206
|
+
/**
|
|
207
|
+
* List purchase intents for the authenticated customer.
|
|
208
|
+
*/
|
|
209
|
+
list(customerToken: string, options?: ListIntentsOptions): Promise<IntentStatusResult[]>;
|
|
210
|
+
}
|
|
211
|
+
|
|
136
212
|
declare class PurchaseModule {
|
|
137
213
|
private baseUrl;
|
|
138
214
|
private apiKey;
|
|
@@ -170,6 +246,8 @@ declare class Tally {
|
|
|
170
246
|
purchases: PurchaseModule;
|
|
171
247
|
/** Balance operations */
|
|
172
248
|
balances: BalanceModule;
|
|
249
|
+
/** Purchase intents (Buy Anywhere) */
|
|
250
|
+
intents: IntentsModule;
|
|
173
251
|
/** Webhook signature verification */
|
|
174
252
|
webhooks: WebhooksModule;
|
|
175
253
|
constructor(config: TallyConfig);
|
|
@@ -197,4 +275,4 @@ declare class TallionError extends Error {
|
|
|
197
275
|
constructor(status: number, message: string, code?: string);
|
|
198
276
|
}
|
|
199
277
|
|
|
200
|
-
export { type AuthUrlResult, AuthorizeModule, BalanceModule, type BalanceResult, type CreateAuthUrlOptions, type ExchangeCodeOptions, type LegacyPurchaseOptions, type LineItem, type MerchantInfo, PurchaseModule, type PurchaseOptions, type PurchaseResult, type RefreshTokenOptions, type SpendLimits, TallionError, Tally, type TallyConfig, type TokenResult, type TransactionContext, type WebhookEvent, WebhooksModule };
|
|
278
|
+
export { type AuthUrlResult, AuthorizeModule, BalanceModule, type BalanceResult, type CreateAuthUrlOptions, type CreateIntentOptions, type ExchangeCodeOptions, type IntentCardDetails, type IntentResult, type IntentStatusResult, IntentsModule, type LegacyPurchaseOptions, type LineItem, type ListIntentsOptions, type MerchantInfo, PurchaseModule, type PurchaseOptions, type PurchaseResult, type RefreshTokenOptions, type SpendLimits, TallionError, Tally, type TallyConfig, type TokenResult, type TransactionContext, type WebhookEvent, WebhooksModule };
|
package/dist/index.d.ts
CHANGED
|
@@ -99,6 +99,59 @@ interface WebhookEvent {
|
|
|
99
99
|
timestamp: string;
|
|
100
100
|
data: Record<string, unknown>;
|
|
101
101
|
}
|
|
102
|
+
interface CreateIntentOptions {
|
|
103
|
+
customerToken: string;
|
|
104
|
+
amount: number;
|
|
105
|
+
currency?: string;
|
|
106
|
+
merchant?: {
|
|
107
|
+
name: string;
|
|
108
|
+
url?: string;
|
|
109
|
+
mcc?: string;
|
|
110
|
+
};
|
|
111
|
+
product?: {
|
|
112
|
+
description: string;
|
|
113
|
+
url?: string;
|
|
114
|
+
};
|
|
115
|
+
walletId?: string;
|
|
116
|
+
amountTolerancePct?: number;
|
|
117
|
+
}
|
|
118
|
+
interface IntentCardDetails {
|
|
119
|
+
pan: string;
|
|
120
|
+
cvv: string;
|
|
121
|
+
expMonth: number;
|
|
122
|
+
expYear: number;
|
|
123
|
+
lastFour: string;
|
|
124
|
+
}
|
|
125
|
+
interface IntentResult {
|
|
126
|
+
intentId: string;
|
|
127
|
+
status: 'card_issued' | 'awaiting_approval' | 'declined';
|
|
128
|
+
amount: number;
|
|
129
|
+
currency: string;
|
|
130
|
+
merchantName?: string;
|
|
131
|
+
expiresAt?: string;
|
|
132
|
+
transactionId?: string;
|
|
133
|
+
/** Card details — only present when status is "card_issued". */
|
|
134
|
+
card?: IntentCardDetails;
|
|
135
|
+
}
|
|
136
|
+
interface IntentStatusResult {
|
|
137
|
+
intentId: string;
|
|
138
|
+
status: string;
|
|
139
|
+
amount: number;
|
|
140
|
+
currency: string;
|
|
141
|
+
merchantName?: string;
|
|
142
|
+
cardLastFour?: string;
|
|
143
|
+
asaVerified: boolean;
|
|
144
|
+
asaAmount?: number;
|
|
145
|
+
asaMerchantDescriptor?: string;
|
|
146
|
+
asaMismatchReason?: string;
|
|
147
|
+
transactionId?: string;
|
|
148
|
+
expiresAt?: string;
|
|
149
|
+
createdAt: string;
|
|
150
|
+
}
|
|
151
|
+
interface ListIntentsOptions {
|
|
152
|
+
limit?: number;
|
|
153
|
+
offset?: number;
|
|
154
|
+
}
|
|
102
155
|
|
|
103
156
|
declare class AuthorizeModule {
|
|
104
157
|
private baseUrl;
|
|
@@ -133,6 +186,29 @@ declare class BalanceModule {
|
|
|
133
186
|
get(customerToken: string, walletId?: string): Promise<BalanceResult>;
|
|
134
187
|
}
|
|
135
188
|
|
|
189
|
+
declare class IntentsModule {
|
|
190
|
+
private baseUrl;
|
|
191
|
+
private apiKey;
|
|
192
|
+
constructor(baseUrl: string, apiKey: string);
|
|
193
|
+
/**
|
|
194
|
+
* Create a purchase intent (Buy Anywhere).
|
|
195
|
+
* Returns a virtual card for the customer to use at the merchant.
|
|
196
|
+
*/
|
|
197
|
+
create(options: CreateIntentOptions): Promise<IntentResult>;
|
|
198
|
+
/**
|
|
199
|
+
* Get the current status of a purchase intent.
|
|
200
|
+
*/
|
|
201
|
+
get(customerToken: string, intentId: string): Promise<IntentStatusResult>;
|
|
202
|
+
/**
|
|
203
|
+
* Cancel an active purchase intent.
|
|
204
|
+
*/
|
|
205
|
+
cancel(customerToken: string, intentId: string): Promise<IntentStatusResult>;
|
|
206
|
+
/**
|
|
207
|
+
* List purchase intents for the authenticated customer.
|
|
208
|
+
*/
|
|
209
|
+
list(customerToken: string, options?: ListIntentsOptions): Promise<IntentStatusResult[]>;
|
|
210
|
+
}
|
|
211
|
+
|
|
136
212
|
declare class PurchaseModule {
|
|
137
213
|
private baseUrl;
|
|
138
214
|
private apiKey;
|
|
@@ -170,6 +246,8 @@ declare class Tally {
|
|
|
170
246
|
purchases: PurchaseModule;
|
|
171
247
|
/** Balance operations */
|
|
172
248
|
balances: BalanceModule;
|
|
249
|
+
/** Purchase intents (Buy Anywhere) */
|
|
250
|
+
intents: IntentsModule;
|
|
173
251
|
/** Webhook signature verification */
|
|
174
252
|
webhooks: WebhooksModule;
|
|
175
253
|
constructor(config: TallyConfig);
|
|
@@ -197,4 +275,4 @@ declare class TallionError extends Error {
|
|
|
197
275
|
constructor(status: number, message: string, code?: string);
|
|
198
276
|
}
|
|
199
277
|
|
|
200
|
-
export { type AuthUrlResult, AuthorizeModule, BalanceModule, type BalanceResult, type CreateAuthUrlOptions, type ExchangeCodeOptions, type LegacyPurchaseOptions, type LineItem, type MerchantInfo, PurchaseModule, type PurchaseOptions, type PurchaseResult, type RefreshTokenOptions, type SpendLimits, TallionError, Tally, type TallyConfig, type TokenResult, type TransactionContext, type WebhookEvent, WebhooksModule };
|
|
278
|
+
export { type AuthUrlResult, AuthorizeModule, BalanceModule, type BalanceResult, type CreateAuthUrlOptions, type CreateIntentOptions, type ExchangeCodeOptions, type IntentCardDetails, type IntentResult, type IntentStatusResult, IntentsModule, type LegacyPurchaseOptions, type LineItem, type ListIntentsOptions, type MerchantInfo, PurchaseModule, type PurchaseOptions, type PurchaseResult, type RefreshTokenOptions, type SpendLimits, TallionError, Tally, type TallyConfig, type TokenResult, type TransactionContext, type WebhookEvent, WebhooksModule };
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AuthorizeModule: () => AuthorizeModule,
|
|
24
24
|
BalanceModule: () => BalanceModule,
|
|
25
|
+
IntentsModule: () => IntentsModule,
|
|
25
26
|
PurchaseModule: () => PurchaseModule,
|
|
26
27
|
TallionError: () => TallionError,
|
|
27
28
|
Tally: () => Tally,
|
|
@@ -206,6 +207,111 @@ var BalanceModule = class {
|
|
|
206
207
|
}
|
|
207
208
|
};
|
|
208
209
|
|
|
210
|
+
// src/intents.ts
|
|
211
|
+
var IntentsModule = class {
|
|
212
|
+
constructor(baseUrl, apiKey) {
|
|
213
|
+
this.baseUrl = baseUrl;
|
|
214
|
+
this.apiKey = apiKey;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Create a purchase intent (Buy Anywhere).
|
|
218
|
+
* Returns a virtual card for the customer to use at the merchant.
|
|
219
|
+
*/
|
|
220
|
+
async create(options) {
|
|
221
|
+
const res = await request(this.baseUrl, "/intents", options.customerToken, {
|
|
222
|
+
method: "POST",
|
|
223
|
+
body: {
|
|
224
|
+
amount: options.amount,
|
|
225
|
+
currency: options.currency || "USD",
|
|
226
|
+
wallet_id: options.walletId,
|
|
227
|
+
merchant: options.merchant ? {
|
|
228
|
+
name: options.merchant.name,
|
|
229
|
+
url: options.merchant.url,
|
|
230
|
+
mcc: options.merchant.mcc
|
|
231
|
+
} : void 0,
|
|
232
|
+
product: options.product ? {
|
|
233
|
+
description: options.product.description,
|
|
234
|
+
url: options.product.url
|
|
235
|
+
} : void 0,
|
|
236
|
+
amount_tolerance_pct: options.amountTolerancePct
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
return {
|
|
240
|
+
intentId: res.intent_id,
|
|
241
|
+
status: res.status,
|
|
242
|
+
amount: res.amount,
|
|
243
|
+
currency: res.currency,
|
|
244
|
+
merchantName: res.merchant_name,
|
|
245
|
+
expiresAt: res.expires_at,
|
|
246
|
+
transactionId: res.transaction_id,
|
|
247
|
+
card: res.card ? {
|
|
248
|
+
pan: res.card.pan,
|
|
249
|
+
cvv: res.card.cvv,
|
|
250
|
+
expMonth: res.card.exp_month,
|
|
251
|
+
expYear: res.card.exp_year,
|
|
252
|
+
lastFour: res.card.last_four
|
|
253
|
+
} : void 0
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get the current status of a purchase intent.
|
|
258
|
+
*/
|
|
259
|
+
async get(customerToken, intentId) {
|
|
260
|
+
const res = await request(
|
|
261
|
+
this.baseUrl,
|
|
262
|
+
`/intents/${intentId}`,
|
|
263
|
+
customerToken
|
|
264
|
+
);
|
|
265
|
+
return mapIntentStatus(res);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Cancel an active purchase intent.
|
|
269
|
+
*/
|
|
270
|
+
async cancel(customerToken, intentId) {
|
|
271
|
+
const res = await request(
|
|
272
|
+
this.baseUrl,
|
|
273
|
+
`/intents/${intentId}/cancel`,
|
|
274
|
+
customerToken,
|
|
275
|
+
{ method: "POST" }
|
|
276
|
+
);
|
|
277
|
+
return mapIntentStatus(res);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* List purchase intents for the authenticated customer.
|
|
281
|
+
*/
|
|
282
|
+
async list(customerToken, options) {
|
|
283
|
+
const params = new URLSearchParams();
|
|
284
|
+
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
285
|
+
if (options?.offset !== void 0)
|
|
286
|
+
params.set("offset", String(options.offset));
|
|
287
|
+
const query = params.toString();
|
|
288
|
+
const path = query ? `/intents?${query}` : "/intents";
|
|
289
|
+
const res = await request(
|
|
290
|
+
this.baseUrl,
|
|
291
|
+
path,
|
|
292
|
+
customerToken
|
|
293
|
+
);
|
|
294
|
+
return res.map(mapIntentStatus);
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
function mapIntentStatus(raw) {
|
|
298
|
+
return {
|
|
299
|
+
intentId: raw.intent_id,
|
|
300
|
+
status: raw.status,
|
|
301
|
+
amount: raw.amount,
|
|
302
|
+
currency: raw.currency,
|
|
303
|
+
merchantName: raw.merchant_name,
|
|
304
|
+
cardLastFour: raw.card_last_four,
|
|
305
|
+
asaVerified: raw.asa_verified,
|
|
306
|
+
asaAmount: raw.asa_amount,
|
|
307
|
+
asaMerchantDescriptor: raw.asa_merchant_descriptor,
|
|
308
|
+
asaMismatchReason: raw.asa_mismatch_reason,
|
|
309
|
+
transactionId: raw.transaction_id,
|
|
310
|
+
expiresAt: raw.expires_at,
|
|
311
|
+
createdAt: raw.created_at
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
209
315
|
// src/purchase.ts
|
|
210
316
|
var PurchaseModule = class {
|
|
211
317
|
constructor(baseUrl, apiKey) {
|
|
@@ -358,6 +464,7 @@ var Tally = class {
|
|
|
358
464
|
this.baseUrl = resolveBaseUrl(config.apiKey, config.baseUrl);
|
|
359
465
|
this.authorize = new AuthorizeModule(this.baseUrl, this.apiKey);
|
|
360
466
|
this.purchases = new PurchaseModule(this.baseUrl, this.apiKey);
|
|
467
|
+
this.intents = new IntentsModule(this.baseUrl, this.apiKey);
|
|
361
468
|
this.balances = new BalanceModule(this.baseUrl, this.apiKey);
|
|
362
469
|
this.webhooks = new WebhooksModule();
|
|
363
470
|
}
|
|
@@ -390,6 +497,7 @@ var Tally = class {
|
|
|
390
497
|
0 && (module.exports = {
|
|
391
498
|
AuthorizeModule,
|
|
392
499
|
BalanceModule,
|
|
500
|
+
IntentsModule,
|
|
393
501
|
PurchaseModule,
|
|
394
502
|
TallionError,
|
|
395
503
|
Tally,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/authorize.ts","../src/balance.ts","../src/purchase.ts","../src/webhooks.ts","../src/tally.ts"],"sourcesContent":["export { Tally } from \"./tally\";\nexport { TallionError } from \"./errors\";\nexport { AuthorizeModule } from \"./authorize\";\nexport { PurchaseModule } from \"./purchase\";\nexport { BalanceModule } from \"./balance\";\nexport { WebhooksModule } from \"./webhooks\";\n\nexport type {\n TallyConfig,\n CreateAuthUrlOptions,\n AuthUrlResult,\n ExchangeCodeOptions,\n TokenResult,\n RefreshTokenOptions,\n PurchaseOptions,\n LegacyPurchaseOptions,\n PurchaseResult,\n MerchantInfo,\n TransactionContext,\n LineItem,\n BalanceResult,\n SpendLimits,\n WebhookEvent,\n} from \"./types\";\n","export class TallionError extends Error {\n public readonly status: number;\n public readonly code?: string;\n\n constructor(status: number, message: string, code?: string) {\n super(message);\n this.name = \"TallionError\";\n this.status = status;\n this.code = code;\n }\n}\n","import { TallionError } from \"./errors\";\n\nconst SANDBOX_URL = \"https://api.sandbox.tallion.ai\";\nconst PRODUCTION_URL = \"https://api.tallion.ai\";\n\nexport function resolveBaseUrl(apiKey: string, overrideUrl?: string): string {\n if (overrideUrl) return overrideUrl;\n if (apiKey.startsWith(\"sk_live_\")) return PRODUCTION_URL;\n return SANDBOX_URL;\n}\n\nexport interface RequestOptions {\n method?: string;\n headers?: Record<string, string>;\n body?: unknown;\n}\n\nexport async function request<T>(\n baseUrl: string,\n path: string,\n apiKey: string,\n options: RequestOptions = {},\n): Promise<T> {\n if (!apiKey) {\n throw new TallionError(\n 401,\n \"Tallion API key is required. Get one at https://tallion.ai/developer\",\n \"missing_api_key\",\n );\n }\n const url = `${baseUrl}/api${path}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...options.headers,\n };\n\n const res = await fetch(url, {\n method: options.method || \"GET\",\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: \"Unknown error\" }));\n throw new TallionError(\n res.status,\n body.error || \"Request failed\",\n body.code,\n );\n }\n\n return res.json() as Promise<T>;\n}\n","import { request } from \"./http\";\nimport type {\n AuthUrlResult,\n CreateAuthUrlOptions,\n ExchangeCodeOptions,\n RefreshTokenOptions,\n TokenResult,\n} from \"./types\";\n\n/** Generate a random string for PKCE */\nfunction generateRandomString(length: number): string {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~\";\n const array = new Uint8Array(length);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => chars[byte % chars.length]).join(\"\");\n}\n\n/** SHA-256 hash for PKCE S256 challenge */\nasync function sha256(plain: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(plain);\n const hash = await crypto.subtle.digest(\"SHA-256\", data);\n return btoa(String.fromCharCode(...new Uint8Array(hash)))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nexport class AuthorizeModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Create an authorization URL for customer consent.\n * Returns the URL to open in a popup/browser plus the PKCE code verifier.\n */\n async createUrl(options: CreateAuthUrlOptions): Promise<AuthUrlResult> {\n const codeVerifier = generateRandomString(64);\n const codeChallenge = await sha256(codeVerifier);\n\n const res = await request<{\n authorization_id: string;\n url: string;\n state: string;\n }>(this.baseUrl, \"/oauth/authorize\", this.apiKey, {\n method: \"POST\",\n body: {\n customer_identifier: options.customerIdentifier,\n redirect_url: options.redirectUrl,\n scopes: options.scopes || [\"purchase\", \"balance:read\"],\n code_challenge: codeChallenge,\n code_challenge_method: options.codeChallengeMethod || \"S256\",\n suggested_limits: options.suggestedLimits\n ? {\n max_per_transaction: options.suggestedLimits.maxPerTransaction,\n max_per_day: options.suggestedLimits.maxPerDay,\n max_per_month: options.suggestedLimits.maxPerMonth,\n require_approval_above: options.suggestedLimits.requireApprovalAbove,\n }\n : undefined,\n purchase_context: options.purchaseContext\n ? {\n amount: options.purchaseContext.amount,\n description: options.purchaseContext.description,\n merchant: options.purchaseContext.merchant,\n reference: options.purchaseContext.reference,\n }\n : undefined,\n },\n });\n\n return {\n url: res.url,\n state: res.state,\n codeVerifier,\n authorizationId: res.authorization_id,\n };\n }\n\n /**\n * Exchange an authorization code for access + refresh tokens.\n */\n async exchangeCode(options: ExchangeCodeOptions): Promise<TokenResult> {\n const res = await request<{\n access_token: string;\n refresh_token: string;\n token_type: string;\n expires_in: number;\n customer_id: string;\n installation_id: string;\n }>(this.baseUrl, \"/oauth/token\", this.apiKey, {\n method: \"POST\",\n body: {\n grant_type: \"authorization_code\",\n code: options.code,\n code_verifier: options.codeVerifier,\n },\n });\n\n return {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n tokenType: res.token_type,\n expiresIn: res.expires_in,\n customerId: res.customer_id,\n installationId: res.installation_id,\n };\n }\n\n /**\n * Refresh an access token using a refresh token.\n */\n async refreshToken(options: RefreshTokenOptions): Promise<TokenResult> {\n const res = await request<{\n access_token: string;\n refresh_token: string;\n token_type: string;\n expires_in: number;\n customer_id: string;\n installation_id: string;\n }>(this.baseUrl, \"/oauth/token\", this.apiKey, {\n method: \"POST\",\n body: {\n grant_type: \"refresh_token\",\n refresh_token: options.refreshToken,\n },\n });\n\n return {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n tokenType: res.token_type,\n expiresIn: res.expires_in,\n customerId: res.customer_id,\n installationId: res.installation_id,\n };\n }\n\n /**\n * Revoke an access or refresh token.\n */\n async revoke(token: string): Promise<void> {\n await request(this.baseUrl, \"/oauth/revoke\", this.apiKey, {\n method: \"POST\",\n body: { token },\n });\n }\n}\n","import { request } from \"./http\";\nimport type { BalanceResult } from \"./types\";\n\nexport class BalanceModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Get wallet balance for a customer (using OAuth token).\n */\n async get(customerToken: string, walletId?: string): Promise<BalanceResult> {\n const path = walletId ? `/wallets/${walletId}/budget` : \"/wallets/me\";\n const res = await request<{\n id?: string;\n wallet_id?: string;\n funding_amount: number;\n spent_amount: number;\n remaining: number;\n }>(this.baseUrl, path, customerToken, {\n method: \"GET\",\n });\n\n return {\n walletId: res.wallet_id || res.id || \"\",\n fundingAmount: res.funding_amount,\n spentAmount: res.spent_amount,\n remaining: res.remaining,\n };\n }\n}\n","import { request } from \"./http\";\nimport type { LegacyPurchaseOptions, PurchaseOptions, PurchaseResult } from \"./types\";\n\nexport class PurchaseModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Make a purchase using an OAuth customer token.\n */\n async create(options: PurchaseOptions): Promise<PurchaseResult> {\n const res = await request<{\n transaction_id: string;\n status: string;\n decision: string;\n decision_reason: string;\n amount: number;\n merchant_name: string;\n approval_deadline?: string;\n }>(this.baseUrl, \"/purchase\", options.customerToken, {\n method: \"POST\",\n headers: {\n \"X-Tallion-Installation\": \"\", // Resolved by OAuth token\n },\n body: {\n amount: options.amount,\n currency: options.currency || \"USD\",\n wallet_id: options.walletId,\n merchant: {\n name: options.merchant.name,\n mcc: options.merchant.mcc || \"\",\n country: options.merchant.country || \"US\",\n },\n context: {\n description: options.context.description,\n category: options.context.category,\n line_items: options.context.lineItems,\n external_reference: options.context.externalReference,\n refund_policy: options.context.refundPolicy,\n metadata: options.context.metadata,\n },\n },\n });\n\n return {\n transactionId: res.transaction_id,\n status: res.status as PurchaseResult[\"status\"],\n decision: res.decision,\n decisionReason: res.decision_reason,\n amount: res.amount,\n merchantName: res.merchant_name,\n approvalDeadline: res.approval_deadline,\n };\n }\n\n /**\n * Make a purchase using the legacy API key + installation ID auth.\n */\n async legacyCreate(options: LegacyPurchaseOptions): Promise<PurchaseResult> {\n const res = await request<{\n transaction_id: string;\n status: string;\n decision: string;\n decision_reason: string;\n amount: number;\n merchant_name: string;\n approval_deadline?: string;\n }>(this.baseUrl, \"/purchase\", this.apiKey, {\n method: \"POST\",\n headers: {\n \"X-Tallion-Installation\": options.installationId,\n },\n body: {\n amount: options.amount,\n merchant_name: options.merchantName,\n merchant_mcc: options.merchantMcc || \"\",\n merchant_country: options.merchantCountry || \"US\",\n currency: options.currency || \"USD\",\n wallet_id: options.walletId,\n reasoning: options.reasoning,\n },\n });\n\n return {\n transactionId: res.transaction_id,\n status: res.status as PurchaseResult[\"status\"],\n decision: res.decision,\n decisionReason: res.decision_reason,\n amount: res.amount,\n merchantName: res.merchant_name,\n approvalDeadline: res.approval_deadline,\n };\n }\n}\n","import type { WebhookEvent } from \"./types\";\nimport { TallionError } from \"./errors\";\n\nexport class WebhooksModule {\n constructor(private secret?: string) {}\n\n /**\n * Verify a webhook signature and parse the event.\n * Uses Web Crypto API (works in Node 18+, Deno, Bun, Cloudflare Workers, etc.)\n *\n * @param body - Raw request body string\n * @param signature - Value of X-Tally-Signature header\n * @param tolerance - Max age in seconds (default: 300 = 5 minutes)\n */\n async verify(\n body: string,\n signature: string,\n tolerance = 300,\n ): Promise<WebhookEvent> {\n if (!this.secret) {\n throw new TallionError(500, \"Webhook secret not configured\");\n }\n\n // Parse signature header: \"t={timestamp},v1={hex_signature}\"\n const parts: Record<string, string> = {};\n for (const part of signature.split(\",\")) {\n const [key, ...val] = part.split(\"=\");\n if (key && val.length > 0) {\n parts[key] = val.join(\"=\");\n }\n }\n\n const timestamp = parts[\"t\"];\n const sig = parts[\"v1\"];\n\n if (!timestamp || !sig) {\n throw new TallionError(400, \"Invalid webhook signature format\");\n }\n\n // Check timestamp freshness\n const ts = parseInt(timestamp, 10);\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - ts) > tolerance) {\n throw new TallionError(400, \"Webhook timestamp expired\");\n }\n\n // Compute HMAC-SHA256\n const message = `${timestamp}.${body}`;\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(this.secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n\n const signatureBytes = await crypto.subtle.sign(\n \"HMAC\",\n key,\n encoder.encode(message),\n );\n\n const computed = Array.from(new Uint8Array(signatureBytes))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n // Constant-time comparison\n if (computed.length !== sig.length || !timingSafeEqual(computed, sig)) {\n throw new TallionError(401, \"Invalid webhook signature\");\n }\n\n return JSON.parse(body) as WebhookEvent;\n }\n}\n\n/** Simple constant-time string comparison */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n","import { AuthorizeModule } from \"./authorize\";\nimport { BalanceModule } from \"./balance\";\nimport { resolveBaseUrl } from \"./http\";\nimport { PurchaseModule } from \"./purchase\";\nimport { WebhooksModule } from \"./webhooks\";\nimport type { PurchaseOptions, PurchaseResult, TallyConfig } from \"./types\";\n\nexport class Tally {\n private baseUrl: string;\n private apiKey: string;\n\n /** OAuth authorization flow */\n public authorize: AuthorizeModule;\n\n /** Purchase operations */\n public purchases: PurchaseModule;\n\n /** Balance operations */\n public balances: BalanceModule;\n\n /** Webhook signature verification */\n public webhooks: WebhooksModule;\n\n constructor(config: TallyConfig) {\n if (!config.apiKey) {\n throw new Error(\n \"Tallion API key is required. Get one at https://tallion.ai/developer\",\n );\n }\n this.apiKey = config.apiKey;\n this.baseUrl = resolveBaseUrl(config.apiKey, config.baseUrl);\n this.authorize = new AuthorizeModule(this.baseUrl, this.apiKey);\n this.purchases = new PurchaseModule(this.baseUrl, this.apiKey);\n this.balances = new BalanceModule(this.baseUrl, this.apiKey);\n this.webhooks = new WebhooksModule();\n }\n\n /**\n * Convenience method: Make a purchase (delegates to purchases.create).\n */\n async purchase(options: PurchaseOptions): Promise<PurchaseResult> {\n return this.purchases.create(options);\n }\n\n /**\n * Convenience method: Get balance for a customer.\n */\n async balance(customerToken: string, walletId?: string) {\n return this.balances.get(customerToken, walletId);\n }\n\n /**\n * Check if this is a sandbox instance.\n */\n get isSandbox(): boolean {\n return this.apiKey.startsWith(\"sk_sandbox_\");\n }\n\n /**\n * Get the resolved base URL.\n */\n get url(): string {\n return this.baseUrl;\n }\n}\n"],"mappings":"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","names":["key"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/http.ts","../src/authorize.ts","../src/balance.ts","../src/intents.ts","../src/purchase.ts","../src/webhooks.ts","../src/tally.ts"],"sourcesContent":["export { Tally } from \"./tally\";\nexport { TallionError } from \"./errors\";\nexport { AuthorizeModule } from \"./authorize\";\nexport { PurchaseModule } from \"./purchase\";\nexport { IntentsModule } from \"./intents\";\nexport { BalanceModule } from \"./balance\";\nexport { WebhooksModule } from \"./webhooks\";\n\nexport type {\n TallyConfig,\n CreateAuthUrlOptions,\n AuthUrlResult,\n ExchangeCodeOptions,\n TokenResult,\n RefreshTokenOptions,\n PurchaseOptions,\n LegacyPurchaseOptions,\n PurchaseResult,\n MerchantInfo,\n TransactionContext,\n LineItem,\n BalanceResult,\n SpendLimits,\n WebhookEvent,\n CreateIntentOptions,\n IntentCardDetails,\n IntentResult,\n IntentStatusResult,\n ListIntentsOptions,\n} from \"./types\";\n","export class TallionError extends Error {\n public readonly status: number;\n public readonly code?: string;\n\n constructor(status: number, message: string, code?: string) {\n super(message);\n this.name = \"TallionError\";\n this.status = status;\n this.code = code;\n }\n}\n","import { TallionError } from \"./errors\";\n\nconst SANDBOX_URL = \"https://api.sandbox.tallion.ai\";\nconst PRODUCTION_URL = \"https://api.tallion.ai\";\n\nexport function resolveBaseUrl(apiKey: string, overrideUrl?: string): string {\n if (overrideUrl) return overrideUrl;\n if (apiKey.startsWith(\"sk_live_\")) return PRODUCTION_URL;\n return SANDBOX_URL;\n}\n\nexport interface RequestOptions {\n method?: string;\n headers?: Record<string, string>;\n body?: unknown;\n}\n\nexport async function request<T>(\n baseUrl: string,\n path: string,\n apiKey: string,\n options: RequestOptions = {},\n): Promise<T> {\n if (!apiKey) {\n throw new TallionError(\n 401,\n \"Tallion API key is required. Get one at https://tallion.ai/developer\",\n \"missing_api_key\",\n );\n }\n const url = `${baseUrl}/api${path}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...options.headers,\n };\n\n const res = await fetch(url, {\n method: options.method || \"GET\",\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: \"Unknown error\" }));\n throw new TallionError(\n res.status,\n body.error || \"Request failed\",\n body.code,\n );\n }\n\n return res.json() as Promise<T>;\n}\n","import { request } from \"./http\";\nimport type {\n AuthUrlResult,\n CreateAuthUrlOptions,\n ExchangeCodeOptions,\n RefreshTokenOptions,\n TokenResult,\n} from \"./types\";\n\n/** Generate a random string for PKCE */\nfunction generateRandomString(length: number): string {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~\";\n const array = new Uint8Array(length);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => chars[byte % chars.length]).join(\"\");\n}\n\n/** SHA-256 hash for PKCE S256 challenge */\nasync function sha256(plain: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(plain);\n const hash = await crypto.subtle.digest(\"SHA-256\", data);\n return btoa(String.fromCharCode(...new Uint8Array(hash)))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nexport class AuthorizeModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Create an authorization URL for customer consent.\n * Returns the URL to open in a popup/browser plus the PKCE code verifier.\n */\n async createUrl(options: CreateAuthUrlOptions): Promise<AuthUrlResult> {\n const codeVerifier = generateRandomString(64);\n const codeChallenge = await sha256(codeVerifier);\n\n const res = await request<{\n authorization_id: string;\n url: string;\n state: string;\n }>(this.baseUrl, \"/oauth/authorize\", this.apiKey, {\n method: \"POST\",\n body: {\n customer_identifier: options.customerIdentifier,\n redirect_url: options.redirectUrl,\n scopes: options.scopes || [\"purchase\", \"balance:read\"],\n code_challenge: codeChallenge,\n code_challenge_method: options.codeChallengeMethod || \"S256\",\n suggested_limits: options.suggestedLimits\n ? {\n max_per_transaction: options.suggestedLimits.maxPerTransaction,\n max_per_day: options.suggestedLimits.maxPerDay,\n max_per_month: options.suggestedLimits.maxPerMonth,\n require_approval_above: options.suggestedLimits.requireApprovalAbove,\n }\n : undefined,\n purchase_context: options.purchaseContext\n ? {\n amount: options.purchaseContext.amount,\n description: options.purchaseContext.description,\n merchant: options.purchaseContext.merchant,\n reference: options.purchaseContext.reference,\n }\n : undefined,\n },\n });\n\n return {\n url: res.url,\n state: res.state,\n codeVerifier,\n authorizationId: res.authorization_id,\n };\n }\n\n /**\n * Exchange an authorization code for access + refresh tokens.\n */\n async exchangeCode(options: ExchangeCodeOptions): Promise<TokenResult> {\n const res = await request<{\n access_token: string;\n refresh_token: string;\n token_type: string;\n expires_in: number;\n customer_id: string;\n installation_id: string;\n }>(this.baseUrl, \"/oauth/token\", this.apiKey, {\n method: \"POST\",\n body: {\n grant_type: \"authorization_code\",\n code: options.code,\n code_verifier: options.codeVerifier,\n },\n });\n\n return {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n tokenType: res.token_type,\n expiresIn: res.expires_in,\n customerId: res.customer_id,\n installationId: res.installation_id,\n };\n }\n\n /**\n * Refresh an access token using a refresh token.\n */\n async refreshToken(options: RefreshTokenOptions): Promise<TokenResult> {\n const res = await request<{\n access_token: string;\n refresh_token: string;\n token_type: string;\n expires_in: number;\n customer_id: string;\n installation_id: string;\n }>(this.baseUrl, \"/oauth/token\", this.apiKey, {\n method: \"POST\",\n body: {\n grant_type: \"refresh_token\",\n refresh_token: options.refreshToken,\n },\n });\n\n return {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n tokenType: res.token_type,\n expiresIn: res.expires_in,\n customerId: res.customer_id,\n installationId: res.installation_id,\n };\n }\n\n /**\n * Revoke an access or refresh token.\n */\n async revoke(token: string): Promise<void> {\n await request(this.baseUrl, \"/oauth/revoke\", this.apiKey, {\n method: \"POST\",\n body: { token },\n });\n }\n}\n","import { request } from \"./http\";\nimport type { BalanceResult } from \"./types\";\n\nexport class BalanceModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Get wallet balance for a customer (using OAuth token).\n */\n async get(customerToken: string, walletId?: string): Promise<BalanceResult> {\n const path = walletId ? `/wallets/${walletId}/budget` : \"/wallets/me\";\n const res = await request<{\n id?: string;\n wallet_id?: string;\n funding_amount: number;\n spent_amount: number;\n remaining: number;\n }>(this.baseUrl, path, customerToken, {\n method: \"GET\",\n });\n\n return {\n walletId: res.wallet_id || res.id || \"\",\n fundingAmount: res.funding_amount,\n spentAmount: res.spent_amount,\n remaining: res.remaining,\n };\n }\n}\n","import { request } from \"./http\";\nimport type {\n CreateIntentOptions,\n IntentResult,\n IntentStatusResult,\n ListIntentsOptions,\n} from \"./types\";\n\nexport class IntentsModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Create a purchase intent (Buy Anywhere).\n * Returns a virtual card for the customer to use at the merchant.\n */\n async create(options: CreateIntentOptions): Promise<IntentResult> {\n const res = await request<{\n intent_id: string;\n status: string;\n amount: number;\n currency: string;\n merchant_name?: string;\n expires_at?: string;\n transaction_id?: string;\n card?: {\n pan: string;\n cvv: string;\n exp_month: number;\n exp_year: number;\n last_four: string;\n };\n }>(this.baseUrl, \"/intents\", options.customerToken, {\n method: \"POST\",\n body: {\n amount: options.amount,\n currency: options.currency || \"USD\",\n wallet_id: options.walletId,\n merchant: options.merchant\n ? {\n name: options.merchant.name,\n url: options.merchant.url,\n mcc: options.merchant.mcc,\n }\n : undefined,\n product: options.product\n ? {\n description: options.product.description,\n url: options.product.url,\n }\n : undefined,\n amount_tolerance_pct: options.amountTolerancePct,\n },\n });\n\n return {\n intentId: res.intent_id,\n status: res.status as IntentResult[\"status\"],\n amount: res.amount,\n currency: res.currency,\n merchantName: res.merchant_name,\n expiresAt: res.expires_at,\n transactionId: res.transaction_id,\n card: res.card\n ? {\n pan: res.card.pan,\n cvv: res.card.cvv,\n expMonth: res.card.exp_month,\n expYear: res.card.exp_year,\n lastFour: res.card.last_four,\n }\n : undefined,\n };\n }\n\n /**\n * Get the current status of a purchase intent.\n */\n async get(\n customerToken: string,\n intentId: string,\n ): Promise<IntentStatusResult> {\n const res = await request<RawIntentStatus>(\n this.baseUrl,\n `/intents/${intentId}`,\n customerToken,\n );\n\n return mapIntentStatus(res);\n }\n\n /**\n * Cancel an active purchase intent.\n */\n async cancel(\n customerToken: string,\n intentId: string,\n ): Promise<IntentStatusResult> {\n const res = await request<RawIntentStatus>(\n this.baseUrl,\n `/intents/${intentId}/cancel`,\n customerToken,\n { method: \"POST\" },\n );\n\n return mapIntentStatus(res);\n }\n\n /**\n * List purchase intents for the authenticated customer.\n */\n async list(\n customerToken: string,\n options?: ListIntentsOptions,\n ): Promise<IntentStatusResult[]> {\n const params = new URLSearchParams();\n if (options?.limit !== undefined) params.set(\"limit\", String(options.limit));\n if (options?.offset !== undefined)\n params.set(\"offset\", String(options.offset));\n\n const query = params.toString();\n const path = query ? `/intents?${query}` : \"/intents\";\n\n const res = await request<RawIntentStatus[]>(\n this.baseUrl,\n path,\n customerToken,\n );\n\n return res.map(mapIntentStatus);\n }\n}\n\n// ── Internal helpers ──\n\ninterface RawIntentStatus {\n intent_id: string;\n status: string;\n amount: number;\n currency: string;\n merchant_name?: string;\n card_last_four?: string;\n asa_verified: boolean;\n asa_amount?: number;\n asa_merchant_descriptor?: string;\n asa_mismatch_reason?: string;\n transaction_id?: string;\n expires_at?: string;\n created_at: string;\n}\n\nfunction mapIntentStatus(raw: RawIntentStatus): IntentStatusResult {\n return {\n intentId: raw.intent_id,\n status: raw.status,\n amount: raw.amount,\n currency: raw.currency,\n merchantName: raw.merchant_name,\n cardLastFour: raw.card_last_four,\n asaVerified: raw.asa_verified,\n asaAmount: raw.asa_amount,\n asaMerchantDescriptor: raw.asa_merchant_descriptor,\n asaMismatchReason: raw.asa_mismatch_reason,\n transactionId: raw.transaction_id,\n expiresAt: raw.expires_at,\n createdAt: raw.created_at,\n };\n}\n","import { request } from \"./http\";\nimport type { LegacyPurchaseOptions, PurchaseOptions, PurchaseResult } from \"./types\";\n\nexport class PurchaseModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Make a purchase using an OAuth customer token.\n */\n async create(options: PurchaseOptions): Promise<PurchaseResult> {\n const res = await request<{\n transaction_id: string;\n status: string;\n decision: string;\n decision_reason: string;\n amount: number;\n merchant_name: string;\n approval_deadline?: string;\n }>(this.baseUrl, \"/purchase\", options.customerToken, {\n method: \"POST\",\n headers: {\n \"X-Tallion-Installation\": \"\", // Resolved by OAuth token\n },\n body: {\n amount: options.amount,\n currency: options.currency || \"USD\",\n wallet_id: options.walletId,\n merchant: {\n name: options.merchant.name,\n mcc: options.merchant.mcc || \"\",\n country: options.merchant.country || \"US\",\n },\n context: {\n description: options.context.description,\n category: options.context.category,\n line_items: options.context.lineItems,\n external_reference: options.context.externalReference,\n refund_policy: options.context.refundPolicy,\n metadata: options.context.metadata,\n },\n },\n });\n\n return {\n transactionId: res.transaction_id,\n status: res.status as PurchaseResult[\"status\"],\n decision: res.decision,\n decisionReason: res.decision_reason,\n amount: res.amount,\n merchantName: res.merchant_name,\n approvalDeadline: res.approval_deadline,\n };\n }\n\n /**\n * Make a purchase using the legacy API key + installation ID auth.\n */\n async legacyCreate(options: LegacyPurchaseOptions): Promise<PurchaseResult> {\n const res = await request<{\n transaction_id: string;\n status: string;\n decision: string;\n decision_reason: string;\n amount: number;\n merchant_name: string;\n approval_deadline?: string;\n }>(this.baseUrl, \"/purchase\", this.apiKey, {\n method: \"POST\",\n headers: {\n \"X-Tallion-Installation\": options.installationId,\n },\n body: {\n amount: options.amount,\n merchant_name: options.merchantName,\n merchant_mcc: options.merchantMcc || \"\",\n merchant_country: options.merchantCountry || \"US\",\n currency: options.currency || \"USD\",\n wallet_id: options.walletId,\n reasoning: options.reasoning,\n },\n });\n\n return {\n transactionId: res.transaction_id,\n status: res.status as PurchaseResult[\"status\"],\n decision: res.decision,\n decisionReason: res.decision_reason,\n amount: res.amount,\n merchantName: res.merchant_name,\n approvalDeadline: res.approval_deadline,\n };\n }\n}\n","import type { WebhookEvent } from \"./types\";\nimport { TallionError } from \"./errors\";\n\nexport class WebhooksModule {\n constructor(private secret?: string) {}\n\n /**\n * Verify a webhook signature and parse the event.\n * Uses Web Crypto API (works in Node 18+, Deno, Bun, Cloudflare Workers, etc.)\n *\n * @param body - Raw request body string\n * @param signature - Value of X-Tally-Signature header\n * @param tolerance - Max age in seconds (default: 300 = 5 minutes)\n */\n async verify(\n body: string,\n signature: string,\n tolerance = 300,\n ): Promise<WebhookEvent> {\n if (!this.secret) {\n throw new TallionError(500, \"Webhook secret not configured\");\n }\n\n // Parse signature header: \"t={timestamp},v1={hex_signature}\"\n const parts: Record<string, string> = {};\n for (const part of signature.split(\",\")) {\n const [key, ...val] = part.split(\"=\");\n if (key && val.length > 0) {\n parts[key] = val.join(\"=\");\n }\n }\n\n const timestamp = parts[\"t\"];\n const sig = parts[\"v1\"];\n\n if (!timestamp || !sig) {\n throw new TallionError(400, \"Invalid webhook signature format\");\n }\n\n // Check timestamp freshness\n const ts = parseInt(timestamp, 10);\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - ts) > tolerance) {\n throw new TallionError(400, \"Webhook timestamp expired\");\n }\n\n // Compute HMAC-SHA256\n const message = `${timestamp}.${body}`;\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(this.secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n\n const signatureBytes = await crypto.subtle.sign(\n \"HMAC\",\n key,\n encoder.encode(message),\n );\n\n const computed = Array.from(new Uint8Array(signatureBytes))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n // Constant-time comparison\n if (computed.length !== sig.length || !timingSafeEqual(computed, sig)) {\n throw new TallionError(401, \"Invalid webhook signature\");\n }\n\n return JSON.parse(body) as WebhookEvent;\n }\n}\n\n/** Simple constant-time string comparison */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n","import { AuthorizeModule } from \"./authorize\";\nimport { BalanceModule } from \"./balance\";\nimport { resolveBaseUrl } from \"./http\";\nimport { IntentsModule } from \"./intents\";\nimport { PurchaseModule } from \"./purchase\";\nimport { WebhooksModule } from \"./webhooks\";\nimport type { PurchaseOptions, PurchaseResult, TallyConfig } from \"./types\";\n\nexport class Tally {\n private baseUrl: string;\n private apiKey: string;\n\n /** OAuth authorization flow */\n public authorize: AuthorizeModule;\n\n /** Purchase operations */\n public purchases: PurchaseModule;\n\n /** Balance operations */\n public balances: BalanceModule;\n\n /** Purchase intents (Buy Anywhere) */\n public intents: IntentsModule;\n\n /** Webhook signature verification */\n public webhooks: WebhooksModule;\n\n constructor(config: TallyConfig) {\n if (!config.apiKey) {\n throw new Error(\n \"Tallion API key is required. Get one at https://tallion.ai/developer\",\n );\n }\n this.apiKey = config.apiKey;\n this.baseUrl = resolveBaseUrl(config.apiKey, config.baseUrl);\n this.authorize = new AuthorizeModule(this.baseUrl, this.apiKey);\n this.purchases = new PurchaseModule(this.baseUrl, this.apiKey);\n this.intents = new IntentsModule(this.baseUrl, this.apiKey);\n this.balances = new BalanceModule(this.baseUrl, this.apiKey);\n this.webhooks = new WebhooksModule();\n }\n\n /**\n * Convenience method: Make a purchase (delegates to purchases.create).\n */\n async purchase(options: PurchaseOptions): Promise<PurchaseResult> {\n return this.purchases.create(options);\n }\n\n /**\n * Convenience method: Get balance for a customer.\n */\n async balance(customerToken: string, walletId?: string) {\n return this.balances.get(customerToken, walletId);\n }\n\n /**\n * Check if this is a sandbox instance.\n */\n get isSandbox(): boolean {\n return this.apiKey.startsWith(\"sk_sandbox_\");\n }\n\n /**\n * Get the resolved base URL.\n */\n get url(): string {\n return this.baseUrl;\n }\n}\n"],"mappings":"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","names":["key"]}
|
package/dist/index.mjs
CHANGED
|
@@ -175,6 +175,111 @@ var BalanceModule = class {
|
|
|
175
175
|
}
|
|
176
176
|
};
|
|
177
177
|
|
|
178
|
+
// src/intents.ts
|
|
179
|
+
var IntentsModule = class {
|
|
180
|
+
constructor(baseUrl, apiKey) {
|
|
181
|
+
this.baseUrl = baseUrl;
|
|
182
|
+
this.apiKey = apiKey;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Create a purchase intent (Buy Anywhere).
|
|
186
|
+
* Returns a virtual card for the customer to use at the merchant.
|
|
187
|
+
*/
|
|
188
|
+
async create(options) {
|
|
189
|
+
const res = await request(this.baseUrl, "/intents", options.customerToken, {
|
|
190
|
+
method: "POST",
|
|
191
|
+
body: {
|
|
192
|
+
amount: options.amount,
|
|
193
|
+
currency: options.currency || "USD",
|
|
194
|
+
wallet_id: options.walletId,
|
|
195
|
+
merchant: options.merchant ? {
|
|
196
|
+
name: options.merchant.name,
|
|
197
|
+
url: options.merchant.url,
|
|
198
|
+
mcc: options.merchant.mcc
|
|
199
|
+
} : void 0,
|
|
200
|
+
product: options.product ? {
|
|
201
|
+
description: options.product.description,
|
|
202
|
+
url: options.product.url
|
|
203
|
+
} : void 0,
|
|
204
|
+
amount_tolerance_pct: options.amountTolerancePct
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
return {
|
|
208
|
+
intentId: res.intent_id,
|
|
209
|
+
status: res.status,
|
|
210
|
+
amount: res.amount,
|
|
211
|
+
currency: res.currency,
|
|
212
|
+
merchantName: res.merchant_name,
|
|
213
|
+
expiresAt: res.expires_at,
|
|
214
|
+
transactionId: res.transaction_id,
|
|
215
|
+
card: res.card ? {
|
|
216
|
+
pan: res.card.pan,
|
|
217
|
+
cvv: res.card.cvv,
|
|
218
|
+
expMonth: res.card.exp_month,
|
|
219
|
+
expYear: res.card.exp_year,
|
|
220
|
+
lastFour: res.card.last_four
|
|
221
|
+
} : void 0
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Get the current status of a purchase intent.
|
|
226
|
+
*/
|
|
227
|
+
async get(customerToken, intentId) {
|
|
228
|
+
const res = await request(
|
|
229
|
+
this.baseUrl,
|
|
230
|
+
`/intents/${intentId}`,
|
|
231
|
+
customerToken
|
|
232
|
+
);
|
|
233
|
+
return mapIntentStatus(res);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Cancel an active purchase intent.
|
|
237
|
+
*/
|
|
238
|
+
async cancel(customerToken, intentId) {
|
|
239
|
+
const res = await request(
|
|
240
|
+
this.baseUrl,
|
|
241
|
+
`/intents/${intentId}/cancel`,
|
|
242
|
+
customerToken,
|
|
243
|
+
{ method: "POST" }
|
|
244
|
+
);
|
|
245
|
+
return mapIntentStatus(res);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* List purchase intents for the authenticated customer.
|
|
249
|
+
*/
|
|
250
|
+
async list(customerToken, options) {
|
|
251
|
+
const params = new URLSearchParams();
|
|
252
|
+
if (options?.limit !== void 0) params.set("limit", String(options.limit));
|
|
253
|
+
if (options?.offset !== void 0)
|
|
254
|
+
params.set("offset", String(options.offset));
|
|
255
|
+
const query = params.toString();
|
|
256
|
+
const path = query ? `/intents?${query}` : "/intents";
|
|
257
|
+
const res = await request(
|
|
258
|
+
this.baseUrl,
|
|
259
|
+
path,
|
|
260
|
+
customerToken
|
|
261
|
+
);
|
|
262
|
+
return res.map(mapIntentStatus);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
function mapIntentStatus(raw) {
|
|
266
|
+
return {
|
|
267
|
+
intentId: raw.intent_id,
|
|
268
|
+
status: raw.status,
|
|
269
|
+
amount: raw.amount,
|
|
270
|
+
currency: raw.currency,
|
|
271
|
+
merchantName: raw.merchant_name,
|
|
272
|
+
cardLastFour: raw.card_last_four,
|
|
273
|
+
asaVerified: raw.asa_verified,
|
|
274
|
+
asaAmount: raw.asa_amount,
|
|
275
|
+
asaMerchantDescriptor: raw.asa_merchant_descriptor,
|
|
276
|
+
asaMismatchReason: raw.asa_mismatch_reason,
|
|
277
|
+
transactionId: raw.transaction_id,
|
|
278
|
+
expiresAt: raw.expires_at,
|
|
279
|
+
createdAt: raw.created_at
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
178
283
|
// src/purchase.ts
|
|
179
284
|
var PurchaseModule = class {
|
|
180
285
|
constructor(baseUrl, apiKey) {
|
|
@@ -327,6 +432,7 @@ var Tally = class {
|
|
|
327
432
|
this.baseUrl = resolveBaseUrl(config.apiKey, config.baseUrl);
|
|
328
433
|
this.authorize = new AuthorizeModule(this.baseUrl, this.apiKey);
|
|
329
434
|
this.purchases = new PurchaseModule(this.baseUrl, this.apiKey);
|
|
435
|
+
this.intents = new IntentsModule(this.baseUrl, this.apiKey);
|
|
330
436
|
this.balances = new BalanceModule(this.baseUrl, this.apiKey);
|
|
331
437
|
this.webhooks = new WebhooksModule();
|
|
332
438
|
}
|
|
@@ -358,6 +464,7 @@ var Tally = class {
|
|
|
358
464
|
export {
|
|
359
465
|
AuthorizeModule,
|
|
360
466
|
BalanceModule,
|
|
467
|
+
IntentsModule,
|
|
361
468
|
PurchaseModule,
|
|
362
469
|
TallionError,
|
|
363
470
|
Tally,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/authorize.ts","../src/balance.ts","../src/purchase.ts","../src/webhooks.ts","../src/tally.ts"],"sourcesContent":["export class TallionError extends Error {\n public readonly status: number;\n public readonly code?: string;\n\n constructor(status: number, message: string, code?: string) {\n super(message);\n this.name = \"TallionError\";\n this.status = status;\n this.code = code;\n }\n}\n","import { TallionError } from \"./errors\";\n\nconst SANDBOX_URL = \"https://api.sandbox.tallion.ai\";\nconst PRODUCTION_URL = \"https://api.tallion.ai\";\n\nexport function resolveBaseUrl(apiKey: string, overrideUrl?: string): string {\n if (overrideUrl) return overrideUrl;\n if (apiKey.startsWith(\"sk_live_\")) return PRODUCTION_URL;\n return SANDBOX_URL;\n}\n\nexport interface RequestOptions {\n method?: string;\n headers?: Record<string, string>;\n body?: unknown;\n}\n\nexport async function request<T>(\n baseUrl: string,\n path: string,\n apiKey: string,\n options: RequestOptions = {},\n): Promise<T> {\n if (!apiKey) {\n throw new TallionError(\n 401,\n \"Tallion API key is required. Get one at https://tallion.ai/developer\",\n \"missing_api_key\",\n );\n }\n const url = `${baseUrl}/api${path}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...options.headers,\n };\n\n const res = await fetch(url, {\n method: options.method || \"GET\",\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: \"Unknown error\" }));\n throw new TallionError(\n res.status,\n body.error || \"Request failed\",\n body.code,\n );\n }\n\n return res.json() as Promise<T>;\n}\n","import { request } from \"./http\";\nimport type {\n AuthUrlResult,\n CreateAuthUrlOptions,\n ExchangeCodeOptions,\n RefreshTokenOptions,\n TokenResult,\n} from \"./types\";\n\n/** Generate a random string for PKCE */\nfunction generateRandomString(length: number): string {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~\";\n const array = new Uint8Array(length);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => chars[byte % chars.length]).join(\"\");\n}\n\n/** SHA-256 hash for PKCE S256 challenge */\nasync function sha256(plain: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(plain);\n const hash = await crypto.subtle.digest(\"SHA-256\", data);\n return btoa(String.fromCharCode(...new Uint8Array(hash)))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nexport class AuthorizeModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Create an authorization URL for customer consent.\n * Returns the URL to open in a popup/browser plus the PKCE code verifier.\n */\n async createUrl(options: CreateAuthUrlOptions): Promise<AuthUrlResult> {\n const codeVerifier = generateRandomString(64);\n const codeChallenge = await sha256(codeVerifier);\n\n const res = await request<{\n authorization_id: string;\n url: string;\n state: string;\n }>(this.baseUrl, \"/oauth/authorize\", this.apiKey, {\n method: \"POST\",\n body: {\n customer_identifier: options.customerIdentifier,\n redirect_url: options.redirectUrl,\n scopes: options.scopes || [\"purchase\", \"balance:read\"],\n code_challenge: codeChallenge,\n code_challenge_method: options.codeChallengeMethod || \"S256\",\n suggested_limits: options.suggestedLimits\n ? {\n max_per_transaction: options.suggestedLimits.maxPerTransaction,\n max_per_day: options.suggestedLimits.maxPerDay,\n max_per_month: options.suggestedLimits.maxPerMonth,\n require_approval_above: options.suggestedLimits.requireApprovalAbove,\n }\n : undefined,\n purchase_context: options.purchaseContext\n ? {\n amount: options.purchaseContext.amount,\n description: options.purchaseContext.description,\n merchant: options.purchaseContext.merchant,\n reference: options.purchaseContext.reference,\n }\n : undefined,\n },\n });\n\n return {\n url: res.url,\n state: res.state,\n codeVerifier,\n authorizationId: res.authorization_id,\n };\n }\n\n /**\n * Exchange an authorization code for access + refresh tokens.\n */\n async exchangeCode(options: ExchangeCodeOptions): Promise<TokenResult> {\n const res = await request<{\n access_token: string;\n refresh_token: string;\n token_type: string;\n expires_in: number;\n customer_id: string;\n installation_id: string;\n }>(this.baseUrl, \"/oauth/token\", this.apiKey, {\n method: \"POST\",\n body: {\n grant_type: \"authorization_code\",\n code: options.code,\n code_verifier: options.codeVerifier,\n },\n });\n\n return {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n tokenType: res.token_type,\n expiresIn: res.expires_in,\n customerId: res.customer_id,\n installationId: res.installation_id,\n };\n }\n\n /**\n * Refresh an access token using a refresh token.\n */\n async refreshToken(options: RefreshTokenOptions): Promise<TokenResult> {\n const res = await request<{\n access_token: string;\n refresh_token: string;\n token_type: string;\n expires_in: number;\n customer_id: string;\n installation_id: string;\n }>(this.baseUrl, \"/oauth/token\", this.apiKey, {\n method: \"POST\",\n body: {\n grant_type: \"refresh_token\",\n refresh_token: options.refreshToken,\n },\n });\n\n return {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n tokenType: res.token_type,\n expiresIn: res.expires_in,\n customerId: res.customer_id,\n installationId: res.installation_id,\n };\n }\n\n /**\n * Revoke an access or refresh token.\n */\n async revoke(token: string): Promise<void> {\n await request(this.baseUrl, \"/oauth/revoke\", this.apiKey, {\n method: \"POST\",\n body: { token },\n });\n }\n}\n","import { request } from \"./http\";\nimport type { BalanceResult } from \"./types\";\n\nexport class BalanceModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Get wallet balance for a customer (using OAuth token).\n */\n async get(customerToken: string, walletId?: string): Promise<BalanceResult> {\n const path = walletId ? `/wallets/${walletId}/budget` : \"/wallets/me\";\n const res = await request<{\n id?: string;\n wallet_id?: string;\n funding_amount: number;\n spent_amount: number;\n remaining: number;\n }>(this.baseUrl, path, customerToken, {\n method: \"GET\",\n });\n\n return {\n walletId: res.wallet_id || res.id || \"\",\n fundingAmount: res.funding_amount,\n spentAmount: res.spent_amount,\n remaining: res.remaining,\n };\n }\n}\n","import { request } from \"./http\";\nimport type { LegacyPurchaseOptions, PurchaseOptions, PurchaseResult } from \"./types\";\n\nexport class PurchaseModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Make a purchase using an OAuth customer token.\n */\n async create(options: PurchaseOptions): Promise<PurchaseResult> {\n const res = await request<{\n transaction_id: string;\n status: string;\n decision: string;\n decision_reason: string;\n amount: number;\n merchant_name: string;\n approval_deadline?: string;\n }>(this.baseUrl, \"/purchase\", options.customerToken, {\n method: \"POST\",\n headers: {\n \"X-Tallion-Installation\": \"\", // Resolved by OAuth token\n },\n body: {\n amount: options.amount,\n currency: options.currency || \"USD\",\n wallet_id: options.walletId,\n merchant: {\n name: options.merchant.name,\n mcc: options.merchant.mcc || \"\",\n country: options.merchant.country || \"US\",\n },\n context: {\n description: options.context.description,\n category: options.context.category,\n line_items: options.context.lineItems,\n external_reference: options.context.externalReference,\n refund_policy: options.context.refundPolicy,\n metadata: options.context.metadata,\n },\n },\n });\n\n return {\n transactionId: res.transaction_id,\n status: res.status as PurchaseResult[\"status\"],\n decision: res.decision,\n decisionReason: res.decision_reason,\n amount: res.amount,\n merchantName: res.merchant_name,\n approvalDeadline: res.approval_deadline,\n };\n }\n\n /**\n * Make a purchase using the legacy API key + installation ID auth.\n */\n async legacyCreate(options: LegacyPurchaseOptions): Promise<PurchaseResult> {\n const res = await request<{\n transaction_id: string;\n status: string;\n decision: string;\n decision_reason: string;\n amount: number;\n merchant_name: string;\n approval_deadline?: string;\n }>(this.baseUrl, \"/purchase\", this.apiKey, {\n method: \"POST\",\n headers: {\n \"X-Tallion-Installation\": options.installationId,\n },\n body: {\n amount: options.amount,\n merchant_name: options.merchantName,\n merchant_mcc: options.merchantMcc || \"\",\n merchant_country: options.merchantCountry || \"US\",\n currency: options.currency || \"USD\",\n wallet_id: options.walletId,\n reasoning: options.reasoning,\n },\n });\n\n return {\n transactionId: res.transaction_id,\n status: res.status as PurchaseResult[\"status\"],\n decision: res.decision,\n decisionReason: res.decision_reason,\n amount: res.amount,\n merchantName: res.merchant_name,\n approvalDeadline: res.approval_deadline,\n };\n }\n}\n","import type { WebhookEvent } from \"./types\";\nimport { TallionError } from \"./errors\";\n\nexport class WebhooksModule {\n constructor(private secret?: string) {}\n\n /**\n * Verify a webhook signature and parse the event.\n * Uses Web Crypto API (works in Node 18+, Deno, Bun, Cloudflare Workers, etc.)\n *\n * @param body - Raw request body string\n * @param signature - Value of X-Tally-Signature header\n * @param tolerance - Max age in seconds (default: 300 = 5 minutes)\n */\n async verify(\n body: string,\n signature: string,\n tolerance = 300,\n ): Promise<WebhookEvent> {\n if (!this.secret) {\n throw new TallionError(500, \"Webhook secret not configured\");\n }\n\n // Parse signature header: \"t={timestamp},v1={hex_signature}\"\n const parts: Record<string, string> = {};\n for (const part of signature.split(\",\")) {\n const [key, ...val] = part.split(\"=\");\n if (key && val.length > 0) {\n parts[key] = val.join(\"=\");\n }\n }\n\n const timestamp = parts[\"t\"];\n const sig = parts[\"v1\"];\n\n if (!timestamp || !sig) {\n throw new TallionError(400, \"Invalid webhook signature format\");\n }\n\n // Check timestamp freshness\n const ts = parseInt(timestamp, 10);\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - ts) > tolerance) {\n throw new TallionError(400, \"Webhook timestamp expired\");\n }\n\n // Compute HMAC-SHA256\n const message = `${timestamp}.${body}`;\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(this.secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n\n const signatureBytes = await crypto.subtle.sign(\n \"HMAC\",\n key,\n encoder.encode(message),\n );\n\n const computed = Array.from(new Uint8Array(signatureBytes))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n // Constant-time comparison\n if (computed.length !== sig.length || !timingSafeEqual(computed, sig)) {\n throw new TallionError(401, \"Invalid webhook signature\");\n }\n\n return JSON.parse(body) as WebhookEvent;\n }\n}\n\n/** Simple constant-time string comparison */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n","import { AuthorizeModule } from \"./authorize\";\nimport { BalanceModule } from \"./balance\";\nimport { resolveBaseUrl } from \"./http\";\nimport { PurchaseModule } from \"./purchase\";\nimport { WebhooksModule } from \"./webhooks\";\nimport type { PurchaseOptions, PurchaseResult, TallyConfig } from \"./types\";\n\nexport class Tally {\n private baseUrl: string;\n private apiKey: string;\n\n /** OAuth authorization flow */\n public authorize: AuthorizeModule;\n\n /** Purchase operations */\n public purchases: PurchaseModule;\n\n /** Balance operations */\n public balances: BalanceModule;\n\n /** Webhook signature verification */\n public webhooks: WebhooksModule;\n\n constructor(config: TallyConfig) {\n if (!config.apiKey) {\n throw new Error(\n \"Tallion API key is required. Get one at https://tallion.ai/developer\",\n );\n }\n this.apiKey = config.apiKey;\n this.baseUrl = resolveBaseUrl(config.apiKey, config.baseUrl);\n this.authorize = new AuthorizeModule(this.baseUrl, this.apiKey);\n this.purchases = new PurchaseModule(this.baseUrl, this.apiKey);\n this.balances = new BalanceModule(this.baseUrl, this.apiKey);\n this.webhooks = new WebhooksModule();\n }\n\n /**\n * Convenience method: Make a purchase (delegates to purchases.create).\n */\n async purchase(options: PurchaseOptions): Promise<PurchaseResult> {\n return this.purchases.create(options);\n }\n\n /**\n * Convenience method: Get balance for a customer.\n */\n async balance(customerToken: string, walletId?: string) {\n return this.balances.get(customerToken, walletId);\n }\n\n /**\n * Check if this is a sandbox instance.\n */\n get isSandbox(): boolean {\n return this.apiKey.startsWith(\"sk_sandbox_\");\n }\n\n /**\n * Get the resolved base URL.\n */\n get url(): string {\n return this.baseUrl;\n }\n}\n"],"mappings":"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","names":["key"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/authorize.ts","../src/balance.ts","../src/intents.ts","../src/purchase.ts","../src/webhooks.ts","../src/tally.ts"],"sourcesContent":["export class TallionError extends Error {\n public readonly status: number;\n public readonly code?: string;\n\n constructor(status: number, message: string, code?: string) {\n super(message);\n this.name = \"TallionError\";\n this.status = status;\n this.code = code;\n }\n}\n","import { TallionError } from \"./errors\";\n\nconst SANDBOX_URL = \"https://api.sandbox.tallion.ai\";\nconst PRODUCTION_URL = \"https://api.tallion.ai\";\n\nexport function resolveBaseUrl(apiKey: string, overrideUrl?: string): string {\n if (overrideUrl) return overrideUrl;\n if (apiKey.startsWith(\"sk_live_\")) return PRODUCTION_URL;\n return SANDBOX_URL;\n}\n\nexport interface RequestOptions {\n method?: string;\n headers?: Record<string, string>;\n body?: unknown;\n}\n\nexport async function request<T>(\n baseUrl: string,\n path: string,\n apiKey: string,\n options: RequestOptions = {},\n): Promise<T> {\n if (!apiKey) {\n throw new TallionError(\n 401,\n \"Tallion API key is required. Get one at https://tallion.ai/developer\",\n \"missing_api_key\",\n );\n }\n const url = `${baseUrl}/api${path}`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...options.headers,\n };\n\n const res = await fetch(url, {\n method: options.method || \"GET\",\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: \"Unknown error\" }));\n throw new TallionError(\n res.status,\n body.error || \"Request failed\",\n body.code,\n );\n }\n\n return res.json() as Promise<T>;\n}\n","import { request } from \"./http\";\nimport type {\n AuthUrlResult,\n CreateAuthUrlOptions,\n ExchangeCodeOptions,\n RefreshTokenOptions,\n TokenResult,\n} from \"./types\";\n\n/** Generate a random string for PKCE */\nfunction generateRandomString(length: number): string {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~\";\n const array = new Uint8Array(length);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => chars[byte % chars.length]).join(\"\");\n}\n\n/** SHA-256 hash for PKCE S256 challenge */\nasync function sha256(plain: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(plain);\n const hash = await crypto.subtle.digest(\"SHA-256\", data);\n return btoa(String.fromCharCode(...new Uint8Array(hash)))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nexport class AuthorizeModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Create an authorization URL for customer consent.\n * Returns the URL to open in a popup/browser plus the PKCE code verifier.\n */\n async createUrl(options: CreateAuthUrlOptions): Promise<AuthUrlResult> {\n const codeVerifier = generateRandomString(64);\n const codeChallenge = await sha256(codeVerifier);\n\n const res = await request<{\n authorization_id: string;\n url: string;\n state: string;\n }>(this.baseUrl, \"/oauth/authorize\", this.apiKey, {\n method: \"POST\",\n body: {\n customer_identifier: options.customerIdentifier,\n redirect_url: options.redirectUrl,\n scopes: options.scopes || [\"purchase\", \"balance:read\"],\n code_challenge: codeChallenge,\n code_challenge_method: options.codeChallengeMethod || \"S256\",\n suggested_limits: options.suggestedLimits\n ? {\n max_per_transaction: options.suggestedLimits.maxPerTransaction,\n max_per_day: options.suggestedLimits.maxPerDay,\n max_per_month: options.suggestedLimits.maxPerMonth,\n require_approval_above: options.suggestedLimits.requireApprovalAbove,\n }\n : undefined,\n purchase_context: options.purchaseContext\n ? {\n amount: options.purchaseContext.amount,\n description: options.purchaseContext.description,\n merchant: options.purchaseContext.merchant,\n reference: options.purchaseContext.reference,\n }\n : undefined,\n },\n });\n\n return {\n url: res.url,\n state: res.state,\n codeVerifier,\n authorizationId: res.authorization_id,\n };\n }\n\n /**\n * Exchange an authorization code for access + refresh tokens.\n */\n async exchangeCode(options: ExchangeCodeOptions): Promise<TokenResult> {\n const res = await request<{\n access_token: string;\n refresh_token: string;\n token_type: string;\n expires_in: number;\n customer_id: string;\n installation_id: string;\n }>(this.baseUrl, \"/oauth/token\", this.apiKey, {\n method: \"POST\",\n body: {\n grant_type: \"authorization_code\",\n code: options.code,\n code_verifier: options.codeVerifier,\n },\n });\n\n return {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n tokenType: res.token_type,\n expiresIn: res.expires_in,\n customerId: res.customer_id,\n installationId: res.installation_id,\n };\n }\n\n /**\n * Refresh an access token using a refresh token.\n */\n async refreshToken(options: RefreshTokenOptions): Promise<TokenResult> {\n const res = await request<{\n access_token: string;\n refresh_token: string;\n token_type: string;\n expires_in: number;\n customer_id: string;\n installation_id: string;\n }>(this.baseUrl, \"/oauth/token\", this.apiKey, {\n method: \"POST\",\n body: {\n grant_type: \"refresh_token\",\n refresh_token: options.refreshToken,\n },\n });\n\n return {\n accessToken: res.access_token,\n refreshToken: res.refresh_token,\n tokenType: res.token_type,\n expiresIn: res.expires_in,\n customerId: res.customer_id,\n installationId: res.installation_id,\n };\n }\n\n /**\n * Revoke an access or refresh token.\n */\n async revoke(token: string): Promise<void> {\n await request(this.baseUrl, \"/oauth/revoke\", this.apiKey, {\n method: \"POST\",\n body: { token },\n });\n }\n}\n","import { request } from \"./http\";\nimport type { BalanceResult } from \"./types\";\n\nexport class BalanceModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Get wallet balance for a customer (using OAuth token).\n */\n async get(customerToken: string, walletId?: string): Promise<BalanceResult> {\n const path = walletId ? `/wallets/${walletId}/budget` : \"/wallets/me\";\n const res = await request<{\n id?: string;\n wallet_id?: string;\n funding_amount: number;\n spent_amount: number;\n remaining: number;\n }>(this.baseUrl, path, customerToken, {\n method: \"GET\",\n });\n\n return {\n walletId: res.wallet_id || res.id || \"\",\n fundingAmount: res.funding_amount,\n spentAmount: res.spent_amount,\n remaining: res.remaining,\n };\n }\n}\n","import { request } from \"./http\";\nimport type {\n CreateIntentOptions,\n IntentResult,\n IntentStatusResult,\n ListIntentsOptions,\n} from \"./types\";\n\nexport class IntentsModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Create a purchase intent (Buy Anywhere).\n * Returns a virtual card for the customer to use at the merchant.\n */\n async create(options: CreateIntentOptions): Promise<IntentResult> {\n const res = await request<{\n intent_id: string;\n status: string;\n amount: number;\n currency: string;\n merchant_name?: string;\n expires_at?: string;\n transaction_id?: string;\n card?: {\n pan: string;\n cvv: string;\n exp_month: number;\n exp_year: number;\n last_four: string;\n };\n }>(this.baseUrl, \"/intents\", options.customerToken, {\n method: \"POST\",\n body: {\n amount: options.amount,\n currency: options.currency || \"USD\",\n wallet_id: options.walletId,\n merchant: options.merchant\n ? {\n name: options.merchant.name,\n url: options.merchant.url,\n mcc: options.merchant.mcc,\n }\n : undefined,\n product: options.product\n ? {\n description: options.product.description,\n url: options.product.url,\n }\n : undefined,\n amount_tolerance_pct: options.amountTolerancePct,\n },\n });\n\n return {\n intentId: res.intent_id,\n status: res.status as IntentResult[\"status\"],\n amount: res.amount,\n currency: res.currency,\n merchantName: res.merchant_name,\n expiresAt: res.expires_at,\n transactionId: res.transaction_id,\n card: res.card\n ? {\n pan: res.card.pan,\n cvv: res.card.cvv,\n expMonth: res.card.exp_month,\n expYear: res.card.exp_year,\n lastFour: res.card.last_four,\n }\n : undefined,\n };\n }\n\n /**\n * Get the current status of a purchase intent.\n */\n async get(\n customerToken: string,\n intentId: string,\n ): Promise<IntentStatusResult> {\n const res = await request<RawIntentStatus>(\n this.baseUrl,\n `/intents/${intentId}`,\n customerToken,\n );\n\n return mapIntentStatus(res);\n }\n\n /**\n * Cancel an active purchase intent.\n */\n async cancel(\n customerToken: string,\n intentId: string,\n ): Promise<IntentStatusResult> {\n const res = await request<RawIntentStatus>(\n this.baseUrl,\n `/intents/${intentId}/cancel`,\n customerToken,\n { method: \"POST\" },\n );\n\n return mapIntentStatus(res);\n }\n\n /**\n * List purchase intents for the authenticated customer.\n */\n async list(\n customerToken: string,\n options?: ListIntentsOptions,\n ): Promise<IntentStatusResult[]> {\n const params = new URLSearchParams();\n if (options?.limit !== undefined) params.set(\"limit\", String(options.limit));\n if (options?.offset !== undefined)\n params.set(\"offset\", String(options.offset));\n\n const query = params.toString();\n const path = query ? `/intents?${query}` : \"/intents\";\n\n const res = await request<RawIntentStatus[]>(\n this.baseUrl,\n path,\n customerToken,\n );\n\n return res.map(mapIntentStatus);\n }\n}\n\n// ── Internal helpers ──\n\ninterface RawIntentStatus {\n intent_id: string;\n status: string;\n amount: number;\n currency: string;\n merchant_name?: string;\n card_last_four?: string;\n asa_verified: boolean;\n asa_amount?: number;\n asa_merchant_descriptor?: string;\n asa_mismatch_reason?: string;\n transaction_id?: string;\n expires_at?: string;\n created_at: string;\n}\n\nfunction mapIntentStatus(raw: RawIntentStatus): IntentStatusResult {\n return {\n intentId: raw.intent_id,\n status: raw.status,\n amount: raw.amount,\n currency: raw.currency,\n merchantName: raw.merchant_name,\n cardLastFour: raw.card_last_four,\n asaVerified: raw.asa_verified,\n asaAmount: raw.asa_amount,\n asaMerchantDescriptor: raw.asa_merchant_descriptor,\n asaMismatchReason: raw.asa_mismatch_reason,\n transactionId: raw.transaction_id,\n expiresAt: raw.expires_at,\n createdAt: raw.created_at,\n };\n}\n","import { request } from \"./http\";\nimport type { LegacyPurchaseOptions, PurchaseOptions, PurchaseResult } from \"./types\";\n\nexport class PurchaseModule {\n constructor(\n private baseUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Make a purchase using an OAuth customer token.\n */\n async create(options: PurchaseOptions): Promise<PurchaseResult> {\n const res = await request<{\n transaction_id: string;\n status: string;\n decision: string;\n decision_reason: string;\n amount: number;\n merchant_name: string;\n approval_deadline?: string;\n }>(this.baseUrl, \"/purchase\", options.customerToken, {\n method: \"POST\",\n headers: {\n \"X-Tallion-Installation\": \"\", // Resolved by OAuth token\n },\n body: {\n amount: options.amount,\n currency: options.currency || \"USD\",\n wallet_id: options.walletId,\n merchant: {\n name: options.merchant.name,\n mcc: options.merchant.mcc || \"\",\n country: options.merchant.country || \"US\",\n },\n context: {\n description: options.context.description,\n category: options.context.category,\n line_items: options.context.lineItems,\n external_reference: options.context.externalReference,\n refund_policy: options.context.refundPolicy,\n metadata: options.context.metadata,\n },\n },\n });\n\n return {\n transactionId: res.transaction_id,\n status: res.status as PurchaseResult[\"status\"],\n decision: res.decision,\n decisionReason: res.decision_reason,\n amount: res.amount,\n merchantName: res.merchant_name,\n approvalDeadline: res.approval_deadline,\n };\n }\n\n /**\n * Make a purchase using the legacy API key + installation ID auth.\n */\n async legacyCreate(options: LegacyPurchaseOptions): Promise<PurchaseResult> {\n const res = await request<{\n transaction_id: string;\n status: string;\n decision: string;\n decision_reason: string;\n amount: number;\n merchant_name: string;\n approval_deadline?: string;\n }>(this.baseUrl, \"/purchase\", this.apiKey, {\n method: \"POST\",\n headers: {\n \"X-Tallion-Installation\": options.installationId,\n },\n body: {\n amount: options.amount,\n merchant_name: options.merchantName,\n merchant_mcc: options.merchantMcc || \"\",\n merchant_country: options.merchantCountry || \"US\",\n currency: options.currency || \"USD\",\n wallet_id: options.walletId,\n reasoning: options.reasoning,\n },\n });\n\n return {\n transactionId: res.transaction_id,\n status: res.status as PurchaseResult[\"status\"],\n decision: res.decision,\n decisionReason: res.decision_reason,\n amount: res.amount,\n merchantName: res.merchant_name,\n approvalDeadline: res.approval_deadline,\n };\n }\n}\n","import type { WebhookEvent } from \"./types\";\nimport { TallionError } from \"./errors\";\n\nexport class WebhooksModule {\n constructor(private secret?: string) {}\n\n /**\n * Verify a webhook signature and parse the event.\n * Uses Web Crypto API (works in Node 18+, Deno, Bun, Cloudflare Workers, etc.)\n *\n * @param body - Raw request body string\n * @param signature - Value of X-Tally-Signature header\n * @param tolerance - Max age in seconds (default: 300 = 5 minutes)\n */\n async verify(\n body: string,\n signature: string,\n tolerance = 300,\n ): Promise<WebhookEvent> {\n if (!this.secret) {\n throw new TallionError(500, \"Webhook secret not configured\");\n }\n\n // Parse signature header: \"t={timestamp},v1={hex_signature}\"\n const parts: Record<string, string> = {};\n for (const part of signature.split(\",\")) {\n const [key, ...val] = part.split(\"=\");\n if (key && val.length > 0) {\n parts[key] = val.join(\"=\");\n }\n }\n\n const timestamp = parts[\"t\"];\n const sig = parts[\"v1\"];\n\n if (!timestamp || !sig) {\n throw new TallionError(400, \"Invalid webhook signature format\");\n }\n\n // Check timestamp freshness\n const ts = parseInt(timestamp, 10);\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - ts) > tolerance) {\n throw new TallionError(400, \"Webhook timestamp expired\");\n }\n\n // Compute HMAC-SHA256\n const message = `${timestamp}.${body}`;\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(this.secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n\n const signatureBytes = await crypto.subtle.sign(\n \"HMAC\",\n key,\n encoder.encode(message),\n );\n\n const computed = Array.from(new Uint8Array(signatureBytes))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n // Constant-time comparison\n if (computed.length !== sig.length || !timingSafeEqual(computed, sig)) {\n throw new TallionError(401, \"Invalid webhook signature\");\n }\n\n return JSON.parse(body) as WebhookEvent;\n }\n}\n\n/** Simple constant-time string comparison */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n","import { AuthorizeModule } from \"./authorize\";\nimport { BalanceModule } from \"./balance\";\nimport { resolveBaseUrl } from \"./http\";\nimport { IntentsModule } from \"./intents\";\nimport { PurchaseModule } from \"./purchase\";\nimport { WebhooksModule } from \"./webhooks\";\nimport type { PurchaseOptions, PurchaseResult, TallyConfig } from \"./types\";\n\nexport class Tally {\n private baseUrl: string;\n private apiKey: string;\n\n /** OAuth authorization flow */\n public authorize: AuthorizeModule;\n\n /** Purchase operations */\n public purchases: PurchaseModule;\n\n /** Balance operations */\n public balances: BalanceModule;\n\n /** Purchase intents (Buy Anywhere) */\n public intents: IntentsModule;\n\n /** Webhook signature verification */\n public webhooks: WebhooksModule;\n\n constructor(config: TallyConfig) {\n if (!config.apiKey) {\n throw new Error(\n \"Tallion API key is required. Get one at https://tallion.ai/developer\",\n );\n }\n this.apiKey = config.apiKey;\n this.baseUrl = resolveBaseUrl(config.apiKey, config.baseUrl);\n this.authorize = new AuthorizeModule(this.baseUrl, this.apiKey);\n this.purchases = new PurchaseModule(this.baseUrl, this.apiKey);\n this.intents = new IntentsModule(this.baseUrl, this.apiKey);\n this.balances = new BalanceModule(this.baseUrl, this.apiKey);\n this.webhooks = new WebhooksModule();\n }\n\n /**\n * Convenience method: Make a purchase (delegates to purchases.create).\n */\n async purchase(options: PurchaseOptions): Promise<PurchaseResult> {\n return this.purchases.create(options);\n }\n\n /**\n * Convenience method: Get balance for a customer.\n */\n async balance(customerToken: string, walletId?: string) {\n return this.balances.get(customerToken, walletId);\n }\n\n /**\n * Check if this is a sandbox instance.\n */\n get isSandbox(): boolean {\n return this.apiKey.startsWith(\"sk_sandbox_\");\n }\n\n /**\n * Get the resolved base URL.\n */\n get url(): string {\n return this.baseUrl;\n }\n}\n"],"mappings":"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","names":["key"]}
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tallion/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Tallion SDK — AI agent spend control for developers",
|
|
5
|
-
"main": "./dist/index.
|
|
6
|
-
"module": "./dist/index.
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
|
-
"import": "./dist/index.
|
|
12
|
-
"require": "./dist/index.
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"files": [
|