@paytaca/opencode-plugin 0.2.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -1
- package/dist/bundled/mcp.d.ts +1 -1
- package/dist/bundled/mcp.d.ts.map +1 -1
- package/dist/bundled/mcp.js +251 -23
- package/dist/bundled/mcp.js.map +1 -1
- package/dist/bundled/proxy.d.ts +1 -1
- package/dist/bundled/proxy.d.ts.map +1 -1
- package/dist/bundled/proxy.js +393 -43
- package/dist/bundled/proxy.js.map +1 -1
- package/dist/bundled/wrapper.d.ts +1 -1
- package/dist/bundled/wrapper.d.ts.map +1 -1
- package/dist/bundled/wrapper.js +123 -3
- package/dist/bundled/wrapper.js.map +1 -1
- package/dist/credits.d.ts +9 -0
- package/dist/credits.d.ts.map +1 -0
- package/dist/credits.js +120 -0
- package/dist/credits.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -1
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +6 -4
- package/dist/proxy.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const WRAPPER_SCRIPT_CONTENT = "#!/usr/bin/env node\n/**\n * Paytaca Pay Wrapper \u2014 handles large request bodies by reading from a file.\n * Imports paytaca-cli modules directly (avoids CLI argument size limits).\n */\n\nimport { readFileSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\n\n// How long to wait for the server to respond before treating the payment as timed out.\n// Default 240s so heavy non-streaming generations (large context / long output) can\n// complete; override with PAYTACA_PAY_TIMEOUT_MS.\nconst PAY_TIMEOUT_MS = Number(process.env.PAYTACA_PAY_TIMEOUT_MS || 240000);\n\n// Find paytaca-cli installation\nfunction findPaytacaCliPath() {\n const possiblePaths = [];\n \n // Try to get global npm root\n try {\n const globalPath = execSync('npm root -g', { encoding: 'utf8' }).trim();\n possiblePaths.push(\n join(globalPath, 'paytaca-cli'),\n join(globalPath, 'opencode-plugin', 'node_modules', 'paytaca-cli'),\n );\n } catch {}\n \n // Common global locations\n possiblePaths.push(\n '/usr/lib/node_modules/paytaca-cli',\n '/usr/local/lib/node_modules/paytaca-cli',\n '/opt/homebrew/lib/node_modules/paytaca-cli',\n );\n \n // Try current file's node_modules (for bundled installs)\n try {\n const currentFile = fileURLToPath(import.meta.url);\n const currentDir = dirname(currentFile);\n possiblePaths.push(\n join(currentDir, '..', 'node_modules', 'paytaca-cli'),\n join(currentDir, '..', '..', 'node_modules', 'paytaca-cli'),\n );\n } catch {}\n \n // Find first valid path\n for (const basePath of possiblePaths) {\n try {\n const walletPath = join(basePath, 'dist', 'wallet', 'index.js');\n readFileSync(walletPath);\n return basePath;\n } catch {}\n }\n \n throw new Error('paytaca-cli not found. Try reinstalling opencode-plugin: npm install @paytaca/opencode-plugin');\n}\n\n// Load paytaca-cli modules\nlet loadMnemonic, loadWallet, LibauthHDWallet, X402Payer, parsePaymentRequiredJson, selectBchPaymentRequirements, BCH_DERIVATION_PATH;\n\ntry {\n const basePath = findPaytacaCliPath();\n \n ({ loadMnemonic, loadWallet } = await import(join(basePath, 'dist', 'wallet', 'index.js')));\n ({ LibauthHDWallet } = await import(join(basePath, 'dist', 'wallet', 'keys.js')));\n ({ X402Payer } = await import(join(basePath, 'dist', 'wallet', 'x402.js')));\n ({ parsePaymentRequiredJson, selectBchPaymentRequirements } = await import(join(basePath, 'dist', 'utils', 'x402.js')));\n ({ BCH_DERIVATION_PATH } = await import(join(basePath, 'dist', 'utils', 'network.js')));\n} catch (err) {\n console.log(JSON.stringify({ success: false, error: 'Failed to load paytaca-cli: ' + err.message }));\n process.exit(1);\n}\n\n// Cauldron payment support (opt-in via config.paymentMethod === 'lift').\n// The LIFT token is sold in a single swap transaction whose output pays the\n// x402 payTo address directly. Uses the same machinery as paytaca-cli's\n// \"paytaca swap\" command, imported via absolute paths because the wrapper runs\n// outside any node_modules tree.\nconst LIFT_TOKEN_ID = process.env.PAYTACA_PAYMENT_TOKEN_ID || '5932b2fd4915d6a75d3ec53282cd49118149a2176ee67ed68b1111ff0786f7fc';\nlet cauldronLoaded = false;\nlet fetchPoolsForToken, apiPoolToMicroPool, microPoolToPoolV0, attemptTrade, watchtowerUtxosToSpendableCoins, ExchangeLab, PayoutAmountRuleType, cashAddressToLockingBytecode, binToHex;\ntry {\n const basePath = findPaytacaCliPath();\n const cauldronDir = join(basePath, 'dist', 'wallet', 'cauldron');\n const cashlabDir = join(basePath, 'node_modules', '@cashlab');\n ({ fetchPoolsForToken } = await import(join(cauldronDir, 'api.js')));\n ({ apiPoolToMicroPool, microPoolToPoolV0 } = await import(join(cauldronDir, 'pools.js')));\n ({ attemptTrade, watchtowerUtxosToSpendableCoins } = await import(join(cauldronDir, 'transact.js')));\n ({ default: ExchangeLab } = await import(join(cashlabDir, 'cauldron', 'out', 'exchange-lab.js')));\n ({ PayoutAmountRuleType } = await import(join(cashlabDir, 'common', 'out', 'constants.js')));\n ({ cashAddressToLockingBytecode, binToHex } = await import(join(cashlabDir, 'common', 'out', 'libauth.js')));\n cauldronLoaded = true;\n} catch (err) {\n // Cauldron modules are only needed for LIFT payments; BCH payments still work.\n cauldronLoaded = false;\n}\n\nasync function main() {\n const configPath = process.argv[2];\n if (!configPath) {\n console.log(JSON.stringify({ success: false, error: 'Usage: node paytaca-pay-wrapper.mjs <config.json>' }));\n process.exit(1);\n }\n\n const config = JSON.parse(readFileSync(configPath, 'utf8'));\n const { url, method, headers, bodyFile, chipnet, confirmed, paymentMethod } = config;\n\n const body = readFileSync(bodyFile, 'utf8');\n\n const data = loadMnemonic();\n if (!data) {\n console.log(JSON.stringify({ success: false, error: 'No wallet found. Run paytaca wallet create first.' }));\n process.exit(1);\n }\n\n const wallet = loadWallet();\n const isChipnet = Boolean(chipnet);\n const bchWallet = wallet.forNetwork(isChipnet);\n const hdWallet = new LibauthHDWallet(data.mnemonic, BCH_DERIVATION_PATH, isChipnet ? 'chipnet' : 'mainnet');\n const x402Payer = new X402Payer({ hdWallet, addressIndex: 0 });\n\n try {\n const result = await executePay(url, method, headers, body, bchWallet, hdWallet, x402Payer, isChipnet, confirmed, paymentMethod);\n console.log(JSON.stringify(result, null, 2));\n } catch (err) {\n console.log(JSON.stringify({ success: false, error: err.message || String(err) }, null, 2));\n process.exit(1);\n }\n}\n\n// Sell LIFT tokens via Cauldron in a single swap transaction that pays the\n// x402 payTo address directly. Returns { txid, vout } for the payment payload.\nasync function payWithLift(bchWallet, hdWallet, requirements, changeAddress) {\n if (!cauldronLoaded) {\n throw new Error('Cauldron payment modules unavailable. Update paytaca-cli to 0.5.0+ to pay with LIFT.');\n }\n const tokenId = LIFT_TOKEN_ID;\n const amountSats = BigInt(requirements.amount);\n\n const [apiPools, allUtxos, tokenUtxos] = await Promise.all([\n fetchPoolsForToken(tokenId),\n bchWallet.getUtxos(),\n bchWallet.getUtxos({ category: tokenId }),\n ]);\n if (!apiPools || apiPools.length === 0) {\n throw new Error('No active Cauldron pools for the payment token.');\n }\n const pools = apiPools.map(apiPoolToMicroPool).map(microPoolToPoolV0);\n\n const tokenBalance = (tokenUtxos || []).reduce((sum, u) => sum + BigInt(u.amount || 0), 0n);\n if (tokenBalance <= 0n) {\n throw new Error('No LIFT tokens in the wallet. Add LIFT to pay this plan with tokens, or pay with BCH.');\n }\n\n const bchUtxos = allUtxos.filter((utxo) => !utxo.is_cashtoken);\n const spendableCoins = watchtowerUtxosToSpendableCoins({\n utxos: [...bchUtxos, ...(tokenUtxos || [])],\n wallet: hdWallet,\n });\n if (spendableCoins.length === 0) {\n throw new Error('No spendable UTXOs available.');\n }\n\n const payToDecoded = cashAddressToLockingBytecode(requirements.payTo);\n if (!payToDecoded || typeof payToDecoded === 'string' || !payToDecoded.bytecode) {\n throw new Error('Invalid payment address: ' + requirements.payTo);\n }\n const changeDecoded = cashAddressToLockingBytecode(changeAddress);\n if (!changeDecoded || typeof changeDecoded === 'string' || !changeDecoded.bytecode) {\n throw new Error('Invalid change address: ' + changeAddress);\n }\n\n const exlab = new ExchangeLab();\n const payoutRules = [\n { type: PayoutAmountRuleType.FIXED, locking_bytecode: payToDecoded.bytecode, amount: amountSats },\n { type: PayoutAmountRuleType.CHANGE, locking_bytecode: changeDecoded.bytecode, allow_mixing_native_and_token: false, allow_mixing_native_and_token_when_bch_change_is_dust: false, add_change_to_txfee_when_bch_change_is_dust: true },\n ];\n\n // Back-compute the token supply for a demand target slightly above the plan\n // cost so the received BCH covers the fixed payout plus fees (excess becomes\n // change). Retry with a bigger buffer if the first target leaves no change.\n let trade = null;\n let tradeTx = null;\n let lastError = null;\n for (const buffer of [2000n, 20000n, 100000n]) {\n try {\n trade = attemptTrade({ pools, isBuyingToken: false, supply: undefined, demand: amountSats + buffer });\n tradeTx = exlab.createTradeTx(trade.entries, spendableCoins, payoutRules, null, 1n);\n exlab.verifyTradeTx(tradeTx);\n break;\n } catch (e) {\n lastError = e;\n }\n }\n if (!tradeTx) {\n const supply = trade?.summary?.supply;\n if (supply && tokenBalance < supply) {\n throw new Error('Insufficient LIFT balance: this payment needs ' + supply + ' base units but the wallet has ' + tokenBalance + '.');\n }\n throw new Error('Could not fund the payment by selling LIFT: ' + (lastError?.message || 'unknown error'));\n }\n\n const tx = tradeTx.libauth_generated_transaction;\n const payToHex = binToHex(payToDecoded.bytecode);\n const vout = tx.outputs.findIndex((o) => binToHex(o.lockingBytecode) === payToHex);\n if (vout === -1) {\n throw new Error('Payment output missing from built transaction.');\n }\n\n const txHex = binToHex(tradeTx.txbin);\n const broadcastResponse = await bchWallet.watchtower.BCH._api.post('broadcast/', { transaction: txHex });\n const data = broadcastResponse.data;\n if (data?.result) {\n data[data.success ? 'txid' : 'error'] = data.result;\n delete data.result;\n }\n if (!data?.success || !data?.txid) {\n throw new Error(data?.error || 'Broadcast failed');\n }\n return { txid: data.txid, vout };\n}\n\nasync function executePay(url, method, headers, body, bchWallet, hdWallet, x402Payer, isChipnet, confirmed, paymentMethod) {\n const response = await fetch(url, {\n method,\n headers,\n body: ['POST', 'PUT', 'PATCH'].includes(method) ? body : undefined,\n signal: AbortSignal.timeout(PAY_TIMEOUT_MS),\n });\n\n const responseHeaders = {};\n response.headers.forEach((value, key) => { responseHeaders[key] = value; });\n const responseText = await response.text();\n let responseData;\n try { responseData = JSON.parse(responseText); } catch { responseData = responseText; }\n\n if (response.status === 402) {\n const paymentRequired = parsePaymentRequiredJson(responseData);\n if (!paymentRequired) {\n return { success: false, status: 402, error: 'Could not parse PaymentRequired from 402 response body' };\n }\n const requirements = selectBchPaymentRequirements(paymentRequired, isChipnet ? 'chipnet' : 'mainnet');\n if (!requirements) {\n return {\n success: false, status: 402, error: 'Server does not accept BCH payment',\n data: { acceptedSchemes: paymentRequired.accepts.map(a => ({ scheme: a.scheme, network: a.network })) },\n };\n }\n\n const payerAddress = x402Payer.getPayerAddress();\n const address = requirements.payTo;\n const amountBch = Number(requirements.amount) / 1e8;\n const changeAddressSet = bchWallet.getAddressSetAt(0);\n const changeAddress = changeAddressSet.change;\n\n if (!confirmed) {\n return {\n success: false, status: 402, error: 'Payment not confirmed.',\n payment: { required: true, amount: requirements.amount, payTo: address },\n };\n }\n\n let txid, vout = 0;\n if (paymentMethod === 'lift') {\n // Sell LIFT via Cauldron; the swap transaction pays the plan directly.\n const liftPayment = await payWithLift(bchWallet, hdWallet, requirements, changeAddress);\n txid = liftPayment.txid;\n vout = liftPayment.vout;\n } else {\n const sendResult = await bchWallet.sendBch(amountBch, address, changeAddress);\n if (!sendResult.success) {\n return { success: false, status: 402, payment: { required: true, error: sendResult.error }, error: sendResult.error };\n }\n txid = sendResult.txid;\n }\n\n const paymentPayload = await x402Payer.createPaymentPayload(requirements, paymentRequired.resource.url, txid, vout, requirements.amount);\n headers['PAYMENT-SIGNATURE'] = JSON.stringify(paymentPayload);\n\n let retryResponse;\n try {\n retryResponse = await fetch(url, {\n method,\n headers,\n body: ['POST', 'PUT', 'PATCH'].includes(method) ? body : undefined,\n signal: AbortSignal.timeout(PAY_TIMEOUT_MS),\n });\n } catch (e) {\n if (e.name === 'AbortError') {\n return { success: false, timeout: true, error: 'Response timed out from server.' };\n }\n throw e;\n }\n const retryResponseHeaders = {};\n retryResponse.headers.forEach((value, key) => { retryResponseHeaders[key] = value; });\n const retryResponseText = await retryResponse.text();\n let retryResponseData;\n try { retryResponseData = JSON.parse(retryResponseText); } catch { retryResponseData = retryResponseText; }\n\n return {\n success: retryResponse.ok,\n status: retryResponse.status,\n statusText: retryResponse.statusText,\n headers: retryResponseHeaders,\n data: retryResponseData,\n payment: { required: true, txid, recipientAddress: address, method: paymentMethod === 'lift' ? 'lift' : 'bch' },\n };\n }\n\n return {\n success: response.ok,\n status: response.status,\n statusText: response.statusText,\n headers: responseHeaders,\n data: responseData,\n payment: { required: false },\n };\n}\n\nmain();\n";
|
|
1
|
+
export declare const WRAPPER_SCRIPT_CONTENT = "#!/usr/bin/env node\n/**\n * Paytaca Pay Wrapper \u2014 handles large request bodies by reading from a file.\n * Imports paytaca-cli modules directly (avoids CLI argument size limits).\n */\n\nimport { readFileSync, realpathSync } from 'fs';\nimport { execSync } from 'child_process';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\n\n// How long to wait for the server to respond before treating the payment as timed out.\n// Default 240s so heavy non-streaming generations (large context / long output) can\n// complete; override with PAYTACA_PAY_TIMEOUT_MS.\nconst PAY_TIMEOUT_MS = Number(process.env.PAYTACA_PAY_TIMEOUT_MS || 240000);\n\n// Pre-payment stability probe. Before broadcasting the payment we sample the\n// plan/config endpoint several times ~500ms apart to catch a \"flapping\"\n// backend (reachable one moment, unreachable the next, e.g. right after a\n// purchase). If any sample fails while others succeed, or the plan price\n// changes between samples, we abort BEFORE any money moves. Disable with\n// PAYTACA_PLAN_PROBE=0.\nconst PLAN_PROBE_ENABLED = process.env.PAYTACA_PLAN_PROBE !== '0';\nconst PLAN_PROBE_SAMPLES = 3;\nconst PLAN_PROBE_SPACING_MS = 500;\nconst PLAN_PROBE_TIMEOUT_MS = 6000;\n\nfunction planProbeSleep(ms) {\n return new Promise(function (resolve) { setTimeout(resolve, ms); });\n}\n\n// Probe /v1/config (models + price tiers) repeatedly. Throws when the endpoint\n// is flapping or the plan price changes between samples. Returns undefined on\n// a stable backend.\nasync function probePlanStability(url, headers) {\n const modelId = headers['X-Model-Id'];\n const minutes = headers['X-Duration-Minutes'];\n if (!modelId || !minutes) return;\n let origin = null;\n try { origin = new URL(url).origin; } catch (e) { return; }\n if (!origin) return;\n\n let okSamples = 0;\n let totalSamples = 0;\n const priceSamples = [];\n let lastError = '';\n\n for (let i = 0; i < PLAN_PROBE_SAMPLES; i++) {\n totalSamples++;\n try {\n const controller = new AbortController();\n const timer = setTimeout(function () { controller.abort(); }, PLAN_PROBE_TIMEOUT_MS);\n let res;\n try {\n res = await fetch(origin + '/v1/config', { signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n if (!res.ok) { lastError = 'HTTP ' + res.status; continue; }\n const data = await res.json();\n const models = Array.isArray(data.models) ? data.models : [];\n const model = models.find(function (m) {\n const id = String(m.id || '').toLowerCase();\n const name = String(m.display_name || '').toLowerCase();\n const q = String(modelId).toLowerCase();\n return id.indexOf(q) !== -1 || name.indexOf(q) !== -1;\n });\n if (!model) { lastError = 'model ' + modelId + ' not in plan config'; continue; }\n const tiers = Array.isArray(model.price_tiers) ? model.price_tiers : [];\n const tier = tiers.find(function (t) { return Number(t.minutes) === Number(minutes); });\n if (!tier) { lastError = 'no ' + minutes + '-min plan for ' + modelId + ' in plan config'; continue; }\n priceSamples.push(Number(tier.price_sats) || 0);\n okSamples++;\n } catch (e) {\n lastError = (e && e.name === 'AbortError') ? 'timeout' : (e && e.message) || String(e);\n }\n if (i < PLAN_PROBE_SAMPLES - 1) await planProbeSleep(PLAN_PROBE_SPACING_MS);\n }\n\n // Stable = every sample succeeded AND every sample quoted the same price.\n if (okSamples === totalSamples && priceSamples.length > 0) {\n const first = priceSamples[0];\n const allEqual = priceSamples.every(function (p) { return p === first; });\n if (allEqual) return;\n }\n throw new Error('Backend plan endpoint looked unstable before purchase (reachable ' + okSamples + '/' + totalSamples + (lastError ? ', last error: ' + lastError : '') + '). No payment was broadcast \u2014 please retry in a few seconds.');\n}\n\n// Find paytaca-cli installation\nfunction findPaytacaCliPath() {\n const possiblePaths = [];\n\n // Resolve the paytaca command itself when it's on PATH. This covers local\n // installs (e.g. the plugin's own node_modules) and per-node asdf globals\n // that `npm root -g` may not reflect when multiple node versions exist.\n try {\n const whichCmd = process.platform === 'win32' ? 'where' : 'which';\n const bin = execSync(`${whichCmd} paytaca`, { encoding: 'utf8' }).trim();\n if (bin) {\n let dir = dirname(realpathSync(bin));\n for (let i = 0; i < 6; i++) {\n const parent = dirname(dir);\n if (parent === dir) break;\n possiblePaths.push(dir);\n dir = parent;\n }\n }\n } catch {}\n\n // Try to get global npm root\n try {\n const globalPath = execSync('npm root -g', { encoding: 'utf8' }).trim();\n possiblePaths.push(\n join(globalPath, 'paytaca-cli'),\n join(globalPath, 'opencode-plugin', 'node_modules', 'paytaca-cli'),\n );\n } catch {}\n \n // Common global locations\n possiblePaths.push(\n '/usr/lib/node_modules/paytaca-cli',\n '/usr/local/lib/node_modules/paytaca-cli',\n '/opt/homebrew/lib/node_modules/paytaca-cli',\n );\n \n // Windows global npm location\n if (process.platform === 'win32' && process.env.APPDATA) {\n possiblePaths.push(join(process.env.APPDATA, 'npm', 'node_modules', 'paytaca-cli'));\n }\n \n // Try current file's node_modules (for bundled installs)\n try {\n const currentFile = fileURLToPath(import.meta.url);\n const currentDir = dirname(currentFile);\n possiblePaths.push(\n join(currentDir, '..', 'node_modules', 'paytaca-cli'),\n join(currentDir, '..', '..', 'node_modules', 'paytaca-cli'),\n );\n } catch {}\n \n // Find first valid path\n for (const basePath of possiblePaths) {\n try {\n const walletPath = join(basePath, 'dist', 'wallet', 'index.js');\n readFileSync(walletPath);\n return basePath;\n } catch {}\n }\n \n throw new Error('paytaca-cli not found. Try reinstalling opencode-plugin: npm install @paytaca/opencode-plugin');\n}\n\n// Load paytaca-cli modules\nlet loadMnemonic, loadWallet, LibauthHDWallet, X402Payer, parsePaymentRequiredJson, selectBchPaymentRequirements, BCH_DERIVATION_PATH;\n\ntry {\n const basePath = findPaytacaCliPath();\n \n ({ loadMnemonic, loadWallet } = await import(join(basePath, 'dist', 'wallet', 'index.js')));\n ({ LibauthHDWallet } = await import(join(basePath, 'dist', 'wallet', 'keys.js')));\n ({ X402Payer } = await import(join(basePath, 'dist', 'wallet', 'x402.js')));\n ({ parsePaymentRequiredJson, selectBchPaymentRequirements } = await import(join(basePath, 'dist', 'utils', 'x402.js')));\n ({ BCH_DERIVATION_PATH } = await import(join(basePath, 'dist', 'utils', 'network.js')));\n} catch (err) {\n console.log(JSON.stringify({ success: false, error: 'Failed to load paytaca-cli: ' + err.message }));\n process.exit(1);\n}\n\n// Cauldron payment support (opt-in via config.paymentMethod === 'lift').\n// The LIFT token is sold in a single swap transaction whose output pays the\n// x402 payTo address directly. Uses the same machinery as paytaca-cli's\n// \"paytaca swap\" command, imported via absolute paths because the wrapper runs\n// outside any node_modules tree.\nconst LIFT_TOKEN_ID = process.env.PAYTACA_PAYMENT_TOKEN_ID || '5932b2fd4915d6a75d3ec53282cd49118149a2176ee67ed68b1111ff0786f7fc';\nlet cauldronLoaded = false;\nlet fetchPoolsForToken, apiPoolToMicroPool, microPoolToPoolV0, attemptTrade, watchtowerUtxosToSpendableCoins, ExchangeLab, PayoutAmountRuleType, cashAddressToLockingBytecode, binToHex;\ntry {\n const basePath = findPaytacaCliPath();\n const cauldronDir = join(basePath, 'dist', 'wallet', 'cauldron');\n const cashlabDir = findCashlabDir(basePath);\n ({ fetchPoolsForToken } = await import(join(cauldronDir, 'api.js')));\n ({ apiPoolToMicroPool, microPoolToPoolV0 } = await import(join(cauldronDir, 'pools.js')));\n ({ attemptTrade, watchtowerUtxosToSpendableCoins } = await import(join(cauldronDir, 'transact.js')));\n ({ default: ExchangeLab } = await import(join(cashlabDir, 'cauldron', 'out', 'exchange-lab.js')));\n ({ PayoutAmountRuleType } = await import(join(cashlabDir, 'common', 'out', 'constants.js')));\n ({ cashAddressToLockingBytecode, binToHex } = await import(join(cashlabDir, 'common', 'out', 'libauth.js')));\n cauldronLoaded = true;\n} catch (err) {\n // Cauldron modules are only needed for LIFT payments; BCH payments still work.\n cauldronLoaded = false;\n}\n\n// Locate the @cashlab package dir by walking up from the paytaca-cli path.\n// Handles hoisted installs (top-level node_modules) and nested installs.\nfunction findCashlabDir(cliPath) {\n for (let dir = cliPath, i = 0; i < 8; i++) {\n const candidate = join(dir, 'node_modules', '@cashlab');\n try {\n readFileSync(join(candidate, 'cauldron', 'out', 'exchange-lab.js'));\n return candidate;\n } catch {}\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\nasync function main() {\n const configPath = process.argv[2];\n if (!configPath) {\n console.log(JSON.stringify({ success: false, error: 'Usage: node paytaca-pay-wrapper.mjs <config.json>' }));\n process.exit(1);\n }\n\n const config = JSON.parse(readFileSync(configPath, 'utf8'));\n const { url, method, headers, bodyFile, chipnet, confirmed, paymentMethod } = config;\n\n const body = readFileSync(bodyFile, 'utf8');\n\n const data = loadMnemonic();\n if (!data) {\n console.log(JSON.stringify({ success: false, error: 'No wallet found. Run paytaca wallet create first.' }));\n process.exit(1);\n }\n\n const wallet = loadWallet();\n const isChipnet = Boolean(chipnet);\n const bchWallet = wallet.forNetwork(isChipnet);\n const hdWallet = new LibauthHDWallet(data.mnemonic, BCH_DERIVATION_PATH, isChipnet ? 'chipnet' : 'mainnet');\n const x402Payer = new X402Payer({ hdWallet, addressIndex: 0 });\n\n try {\n if (PLAN_PROBE_ENABLED) {\n await probePlanStability(url, headers);\n }\n const result = await executePay(url, method, headers, body, bchWallet, hdWallet, x402Payer, isChipnet, confirmed, paymentMethod);\n console.log(JSON.stringify(result, null, 2));\n } catch (err) {\n console.log(JSON.stringify({ success: false, error: err.message || String(err) }, null, 2));\n process.exit(1);\n }\n}\n\n// Sell LIFT tokens via Cauldron in a single swap transaction that pays the\n// x402 payTo address directly. Returns { txid, vout } for the payment payload.\nasync function payWithLift(bchWallet, hdWallet, requirements, changeAddress) {\n if (!cauldronLoaded) {\n throw new Error('Cauldron payment modules unavailable. Update paytaca-cli to 0.5.0+ to pay with LIFT.');\n }\n const tokenId = LIFT_TOKEN_ID;\n const amountSats = BigInt(requirements.amount);\n\n const [apiPools, allUtxos, tokenUtxos] = await Promise.all([\n fetchPoolsForToken(tokenId),\n bchWallet.getUtxos(),\n bchWallet.getUtxos({ category: tokenId }),\n ]);\n if (!apiPools || apiPools.length === 0) {\n throw new Error('No active Cauldron pools for the payment token.');\n }\n const pools = apiPools.map(apiPoolToMicroPool).map(microPoolToPoolV0);\n\n const tokenBalance = (tokenUtxos || []).reduce((sum, u) => sum + BigInt(u.amount || 0), 0n);\n if (tokenBalance <= 0n) {\n throw new Error('No LIFT tokens in the wallet. Add LIFT to pay this plan with tokens, or pay with BCH.');\n }\n\n const bchUtxos = allUtxos.filter((utxo) => !utxo.is_cashtoken);\n const spendableCoins = watchtowerUtxosToSpendableCoins({\n utxos: [...bchUtxos, ...(tokenUtxos || [])],\n wallet: hdWallet,\n });\n if (spendableCoins.length === 0) {\n throw new Error('No spendable UTXOs available.');\n }\n\n const payToDecoded = cashAddressToLockingBytecode(requirements.payTo);\n if (!payToDecoded || typeof payToDecoded === 'string' || !payToDecoded.bytecode) {\n throw new Error('Invalid payment address: ' + requirements.payTo);\n }\n const changeDecoded = cashAddressToLockingBytecode(changeAddress);\n if (!changeDecoded || typeof changeDecoded === 'string' || !changeDecoded.bytecode) {\n throw new Error('Invalid change address: ' + changeAddress);\n }\n\n const exlab = new ExchangeLab();\n const payoutRules = [\n { type: PayoutAmountRuleType.FIXED, locking_bytecode: payToDecoded.bytecode, amount: amountSats },\n { type: PayoutAmountRuleType.CHANGE, locking_bytecode: changeDecoded.bytecode, allow_mixing_native_and_token: false, allow_mixing_native_and_token_when_bch_change_is_dust: false, add_change_to_txfee_when_bch_change_is_dust: true },\n ];\n\n // Back-compute the token supply for a demand target slightly above the plan\n // cost so the received BCH covers the fixed payout plus fees (excess becomes\n // change). Retry with a bigger buffer if the first target leaves no change.\n let trade = null;\n let tradeTx = null;\n let lastError = null;\n for (const buffer of [2000n, 20000n, 100000n]) {\n try {\n trade = attemptTrade({ pools, isBuyingToken: false, supply: undefined, demand: amountSats + buffer });\n tradeTx = exlab.createTradeTx(trade.entries, spendableCoins, payoutRules, null, 1n);\n exlab.verifyTradeTx(tradeTx);\n break;\n } catch (e) {\n lastError = e;\n }\n }\n if (!tradeTx) {\n const supply = trade?.summary?.supply;\n if (supply && tokenBalance < supply) {\n throw new Error('Insufficient LIFT balance: this payment needs ' + supply + ' base units but the wallet has ' + tokenBalance + '.');\n }\n throw new Error('Could not fund the payment by selling LIFT: ' + (lastError?.message || 'unknown error'));\n }\n\n const tx = tradeTx.libauth_generated_transaction;\n const payToHex = binToHex(payToDecoded.bytecode);\n const vout = tx.outputs.findIndex((o) => binToHex(o.lockingBytecode) === payToHex);\n if (vout === -1) {\n throw new Error('Payment output missing from built transaction.');\n }\n\n const txHex = binToHex(tradeTx.txbin);\n const broadcastResponse = await bchWallet.watchtower.BCH._api.post('broadcast/', { transaction: txHex });\n const data = broadcastResponse.data;\n if (data?.result) {\n data[data.success ? 'txid' : 'error'] = data.result;\n delete data.result;\n }\n if (!data?.success || !data?.txid) {\n throw new Error(data?.error || 'Broadcast failed');\n }\n return { txid: data.txid, vout };\n}\n\nasync function executePay(url, method, headers, body, bchWallet, hdWallet, x402Payer, isChipnet, confirmed, paymentMethod) {\n // Tell the backend the payment method so it can apply the LIFT discount and\n // record how the plan was paid. Set once here \u2014 the same headers object is\n // reused for the 402 fetch and the PAYMENT-SIGNATURE retry.\n if (paymentMethod === 'lift') {\n headers['X-Payment-Method'] = 'lift';\n }\n\n const response = await fetch(url, {\n method,\n headers,\n body: ['POST', 'PUT', 'PATCH'].includes(method) ? body : undefined,\n signal: AbortSignal.timeout(PAY_TIMEOUT_MS),\n });\n\n const responseHeaders = {};\n response.headers.forEach((value, key) => { responseHeaders[key] = value; });\n const responseText = await response.text();\n let responseData;\n try { responseData = JSON.parse(responseText); } catch { responseData = responseText; }\n\n if (response.status === 402) {\n const paymentRequired = parsePaymentRequiredJson(responseData);\n if (!paymentRequired) {\n return { success: false, status: 402, error: 'Could not parse PaymentRequired from 402 response body' };\n }\n const requirements = selectBchPaymentRequirements(paymentRequired, isChipnet ? 'chipnet' : 'mainnet');\n if (!requirements) {\n return {\n success: false, status: 402, error: 'Server does not accept BCH payment',\n data: { acceptedSchemes: paymentRequired.accepts.map(a => ({ scheme: a.scheme, network: a.network })) },\n };\n }\n\n const payerAddress = x402Payer.getPayerAddress();\n const address = requirements.payTo;\n const amountBch = Number(requirements.amount) / 1e8;\n const changeAddressSet = bchWallet.getAddressSetAt(0);\n const changeAddress = changeAddressSet.change;\n\n if (!confirmed) {\n return {\n success: false, status: 402, error: 'Payment not confirmed.',\n payment: { required: true, amount: requirements.amount, payTo: address },\n };\n }\n\n let txid, vout = 0;\n if (paymentMethod === 'lift') {\n // Sell LIFT via Cauldron; the swap transaction pays the plan directly.\n const liftPayment = await payWithLift(bchWallet, hdWallet, requirements, changeAddress);\n txid = liftPayment.txid;\n vout = liftPayment.vout;\n } else {\n const sendResult = await bchWallet.sendBch(amountBch, address, changeAddress);\n if (!sendResult.success) {\n return { success: false, status: 402, payment: { required: true, error: sendResult.error }, error: sendResult.error };\n }\n txid = sendResult.txid;\n }\n\n const paymentPayload = await x402Payer.createPaymentPayload(requirements, paymentRequired.resource.url, txid, vout, requirements.amount);\n headers['PAYMENT-SIGNATURE'] = JSON.stringify(paymentPayload);\n\n let retryResponse;\n try {\n retryResponse = await fetch(url, {\n method,\n headers,\n body: ['POST', 'PUT', 'PATCH'].includes(method) ? body : undefined,\n signal: AbortSignal.timeout(PAY_TIMEOUT_MS),\n });\n } catch (e) {\n if (e.name === 'AbortError') {\n return { success: false, timeout: true, error: 'Response timed out from server.' };\n }\n throw e;\n }\n const retryResponseHeaders = {};\n retryResponse.headers.forEach((value, key) => { retryResponseHeaders[key] = value; });\n const retryResponseText = await retryResponse.text();\n let retryResponseData;\n try { retryResponseData = JSON.parse(retryResponseText); } catch { retryResponseData = retryResponseText; }\n\n return {\n success: retryResponse.ok,\n status: retryResponse.status,\n statusText: retryResponse.statusText,\n headers: retryResponseHeaders,\n data: retryResponseData,\n payment: { required: true, txid, recipientAddress: address, method: paymentMethod === 'lift' ? 'lift' : 'bch' },\n };\n }\n\n return {\n success: response.ok,\n status: response.status,\n statusText: response.statusText,\n headers: responseHeaders,\n data: responseData,\n payment: { required: false },\n };\n}\n\nmain();\n";
|
|
2
2
|
//# sourceMappingURL=wrapper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../../src/bundled/wrapper.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,
|
|
1
|
+
{"version":3,"file":"wrapper.d.ts","sourceRoot":"","sources":["../../src/bundled/wrapper.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,+wkBAyblC,CAAC"}
|
package/dist/bundled/wrapper.js
CHANGED
|
@@ -10,7 +10,7 @@ exports.WRAPPER_SCRIPT_CONTENT = `#!/usr/bin/env node
|
|
|
10
10
|
* Imports paytaca-cli modules directly (avoids CLI argument size limits).
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { readFileSync } from 'fs';
|
|
13
|
+
import { readFileSync, realpathSync } from 'fs';
|
|
14
14
|
import { execSync } from 'child_process';
|
|
15
15
|
import { fileURLToPath } from 'url';
|
|
16
16
|
import { dirname, join } from 'path';
|
|
@@ -20,10 +20,99 @@ import { dirname, join } from 'path';
|
|
|
20
20
|
// complete; override with PAYTACA_PAY_TIMEOUT_MS.
|
|
21
21
|
const PAY_TIMEOUT_MS = Number(process.env.PAYTACA_PAY_TIMEOUT_MS || 240000);
|
|
22
22
|
|
|
23
|
+
// Pre-payment stability probe. Before broadcasting the payment we sample the
|
|
24
|
+
// plan/config endpoint several times ~500ms apart to catch a "flapping"
|
|
25
|
+
// backend (reachable one moment, unreachable the next, e.g. right after a
|
|
26
|
+
// purchase). If any sample fails while others succeed, or the plan price
|
|
27
|
+
// changes between samples, we abort BEFORE any money moves. Disable with
|
|
28
|
+
// PAYTACA_PLAN_PROBE=0.
|
|
29
|
+
const PLAN_PROBE_ENABLED = process.env.PAYTACA_PLAN_PROBE !== '0';
|
|
30
|
+
const PLAN_PROBE_SAMPLES = 3;
|
|
31
|
+
const PLAN_PROBE_SPACING_MS = 500;
|
|
32
|
+
const PLAN_PROBE_TIMEOUT_MS = 6000;
|
|
33
|
+
|
|
34
|
+
function planProbeSleep(ms) {
|
|
35
|
+
return new Promise(function (resolve) { setTimeout(resolve, ms); });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Probe /v1/config (models + price tiers) repeatedly. Throws when the endpoint
|
|
39
|
+
// is flapping or the plan price changes between samples. Returns undefined on
|
|
40
|
+
// a stable backend.
|
|
41
|
+
async function probePlanStability(url, headers) {
|
|
42
|
+
const modelId = headers['X-Model-Id'];
|
|
43
|
+
const minutes = headers['X-Duration-Minutes'];
|
|
44
|
+
if (!modelId || !minutes) return;
|
|
45
|
+
let origin = null;
|
|
46
|
+
try { origin = new URL(url).origin; } catch (e) { return; }
|
|
47
|
+
if (!origin) return;
|
|
48
|
+
|
|
49
|
+
let okSamples = 0;
|
|
50
|
+
let totalSamples = 0;
|
|
51
|
+
const priceSamples = [];
|
|
52
|
+
let lastError = '';
|
|
53
|
+
|
|
54
|
+
for (let i = 0; i < PLAN_PROBE_SAMPLES; i++) {
|
|
55
|
+
totalSamples++;
|
|
56
|
+
try {
|
|
57
|
+
const controller = new AbortController();
|
|
58
|
+
const timer = setTimeout(function () { controller.abort(); }, PLAN_PROBE_TIMEOUT_MS);
|
|
59
|
+
let res;
|
|
60
|
+
try {
|
|
61
|
+
res = await fetch(origin + '/v1/config', { signal: controller.signal });
|
|
62
|
+
} finally {
|
|
63
|
+
clearTimeout(timer);
|
|
64
|
+
}
|
|
65
|
+
if (!res.ok) { lastError = 'HTTP ' + res.status; continue; }
|
|
66
|
+
const data = await res.json();
|
|
67
|
+
const models = Array.isArray(data.models) ? data.models : [];
|
|
68
|
+
const model = models.find(function (m) {
|
|
69
|
+
const id = String(m.id || '').toLowerCase();
|
|
70
|
+
const name = String(m.display_name || '').toLowerCase();
|
|
71
|
+
const q = String(modelId).toLowerCase();
|
|
72
|
+
return id.indexOf(q) !== -1 || name.indexOf(q) !== -1;
|
|
73
|
+
});
|
|
74
|
+
if (!model) { lastError = 'model ' + modelId + ' not in plan config'; continue; }
|
|
75
|
+
const tiers = Array.isArray(model.price_tiers) ? model.price_tiers : [];
|
|
76
|
+
const tier = tiers.find(function (t) { return Number(t.minutes) === Number(minutes); });
|
|
77
|
+
if (!tier) { lastError = 'no ' + minutes + '-min plan for ' + modelId + ' in plan config'; continue; }
|
|
78
|
+
priceSamples.push(Number(tier.price_sats) || 0);
|
|
79
|
+
okSamples++;
|
|
80
|
+
} catch (e) {
|
|
81
|
+
lastError = (e && e.name === 'AbortError') ? 'timeout' : (e && e.message) || String(e);
|
|
82
|
+
}
|
|
83
|
+
if (i < PLAN_PROBE_SAMPLES - 1) await planProbeSleep(PLAN_PROBE_SPACING_MS);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Stable = every sample succeeded AND every sample quoted the same price.
|
|
87
|
+
if (okSamples === totalSamples && priceSamples.length > 0) {
|
|
88
|
+
const first = priceSamples[0];
|
|
89
|
+
const allEqual = priceSamples.every(function (p) { return p === first; });
|
|
90
|
+
if (allEqual) return;
|
|
91
|
+
}
|
|
92
|
+
throw new Error('Backend plan endpoint looked unstable before purchase (reachable ' + okSamples + '/' + totalSamples + (lastError ? ', last error: ' + lastError : '') + '). No payment was broadcast — please retry in a few seconds.');
|
|
93
|
+
}
|
|
94
|
+
|
|
23
95
|
// Find paytaca-cli installation
|
|
24
96
|
function findPaytacaCliPath() {
|
|
25
97
|
const possiblePaths = [];
|
|
26
|
-
|
|
98
|
+
|
|
99
|
+
// Resolve the paytaca command itself when it's on PATH. This covers local
|
|
100
|
+
// installs (e.g. the plugin's own node_modules) and per-node asdf globals
|
|
101
|
+
// that \`npm root -g\` may not reflect when multiple node versions exist.
|
|
102
|
+
try {
|
|
103
|
+
const whichCmd = process.platform === 'win32' ? 'where' : 'which';
|
|
104
|
+
const bin = execSync(\`\${whichCmd} paytaca\`, { encoding: 'utf8' }).trim();
|
|
105
|
+
if (bin) {
|
|
106
|
+
let dir = dirname(realpathSync(bin));
|
|
107
|
+
for (let i = 0; i < 6; i++) {
|
|
108
|
+
const parent = dirname(dir);
|
|
109
|
+
if (parent === dir) break;
|
|
110
|
+
possiblePaths.push(dir);
|
|
111
|
+
dir = parent;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} catch {}
|
|
115
|
+
|
|
27
116
|
// Try to get global npm root
|
|
28
117
|
try {
|
|
29
118
|
const globalPath = execSync('npm root -g', { encoding: 'utf8' }).trim();
|
|
@@ -40,6 +129,11 @@ function findPaytacaCliPath() {
|
|
|
40
129
|
'/opt/homebrew/lib/node_modules/paytaca-cli',
|
|
41
130
|
);
|
|
42
131
|
|
|
132
|
+
// Windows global npm location
|
|
133
|
+
if (process.platform === 'win32' && process.env.APPDATA) {
|
|
134
|
+
possiblePaths.push(join(process.env.APPDATA, 'npm', 'node_modules', 'paytaca-cli'));
|
|
135
|
+
}
|
|
136
|
+
|
|
43
137
|
// Try current file's node_modules (for bundled installs)
|
|
44
138
|
try {
|
|
45
139
|
const currentFile = fileURLToPath(import.meta.url);
|
|
@@ -89,7 +183,7 @@ let fetchPoolsForToken, apiPoolToMicroPool, microPoolToPoolV0, attemptTrade, wat
|
|
|
89
183
|
try {
|
|
90
184
|
const basePath = findPaytacaCliPath();
|
|
91
185
|
const cauldronDir = join(basePath, 'dist', 'wallet', 'cauldron');
|
|
92
|
-
const cashlabDir =
|
|
186
|
+
const cashlabDir = findCashlabDir(basePath);
|
|
93
187
|
({ fetchPoolsForToken } = await import(join(cauldronDir, 'api.js')));
|
|
94
188
|
({ apiPoolToMicroPool, microPoolToPoolV0 } = await import(join(cauldronDir, 'pools.js')));
|
|
95
189
|
({ attemptTrade, watchtowerUtxosToSpendableCoins } = await import(join(cauldronDir, 'transact.js')));
|
|
@@ -102,6 +196,22 @@ try {
|
|
|
102
196
|
cauldronLoaded = false;
|
|
103
197
|
}
|
|
104
198
|
|
|
199
|
+
// Locate the @cashlab package dir by walking up from the paytaca-cli path.
|
|
200
|
+
// Handles hoisted installs (top-level node_modules) and nested installs.
|
|
201
|
+
function findCashlabDir(cliPath) {
|
|
202
|
+
for (let dir = cliPath, i = 0; i < 8; i++) {
|
|
203
|
+
const candidate = join(dir, 'node_modules', '@cashlab');
|
|
204
|
+
try {
|
|
205
|
+
readFileSync(join(candidate, 'cauldron', 'out', 'exchange-lab.js'));
|
|
206
|
+
return candidate;
|
|
207
|
+
} catch {}
|
|
208
|
+
const parent = dirname(dir);
|
|
209
|
+
if (parent === dir) break;
|
|
210
|
+
dir = parent;
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
|
|
105
215
|
async function main() {
|
|
106
216
|
const configPath = process.argv[2];
|
|
107
217
|
if (!configPath) {
|
|
@@ -127,6 +237,9 @@ async function main() {
|
|
|
127
237
|
const x402Payer = new X402Payer({ hdWallet, addressIndex: 0 });
|
|
128
238
|
|
|
129
239
|
try {
|
|
240
|
+
if (PLAN_PROBE_ENABLED) {
|
|
241
|
+
await probePlanStability(url, headers);
|
|
242
|
+
}
|
|
130
243
|
const result = await executePay(url, method, headers, body, bchWallet, hdWallet, x402Payer, isChipnet, confirmed, paymentMethod);
|
|
131
244
|
console.log(JSON.stringify(result, null, 2));
|
|
132
245
|
} catch (err) {
|
|
@@ -228,6 +341,13 @@ async function payWithLift(bchWallet, hdWallet, requirements, changeAddress) {
|
|
|
228
341
|
}
|
|
229
342
|
|
|
230
343
|
async function executePay(url, method, headers, body, bchWallet, hdWallet, x402Payer, isChipnet, confirmed, paymentMethod) {
|
|
344
|
+
// Tell the backend the payment method so it can apply the LIFT discount and
|
|
345
|
+
// record how the plan was paid. Set once here — the same headers object is
|
|
346
|
+
// reused for the 402 fetch and the PAYMENT-SIGNATURE retry.
|
|
347
|
+
if (paymentMethod === 'lift') {
|
|
348
|
+
headers['X-Payment-Method'] = 'lift';
|
|
349
|
+
}
|
|
350
|
+
|
|
231
351
|
const response = await fetch(url, {
|
|
232
352
|
method,
|
|
233
353
|
headers,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../../src/bundled/wrapper.ts"],"names":[],"mappings":";AAAA,oEAAoE;AACpE,4EAA4E;AAC5E,mFAAmF;;;AAEtE,QAAA,sBAAsB,GAAG
|
|
1
|
+
{"version":3,"file":"wrapper.js","sourceRoot":"","sources":["../../src/bundled/wrapper.ts"],"names":[],"mappings":";AAAA,oEAAoE;AACpE,4EAA4E;AAC5E,mFAAmF;;;AAEtE,QAAA,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAybrC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credits.d.ts","sourceRoot":"","sources":["../src/credits.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,EAAE,MAAM,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,MAAM,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,gBAAgB;;EAiG7D"}
|
package/dist/credits.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Credits → TUI toast notifications.
|
|
3
|
+
//
|
|
4
|
+
// Watches remaining Paytaca AI time credits and nudges the user through TUI
|
|
5
|
+
// toasts: a warning when credits run low or are exhausted, and a success toast
|
|
6
|
+
// when more credits appear (manual buy or auto-refill). Purely advisory — every
|
|
7
|
+
// toast call is wrapped so a failure (headless session, no TUI attached) can
|
|
8
|
+
// never break a session.
|
|
9
|
+
//
|
|
10
|
+
// Disable entirely by setting PAYTACA_CREDITS_TOASTS=0.
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createCreditsToastWatch = createCreditsToastWatch;
|
|
13
|
+
const ENABLED = process.env.PAYTACA_CREDITS_TOASTS !== '0';
|
|
14
|
+
const MIN_INTERVAL_MS = 60000; // at most one backend poll per minute
|
|
15
|
+
const REFILL_DELTA_S = 60; // remaining grew by >= this ⇒ treat as a refill
|
|
16
|
+
const TOAST_DURATION_MS = 9000;
|
|
17
|
+
// Buckets of remaining time. Higher band = more time. Bands 0-2 are "low" and
|
|
18
|
+
// produce a toast when crossed downward; 3-4 are healthy and stay quiet.
|
|
19
|
+
const bandForSeconds = (s) => {
|
|
20
|
+
if (s <= 0)
|
|
21
|
+
return 0; // exhausted
|
|
22
|
+
if (s < 120)
|
|
23
|
+
return 1; // < 2 min
|
|
24
|
+
if (s < 600)
|
|
25
|
+
return 2; // < 10 min
|
|
26
|
+
if (s < 1800)
|
|
27
|
+
return 3; // < 30 min
|
|
28
|
+
return 4; // >= 30 min
|
|
29
|
+
};
|
|
30
|
+
const formatShort = (seconds) => {
|
|
31
|
+
if (seconds >= 3600) {
|
|
32
|
+
return `${Math.floor(seconds / 3600)}h ${Math.round((seconds % 3600) / 60)}m`;
|
|
33
|
+
}
|
|
34
|
+
return `${Math.max(1, Math.round(seconds / 60))}m`;
|
|
35
|
+
};
|
|
36
|
+
function createCreditsToastWatch(deps) {
|
|
37
|
+
let lastRemaining = NaN;
|
|
38
|
+
let lastBand = NaN;
|
|
39
|
+
let lastCheckAt = 0;
|
|
40
|
+
const push = (title, message, variant) => {
|
|
41
|
+
try {
|
|
42
|
+
const tui = deps.client?.tui;
|
|
43
|
+
if (!tui || typeof tui.showToast !== 'function') {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const result = tui.showToast({
|
|
47
|
+
body: { title, message, variant, duration: TOAST_DURATION_MS },
|
|
48
|
+
});
|
|
49
|
+
result?.catch?.(() => { });
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// Never throw into a session.
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
const emitBand = (band, remaining, name) => {
|
|
56
|
+
if (band === 0) {
|
|
57
|
+
push('⛔ Paytaca credits exhausted', `${name} is out of time. The next request will ask you to buy a plan (or arm auto-refill).`, 'error');
|
|
58
|
+
}
|
|
59
|
+
else if (band === 1) {
|
|
60
|
+
push('🛑 Paytaca credits almost gone', `${name}: under ${formatShort(120)} left — buy a plan soon or arm auto-refill.`, 'error');
|
|
61
|
+
}
|
|
62
|
+
else if (band === 2) {
|
|
63
|
+
push('⏳ Paytaca credits running low', `${name}: about ${formatShort(remaining)} remaining.`, 'warning');
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
const check = async () => {
|
|
67
|
+
if (!ENABLED)
|
|
68
|
+
return;
|
|
69
|
+
if (!deps.client)
|
|
70
|
+
return;
|
|
71
|
+
const backendUrl = deps.backendUrl();
|
|
72
|
+
const walletHash = deps.walletHash();
|
|
73
|
+
if (!backendUrl || !walletHash)
|
|
74
|
+
return;
|
|
75
|
+
const now = Date.now();
|
|
76
|
+
if (now - lastCheckAt < MIN_INTERVAL_MS)
|
|
77
|
+
return;
|
|
78
|
+
lastCheckAt = now;
|
|
79
|
+
let sessions = [];
|
|
80
|
+
try {
|
|
81
|
+
const res = await fetch(`${backendUrl}/v1/wallet/status`, {
|
|
82
|
+
headers: { 'X-Wallet-Hash': walletHash },
|
|
83
|
+
});
|
|
84
|
+
if (!res.ok)
|
|
85
|
+
return;
|
|
86
|
+
const data = await res.json();
|
|
87
|
+
sessions = Array.isArray(data.sessions) ? data.sessions : [];
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return; // backend unreachable — nothing to toast about
|
|
91
|
+
}
|
|
92
|
+
// The session with the most remaining time is the one the user is most
|
|
93
|
+
// likely actively using; report on it even when it's exhausted (so we can
|
|
94
|
+
// name the model in the "out of time" toast).
|
|
95
|
+
const tracked = sessions
|
|
96
|
+
.filter((s) => Number.isFinite(Number(s.time_remaining_seconds)))
|
|
97
|
+
.sort((a, b) => (Number(b.time_remaining_seconds) || 0) - (Number(a.time_remaining_seconds) || 0));
|
|
98
|
+
const best = tracked[0];
|
|
99
|
+
const remaining = best ? Number(best.time_remaining_seconds) || 0 : 0;
|
|
100
|
+
const name = best ? best.display_name || best.ai_model || 'model' : '';
|
|
101
|
+
const band = bandForSeconds(remaining);
|
|
102
|
+
if (!isFinite(lastRemaining)) {
|
|
103
|
+
// First read — only warn if already low, so a fresh session isn't noisy.
|
|
104
|
+
if (band <= 2) {
|
|
105
|
+
emitBand(band, remaining, name);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (remaining > lastRemaining + REFILL_DELTA_S) {
|
|
109
|
+
// New credits appeared — either a manual buy or an auto-refill.
|
|
110
|
+
push('⚡ Paytaca credits added', `${name}: ${formatShort(remaining)} remaining now.`, 'success');
|
|
111
|
+
}
|
|
112
|
+
else if (band < lastBand || !isFinite(lastBand)) {
|
|
113
|
+
emitBand(band, remaining, name);
|
|
114
|
+
}
|
|
115
|
+
lastRemaining = remaining;
|
|
116
|
+
lastBand = band;
|
|
117
|
+
};
|
|
118
|
+
return { check };
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=credits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credits.js","sourceRoot":"","sources":["../src/credits.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
declare function OpencodePlugin(
|
|
1
|
+
declare function OpencodePlugin(input?: any, _options?: any): Promise<{
|
|
2
2
|
config?: undefined;
|
|
3
|
+
event?: undefined;
|
|
3
4
|
"chat.headers"?: undefined;
|
|
4
5
|
"experimental.chat.messages.transform"?: undefined;
|
|
5
6
|
} | {
|
|
6
7
|
config: (cfg: any) => Promise<void>;
|
|
8
|
+
event: (eventInput: any) => Promise<void>;
|
|
7
9
|
"chat.headers": (_input: any, output: any) => Promise<void>;
|
|
8
10
|
"experimental.chat.messages.transform": (_input: any, output: any) => Promise<void>;
|
|
9
11
|
}>;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,iBAAe,cAAc,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,GAAG;;;;;;kBA2IjC,GAAG;wBAyFG,GAAG;6BAWE,GAAG,UAAU,GAAG;qDA6BQ,GAAG,UAAU,GAAG;GAiB1E;;;;;AAED,kBAAoE"}
|
package/dist/index.js
CHANGED
|
@@ -38,10 +38,12 @@ const proxy_1 = require("./proxy");
|
|
|
38
38
|
const mcp_1 = require("./bundled/mcp");
|
|
39
39
|
const context_1 = require("./context");
|
|
40
40
|
const selfheal_1 = require("./selfheal");
|
|
41
|
+
const credits_1 = require("./credits");
|
|
41
42
|
const fs = __importStar(require("fs"));
|
|
42
43
|
const path = __importStar(require("path"));
|
|
43
44
|
const os = __importStar(require("os"));
|
|
44
|
-
async function OpencodePlugin(
|
|
45
|
+
async function OpencodePlugin(input, _options) {
|
|
46
|
+
const client = input?.client;
|
|
45
47
|
const configDir = (0, config_1.getConfigDir)();
|
|
46
48
|
(0, config_1.ensureConfigDir)(configDir);
|
|
47
49
|
let config = (0, config_1.loadConfig)(configDir);
|
|
@@ -118,6 +120,16 @@ async function OpencodePlugin(_input, _options) {
|
|
|
118
120
|
}
|
|
119
121
|
// Start or reuse proxy
|
|
120
122
|
const proxy = await (0, proxy_1.startProxy)(configDir, config);
|
|
123
|
+
// Credits → TUI toasts: warn when time runs low/exhausted and celebrate
|
|
124
|
+
// refills. Runs once shortly after startup and then after each idle session.
|
|
125
|
+
const creditsToaster = (0, credits_1.createCreditsToastWatch)({
|
|
126
|
+
client,
|
|
127
|
+
backendUrl: () => config.backendUrl || '',
|
|
128
|
+
walletHash: () => cachedWalletHash,
|
|
129
|
+
});
|
|
130
|
+
setTimeout(() => {
|
|
131
|
+
void creditsToaster.check();
|
|
132
|
+
}, 4000);
|
|
121
133
|
// Write the MCP server script so opencode can spawn it (registered in the
|
|
122
134
|
// config hook below). It exposes read-only account tools (credits, balance,
|
|
123
135
|
// models, plans) so the assistant can answer account questions directly.
|
|
@@ -239,8 +251,23 @@ async function OpencodePlugin(_input, _options) {
|
|
|
239
251
|
if (permissions['paytaca_buy_plan'] === undefined) {
|
|
240
252
|
permissions['paytaca_buy_plan'] = 'ask';
|
|
241
253
|
}
|
|
254
|
+
if (permissions['paytaca_auto_refill'] === undefined) {
|
|
255
|
+
permissions['paytaca_auto_refill'] = 'ask';
|
|
256
|
+
}
|
|
242
257
|
cfg.permission = permissions;
|
|
243
258
|
},
|
|
259
|
+
event: async (eventInput) => {
|
|
260
|
+
// Re-check credits whenever a session finishes a turn, so the user is
|
|
261
|
+
// nudged as soon as time runs low — or when a refill lands.
|
|
262
|
+
try {
|
|
263
|
+
if (eventInput?.event?.type === 'session.idle') {
|
|
264
|
+
await creditsToaster.check();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
console.error('Credits toast check failed:', e.message);
|
|
269
|
+
}
|
|
270
|
+
},
|
|
244
271
|
"chat.headers": async (_input, output) => {
|
|
245
272
|
// Secondary fallback delivery path. Never send an empty value —
|
|
246
273
|
// opencode/SDK may strip an empty header, which would make the
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qCAA+F;AAC/F,qCAA2F;AAC3F,mCAAwD;AACxD,uCAAmD;AACnD,uCAA+C;AAC/C,yCAAyC;AACzC,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;AAEzB,KAAK,UAAU,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAc5C,wBAAgB,iBAAiB,IAAI,MAAM,CA4C1C;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYpE;AAuCD,wBAAsB,iBAAiB,CAAC,SAAS,GAAE,MAAa,EAAE,OAAO,GAAE,MAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAOzG;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBlH;AAED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAc5C,wBAAgB,iBAAiB,IAAI,MAAM,CA4C1C;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYpE;AAuCD,wBAAsB,iBAAiB,CAAC,SAAS,GAAE,MAAa,EAAE,OAAO,GAAE,MAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAOzG;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBlH;AAED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAiHtF;AAqBD,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAU5G"}
|
package/dist/proxy.js
CHANGED
|
@@ -173,17 +173,21 @@ async function startProxy(configDir, config) {
|
|
|
173
173
|
const logFile = (0, config_1.getLogFile)(configDir);
|
|
174
174
|
const wrapperScript = (0, config_1.getWrapperScript)(configDir);
|
|
175
175
|
(0, config_1.ensureConfigDir)(configDir);
|
|
176
|
+
// Always refresh the payment wrapper on disk. It is executed fresh on every
|
|
177
|
+
// payment, so it must never go stale even when the proxy is reused/restarted.
|
|
178
|
+
fs.writeFileSync(wrapperScript, wrapper_1.WRAPPER_SCRIPT_CONTENT, 'utf8');
|
|
179
|
+
fs.chmodSync(wrapperScript, '755');
|
|
176
180
|
const currentHash = scriptHash();
|
|
177
181
|
const persistedConfig = (0, config_1.loadConfig)(configDir);
|
|
178
182
|
let existingStatus = await getProxyStatus(configDir);
|
|
179
183
|
const needsRestart = existingStatus.running &&
|
|
180
184
|
(existingStatus.pid || 0) > 0 &&
|
|
181
185
|
persistedConfig.proxyScriptHash !== currentHash;
|
|
182
|
-
fs.writeFileSync(proxyScript, proxy_1.PROXY_SCRIPT_CONTENT, 'utf8');
|
|
183
|
-
fs.chmodSync(proxyScript, '755');
|
|
184
186
|
if (existingStatus.running && existingStatus.pid && existingStatus.port && !needsRestart) {
|
|
185
187
|
return await reuseExistingProxy(configDir, config, { port: existingStatus.port, pid: existingStatus.pid }, currentHash);
|
|
186
188
|
}
|
|
189
|
+
fs.writeFileSync(proxyScript, proxy_1.PROXY_SCRIPT_CONTENT, 'utf8');
|
|
190
|
+
fs.chmodSync(proxyScript, '755');
|
|
187
191
|
if (existingStatus.running && existingStatus.pid) {
|
|
188
192
|
try {
|
|
189
193
|
process.kill(existingStatus.pid);
|
|
@@ -197,8 +201,6 @@ async function startProxy(configDir, config) {
|
|
|
197
201
|
if (adopted) {
|
|
198
202
|
return adopted;
|
|
199
203
|
}
|
|
200
|
-
fs.writeFileSync(wrapperScript, wrapper_1.WRAPPER_SCRIPT_CONTENT, 'utf8');
|
|
201
|
-
fs.chmodSync(wrapperScript, '755');
|
|
202
204
|
const paytacaCmd = getPaytacaCommand();
|
|
203
205
|
const MAX_ATTEMPTS = 3;
|
|
204
206
|
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
package/dist/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,8CA4CC;AAED,0CAYC;AAuCD,8CAOC;AAED,4CAOC;AAED,wCAiBC;AAED,
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED