@framers/agentos-ext-wallet 0.2.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.
Files changed (108) hide show
  1. package/LICENSE +98 -0
  2. package/dist/AgentWalletManager.d.ts +68 -0
  3. package/dist/AgentWalletManager.d.ts.map +1 -0
  4. package/dist/AgentWalletManager.js +238 -0
  5. package/dist/AgentWalletManager.js.map +1 -0
  6. package/dist/SpendingPolicyEnforcer.d.ts +33 -0
  7. package/dist/SpendingPolicyEnforcer.d.ts.map +1 -0
  8. package/dist/SpendingPolicyEnforcer.js +128 -0
  9. package/dist/SpendingPolicyEnforcer.js.map +1 -0
  10. package/dist/cards/CardManager.d.ts +71 -0
  11. package/dist/cards/CardManager.d.ts.map +1 -0
  12. package/dist/cards/CardManager.js +212 -0
  13. package/dist/cards/CardManager.js.map +1 -0
  14. package/dist/cards/LithicCardAdapter.d.ts +40 -0
  15. package/dist/cards/LithicCardAdapter.d.ts.map +1 -0
  16. package/dist/cards/LithicCardAdapter.js +116 -0
  17. package/dist/cards/LithicCardAdapter.js.map +1 -0
  18. package/dist/cards/MccCategoryMap.d.ts +36 -0
  19. package/dist/cards/MccCategoryMap.d.ts.map +1 -0
  20. package/dist/cards/MccCategoryMap.js +113 -0
  21. package/dist/cards/MccCategoryMap.js.map +1 -0
  22. package/dist/cards/types.d.ts +131 -0
  23. package/dist/cards/types.d.ts.map +1 -0
  24. package/dist/cards/types.js +12 -0
  25. package/dist/cards/types.js.map +1 -0
  26. package/dist/chains/EvmWalletAdapter.d.ts +30 -0
  27. package/dist/chains/EvmWalletAdapter.d.ts.map +1 -0
  28. package/dist/chains/EvmWalletAdapter.js +135 -0
  29. package/dist/chains/EvmWalletAdapter.js.map +1 -0
  30. package/dist/chains/SolanaWalletAdapter.d.ts +32 -0
  31. package/dist/chains/SolanaWalletAdapter.d.ts.map +1 -0
  32. package/dist/chains/SolanaWalletAdapter.js +128 -0
  33. package/dist/chains/SolanaWalletAdapter.js.map +1 -0
  34. package/dist/index.d.ts +61 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +228 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/tools/CardSpendingSummaryTool.d.ts +14 -0
  39. package/dist/tools/CardSpendingSummaryTool.d.ts.map +1 -0
  40. package/dist/tools/CardSpendingSummaryTool.js +40 -0
  41. package/dist/tools/CardSpendingSummaryTool.js.map +1 -0
  42. package/dist/tools/CardStatusTool.d.ts +21 -0
  43. package/dist/tools/CardStatusTool.d.ts.map +1 -0
  44. package/dist/tools/CardStatusTool.js +48 -0
  45. package/dist/tools/CardStatusTool.js.map +1 -0
  46. package/dist/tools/CheckBalanceTool.d.ts +23 -0
  47. package/dist/tools/CheckBalanceTool.d.ts.map +1 -0
  48. package/dist/tools/CheckBalanceTool.js +116 -0
  49. package/dist/tools/CheckBalanceTool.js.map +1 -0
  50. package/dist/tools/FreezeCardTool.d.ts +15 -0
  51. package/dist/tools/FreezeCardTool.d.ts.map +1 -0
  52. package/dist/tools/FreezeCardTool.js +39 -0
  53. package/dist/tools/FreezeCardTool.js.map +1 -0
  54. package/dist/tools/IssueCardTool.d.ts +22 -0
  55. package/dist/tools/IssueCardTool.d.ts.map +1 -0
  56. package/dist/tools/IssueCardTool.js +55 -0
  57. package/dist/tools/IssueCardTool.js.map +1 -0
  58. package/dist/tools/PayWithCardTool.d.ts +29 -0
  59. package/dist/tools/PayWithCardTool.d.ts.map +1 -0
  60. package/dist/tools/PayWithCardTool.js +79 -0
  61. package/dist/tools/PayWithCardTool.js.map +1 -0
  62. package/dist/tools/SendCryptoTool.d.ts +33 -0
  63. package/dist/tools/SendCryptoTool.d.ts.map +1 -0
  64. package/dist/tools/SendCryptoTool.js +136 -0
  65. package/dist/tools/SendCryptoTool.js.map +1 -0
  66. package/dist/tools/UnfreezeCardTool.d.ts +15 -0
  67. package/dist/tools/UnfreezeCardTool.d.ts.map +1 -0
  68. package/dist/tools/UnfreezeCardTool.js +39 -0
  69. package/dist/tools/UnfreezeCardTool.js.map +1 -0
  70. package/dist/tools/WalletHistoryTool.d.ts +35 -0
  71. package/dist/tools/WalletHistoryTool.d.ts.map +1 -0
  72. package/dist/tools/WalletHistoryTool.js +75 -0
  73. package/dist/tools/WalletHistoryTool.js.map +1 -0
  74. package/dist/types.d.ts +146 -0
  75. package/dist/types.d.ts.map +1 -0
  76. package/dist/types.js +29 -0
  77. package/dist/types.js.map +1 -0
  78. package/manifest.json +98 -0
  79. package/package.json +78 -0
  80. package/src/AgentWalletManager.ts +324 -0
  81. package/src/SpendingPolicyEnforcer.ts +169 -0
  82. package/src/cards/CardManager.ts +274 -0
  83. package/src/cards/LithicCardAdapter.ts +159 -0
  84. package/src/cards/MccCategoryMap.ts +138 -0
  85. package/src/cards/types.ts +169 -0
  86. package/src/chains/EvmWalletAdapter.ts +170 -0
  87. package/src/chains/SolanaWalletAdapter.ts +184 -0
  88. package/src/index.ts +315 -0
  89. package/src/tools/CardSpendingSummaryTool.ts +52 -0
  90. package/src/tools/CardStatusTool.ts +68 -0
  91. package/src/tools/CheckBalanceTool.ts +145 -0
  92. package/src/tools/FreezeCardTool.ts +52 -0
  93. package/src/tools/IssueCardTool.ts +76 -0
  94. package/src/tools/PayWithCardTool.ts +109 -0
  95. package/src/tools/SendCryptoTool.ts +185 -0
  96. package/src/tools/UnfreezeCardTool.ts +52 -0
  97. package/src/tools/WalletHistoryTool.ts +113 -0
  98. package/src/types.ts +230 -0
  99. package/test/AgentWalletManager.spec.ts +301 -0
  100. package/test/CardManager.spec.ts +428 -0
  101. package/test/LithicCardAdapter.spec.ts +224 -0
  102. package/test/MccCategoryMap.spec.ts +153 -0
  103. package/test/SpendingPolicyEnforcer.spec.ts +254 -0
  104. package/test/card-integration.spec.ts +242 -0
  105. package/test/card-tools.spec.ts +285 -0
  106. package/test/integration.spec.ts +171 -0
  107. package/test/wallet-tools.spec.ts +275 -0
  108. package/tsconfig.json +22 -0
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @fileoverview High-level card lifecycle manager.
3
+ *
4
+ * Mirrors AgentWalletManager's pattern: one card per agent, spending policy
5
+ * enforcement via the shared SpendingPolicyEnforcer, and in-memory/DB store
6
+ * abstraction via ICardStore.
7
+ *
8
+ * @module wallet/cards/CardManager
9
+ */
10
+ import type { SpendingPolicyEnforcer } from '../SpendingPolicyEnforcer.js';
11
+ import type { SpendCategory } from '../types.js';
12
+ import type { MccCategoryMap } from './MccCategoryMap.js';
13
+ import type { AgentCardRecord, CardConfig, ICardAdapter, ICardStore, LithicTransaction, SpendingSummary } from './types.js';
14
+ export interface CardManagerOptions {
15
+ adapter: ICardAdapter;
16
+ store: ICardStore;
17
+ policyEnforcer: SpendingPolicyEnforcer;
18
+ mccMap: MccCategoryMap;
19
+ config: CardConfig;
20
+ }
21
+ export declare class CardManager {
22
+ private readonly adapter;
23
+ private readonly store;
24
+ private readonly policy;
25
+ private readonly mccMap;
26
+ private readonly config;
27
+ constructor(opts: CardManagerOptions);
28
+ /**
29
+ * Issue a new virtual card for the agent.
30
+ * One card per agent — throws if card already exists.
31
+ */
32
+ issueCard(agentId: string, opts?: {
33
+ memo?: string;
34
+ spendLimitUsd?: number;
35
+ }): Promise<AgentCardRecord>;
36
+ /** Get the agent's card record, or null. */
37
+ getCard(agentId: string): Promise<AgentCardRecord | null>;
38
+ /**
39
+ * Get sensitive card details (PAN, CVV, expiry) for online payments.
40
+ * Enforces spending policy before revealing details.
41
+ */
42
+ getCardDetails(agentId: string, estimatedAmountUsd?: number, category?: SpendCategory): Promise<{
43
+ last4: string;
44
+ expMonth: string;
45
+ expYear: string;
46
+ cvv: string;
47
+ pan: string;
48
+ }>;
49
+ /** Freeze (pause) the agent's card. */
50
+ freezeCard(agentId: string): Promise<void>;
51
+ /** Unfreeze (resume) the agent's card. */
52
+ unfreezeCard(agentId: string): Promise<void>;
53
+ /** Permanently close the agent's card. */
54
+ closeCard(agentId: string): Promise<void>;
55
+ getSpendingSummary(agentId: string, period?: 'day' | 'month'): Promise<SpendingSummary>;
56
+ /**
57
+ * Process a Lithic transaction webhook event.
58
+ * Resolves MCC → category and records the spend in the shared ledger.
59
+ */
60
+ processWebhookTransaction(agentId: string, lithicTx: LithicTransaction): Promise<void>;
61
+ private requireCard;
62
+ /**
63
+ * Build a flat list of blocked MCC codes from the spending policy's
64
+ * blockedCategories, expanded via the MCC map.
65
+ */
66
+ private getBlockedMccs;
67
+ }
68
+ export declare class CardSpendingBlockedError extends Error {
69
+ constructor(reason: string);
70
+ }
71
+ //# sourceMappingURL=CardManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CardManager.d.ts","sourceRoot":"","sources":["../../src/cards/CardManager.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EAEV,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,eAAe,EAChB,MAAM,YAAY,CAAC;AAMpB,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;IAClB,cAAc,EAAE,sBAAsB,CAAC;IACvC,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;gBAExB,IAAI,EAAE,kBAAkB;IAYpC;;;OAGG;IACG,SAAS,CACb,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAC/C,OAAO,CAAC,eAAe,CAAC;IA0C3B,4CAA4C;IACtC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAI/D;;;OAGG;IACG,cAAc,CAClB,OAAO,EAAE,MAAM,EACf,kBAAkB,CAAC,EAAE,MAAM,EAC3B,QAAQ,CAAC,EAAE,aAAa,GACvB,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAsB1F,uCAAuC;IACjC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD,0CAA0C;IACpC,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASlD,0CAA0C;IACpC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYzC,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,KAAK,GAAG,OAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;IAkCtG;;;OAGG;IACG,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;YA+B9E,WAAW;IAQzB;;;OAGG;IACH,OAAO,CAAC,cAAc;CAQvB;AAMD,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,MAAM,EAAE,MAAM;CAI3B"}
@@ -0,0 +1,212 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * @fileoverview High-level card lifecycle manager.
4
+ *
5
+ * Mirrors AgentWalletManager's pattern: one card per agent, spending policy
6
+ * enforcement via the shared SpendingPolicyEnforcer, and in-memory/DB store
7
+ * abstraction via ICardStore.
8
+ *
9
+ * @module wallet/cards/CardManager
10
+ */
11
+ import { v4 as uuidv4 } from 'uuid';
12
+ export class CardManager {
13
+ adapter;
14
+ store;
15
+ policy;
16
+ mccMap;
17
+ config;
18
+ constructor(opts) {
19
+ this.adapter = opts.adapter;
20
+ this.store = opts.store;
21
+ this.policy = opts.policyEnforcer;
22
+ this.mccMap = opts.mccMap;
23
+ this.config = opts.config;
24
+ }
25
+ // -----------------------------------------------------------------------
26
+ // Card lifecycle
27
+ // -----------------------------------------------------------------------
28
+ /**
29
+ * Issue a new virtual card for the agent.
30
+ * One card per agent — throws if card already exists.
31
+ */
32
+ async issueCard(agentId, opts) {
33
+ const existing = await this.store.getCard(agentId);
34
+ if (existing) {
35
+ throw new Error(`Agent ${agentId} already has a card (last4: ${existing.last4})`);
36
+ }
37
+ const spendLimit = opts?.spendLimitUsd ?? this.config.defaultSpendLimitUsd;
38
+ const lithicCard = await this.adapter.createCard({
39
+ type: 'VIRTUAL',
40
+ memo: opts?.memo || `Agent ${agentId} virtual card`,
41
+ spend_limit: Math.round(spendLimit * 100), // Lithic uses cents
42
+ spend_limit_duration: 'MONTHLY',
43
+ state: 'OPEN',
44
+ });
45
+ // Set auth rules for blocked categories
46
+ const blockedMccs = this.getBlockedMccs();
47
+ if (blockedMccs.length > 0) {
48
+ await this.adapter.createAuthRule(lithicCard.token, {
49
+ blocked_mcc: blockedMccs,
50
+ });
51
+ }
52
+ const record = {
53
+ id: uuidv4(),
54
+ agentId,
55
+ lithicCardToken: lithicCard.token,
56
+ last4: lithicCard.last_four,
57
+ cardType: lithicCard.type,
58
+ state: lithicCard.state,
59
+ spendLimitUsd: spendLimit,
60
+ spendLimitDuration: 'MONTHLY',
61
+ network: 'VISA',
62
+ memo: opts?.memo,
63
+ createdAt: Date.now(),
64
+ };
65
+ await this.store.saveCard(record);
66
+ return record;
67
+ }
68
+ /** Get the agent's card record, or null. */
69
+ async getCard(agentId) {
70
+ return this.store.getCard(agentId);
71
+ }
72
+ /**
73
+ * Get sensitive card details (PAN, CVV, expiry) for online payments.
74
+ * Enforces spending policy before revealing details.
75
+ */
76
+ async getCardDetails(agentId, estimatedAmountUsd, category) {
77
+ const card = await this.requireCard(agentId);
78
+ // If an estimated amount is provided, check spending policy first
79
+ if (estimatedAmountUsd !== undefined) {
80
+ const check = await this.policy.canSpend(agentId, estimatedAmountUsd, category || 'shopping');
81
+ if (!check.allowed) {
82
+ throw new CardSpendingBlockedError(check.reason || 'Spending policy violation');
83
+ }
84
+ }
85
+ const lithicCard = await this.adapter.getCard(card.lithicCardToken);
86
+ return {
87
+ last4: lithicCard.last_four,
88
+ expMonth: lithicCard.exp_month || '',
89
+ expYear: lithicCard.exp_year || '',
90
+ cvv: lithicCard.cvv || '',
91
+ pan: lithicCard.pan || '',
92
+ };
93
+ }
94
+ /** Freeze (pause) the agent's card. */
95
+ async freezeCard(agentId) {
96
+ const card = await this.requireCard(agentId);
97
+ if (card.state === 'PAUSED')
98
+ return;
99
+ if (card.state === 'CLOSED')
100
+ throw new Error('Cannot freeze a closed card');
101
+ await this.adapter.pauseCard(card.lithicCardToken);
102
+ await this.store.updateCardState(agentId, 'PAUSED');
103
+ }
104
+ /** Unfreeze (resume) the agent's card. */
105
+ async unfreezeCard(agentId) {
106
+ const card = await this.requireCard(agentId);
107
+ if (card.state === 'OPEN')
108
+ return;
109
+ if (card.state === 'CLOSED')
110
+ throw new Error('Cannot unfreeze a closed card');
111
+ await this.adapter.resumeCard(card.lithicCardToken);
112
+ await this.store.updateCardState(agentId, 'OPEN');
113
+ }
114
+ /** Permanently close the agent's card. */
115
+ async closeCard(agentId) {
116
+ const card = await this.requireCard(agentId);
117
+ if (card.state === 'CLOSED')
118
+ return;
119
+ await this.adapter.closeCard(card.lithicCardToken);
120
+ await this.store.updateCardState(agentId, 'CLOSED');
121
+ }
122
+ // -----------------------------------------------------------------------
123
+ // Spending summary
124
+ // -----------------------------------------------------------------------
125
+ async getSpendingSummary(agentId, period = 'month') {
126
+ const card = await this.requireCard(agentId);
127
+ const now = new Date();
128
+ let since;
129
+ if (period === 'day') {
130
+ since = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
131
+ }
132
+ else {
133
+ since = new Date(now.getFullYear(), now.getMonth(), 1).getTime();
134
+ }
135
+ const txs = await this.store.getTransactionsByPeriod(card.id, since);
136
+ const settled = txs.filter(t => t.status === 'SETTLED' || t.status === 'PENDING');
137
+ const byCategory = new Map();
138
+ let totalUsd = 0;
139
+ for (const tx of settled) {
140
+ totalUsd += tx.amountUsd;
141
+ byCategory.set(tx.category, (byCategory.get(tx.category) || 0) + tx.amountUsd);
142
+ }
143
+ return {
144
+ totalUsd,
145
+ period,
146
+ byCategory: [...byCategory.entries()].map(([category, amountUsd]) => ({ category, amountUsd })),
147
+ transactionCount: settled.length,
148
+ };
149
+ }
150
+ // -----------------------------------------------------------------------
151
+ // Webhook processing
152
+ // -----------------------------------------------------------------------
153
+ /**
154
+ * Process a Lithic transaction webhook event.
155
+ * Resolves MCC → category and records the spend in the shared ledger.
156
+ */
157
+ async processWebhookTransaction(agentId, lithicTx) {
158
+ const card = await this.store.getCard(agentId);
159
+ if (!card)
160
+ return; // Unknown card — ignore
161
+ const category = this.mccMap.mccToCategory(lithicTx.merchant.mcc);
162
+ const amountUsd = Math.abs(lithicTx.amount) / 100; // Lithic amounts are in cents
163
+ const txRecord = {
164
+ id: uuidv4(),
165
+ cardId: card.id,
166
+ lithicTxToken: lithicTx.token,
167
+ merchantName: lithicTx.merchant.descriptor,
168
+ merchantMcc: lithicTx.merchant.mcc,
169
+ category,
170
+ amountUsd,
171
+ status: lithicTx.status,
172
+ createdAt: Date.now(),
173
+ };
174
+ await this.store.insertTransaction(txRecord);
175
+ // Record in shared spending ledger (same as crypto sends)
176
+ if (lithicTx.status === 'SETTLED' || lithicTx.status === 'PENDING') {
177
+ await this.policy.recordSpend(agentId, amountUsd, category);
178
+ }
179
+ }
180
+ // -----------------------------------------------------------------------
181
+ // Internal helpers
182
+ // -----------------------------------------------------------------------
183
+ async requireCard(agentId) {
184
+ const card = await this.store.getCard(agentId);
185
+ if (!card) {
186
+ throw new Error(`No card found for agent ${agentId}. Issue one first.`);
187
+ }
188
+ return card;
189
+ }
190
+ /**
191
+ * Build a flat list of blocked MCC codes from the spending policy's
192
+ * blockedCategories, expanded via the MCC map.
193
+ */
194
+ getBlockedMccs() {
195
+ // Access the policy's config to get blocked categories
196
+ // The SpendingPolicyEnforcer doesn't expose config directly,
197
+ // so we pass blocked categories through the card config or
198
+ // use the MCC map to expand known blocked categories.
199
+ // For now, this is handled at the extension pack level.
200
+ return [];
201
+ }
202
+ }
203
+ // ---------------------------------------------------------------------------
204
+ // Error classes
205
+ // ---------------------------------------------------------------------------
206
+ export class CardSpendingBlockedError extends Error {
207
+ constructor(reason) {
208
+ super(reason);
209
+ this.name = 'CardSpendingBlockedError';
210
+ }
211
+ }
212
+ //# sourceMappingURL=CardManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CardManager.js","sourceRoot":"","sources":["../../src/cards/CardManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @fileoverview Pure REST client for the Lithic card issuance API.
3
+ *
4
+ * No SDK dependency — uses fetch() directly. Supports sandbox and production
5
+ * environments via configurable base URL.
6
+ *
7
+ * @see https://docs.lithic.com/reference
8
+ * @module wallet/cards/LithicCardAdapter
9
+ */
10
+ import type { AuthRuleParams, CreateCardParams, ICardAdapter, LithicCardResponse, LithicTransaction, ListTxOpts, UpdateCardParams } from './types.js';
11
+ export interface LithicCardAdapterOptions {
12
+ apiKey: string;
13
+ /** Use sandbox environment. Defaults to true. */
14
+ sandbox?: boolean;
15
+ /** Override base URL (for testing). */
16
+ baseUrl?: string;
17
+ }
18
+ export declare class LithicCardAdapter implements ICardAdapter {
19
+ private readonly apiKey;
20
+ private readonly baseUrl;
21
+ constructor(opts: LithicCardAdapterOptions);
22
+ createCard(params: CreateCardParams): Promise<LithicCardResponse>;
23
+ getCard(cardToken: string): Promise<LithicCardResponse>;
24
+ updateCard(cardToken: string, updates: UpdateCardParams): Promise<LithicCardResponse>;
25
+ pauseCard(cardToken: string): Promise<void>;
26
+ resumeCard(cardToken: string): Promise<void>;
27
+ closeCard(cardToken: string): Promise<void>;
28
+ listTransactions(cardToken: string, opts?: ListTxOpts): Promise<LithicTransaction[]>;
29
+ createAuthRule(cardToken: string, rule: AuthRuleParams): Promise<void>;
30
+ private get;
31
+ private post;
32
+ private patch;
33
+ private request;
34
+ }
35
+ export declare class LithicApiError extends Error {
36
+ readonly statusCode: number;
37
+ readonly path: string;
38
+ constructor(statusCode: number, message: string, path: string);
39
+ }
40
+ //# sourceMappingURL=LithicCardAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LithicCardAdapter.d.ts","sourceRoot":"","sources":["../../src/cards/LithicCardAdapter.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAMpB,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AASD,qBAAa,iBAAkB,YAAW,YAAY;IACpD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,IAAI,EAAE,wBAAwB;IASpC,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIjE,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIvD,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAIrF,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3C,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAepF,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;YAW9D,GAAG;YAIH,IAAI;YAIJ,KAAK;YAIL,OAAO;CAwBtB;AAMD,qBAAa,cAAe,SAAQ,KAAK;aAErB,UAAU,EAAE,MAAM;aAElB,IAAI,EAAE,MAAM;gBAFZ,UAAU,EAAE,MAAM,EAClC,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM;CAK/B"}
@@ -0,0 +1,116 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * @fileoverview Pure REST client for the Lithic card issuance API.
4
+ *
5
+ * No SDK dependency — uses fetch() directly. Supports sandbox and production
6
+ * environments via configurable base URL.
7
+ *
8
+ * @see https://docs.lithic.com/reference
9
+ * @module wallet/cards/LithicCardAdapter
10
+ */
11
+ const SANDBOX_URL = 'https://sandbox.lithic.com/v1';
12
+ const PRODUCTION_URL = 'https://api.lithic.com/v1';
13
+ // ---------------------------------------------------------------------------
14
+ // Adapter
15
+ // ---------------------------------------------------------------------------
16
+ export class LithicCardAdapter {
17
+ apiKey;
18
+ baseUrl;
19
+ constructor(opts) {
20
+ this.apiKey = opts.apiKey;
21
+ this.baseUrl = opts.baseUrl || (opts.sandbox !== false ? SANDBOX_URL : PRODUCTION_URL);
22
+ }
23
+ // -----------------------------------------------------------------------
24
+ // Card CRUD
25
+ // -----------------------------------------------------------------------
26
+ async createCard(params) {
27
+ return this.post('/cards', params);
28
+ }
29
+ async getCard(cardToken) {
30
+ return this.get(`/cards/${cardToken}`);
31
+ }
32
+ async updateCard(cardToken, updates) {
33
+ return this.patch(`/cards/${cardToken}`, updates);
34
+ }
35
+ async pauseCard(cardToken) {
36
+ await this.patch(`/cards/${cardToken}`, { state: 'PAUSED' });
37
+ }
38
+ async resumeCard(cardToken) {
39
+ await this.patch(`/cards/${cardToken}`, { state: 'OPEN' });
40
+ }
41
+ async closeCard(cardToken) {
42
+ await this.patch(`/cards/${cardToken}`, { state: 'CLOSED' });
43
+ }
44
+ // -----------------------------------------------------------------------
45
+ // Transactions
46
+ // -----------------------------------------------------------------------
47
+ async listTransactions(cardToken, opts) {
48
+ const params = new URLSearchParams();
49
+ params.set('card_token', cardToken);
50
+ if (opts?.begin)
51
+ params.set('begin', opts.begin);
52
+ if (opts?.end)
53
+ params.set('end', opts.end);
54
+ if (opts?.page_size)
55
+ params.set('page_size', String(opts.page_size));
56
+ const result = await this.get(`/transactions?${params.toString()}`);
57
+ return result.data;
58
+ }
59
+ // -----------------------------------------------------------------------
60
+ // Auth rules (MCC-based spending controls)
61
+ // -----------------------------------------------------------------------
62
+ async createAuthRule(cardToken, rule) {
63
+ await this.post('/auth_rules', {
64
+ card_tokens: [cardToken],
65
+ ...rule,
66
+ });
67
+ }
68
+ // -----------------------------------------------------------------------
69
+ // HTTP helpers
70
+ // -----------------------------------------------------------------------
71
+ async get(path) {
72
+ return this.request('GET', path);
73
+ }
74
+ async post(path, body) {
75
+ return this.request('POST', path, body);
76
+ }
77
+ async patch(path, body) {
78
+ return this.request('PATCH', path, body);
79
+ }
80
+ async request(method, path, body) {
81
+ const url = `${this.baseUrl}${path}`;
82
+ const headers = {
83
+ 'Authorization': this.apiKey,
84
+ 'Accept': 'application/json',
85
+ };
86
+ if (body)
87
+ headers['Content-Type'] = 'application/json';
88
+ const resp = await fetch(url, {
89
+ method,
90
+ headers,
91
+ body: body ? JSON.stringify(body) : undefined,
92
+ });
93
+ if (!resp.ok) {
94
+ const text = await resp.text().catch(() => '');
95
+ throw new LithicApiError(resp.status, `Lithic API error ${resp.status}: ${text}`, path);
96
+ }
97
+ // Some endpoints return no body (204)
98
+ if (resp.status === 204)
99
+ return undefined;
100
+ return resp.json();
101
+ }
102
+ }
103
+ // ---------------------------------------------------------------------------
104
+ // Error
105
+ // ---------------------------------------------------------------------------
106
+ export class LithicApiError extends Error {
107
+ statusCode;
108
+ path;
109
+ constructor(statusCode, message, path) {
110
+ super(message);
111
+ this.statusCode = statusCode;
112
+ this.path = path;
113
+ this.name = 'LithicApiError';
114
+ }
115
+ }
116
+ //# sourceMappingURL=LithicCardAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LithicCardAdapter.js","sourceRoot":"","sources":["../../src/cards/LithicCardAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @fileoverview Merchant Category Code (MCC) → SpendCategory mapping.
3
+ *
4
+ * Maps 4-digit MCC codes used by card networks to the wallet extension's
5
+ * SpendCategory enum. Uses range-based matching for efficient lookup.
6
+ *
7
+ * @module wallet/cards/MccCategoryMap
8
+ */
9
+ import type { SpendCategory } from '../types.js';
10
+ export declare class MccCategoryMap {
11
+ private readonly ranges;
12
+ constructor();
13
+ /**
14
+ * Resolve a 4-digit MCC string to a SpendCategory.
15
+ * Returns 'other' if no matching range is found.
16
+ */
17
+ mccToCategory(mcc: string): SpendCategory;
18
+ /**
19
+ * Get all MCC ranges that map to a given SpendCategory.
20
+ * Useful for building Lithic auth rules.
21
+ */
22
+ categoryToMccRanges(category: SpendCategory): Array<{
23
+ min: number;
24
+ max: number;
25
+ }>;
26
+ /**
27
+ * Get all individual MCC codes for a category (expands ranges).
28
+ * Useful for Lithic's blocked_mcc list which expects individual codes.
29
+ */
30
+ categoryToMccCodes(category: SpendCategory): string[];
31
+ /**
32
+ * Get all categories that have MCC mappings.
33
+ */
34
+ getMappedCategories(): SpendCategory[];
35
+ }
36
+ //# sourceMappingURL=MccCategoryMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MccCategoryMap.d.ts","sourceRoot":"","sources":["../../src/cards/MccCategoryMap.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAoEjD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;;IAOpC;;;OAGG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa;IAYzC;;;OAGG;IACH,mBAAmB,CAAC,QAAQ,EAAE,aAAa,GAAG,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAMjF;;;OAGG;IACH,kBAAkB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,EAAE;IAWrD;;OAEG;IACH,mBAAmB,IAAI,aAAa,EAAE;CAOvC"}
@@ -0,0 +1,113 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * @fileoverview Merchant Category Code (MCC) → SpendCategory mapping.
4
+ *
5
+ * Maps 4-digit MCC codes used by card networks to the wallet extension's
6
+ * SpendCategory enum. Uses range-based matching for efficient lookup.
7
+ *
8
+ * @module wallet/cards/MccCategoryMap
9
+ */
10
+ /**
11
+ * Ordered list of MCC ranges → SpendCategory mappings.
12
+ * Ranges are inclusive on both ends.
13
+ */
14
+ const MCC_RANGES = [
15
+ // Travel: airlines, hotels, rental cars, travel agencies
16
+ { min: 3000, max: 3999, category: 'travel' },
17
+ { min: 4511, max: 4511, category: 'travel' }, // airlines
18
+ { min: 4722, max: 4722, category: 'travel' }, // travel agencies
19
+ { min: 7011, max: 7012, category: 'travel' }, // hotels, timeshares
20
+ { min: 7033, max: 7033, category: 'travel' }, // trailer parks
21
+ { min: 7512, max: 7519, category: 'travel' }, // car rental
22
+ // Utilities: telecom, electric, gas, water
23
+ { min: 4812, max: 4816, category: 'utilities' }, // telecom
24
+ { min: 4899, max: 4900, category: 'utilities' }, // cable, electric/gas/water
25
+ // Shopping: general retail
26
+ { min: 5200, max: 5499, category: 'shopping' }, // home supply, dept stores
27
+ { min: 5511, max: 5599, category: 'shopping' }, // auto dealers, auto parts
28
+ { min: 5600, max: 5699, category: 'shopping' }, // apparel
29
+ { min: 5700, max: 5799, category: 'shopping' }, // furniture, electronics
30
+ { min: 5900, max: 5999, category: 'shopping' }, // retail stores, misc
31
+ // Dining: restaurants, bars, fast food
32
+ { min: 5811, max: 5811, category: 'dining' }, // caterers
33
+ { min: 5812, max: 5812, category: 'dining' }, // eating places/restaurants
34
+ { min: 5813, max: 5813, category: 'dining' }, // bars/taverns
35
+ { min: 5814, max: 5814, category: 'dining' }, // fast food
36
+ // Subscriptions: digital goods/services
37
+ { min: 5815, max: 5818, category: 'subscriptions' }, // digital goods, games, apps, streaming
38
+ // Entertainment: movies, theaters, events, recreation
39
+ { min: 7832, max: 7833, category: 'entertainment' }, // movie theaters
40
+ { min: 7841, max: 7841, category: 'entertainment' }, // video tape rental
41
+ { min: 7911, max: 7911, category: 'entertainment' }, // dance halls/studios
42
+ { min: 7922, max: 7922, category: 'entertainment' }, // theatrical producers
43
+ { min: 7929, max: 7929, category: 'entertainment' }, // bands/orchestras
44
+ { min: 7932, max: 7933, category: 'entertainment' }, // billiards, bowling
45
+ { min: 7941, max: 7941, category: 'entertainment' }, // sports clubs/fields
46
+ { min: 7991, max: 7999, category: 'entertainment' }, // tourist attractions, recreation
47
+ // Web services: computer programming, data processing, IT
48
+ { min: 7372, max: 7379, category: 'web_services' }, // computer services
49
+ { min: 4816, max: 4816, category: 'web_services' }, // computer network/info services (re-mapped from utilities for precision)
50
+ // API costs: SaaS / cloud compute (commonly billed under computer services)
51
+ // Note: most SaaS bills under 7372 (web_services). If needed, specific
52
+ // merchant descriptors can override at the CardManager level.
53
+ ];
54
+ // ---------------------------------------------------------------------------
55
+ // Lookup class
56
+ // ---------------------------------------------------------------------------
57
+ export class MccCategoryMap {
58
+ ranges;
59
+ constructor() {
60
+ // Sort by min for binary-search-friendly access
61
+ this.ranges = [...MCC_RANGES].sort((a, b) => a.min - b.min);
62
+ }
63
+ /**
64
+ * Resolve a 4-digit MCC string to a SpendCategory.
65
+ * Returns 'other' if no matching range is found.
66
+ */
67
+ mccToCategory(mcc) {
68
+ const code = parseInt(mcc, 10);
69
+ if (isNaN(code))
70
+ return 'other';
71
+ for (const range of this.ranges) {
72
+ if (code >= range.min && code <= range.max) {
73
+ return range.category;
74
+ }
75
+ }
76
+ return 'other';
77
+ }
78
+ /**
79
+ * Get all MCC ranges that map to a given SpendCategory.
80
+ * Useful for building Lithic auth rules.
81
+ */
82
+ categoryToMccRanges(category) {
83
+ return this.ranges
84
+ .filter(r => r.category === category)
85
+ .map(({ min, max }) => ({ min, max }));
86
+ }
87
+ /**
88
+ * Get all individual MCC codes for a category (expands ranges).
89
+ * Useful for Lithic's blocked_mcc list which expects individual codes.
90
+ */
91
+ categoryToMccCodes(category) {
92
+ const codes = [];
93
+ for (const range of this.ranges) {
94
+ if (range.category !== category)
95
+ continue;
96
+ for (let code = range.min; code <= range.max; code++) {
97
+ codes.push(code.toString().padStart(4, '0'));
98
+ }
99
+ }
100
+ return codes;
101
+ }
102
+ /**
103
+ * Get all categories that have MCC mappings.
104
+ */
105
+ getMappedCategories() {
106
+ const categories = new Set();
107
+ for (const range of this.ranges) {
108
+ categories.add(range.category);
109
+ }
110
+ return [...categories];
111
+ }
112
+ }
113
+ //# sourceMappingURL=MccCategoryMap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MccCategoryMap.js","sourceRoot":"","sources":["../../src/cards/MccCategoryMap.ts"],"names":[],"mappings":"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"}