@paytaca/opencode-plugin 0.2.2 ā 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundled/mcp.d.ts +1 -1
- package/dist/bundled/mcp.d.ts.map +1 -1
- package/dist/bundled/mcp.js +133 -21
- 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 +151 -38
- 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 +7 -0
- package/dist/bundled/wrapper.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
package/dist/bundled/proxy.js
CHANGED
|
@@ -110,6 +110,43 @@ async function getWalletBalance() {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
// LIFT token balance in base units (2 decimals); null when unavailable.
|
|
114
|
+
const LIFT_TOKEN_ID = '5932b2fd4915d6a75d3ec53282cd49118149a2176ee67ed68b1111ff0786f7fc';
|
|
115
|
+
async function getLiftBalance() {
|
|
116
|
+
try {
|
|
117
|
+
const output = await runCommand(PAYTACA_CMD, ['token', 'info', LIFT_TOKEN_ID]);
|
|
118
|
+
const match = output.match(/Balance:\\s*([\\d.]+)\\s*LIFT/i);
|
|
119
|
+
if (match) return Math.round(parseFloat(match[1]) * 100);
|
|
120
|
+
return null;
|
|
121
|
+
} catch (err) {
|
|
122
|
+
log('Failed to get LIFT balance: ' + err.message);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// LIFT payment discount percent advertised by the backend (/v1/config), cached
|
|
128
|
+
// briefly (30s) so a server-side rate change is picked up quickly. Returns 0
|
|
129
|
+
// when unset/unavailable so callers can fall back to no-discount messaging.
|
|
130
|
+
let liftDiscountCache = { at: 0, percent: 0 };
|
|
131
|
+
async function getLiftDiscountPercent() {
|
|
132
|
+
const now = Date.now();
|
|
133
|
+
if (liftDiscountCache.at && now - liftDiscountCache.at < 30000) {
|
|
134
|
+
return liftDiscountCache.percent;
|
|
135
|
+
}
|
|
136
|
+
let percent = 0;
|
|
137
|
+
try {
|
|
138
|
+
const configRes = await fetch(BACKEND_URL + '/v1/config');
|
|
139
|
+
if (configRes.ok) {
|
|
140
|
+
const data = await configRes.json();
|
|
141
|
+
percent = Number(data.lift_payment_discount_percent) || 0;
|
|
142
|
+
}
|
|
143
|
+
} catch (err) {
|
|
144
|
+
log('Failed to fetch LIFT discount config: ' + err.message);
|
|
145
|
+
}
|
|
146
|
+
liftDiscountCache = { at: now, percent };
|
|
147
|
+
return percent;
|
|
148
|
+
}
|
|
149
|
+
|
|
113
150
|
// Utility: get receiving address
|
|
114
151
|
async function getReceivingAddress() {
|
|
115
152
|
try {
|
|
@@ -255,10 +292,20 @@ async function streamTierSelectionBody(res, walletHash, modelName, tiers, includ
|
|
|
255
292
|
choices: [{ index: 0, delta: { content: tiersContent }, finish_reason: null }],
|
|
256
293
|
});
|
|
257
294
|
|
|
295
|
+
// Advertise the LIFT discount when the backend advertises one.
|
|
296
|
+
const liftPercent = await getLiftDiscountPercent();
|
|
297
|
+
if (liftPercent > 0) {
|
|
298
|
+
sseLine(res, {
|
|
299
|
+
id: 'tier-10b',
|
|
300
|
+
object: 'chat.completion.chunk',
|
|
301
|
+
choices: [{ index: 0, delta: { content: '\\nš” **' + liftPercent + '% off** when you pay with LIFT tokens ā type \`LIFT\` to pay with LIFT and get the discount.\\n' }, finish_reason: null }],
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
258
305
|
sseLine(res, {
|
|
259
306
|
id: 'tier-11',
|
|
260
307
|
object: 'chat.completion.chunk',
|
|
261
|
-
choices: [{ index: 0, delta: { content: '\\nEnter a number (1-' + tiers.length + '),
|
|
308
|
+
choices: [{ index: 0, delta: { content: '\\nEnter a number (1-' + tiers.length + ') to pay with BCH, or type \`LIFT\` to pay with LIFT tokens' + (liftPercent > 0 ? ' and get ' + liftPercent + '% off' : '') + ':\\n' }, finish_reason: 'stop' }],
|
|
262
309
|
});
|
|
263
310
|
|
|
264
311
|
// If other models still have paid credits, tell the user they can switch
|
|
@@ -731,7 +778,7 @@ async function streamPaymentFailureAndRetry(res, walletHash, pendingPayload, mes
|
|
|
731
778
|
}
|
|
732
779
|
|
|
733
780
|
// Run paytaca pay internally and return the response
|
|
734
|
-
function runPaytacaPay(djangoUrl, body, walletHash, extraHeaders, callback) {
|
|
781
|
+
function runPaytacaPay(djangoUrl, body, walletHash, extraHeaders, paymentMethod, callback) {
|
|
735
782
|
const url = djangoUrl + '/chat/completions?wallet_hash=' + encodeURIComponent(walletHash || '');
|
|
736
783
|
const payBody = forceNonStreaming(body);
|
|
737
784
|
|
|
@@ -753,6 +800,9 @@ function runPaytacaPay(djangoUrl, body, walletHash, extraHeaders, callback) {
|
|
|
753
800
|
bodyFile,
|
|
754
801
|
confirmed: true,
|
|
755
802
|
};
|
|
803
|
+
if (paymentMethod === 'lift') {
|
|
804
|
+
config.paymentMethod = 'lift';
|
|
805
|
+
}
|
|
756
806
|
|
|
757
807
|
try {
|
|
758
808
|
fs.writeFileSync(configFile, JSON.stringify(config), 'utf8');
|
|
@@ -1167,20 +1217,43 @@ const server = http.createServer(async (req, res) => {
|
|
|
1167
1217
|
await handlePricingCommand(res);
|
|
1168
1218
|
return;
|
|
1169
1219
|
}
|
|
1220
|
+
|
|
1221
|
+
// LIFT payment option: user typed "LIFT" (optionally followed by a
|
|
1222
|
+
// tier number, e.g. "LIFT 2"). Defaults to the first tier.
|
|
1223
|
+
let paymentMethod = 'bch';
|
|
1224
|
+
if (timeCmd === 'lift' || (timeCmd && /^lift[\s]+\\d+$/.test(timeCmd))) {
|
|
1225
|
+
paymentMethod = 'lift';
|
|
1226
|
+
}
|
|
1227
|
+
let liftTierIndex = -1;
|
|
1228
|
+
if (timeCmd && /^lift[\s]+\\d+$/.test(timeCmd)) {
|
|
1229
|
+
const liftNum = parseInt(timeCmd.split(/\\s+/)[1], 10);
|
|
1230
|
+
if (!isNaN(liftNum) && liftNum >= 1 && liftNum <= pendingPayload.tiers.length) {
|
|
1231
|
+
liftTierIndex = liftNum - 1;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1170
1235
|
let selectedIndex = -1;
|
|
1171
1236
|
|
|
1172
|
-
//
|
|
1173
|
-
|
|
1174
|
-
if (
|
|
1175
|
-
selectedIndex =
|
|
1237
|
+
// "LIFT" alone selects the first (cheapest) tier paid with LIFT;
|
|
1238
|
+
// "LIFT N" selects tier N.
|
|
1239
|
+
if (paymentMethod === 'lift' && liftTierIndex >= 0) {
|
|
1240
|
+
selectedIndex = liftTierIndex;
|
|
1241
|
+
} else if (paymentMethod === 'lift') {
|
|
1242
|
+
selectedIndex = 0;
|
|
1176
1243
|
} else {
|
|
1177
|
-
// Try to
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1244
|
+
// Try to parse user input as a number (1-based)
|
|
1245
|
+
const num = parseInt(userInput, 10);
|
|
1246
|
+
if (!isNaN(num) && num >= 1 && num <= pendingPayload.tiers.length) {
|
|
1247
|
+
selectedIndex = num - 1;
|
|
1248
|
+
} else {
|
|
1249
|
+
// Try to match by duration minutes
|
|
1250
|
+
for (let i = 0; i < pendingPayload.tiers.length; i++) {
|
|
1251
|
+
if (userInput === String(pendingPayload.tiers[i].minutes) ||
|
|
1252
|
+
userInput === pendingPayload.tiers[i].minutes + ' minutes' ||
|
|
1253
|
+
userInput === pendingPayload.tiers[i].minutes + ' min') {
|
|
1254
|
+
selectedIndex = i;
|
|
1255
|
+
break;
|
|
1256
|
+
}
|
|
1184
1257
|
}
|
|
1185
1258
|
}
|
|
1186
1259
|
}
|
|
@@ -1188,9 +1261,10 @@ const server = http.createServer(async (req, res) => {
|
|
|
1188
1261
|
if (selectedIndex >= 0) {
|
|
1189
1262
|
const selectedTier = pendingPayload.tiers[selectedIndex];
|
|
1190
1263
|
pendingPayload.durationMinutes = selectedTier.minutes;
|
|
1264
|
+
pendingPayload.paymentMethod = paymentMethod;
|
|
1191
1265
|
pendingPayload.step = 'processing';
|
|
1192
1266
|
|
|
1193
|
-
log('Tier selected: ' + selectedTier.minutes + ' min for wallet ' + walletHash?.substring(0, 16) + '...');
|
|
1267
|
+
log('Tier selected: ' + selectedTier.minutes + ' min (' + paymentMethod + ') for wallet ' + walletHash?.substring(0, 16) + '...');
|
|
1194
1268
|
|
|
1195
1269
|
// Build extra headers for payment wrapper
|
|
1196
1270
|
const extraHeaders = {};
|
|
@@ -1198,28 +1272,56 @@ const server = http.createServer(async (req, res) => {
|
|
|
1198
1272
|
extraHeaders['X-Model-Id'] = pendingPayload.modelId;
|
|
1199
1273
|
}
|
|
1200
1274
|
extraHeaders['X-Duration-Minutes'] = String(selectedTier.minutes);
|
|
1275
|
+
if (paymentMethod === 'lift') {
|
|
1276
|
+
extraHeaders['X-Payment-Method'] = 'lift';
|
|
1277
|
+
}
|
|
1201
1278
|
|
|
1202
|
-
// Check wallet balance before attempting payment
|
|
1203
|
-
|
|
1204
|
-
if (
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1279
|
+
// Check wallet balance before attempting payment ā only for BCH.
|
|
1280
|
+
// The LIFT path sells tokens, so no BCH balance is required.
|
|
1281
|
+
if (paymentMethod !== 'lift') {
|
|
1282
|
+
const currentBalanceSats = await getWalletBalance();
|
|
1283
|
+
if (currentBalanceSats !== null && selectedTier.price_sats && currentBalanceSats < selectedTier.price_sats) {
|
|
1284
|
+
log('Insufficient balance for wallet ' + walletHash?.substring(0, 16) + '...: ' + currentBalanceSats + ' sats < ' + selectedTier.price_sats + ' sats needed');
|
|
1285
|
+
pendingPayments.delete(walletHash);
|
|
1286
|
+
const addr = await getReceivingAddress();
|
|
1287
|
+
const neededBch = (selectedTier.price_sats - currentBalanceSats) / 100000000;
|
|
1288
|
+
const neededLine = addr ? '\\n\\nš„ **Fund your wallet:** \\\`' + addr + '\\\`\\nOr run: paytaca receive (in another terminal) for QR code' : '';
|
|
1289
|
+
sseLine(res, {
|
|
1290
|
+
id: 'balance-err',
|
|
1291
|
+
object: 'chat.completion.chunk',
|
|
1292
|
+
choices: [{ index: 0, delta: { content: PROXY_MARKER + '\\n\\nā **Insufficient balance** ā You have **' + (currentBalanceSats / 100000000).toFixed(8) + ' BCH** but need **' + (selectedTier.price_sats / 100000000).toFixed(8) + ' BCH** for this plan. Top up at least **' + neededBch.toFixed(8) + ' BCH** more.' + neededLine + '\\n\\nType \\\`balance\\\` to re-check or try a different plan:' }, finish_reason: 'stop' }],
|
|
1293
|
+
});
|
|
1294
|
+
sseLine(res, {
|
|
1295
|
+
id: 'balance-err-done',
|
|
1296
|
+
object: 'chat.completion.chunk',
|
|
1297
|
+
choices: [{ index: 0, delta: {}, finish_reason: 'stop' }],
|
|
1298
|
+
});
|
|
1299
|
+
sseDone(res);
|
|
1300
|
+
res.end();
|
|
1301
|
+
return;
|
|
1302
|
+
}
|
|
1303
|
+
} else {
|
|
1304
|
+
// LIFT path: fail fast if the wallet holds no LIFT tokens.
|
|
1305
|
+
const liftBalanceUnits = await getLiftBalance();
|
|
1306
|
+
if (liftBalanceUnits !== null && liftBalanceUnits <= 0) {
|
|
1307
|
+
log('No LIFT tokens for wallet ' + walletHash?.substring(0, 16) + '...');
|
|
1308
|
+
pendingPayments.delete(walletHash);
|
|
1309
|
+
const addr = await getReceivingAddress();
|
|
1310
|
+
const fundLine = addr ? '\\n\\nš„ **Add LIFT to your wallet:** \\\`' + addr + '\\\` (send LIFT tokens) or buy LIFT on the Cauldron DEX' : '';
|
|
1311
|
+
sseLine(res, {
|
|
1312
|
+
id: 'lift-err',
|
|
1313
|
+
object: 'chat.completion.chunk',
|
|
1314
|
+
choices: [{ index: 0, delta: { content: PROXY_MARKER + '\\n\\nā **No LIFT tokens** ā you need LIFT to pay with tokens. Add LIFT to your wallet, then type a plan number above or \\\`LIFT\\\` again.' + fundLine + '\\n\\nType \\\`balance\\\` to re-check:' }, finish_reason: 'stop' }],
|
|
1315
|
+
});
|
|
1316
|
+
sseLine(res, {
|
|
1317
|
+
id: 'lift-err-done',
|
|
1318
|
+
object: 'chat.completion.chunk',
|
|
1319
|
+
choices: [{ index: 0, delta: {}, finish_reason: 'stop' }],
|
|
1320
|
+
});
|
|
1321
|
+
sseDone(res);
|
|
1322
|
+
res.end();
|
|
1323
|
+
return;
|
|
1324
|
+
}
|
|
1223
1325
|
}
|
|
1224
1326
|
|
|
1225
1327
|
// Keepalive during payment processing
|
|
@@ -1236,7 +1338,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
1236
1338
|
res.write(': keepalive\\n\\n');
|
|
1237
1339
|
}, 2000);
|
|
1238
1340
|
|
|
1239
|
-
runPaytacaPay(BACKEND_URL + '/v1', pendingPayload.body, walletHash, extraHeaders, async (err, responseJson) => {
|
|
1341
|
+
runPaytacaPay(BACKEND_URL + '/v1', pendingPayload.body, walletHash, extraHeaders, pendingPayload.paymentMethod || 'bch', async (err, responseJson) => {
|
|
1240
1342
|
pendingPayments.delete(walletHash);
|
|
1241
1343
|
clearInterval(keepalive);
|
|
1242
1344
|
|
|
@@ -1299,7 +1401,18 @@ const server = http.createServer(async (req, res) => {
|
|
|
1299
1401
|
|
|
1300
1402
|
if (wasStreaming) {
|
|
1301
1403
|
try {
|
|
1302
|
-
|
|
1404
|
+
let prepend = '\\nš³ Payment successful ā generating your response...\\n\\n';
|
|
1405
|
+
if (pendingPayload.paymentMethod === 'lift') {
|
|
1406
|
+
const liftPercent = await getLiftDiscountPercent();
|
|
1407
|
+
const selectedTier = (pendingPayload.tiers || []).find((t) => t.minutes === pendingPayload.durationMinutes);
|
|
1408
|
+
if (liftPercent > 0 && selectedTier && selectedTier.price_sats) {
|
|
1409
|
+
const savedBch = (selectedTier.price_sats * (liftPercent / 100) / 100000000).toFixed(8);
|
|
1410
|
+
prepend = '\\nš³ Payment successful ā paid with LIFT (**' + liftPercent + '% off**, saved **' + savedBch + ' BCH**). Generating your response...\\n\\n';
|
|
1411
|
+
} else {
|
|
1412
|
+
prepend = '\\nš³ Payment successful ā paid with LIFT tokens. Generating your response...\\n\\n';
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
jsonToSse(res, chatCompletion, { prependContent: prepend });
|
|
1303
1416
|
} catch (e) { log('jsonToSse threw: ' + e.message); }
|
|
1304
1417
|
} else {
|
|
1305
1418
|
try {
|
|
@@ -1345,7 +1458,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
1345
1458
|
res.write(': keepalive\\n\\n');
|
|
1346
1459
|
}, 2000);
|
|
1347
1460
|
|
|
1348
|
-
runPaytacaPay(BACKEND_URL + '/v1', pendingPayload.body, walletHash, extraHeaders, (err, responseJson) => {
|
|
1461
|
+
runPaytacaPay(BACKEND_URL + '/v1', pendingPayload.body, walletHash, extraHeaders, 'bch', (err, responseJson) => {
|
|
1349
1462
|
clearInterval(keepalive);
|
|
1350
1463
|
if (err) {
|
|
1351
1464
|
log('paytaca pay failed: ' + err.message);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/bundled/proxy.ts"],"names":[],"mappings":";AAAA,0DAA0D;AAC1D,6DAA6D;;;AAEhD,QAAA,oBAAoB,GAAG
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/bundled/proxy.ts"],"names":[],"mappings":";AAAA,0DAA0D;AAC1D,6DAA6D;;;AAEhD,QAAA,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAquDnC,CAAC"}
|
|
@@ -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 } 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 // 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,6lbAwUlC,CAAC"}
|
package/dist/bundled/wrapper.js
CHANGED
|
@@ -228,6 +228,13 @@ async function payWithLift(bchWallet, hdWallet, requirements, changeAddress) {
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
async function executePay(url, method, headers, body, bchWallet, hdWallet, x402Payer, isChipnet, confirmed, paymentMethod) {
|
|
231
|
+
// Tell the backend the payment method so it can apply the LIFT discount and
|
|
232
|
+
// record how the plan was paid. Set once here ā the same headers object is
|
|
233
|
+
// reused for the 402 fetch and the PAYMENT-SIGNATURE retry.
|
|
234
|
+
if (paymentMethod === 'lift') {
|
|
235
|
+
headers['X-Payment-Method'] = 'lift';
|
|
236
|
+
}
|
|
237
|
+
|
|
231
238
|
const response = await fetch(url, {
|
|
232
239
|
method,
|
|
233
240
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwUrC,CAAC"}
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,8CA4CC;AAED,0CAYC;AAuCD,8CAOC;AAED,4CAOC;AAED,wCAiBC;AAED,gCAiHC;AAqBD,wCAUC;AAxSD,uCAAyB;AACzB,2CAA6B;AAC7B,+CAAiC;AACjC,iDAAgD;AAEhD,qCASkB;AAClB,2CAAuD;AACvD,+CAA2D;AAE3D,SAAgB,iBAAiB;IAC/B,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;QAClE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;IACnF,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAA,wBAAQ,EAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxE,MAAM,YAAY,GAAG;YACnB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,CAAC;YACzD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,iBAAiB,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,CAAC;SACzG,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;YAC7B,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrB,OAAO,CAAC,CAAC;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,MAAM,WAAW,GAAG;QAClB,kDAAkD;QAClD,wDAAwD;QACxD,2DAA2D;KAC5D,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/D,MAAM,MAAM,GAAG,IAAA,wBAAQ,EAAC,GAAG,KAAK,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACxF,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,OAAO,SAAS,CAAC;AACnB,CAAC;AAEM,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,YAAY,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACxB,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,UAAkB,KAAK;IAClE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,OAAO,EAAE,CAAC;QACpC,IAAI,MAAM,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,4BAAoB,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,gBAAgB,CAAC,SAAiB,EAAE,MAAc,EAAE,IAAY,EAAE,GAAW,EAAE,WAAmB;IACzG,EAAE,CAAC,aAAa,CAAC,IAAA,mBAAU,EAAC,SAAS,CAAC,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxD,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC;IACtB,MAAM,CAAC,eAAe,GAAG,WAAW,CAAC;IACrC,IAAA,mBAAU,EAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,SAAiB,EAAE,MAAc,EAAE,MAAqC,EAAE,WAAmB;IAC7H,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;AAChD,CAAC;AAED,KAAK,UAAU,0BAA0B,CAAC,SAAiB,EAAE,MAAc,EAAE,WAAmB;IAC9F,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,GAAG,CAAC;QAC7D,IAAA,mBAAU,EAAC,SAAS,CAAC,CAAC,eAAe,KAAK,WAAW,EAAE,CAAC;QAC1D,OAAO,MAAM,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;IAC1G,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAEM,KAAK,UAAU,iBAAiB,CAAC,YAAoB,IAAI,EAAE,UAAkB,IAAI;IACtF,KAAK,IAAI,IAAI,GAAG,SAAS,EAAE,IAAI,IAAI,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QACnD,IAAI,MAAM,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,+BAA+B,SAAS,IAAI,OAAO,EAAE,CAAC,CAAC;AACzE,CAAC;AAED,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,SAAiB;IACpD,MAAM,OAAO,GAAG,IAAA,mBAAU,EAAC,SAAS,CAAC,CAAC;IAEtC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9D,IAAI,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,IAAA,mBAAU,EAAC,SAAS,CAAC,CAAC;YACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC;QACxD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;IACT,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC;AAEM,KAAK,UAAU,UAAU,CAAC,SAAiB,EAAE,MAAc;IAChE,MAAM,WAAW,GAAG,IAAA,uBAAc,EAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAA,mBAAU,EAAC,SAAS,CAAC,CAAC;IACtC,MAAM,aAAa,GAAG,IAAA,yBAAgB,EAAC,SAAS,CAAC,CAAC;IAElD,IAAA,wBAAe,EAAC,SAAS,CAAC,CAAC;IAE3B,4EAA4E;IAC5E,8EAA8E;IAC9E,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,gCAAsB,EAAE,MAAM,CAAC,CAAC;IAChE,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAEnC,MAAM,WAAW,GAAG,UAAU,EAAE,CAAC;IACjC,MAAM,eAAe,GAAG,IAAA,mBAAU,EAAC,SAAS,CAAC,CAAC;IAE9C,IAAI,cAAc,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;IAErD,MAAM,YAAY,GAAG,cAAc,CAAC,OAAO;QACzC,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC;QAC7B,eAAe,CAAC,eAAe,KAAK,WAAW,CAAC;IAElD,IAAI,cAAc,CAAC,OAAO,IAAI,cAAc,CAAC,GAAG,IAAI,cAAc,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACzF,OAAO,MAAM,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,cAAc,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;IAC1H,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,4BAAoB,EAAE,MAAM,CAAC,CAAC;IAC5D,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAEjC,IAAI,cAAc,CAAC,OAAO,IAAI,cAAc,CAAC,GAAG,EAAE,CAAC;QACjD,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC;YACxB,MAAM,eAAe,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IACjF,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC;IAEvC,MAAM,YAAY,GAAG,CAAC,CAAC;IACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC;QACzD,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,IAAA,qBAAK,EAAC,MAAM,EAAE;YAC1B,WAAW;YACX,MAAM,CAAC,UAAU;YACjB,IAAI,CAAC,QAAQ,EAAE;SAChB,EAAE;YACD,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;YACjC,GAAG,EAAE;gBACH,GAAG,OAAO,CAAC,GAAG;gBACd,WAAW,EAAE,UAAU;aACxB;SACF,CAAC,CAAC;QAEH,KAAK,CAAC,KAAK,EAAE,CAAC;QAEd,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACf,SAAS;QACX,CAAC;QAED,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAElD,MAAM,SAAS,GAAG,EAAE,CAAC,iBAAiB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAChE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9B,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAE9B,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAE9C,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,MAAM,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YAC3E,IAAI,CAAC,EAAE,CAAC;gBACN,OAAO,CAAC,CAAC;YACX,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,CAAC,GAAG,MAAM,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;gBAC3E,IAAI,CAAC,EAAE,CAAC;oBACN,OAAO,CAAC,CAAC;gBACX,CAAC;gBACD,SAAS;YACX,CAAC;YACD,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;YAClE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;QAClC,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/C,IAAI,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;YAC3B,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;YAClE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;QAClC,CAAC;QACD,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,MAAM,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YAC3E,IAAI,CAAC,EAAE,CAAC;gBACN,OAAO,CAAC,CAAC;YACX,CAAC;QACH,CAAC;QACD,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,0CAA0C,YAAY,WAAW,CAAC,CAAC;IACjF,MAAM,IAAI,KAAK,CAAC,gCAAgC,YAAY,WAAW,CAAC,CAAC;AAC3E,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,UAAkB,KAAK;IAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,OAAO,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,oBAAoB,IAAI,YAAY,EAAE;gBACjE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;aAClC,CAAC,CAAC;YACH,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;QACT,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,SAAiB;IACpD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,IAAA,mBAAU,EAAC,SAAS,CAAC,CAAC;QACrC,OAAO;YACL,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED