z-zero-mcp-server 1.0.7 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ // extract-total-price.ts
3
+ // Phase 2: Smart Routing - DOM Price Extractor
4
+ // Scans a checkout page via Playwright and returns the cart total in USD.
5
+ // Returns null if no price can be confidently found.
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.extractTotalPrice = extractTotalPrice;
8
+ /**
9
+ * Multi-strategy total price extractor.
10
+ * Strategy order (most reliable → least reliable):
11
+ * 1. Known CSS selectors for major platforms (Shopify, Stripe, Woo)
12
+ * 2. Aria / data-testid patterns
13
+ * 3. Text heuristic: find largest $ amount near keywords "total", "amount due"
14
+ */
15
+ async function extractTotalPrice(page) {
16
+ // ─── Strategy 1: Well-known selector list ────────────────────────────────
17
+ const knownSelectors = [
18
+ // Shopify
19
+ '[data-checkout-payment-amount]',
20
+ '.payment-due__price',
21
+ // Stripe Checkout
22
+ '[data-testid="total-amount"]',
23
+ '.OrderAmountRow--total .OrderAmountRow-amount',
24
+ // Woocommerce
25
+ '.order-total .amount',
26
+ '.woocommerce-Price-amount.amount',
27
+ // Generic
28
+ '[data-testid*="total" i]',
29
+ '[class*="order-total" i]',
30
+ '[class*="total-price" i]',
31
+ '[class*="grand-total" i]',
32
+ '[id*="order-total" i]',
33
+ '[id*="grand-total" i]',
34
+ 'span[class*="total"]',
35
+ 'td[class*="total"]',
36
+ ];
37
+ for (const selector of knownSelectors) {
38
+ try {
39
+ const el = await page.$(selector);
40
+ if (!el)
41
+ continue;
42
+ const text = await el.innerText();
43
+ const parsed = parseMoneyString(text);
44
+ if (parsed !== null && parsed > 0) {
45
+ console.error(`[PRICE] ✅ Strategy 1 found via selector "${selector}": $${parsed}`);
46
+ return parsed;
47
+ }
48
+ }
49
+ catch {
50
+ // element may have been removed from DOM — continue
51
+ }
52
+ }
53
+ // ─── Strategy 2: Scan all visible text near "total" keyword ──────────────
54
+ try {
55
+ const amount = await page.evaluate(() => {
56
+ const allText = Array.from(document.querySelectorAll('*'))
57
+ .filter((el) => {
58
+ if (!(el instanceof HTMLElement))
59
+ return false;
60
+ const style = window.getComputedStyle(el);
61
+ return style.display !== 'none' && style.visibility !== 'hidden';
62
+ })
63
+ .filter(el => {
64
+ const text = el.innerText?.toLowerCase() ?? '';
65
+ return ((text.includes('total') || text.includes('amount due') || text.includes('you pay')) &&
66
+ el.children.length < 5 // narrow to leaf-ish nodes
67
+ );
68
+ })
69
+ .map(el => el.innerText ?? '');
70
+ // Find first valid $ pattern in those elements
71
+ const priceRegex = /\$\s*([\d,]+(?:\.\d{1,2})?)/;
72
+ for (const text of allText) {
73
+ const match = text.match(priceRegex);
74
+ if (match) {
75
+ const value = parseFloat(match[1].replace(/,/g, ''));
76
+ if (value > 0 && value < 10000)
77
+ return value; // sanity bound
78
+ }
79
+ }
80
+ return null;
81
+ });
82
+ if (amount !== null && amount > 0) {
83
+ console.error(`[PRICE] ✅ Strategy 2 (text heuristic) found: $${amount}`);
84
+ return amount;
85
+ }
86
+ }
87
+ catch (e) {
88
+ console.error(`[PRICE] Strategy 2 failed: ${e}`);
89
+ }
90
+ // ─── Strategy 3: Last resort — biggest dollar amount visible on page ─────
91
+ try {
92
+ const amount = await page.evaluate(() => {
93
+ const regex = /\$\s*([\d,]+(?:\.\d{1,2})?)/g;
94
+ const bodyText = document.body.innerText ?? '';
95
+ const values = [];
96
+ let m;
97
+ while ((m = regex.exec(bodyText)) !== null) {
98
+ const v = parseFloat(m[1].replace(/,/g, ''));
99
+ if (v >= 0.5 && v < 10000)
100
+ values.push(v);
101
+ }
102
+ if (values.length === 0)
103
+ return null;
104
+ return Math.max(...values);
105
+ });
106
+ if (amount !== null && amount > 0) {
107
+ console.error(`[PRICE] ⚠️ Strategy 3 (largest $ on page): $${amount}. Low confidence.`);
108
+ return amount;
109
+ }
110
+ }
111
+ catch (e) {
112
+ console.error(`[PRICE] Strategy 3 failed: ${e}`);
113
+ }
114
+ console.error('[PRICE] ❌ Could not detect total price on this page.');
115
+ return null;
116
+ }
117
+ // ─── Utility ─────────────────────────────────────────────────────────────────
118
+ function parseMoneyString(text) {
119
+ // Handles: "$49.99", "USD 49.99", "49,99 $", "49.99 USD"
120
+ const match = text.match(/[\d,]+(?:\.\d{1,2})?/);
121
+ if (!match)
122
+ return null;
123
+ const value = parseFloat(match[0].replace(/,/g, ''));
124
+ if (isNaN(value) || value <= 0)
125
+ return null;
126
+ return value;
127
+ }
@@ -0,0 +1,13 @@
1
+ /** Read the current active Passport Key. */
2
+ export declare function getPassportKey(): string;
3
+ /**
4
+ * Replace the active Passport Key in memory (no restart needed).
5
+ * @param newKey - must start with "zk_live_" or "zk_test_"
6
+ * @returns true if the key looks valid, false if rejected
7
+ */
8
+ export declare function setPassportKey(newKey: string): {
9
+ ok: boolean;
10
+ message: string;
11
+ };
12
+ /** Check if a key is currently configured. */
13
+ export declare function hasPassportKey(): boolean;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ // key-store.ts
3
+ // Shared, mutable in-memory store for the Passport Key (Z_ZERO_API_KEY).
4
+ // All API backends (custodial + WDK) import getPassportKey() from here
5
+ // so a single set_api_key MCP tool updates the key for ALL backends at once.
6
+ //
7
+ // Thread-safety: Node.js is single-threaded. Module-level `let` is safe.
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.getPassportKey = getPassportKey;
10
+ exports.setPassportKey = setPassportKey;
11
+ exports.hasPassportKey = hasPassportKey;
12
+ let _passportKey = process.env.Z_ZERO_API_KEY || "";
13
+ /** Read the current active Passport Key. */
14
+ function getPassportKey() {
15
+ return _passportKey;
16
+ }
17
+ /**
18
+ * Replace the active Passport Key in memory (no restart needed).
19
+ * @param newKey - must start with "zk_live_" or "zk_test_"
20
+ * @returns true if the key looks valid, false if rejected
21
+ */
22
+ function setPassportKey(newKey) {
23
+ const trimmed = newKey.trim();
24
+ if (!trimmed) {
25
+ return { ok: false, message: "Key cannot be empty." };
26
+ }
27
+ if (!trimmed.startsWith("zk_live_") && !trimmed.startsWith("zk_test_")) {
28
+ return { ok: false, message: `Invalid key format — must start with "zk_live_" or "zk_test_". Got: "${trimmed.slice(0, 12)}..."` };
29
+ }
30
+ const previous = _passportKey;
31
+ _passportKey = trimmed;
32
+ console.error(`[KEY-STORE] ✅ Passport Key updated: ${previous.slice(0, 10)}... → ${trimmed.slice(0, 10)}...`);
33
+ return { ok: true, message: `Passport Key updated successfully. Active key prefix: ${trimmed.slice(0, 10)}...` };
34
+ }
35
+ /** Check if a key is currently configured. */
36
+ function hasPassportKey() {
37
+ return _passportKey.length > 0;
38
+ }
@@ -0,0 +1,20 @@
1
+ export interface Web3TxParams {
2
+ to: string;
3
+ value?: string;
4
+ data?: string;
5
+ chainId?: number;
6
+ eip681_amount?: number;
7
+ }
8
+ export interface Web3DetectionResult {
9
+ detected: boolean;
10
+ method: "eth_sendTransaction" | "EIP-681" | null;
11
+ params: Web3TxParams | null;
12
+ message: string;
13
+ }
14
+ /**
15
+ * Opens the checkout URL in a headless browser.
16
+ * Injects a mock window.ethereum (MetaMask emulation).
17
+ * Scans for EIP-681 links.
18
+ * Returns the tx params if Web3 payment is detected, else null.
19
+ */
20
+ export declare function detectWeb3Payment(checkoutUrl: string): Promise<Web3DetectionResult>;
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ // web3-detector.ts
3
+ // Phase 2: Smart Routing — Web3 Payment Detector
4
+ // Injects a mock window.ethereum into a checkout page, waits for Web3 tx request.
5
+ // If the page calls eth_sendTransaction → capture params and return them.
6
+ // If page is not Web3-aware → return null (caller falls back to Fiat JIT card).
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.detectWeb3Payment = detectWeb3Payment;
9
+ const playwright_1 = require("playwright");
10
+ const WEB3_DETECT_TIMEOUT_MS = 12_000; // 12s max to detect Web3 button click
11
+ /**
12
+ * Opens the checkout URL in a headless browser.
13
+ * Injects a mock window.ethereum (MetaMask emulation).
14
+ * Scans for EIP-681 links.
15
+ * Returns the tx params if Web3 payment is detected, else null.
16
+ */
17
+ async function detectWeb3Payment(checkoutUrl) {
18
+ const browser = await playwright_1.chromium.launch({ headless: true });
19
+ const context = await browser.newContext();
20
+ const page = await context.newPage();
21
+ try {
22
+ // ─── Inject mock window.ethereum BEFORE page loads ───────────────────
23
+ // This ensures the page's `if (typeof window.ethereum !== 'undefined')` check passes.
24
+ await page.addInitScript(() => {
25
+ const mockEthereum = {
26
+ isMetaMask: true,
27
+ selectedAddress: "0x0000000000000000000000000000000000000001",
28
+ chainId: "0x89",
29
+ networkVersion: "137",
30
+ request: async ({ method, params }) => {
31
+ if (method === "eth_requestAccounts" || method === "eth_accounts") {
32
+ return ["0x0000000000000000000000000000000000000001"];
33
+ }
34
+ if (method === "eth_chainId")
35
+ return "0x89";
36
+ if (method === "net_version")
37
+ return "137";
38
+ if (method === "eth_sendTransaction") {
39
+ const tx = params?.[0];
40
+ window["__wdkCapturedTx"] = tx;
41
+ return "0xdeadbeef00000000000000000000000000000000000000000000000000000001";
42
+ }
43
+ if (method === "wallet_switchEthereumChain")
44
+ return null;
45
+ if (method === "eth_getBalance")
46
+ return "0x0";
47
+ // C3 FIX: Log unrecognized methods for debugging DApp compatibility
48
+ window["__wdkUnknownMethod_" + method] = true;
49
+ return null;
50
+ },
51
+ on: (event, handler) => {
52
+ if (event === "connect")
53
+ setTimeout(() => handler({ chainId: "0x89" }), 100);
54
+ if (event === "accountsChanged")
55
+ setTimeout(() => handler(["0x0000000000000000000000000000000000000001"]), 200);
56
+ },
57
+ removeListener: () => { },
58
+ removeAllListeners: () => { },
59
+ isConnected: () => true,
60
+ };
61
+ Object.defineProperty(window, "ethereum", {
62
+ value: mockEthereum,
63
+ writable: false,
64
+ configurable: true,
65
+ });
66
+ });
67
+ // ─── Navigate to page ─────────────────────────────────────────────────
68
+ await page.goto(checkoutUrl, { waitUntil: "domcontentloaded", timeout: 20_000 });
69
+ // ─── Strategy A: Scan for EIP-681 links ──────────────────────────────
70
+ // Look for links like: ethereum:0xabc...@137/transfer?address=0xabc&uint256=10000000
71
+ const eip681Result = await page.evaluate(() => {
72
+ const links = Array.from(document.querySelectorAll("a[href]"))
73
+ .map(a => a.href)
74
+ .filter(href => href.startsWith("ethereum:"));
75
+ const texts = [document.body.innerText ?? ""];
76
+ const allText = texts.join(" ");
77
+ const inlineMatch = allText.match(/ethereum:0x[0-9a-fA-F]{40}[^\s]*/);
78
+ const href = links[0] ?? inlineMatch?.[0] ?? null;
79
+ if (!href)
80
+ return null;
81
+ // Parse: ethereum:0xCONTRACT@137/transfer?address=0xRECIPIENT&uint256=10000000
82
+ const contractMatch = href.match(/ethereum:(0x[0-9a-fA-F]{40})/);
83
+ const chainMatch = href.match(/@(\d+)/);
84
+ const uint256Match = href.match(/uint256=(\d+)/);
85
+ // ✅ BUG 6 FIX: Parse recipient from 'address=' query param (not the contract address)
86
+ const recipientMatch = href.match(/[?&]address=(0x[0-9a-fA-F]{40})/);
87
+ return {
88
+ // Prefer recipient address from query param; fall back to contract only as last resort
89
+ to: recipientMatch?.[1] ?? contractMatch?.[1] ?? null,
90
+ contract: contractMatch?.[1] ?? null, // USDT contract (kept for logging)
91
+ chainId: chainMatch ? parseInt(chainMatch[1]) : 137,
92
+ uint256: uint256Match?.[1] ?? null,
93
+ raw: href,
94
+ };
95
+ });
96
+ if (eip681Result?.to) {
97
+ const usdtAmount = eip681Result.uint256
98
+ ? parseInt(eip681Result.uint256) / 1_000_000 // USDT has 6 decimals
99
+ : null;
100
+ console.error(`[WEB3] ✅ EIP-681 detected: recipient=${eip681Result.to}, contract=${eip681Result.contract}, amount=${usdtAmount} USDT`);
101
+ return {
102
+ detected: true,
103
+ method: "EIP-681",
104
+ params: {
105
+ to: eip681Result.to,
106
+ chainId: eip681Result.chainId,
107
+ eip681_amount: usdtAmount ?? undefined,
108
+ },
109
+ message: `EIP-681 payment link found. Merchant: ${eip681Result.to}, amount: ${usdtAmount} USDT.`,
110
+ };
111
+ }
112
+ // ─── Strategy B: Wait for eth_sendTransaction after clicking "Pay" ────
113
+ // ✅ BUG 5 FIX: Auto-click common Web3 pay buttons so DApp triggers eth_sendTransaction
114
+ const web3ButtonSelectors = [
115
+ 'button:has-text("MetaMask")', 'button:has-text("Pay with Crypto")',
116
+ 'button:has-text("Connect Wallet")', 'button:has-text("Pay with Web3")',
117
+ 'button:has-text("Pay with Wallet")', '#pay-metamask-btn',
118
+ '[class*="web3"] button', '[class*="metamask"] button',
119
+ ];
120
+ for (const sel of web3ButtonSelectors) {
121
+ try {
122
+ const btn = await page.$(sel);
123
+ if (btn && await btn.isVisible()) {
124
+ console.error(`[WEB3] Clicking Web3 pay button: ${sel}`);
125
+ await btn.click();
126
+ break;
127
+ }
128
+ }
129
+ catch { /* selector may not exist — continue */ }
130
+ }
131
+ // Poll for captured tx (window.ethereum.request intercepted by mock)
132
+ const capturedTx = await Promise.race([
133
+ // Poll for captured tx
134
+ (async () => {
135
+ const start = Date.now();
136
+ while (Date.now() - start < WEB3_DETECT_TIMEOUT_MS) {
137
+ const tx = await page.evaluate(() => {
138
+ return window["__wdkCapturedTx"] ?? null;
139
+ });
140
+ if (tx)
141
+ return tx;
142
+ await page.waitForTimeout(500);
143
+ }
144
+ return null;
145
+ })(),
146
+ ]);
147
+ if (capturedTx) {
148
+ console.error(`[WEB3] ✅ eth_sendTransaction captured: to=${capturedTx["to"]}`);
149
+ return {
150
+ detected: true,
151
+ method: "eth_sendTransaction",
152
+ params: {
153
+ to: capturedTx["to"],
154
+ value: capturedTx["value"],
155
+ data: capturedTx["data"],
156
+ chainId: 137,
157
+ },
158
+ message: `Web3 payment detected via eth_sendTransaction. Recipient: ${capturedTx["to"]}`,
159
+ };
160
+ }
161
+ console.error("[WEB3] ❌ No Web3 payment detected on this page. Fallback to Fiat.");
162
+ return {
163
+ detected: false,
164
+ method: null,
165
+ params: null,
166
+ message: "No Web3 payment gateway detected. Will proceed with JIT Visa Card (Fiat) route.",
167
+ };
168
+ }
169
+ catch (err) {
170
+ const msg = err instanceof Error ? err.message : String(err);
171
+ console.error(`[WEB3] Error during detection: ${msg}`);
172
+ return {
173
+ detected: false,
174
+ method: null,
175
+ params: null,
176
+ message: `Detection failed: ${msg}. Defaulting to Fiat route.`,
177
+ };
178
+ }
179
+ finally {
180
+ await browser.close().catch(() => { });
181
+ }
182
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * lib/with-timeout.ts
3
+ * Generic async timeout wrapper for MCP operations.
4
+ *
5
+ * Extensible usage:
6
+ * await withTimeout(fillCheckoutForm(url, card), 60_000, 'Checkout')
7
+ * await withTimeout(burnTokenRemote(token), 10_000, 'Burn')
8
+ * await withTimeout(resolveTokenRemote(token), 8_000, 'Resolve')
9
+ * await withTimeout(anyAsyncFn(), 5_000, 'MyOperation')
10
+ */
11
+ export declare class TimeoutError extends Error {
12
+ constructor(operationName: string, ms: number);
13
+ }
14
+ /**
15
+ * Race an async operation against a hard deadline.
16
+ * @param promise The async operation to run
17
+ * @param ms Timeout in milliseconds
18
+ * @param name Human-readable name for error messages (default: 'Operation')
19
+ * @param onTimeout Optional cleanup callback called on timeout
20
+ */
21
+ export declare function withTimeout<T>(promise: Promise<T>, ms: number, name?: string, onTimeout?: () => void | Promise<void>): Promise<T>;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ /**
3
+ * lib/with-timeout.ts
4
+ * Generic async timeout wrapper for MCP operations.
5
+ *
6
+ * Extensible usage:
7
+ * await withTimeout(fillCheckoutForm(url, card), 60_000, 'Checkout')
8
+ * await withTimeout(burnTokenRemote(token), 10_000, 'Burn')
9
+ * await withTimeout(resolveTokenRemote(token), 8_000, 'Resolve')
10
+ * await withTimeout(anyAsyncFn(), 5_000, 'MyOperation')
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.TimeoutError = void 0;
14
+ exports.withTimeout = withTimeout;
15
+ class TimeoutError extends Error {
16
+ constructor(operationName, ms) {
17
+ super(`[TIMEOUT] ${operationName} exceeded ${ms}ms hard cap`);
18
+ this.name = 'TimeoutError';
19
+ }
20
+ }
21
+ exports.TimeoutError = TimeoutError;
22
+ /**
23
+ * Race an async operation against a hard deadline.
24
+ * @param promise The async operation to run
25
+ * @param ms Timeout in milliseconds
26
+ * @param name Human-readable name for error messages (default: 'Operation')
27
+ * @param onTimeout Optional cleanup callback called on timeout
28
+ */
29
+ function withTimeout(promise, ms, name = 'Operation', onTimeout) {
30
+ const timeoutPromise = new Promise((_, reject) => {
31
+ const timer = setTimeout(async () => {
32
+ if (onTimeout) {
33
+ try {
34
+ await onTimeout();
35
+ }
36
+ catch { /* ignore cleanup errors */ }
37
+ }
38
+ reject(new TimeoutError(name, ms));
39
+ }, ms);
40
+ // Allow Node.js to exit even if timer is pending
41
+ if (timer.unref)
42
+ timer.unref();
43
+ });
44
+ return Promise.race([promise, timeoutPromise]);
45
+ }
@@ -2,5 +2,6 @@ import type { CardData, PaymentResult } from "./types.js";
2
2
  /**
3
3
  * Detects and fills credit card form fields on a checkout page.
4
4
  * Card data exists ONLY in RAM and is wiped after injection.
5
+ * Hard timeout of 60s prevents merchant page from hanging indefinitely.
5
6
  */
6
7
  export declare function fillCheckoutForm(checkoutUrl: string, cardData: CardData): Promise<PaymentResult>;
@@ -4,16 +4,48 @@
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.fillCheckoutForm = fillCheckoutForm;
6
6
  const playwright_1 = require("playwright");
7
+ const with_timeout_js_1 = require("./lib/with-timeout.js");
8
+ const CHECKOUT_HARD_TIMEOUT_MS = 60_000; // 60s absolute cap — prevents slow-loris attacks
7
9
  /**
8
10
  * Detects and fills credit card form fields on a checkout page.
9
11
  * Card data exists ONLY in RAM and is wiped after injection.
12
+ * Hard timeout of 60s prevents merchant page from hanging indefinitely.
10
13
  */
11
14
  async function fillCheckoutForm(checkoutUrl, cardData) {
12
15
  const browser = await playwright_1.chromium.launch({ headless: true });
13
16
  const context = await browser.newContext();
14
17
  const page = await context.newPage();
18
+ // 🔒 Wrap entire checkout flow in 60s hard timeout
19
+ // onTimeout: force-close browser to free memory
15
20
  try {
16
- await page.goto(checkoutUrl, { waitUntil: "domcontentloaded", timeout: 30000 });
21
+ return await (0, with_timeout_js_1.withTimeout)(_fillCheckoutFormInner(page, checkoutUrl, cardData), // BUG 8 FIX: pass URL
22
+ CHECKOUT_HARD_TIMEOUT_MS, 'fillCheckoutForm', async () => {
23
+ console.error('[PLAYWRIGHT] ⚠️ Hard timeout hit — force-closing browser');
24
+ await browser.close().catch(() => { });
25
+ });
26
+ }
27
+ catch (err) {
28
+ if (err instanceof with_timeout_js_1.TimeoutError) {
29
+ return {
30
+ success: false,
31
+ message: `Checkout timed out after ${CHECKOUT_HARD_TIMEOUT_MS / 1000}s. The merchant page may be too slow or blocking automation.`,
32
+ };
33
+ }
34
+ const errMsg = err instanceof Error ? err.message : String(err);
35
+ return { success: false, message: `Payment failed: ${errMsg}` };
36
+ }
37
+ finally {
38
+ // RAM wipe happens inside _fillCheckoutFormInner's finally block
39
+ // Ensure browser is closed even if timeout cleanup failed
40
+ await browser.close().catch(() => { });
41
+ }
42
+ }
43
+ /** Internal implementation — called by fillCheckoutForm inside a timeout wrapper */
44
+ async function _fillCheckoutFormInner(page, checkoutUrl, // ✅ BUG 8 FIX: need URL to navigate to
45
+ cardData) {
46
+ try {
47
+ // ✅ BUG 8 FIX: Navigate to the checkout page (was missing — page was blank!)
48
+ await page.goto(checkoutUrl, { waitUntil: "domcontentloaded", timeout: 20_000 });
17
49
  // ============================================================
18
50
  // STRATEGY 1: Standard HTML form fields
19
51
  // ============================================================
@@ -199,6 +231,6 @@ async function fillCheckoutForm(checkoutUrl, cardData) {
199
231
  cardData.exp_month = "00";
200
232
  cardData.exp_year = "0000";
201
233
  cardData.name = "";
202
- await browser.close();
234
+ // Note: browser.close() is handled by fillCheckoutForm's outer finally block
203
235
  }
204
236
  }
package/dist/types.d.ts CHANGED
@@ -27,6 +27,7 @@ export interface CardData {
27
27
  exp_year: string;
28
28
  cvv: string;
29
29
  name: string;
30
+ authorized_amount?: number;
30
31
  error?: string;
31
32
  message?: string;
32
33
  }
@@ -0,0 +1,9 @@
1
+ import type { CardData } from "./types.js";
2
+ export declare function listCardsRemote(): Promise<any>;
3
+ export declare function getBalanceRemote(cardAlias: string): Promise<any>;
4
+ export declare function getDepositAddressesRemote(): Promise<any>;
5
+ export declare function issueTokenRemote(cardAlias: string, amount: number, merchant: string): Promise<any | null>;
6
+ export declare function resolveTokenRemote(token: string): Promise<CardData | null>;
7
+ export declare function burnTokenRemote(token: string, receipt_id?: string): Promise<boolean>;
8
+ export declare function cancelTokenRemote(token: string): Promise<any>;
9
+ export declare function refundUnderspendRemote(token: string, actualSpent: number): Promise<void>;