@dvmkit/sdk 0.1.5-rc.9 → 0.2.1-rc.9
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 +14 -0
- package/dist/{chunk-MLRCSJYX.js → chunk-2D75MNNG.js} +178 -550
- package/dist/{chunk-BIFLRKMO.js → chunk-2KGG5ORW.js} +1 -1
- package/dist/{chunk-27V2ILSR.js → chunk-4A2RAKCW.js} +2 -2
- package/dist/{chunk-5URG56JJ.js → chunk-A4CM2BD3.js} +18 -2
- package/dist/{chunk-L4OYF4DQ.js → chunk-AJNFXR7J.js} +2 -2
- package/dist/{chunk-S3XAHZQY.js → chunk-COYKJRMM.js} +24 -3
- package/dist/{chunk-UP2F5RRT.js → chunk-D7YQYLLM.js} +1 -4
- package/dist/{chunk-CEOAHV2I.js → chunk-FDKRXOZO.js} +0 -5
- package/dist/{chunk-TQWGQCNV.js → chunk-FPOLJRBF.js} +5 -5
- package/dist/{chunk-BTZY7VPH.js → chunk-GAIPXGM3.js} +1 -1
- package/dist/{chunk-SSSZUVWM.js → chunk-JAHRF5X3.js} +89 -39
- package/dist/{chunk-5PBOA25N.js → chunk-JNKQZVZX.js} +472 -617
- package/dist/{chunk-U6M3ATSG.js → chunk-MD3H3BF7.js} +40 -6
- package/dist/{chunk-CGKZDODG.js → chunk-MG67KXU7.js} +0 -5
- package/dist/{chunk-KSQEFVFJ.js → chunk-MMCE7XSR.js} +1 -1
- package/dist/{chunk-JZWELPFH.js → chunk-N5B66UOS.js} +4 -16
- package/dist/{chunk-BIP6G74V.js → chunk-O6D72KYA.js} +10 -10
- package/dist/{chunk-KXCKFIJI.js → chunk-QX52F6IB.js} +1 -1
- package/dist/{chunk-RW5LP57K.js → chunk-SDK6KDJN.js} +0 -1
- package/dist/{chunk-KVEHHC7W.js → chunk-U5VNEALI.js} +24 -13
- package/dist/{chunk-FROTD5XQ.js → chunk-V5ZRATJH.js} +2 -3
- package/dist/{chunk-EVBK675R.js → chunk-VA7GT6C6.js} +31 -37
- package/dist/{chunk-2UUXIIOC.js → chunk-VIVXB4CD.js} +3 -3
- package/dist/{chunk-6BQM7TOW.js → chunk-XMDQOXHO.js} +11 -38
- package/dist/{chunk-DMNLFNTW.js → chunk-XRLKGCAW.js} +2 -2
- package/dist/{chunk-M7LHFJ5K.js → chunk-XZ7LW4S5.js} +2 -3
- package/dist/{chunk-E4EVGPDX.js → chunk-YO56VCTQ.js} +0 -6
- package/dist/{credit-ledger-2DFQHNLB.js → credit-ledger-MHA652TV.js} +2 -2
- package/dist/{credit-menu-enwMbn55.d.ts → credit-menu-kDA9RVzD.d.ts} +524 -1077
- package/dist/{fx-D860pZvP.d.ts → fx-DhyT1Cjh.d.ts} +38 -82
- package/dist/index.d.ts +11 -26
- package/dist/index.js +2 -2
- package/dist/internal/caller.d.ts +644 -2140
- package/dist/internal/caller.js +32 -66
- package/dist/internal/server.d.ts +40 -90
- package/dist/internal/server.js +16 -16
- package/dist/{job-store-BUGqvCfL.d.ts → job-store-D3CcZp_g.d.ts} +73 -66
- package/dist/{lightning-backend-BozcevPZ.d.ts → lightning-backend-BhsyrBLa.d.ts} +19 -41
- package/dist/{memory-credit-ledger-MNUOTQO5.js → memory-credit-ledger-BYBATRN3.js} +3 -3
- package/dist/{mpp-secret-state-WNAQQ6K4.js → mpp-secret-state-B5GCILVH.js} +1 -1
- package/dist/{mpp-setup-4FJD6ZHV.js → mpp-setup-MPP3ST5X.js} +1 -1
- package/dist/{payout-reporter-RG6XNGPI.js → payout-reporter-KEMUXEUO.js} +2 -2
- package/dist/{postgres-consumed-credential-store-VHBT4KEA.js → postgres-consumed-credential-store-6N2V5MJN.js} +2 -2
- package/dist/postgres-job-store-MZZZMS2B.js +7 -0
- package/dist/postgres-kv-store-DXGTKXLU.js +7 -0
- package/dist/{postgres-replay-store-UJXRT6VO.js → postgres-replay-store-ZF4JNZOW.js} +2 -2
- package/dist/{pricing-4CEB34RM.js → pricing-MU5GNUJZ.js} +1 -1
- package/dist/{processed-payment-store-HAA4SFNK.js → processed-payment-store-GKMAWOM3.js} +2 -2
- package/dist/revenue-reporter-O75BGYFK.js +7 -0
- package/dist/server/index.d.ts +47 -159
- package/dist/server/index.js +67 -138
- package/dist/{ssrf-DbFkpDv0.d.ts → ssrf-dMooihtY.d.ts} +1 -2
- package/dist/{step-cache-5dljDqrQ.d.ts → step-cache-v2yhyhSZ.d.ts} +617 -1532
- package/dist/{tempo-charge-store-RIFTALZK.js → tempo-charge-store-SDTUNTKA.js} +2 -2
- package/dist/{tempo-lifecycle-DFIXQ54Q.js → tempo-lifecycle-G5SB4HFC.js} +5 -5
- package/dist/{tempo-session-store-2JNOKJGX.js → tempo-session-store-WF3VZXNF.js} +2 -2
- package/dist/{tempo-wallet-4QKSV65O.js → tempo-wallet-ZFNUDFVO.js} +2 -2
- package/dist/testing/index.d.ts +5 -15
- package/dist/testing/index.js +4 -11
- package/dist/{usd-DoRuAckA.d.ts → usd-Cu9G6xv2.d.ts} +14 -16
- package/dist/{wallet-CJC8lwxx.d.ts → wallet-Dwjs5n_M.d.ts} +1 -1
- package/dist/{x402-5H27DCBE.js → x402-CI6PSHNO.js} +5 -5
- package/package.json +3 -2
- package/dist/postgres-job-store-3RAXMNSY.js +0 -7
- package/dist/postgres-kv-store-JFBDP5IP.js +0 -7
- package/dist/revenue-reporter-ASZ7SHHH.js +0 -7
package/dist/internal/caller.js
CHANGED
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
withIdentitiesLock,
|
|
56
56
|
withTempoChannelLock,
|
|
57
57
|
withholdsTempoCreditSession
|
|
58
|
-
} from "../chunk-
|
|
58
|
+
} from "../chunk-FPOLJRBF.js";
|
|
59
59
|
import {
|
|
60
60
|
TEMPO_CHAIN_ID,
|
|
61
61
|
TEMPO_MODERATO_CHAIN_ID,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
tempoTokenReference,
|
|
72
72
|
tempoWrongAssetHint,
|
|
73
73
|
tryResolveTempoAsset
|
|
74
|
-
} from "../chunk-
|
|
74
|
+
} from "../chunk-VIVXB4CD.js";
|
|
75
75
|
import {
|
|
76
76
|
DvmX402ChannelStorage,
|
|
77
77
|
X402_EXACT_AUTHORIZATION_TTL_SECONDS,
|
|
@@ -116,7 +116,7 @@ import {
|
|
|
116
116
|
x402PendingStale,
|
|
117
117
|
x402PendingUnsettled,
|
|
118
118
|
x402WrongAssetHint
|
|
119
|
-
} from "../chunk-
|
|
119
|
+
} from "../chunk-O6D72KYA.js";
|
|
120
120
|
import {
|
|
121
121
|
RAIL_FLAGS,
|
|
122
122
|
SUPPORTED_PROTOCOL_VERSION,
|
|
@@ -163,7 +163,7 @@ import {
|
|
|
163
163
|
setOutputTraceId,
|
|
164
164
|
settleDrainEvidence,
|
|
165
165
|
withinAdvertisedTolerance
|
|
166
|
-
} from "../chunk-
|
|
166
|
+
} from "../chunk-MMCE7XSR.js";
|
|
167
167
|
import {
|
|
168
168
|
CREDIT_POSTURES,
|
|
169
169
|
FEEDBACK_POSTURES,
|
|
@@ -181,10 +181,10 @@ import {
|
|
|
181
181
|
retireConfigBackup,
|
|
182
182
|
rollbackConfig,
|
|
183
183
|
updateConfig
|
|
184
|
-
} from "../chunk-
|
|
184
|
+
} from "../chunk-MG67KXU7.js";
|
|
185
185
|
import {
|
|
186
186
|
CAPABILITY_NAME_RE
|
|
187
|
-
} from "../chunk-
|
|
187
|
+
} from "../chunk-GAIPXGM3.js";
|
|
188
188
|
import {
|
|
189
189
|
DbTransport,
|
|
190
190
|
NwcBackend,
|
|
@@ -209,10 +209,10 @@ import {
|
|
|
209
209
|
sha256hex,
|
|
210
210
|
validateX402Env,
|
|
211
211
|
withNwcPool
|
|
212
|
-
} from "../chunk-
|
|
212
|
+
} from "../chunk-FDKRXOZO.js";
|
|
213
213
|
import {
|
|
214
214
|
MemoryKVStore
|
|
215
|
-
} from "../chunk-
|
|
215
|
+
} from "../chunk-SDK6KDJN.js";
|
|
216
216
|
import {
|
|
217
217
|
ADMIN_STATE_UNAVAILABLE,
|
|
218
218
|
DEFAULT_AGENT_MINT_URL,
|
|
@@ -289,7 +289,7 @@ import {
|
|
|
289
289
|
withWalletLock,
|
|
290
290
|
writeAgentMnemonic,
|
|
291
291
|
writeIdentity
|
|
292
|
-
} from "../chunk-
|
|
292
|
+
} from "../chunk-QX52F6IB.js";
|
|
293
293
|
import {
|
|
294
294
|
X402_BATCH_SETTLEMENT_SCHEME,
|
|
295
295
|
X402_DEFAULT_FACILITATOR,
|
|
@@ -343,7 +343,7 @@ import {
|
|
|
343
343
|
parseBudget,
|
|
344
344
|
usdToMsats,
|
|
345
345
|
usdcToMsats
|
|
346
|
-
} from "../chunk-
|
|
346
|
+
} from "../chunk-A4CM2BD3.js";
|
|
347
347
|
import {
|
|
348
348
|
AGENT_MNEMONIC_FILE,
|
|
349
349
|
BTC_RATE_FILE,
|
|
@@ -398,7 +398,7 @@ import {
|
|
|
398
398
|
randomTraceId,
|
|
399
399
|
setEmitter,
|
|
400
400
|
withTraceContext
|
|
401
|
-
} from "../chunk-
|
|
401
|
+
} from "../chunk-YO56VCTQ.js";
|
|
402
402
|
import "../chunk-66HGCPBU.js";
|
|
403
403
|
import {
|
|
404
404
|
redactUrl,
|
|
@@ -408,7 +408,7 @@ import {
|
|
|
408
408
|
FX_CACHE_TTL_MS,
|
|
409
409
|
FX_RETRY_COUNT,
|
|
410
410
|
warmFxSnapshot
|
|
411
|
-
} from "../chunk-
|
|
411
|
+
} from "../chunk-4A2RAKCW.js";
|
|
412
412
|
import {
|
|
413
413
|
InvalidUsdPriceError,
|
|
414
414
|
parseUsdPrice
|
|
@@ -503,7 +503,7 @@ async function enforceGlobalBudget(opts) {
|
|
|
503
503
|
window: check.window,
|
|
504
504
|
spent: {
|
|
505
505
|
display: `$${formatUsd(check.spentUsd)}`,
|
|
506
|
-
//
|
|
506
|
+
// the cap counts both what the agent paid DVMs and what it
|
|
507
507
|
// moved out of the Lightning float, so name the split rather than
|
|
508
508
|
// leaving the user to wonder why the number is higher than their jobs.
|
|
509
509
|
jobs: `$${formatUsd(check.breakdown.jobsUsd)}`,
|
|
@@ -1154,11 +1154,6 @@ function toFloatError(err) {
|
|
|
1154
1154
|
next_step: "Add funds to the wallet, or ask for a smaller amount."
|
|
1155
1155
|
}
|
|
1156
1156
|
);
|
|
1157
|
-
// NIP-47 draws a line here that the remedy depends on entirely (internal-review).
|
|
1158
|
-
// `UNAUTHORIZED` is the wallet saying it has never heard of this
|
|
1159
|
-
// connection; `RESTRICTED` is the wallet saying it knows the connection
|
|
1160
|
-
// perfectly well and will not let it do *this*. Recreating the connection
|
|
1161
|
-
// fixes the first and reproduces the second, verbatim, forever.
|
|
1162
1157
|
case "UNAUTHORIZED":
|
|
1163
1158
|
return new DvmError(
|
|
1164
1159
|
"float_unauthorized",
|
|
@@ -1189,11 +1184,6 @@ function toFloatError(err) {
|
|
|
1189
1184
|
next_step: "Switch to a wallet that can pay invoices over a connection, such as Alby Hub."
|
|
1190
1185
|
}
|
|
1191
1186
|
);
|
|
1192
|
-
// The wallet's own reason is the payload here (internal-review): a routing-floor
|
|
1193
|
-
// failure and a transient liquidity blip look identical without it, and
|
|
1194
|
-
// the drill lost two round trips to an unconditional "retry" hint that a
|
|
1195
|
-
// floor failure can never satisfy. Surface the reason and let the caller
|
|
1196
|
-
// that knows an advertised floor (credit-fund.ts) sharpen the hint.
|
|
1197
1187
|
case "PAYMENT_FAILED":
|
|
1198
1188
|
return new DvmError(
|
|
1199
1189
|
"float_payment_failed",
|
|
@@ -4291,7 +4281,7 @@ async function prepareAgentSpend(args) {
|
|
|
4291
4281
|
swapping: void 0,
|
|
4292
4282
|
cashu_token: cashuToken,
|
|
4293
4283
|
...boundContext ? { context: boundContext } : {},
|
|
4294
|
-
// What a later reclaim needs
|
|
4284
|
+
// What a later reclaim needs. Only the swap path
|
|
4295
4285
|
// writes these: reserve-direct entries ship proofs that still
|
|
4296
4286
|
// live in `wallet.proofs[]`, and `release` / the in-flight
|
|
4297
4287
|
// revert already own their recovery.
|
|
@@ -4968,7 +4958,7 @@ async function shipEntry(entry, httpPost) {
|
|
|
4968
4958
|
}
|
|
4969
4959
|
return { kind: "still_pending", entry, reason: errCode };
|
|
4970
4960
|
}
|
|
4971
|
-
if (errCode === "wrong_lock_pubkey" || errCode === "not_p2pk_locked" || errCode === "payment_invalid" || errCode === "proof_not_unspent" || // Credit-route permanent refusals
|
|
4961
|
+
if (errCode === "wrong_lock_pubkey" || errCode === "not_p2pk_locked" || errCode === "payment_invalid" || errCode === "proof_not_unspent" || // Credit-route permanent refusals: the fund can never land
|
|
4972
4962
|
// under this signed body.
|
|
4973
4963
|
errCode === "credit_id_unavailable" || errCode === "caller_mismatch" || errCode === "credit_not_supported") {
|
|
4974
4964
|
return { kind: "abandoned", entry, reason: errCode };
|
|
@@ -5152,7 +5142,7 @@ function jobRecordFromEntry(entry, jobId, body, feedbackClaim) {
|
|
|
5152
5142
|
...ctx?.policy ? { policy: ctx.policy } : {},
|
|
5153
5143
|
...ctx?.strict_per_call ? { strictPerCall: true } : {},
|
|
5154
5144
|
...ctx?.max_cashu_fee_sats !== void 0 ? { maxCashuFeeSats: ctx.max_cashu_fee_sats } : {},
|
|
5155
|
-
//
|
|
5145
|
+
// the per-job token an anonymous caller needs on every later read.
|
|
5156
5146
|
...typeof body?.job_token === "string" ? { jobToken: body.job_token } : {}
|
|
5157
5147
|
};
|
|
5158
5148
|
}
|
|
@@ -5309,7 +5299,7 @@ async function releaseAgentReserve(opts) {
|
|
|
5309
5299
|
throw new DvmError(
|
|
5310
5300
|
"missing_canonical_id",
|
|
5311
5301
|
"DVM advertises no `cashu.canonical_id` on /v1/info.",
|
|
5312
|
-
"Release needs canonical_id so the agent can derive the matching per-DVM refund subkey. Upgrade the builder SDK
|
|
5302
|
+
"Release needs canonical_id so the agent can derive the matching per-DVM refund subkey. Upgrade the builder SDK."
|
|
5313
5303
|
);
|
|
5314
5304
|
}
|
|
5315
5305
|
const outputMode = opts.outputMode ?? "locked";
|
|
@@ -5475,7 +5465,7 @@ async function reserveAgentWallet(amountSats, opts) {
|
|
|
5475
5465
|
throw new DvmError(
|
|
5476
5466
|
"missing_cashu_info",
|
|
5477
5467
|
"DVM does not advertise a `cashu` object on /v1/info.",
|
|
5478
|
-
"Reserve requires the builder to expose lock_pubkeys, mints, and canonical_id. Check the builder is running an SDK that supports pre-fund
|
|
5468
|
+
"Reserve requires the builder to expose lock_pubkeys, mints, and canonical_id. Check the builder is running an SDK that supports pre-fund."
|
|
5479
5469
|
);
|
|
5480
5470
|
}
|
|
5481
5471
|
const lockPubkey = cashu.lock_pubkeys[0];
|
|
@@ -5497,7 +5487,7 @@ async function reserveAgentWallet(amountSats, opts) {
|
|
|
5497
5487
|
throw new DvmError(
|
|
5498
5488
|
"missing_canonical_id",
|
|
5499
5489
|
"DVM advertises no `cashu.canonical_id` on /v1/info.",
|
|
5500
|
-
"Pre-fund requires canonical_id so the agent can derive a per-DVM refund subkey. Upgrade the builder SDK to one that advertises it
|
|
5490
|
+
"Pre-fund requires canonical_id so the agent can derive a per-DVM refund subkey. Upgrade the builder SDK to one that advertises it."
|
|
5501
5491
|
);
|
|
5502
5492
|
}
|
|
5503
5493
|
if (!cashu.mints.includes(opts.mintUrl)) {
|
|
@@ -6154,7 +6144,7 @@ async function refundX402BatchChannelLocked(args) {
|
|
|
6154
6144
|
// own `balance <= charged` guard lets the request out. How much comes
|
|
6155
6145
|
// back is the DVM's to decide: it settles against a base derived from
|
|
6156
6146
|
// the credit it owes, and corrects this one over a 402 when they differ
|
|
6157
|
-
//
|
|
6147
|
+
// Deliberately no `amount` below, for the same reason.
|
|
6158
6148
|
//
|
|
6159
6149
|
// The exposure above deliberately does *not* raise this seed. The
|
|
6160
6150
|
// voucher signed here is fresh claim authority handed to the DVM, and
|
|
@@ -6328,9 +6318,7 @@ function createScheme(wallet, depositMicro, network = wallet.network, recordedSa
|
|
|
6328
6318
|
const scheme = new BatchSettlementEvmScheme(signer, {
|
|
6329
6319
|
storage,
|
|
6330
6320
|
salt,
|
|
6331
|
-
//
|
|
6332
|
-
// policy amount gives the channel exactly that runway, never upstream's
|
|
6333
|
-
// generic 5x request multiplier.
|
|
6321
|
+
// Use at least the policy amount and upstream minimum, rather than its 5x default.
|
|
6334
6322
|
depositStrategy: ({ minimumDepositAmount }) => (BigInt(minimumDepositAmount) > BigInt(depositMicro) ? BigInt(minimumDepositAmount) : BigInt(depositMicro)).toString(),
|
|
6335
6323
|
...url ? { rpcUrl: url } : {}
|
|
6336
6324
|
});
|
|
@@ -7342,7 +7330,7 @@ async function fundOverX402(args, fundId, resumed, corrected = false, locked = f
|
|
|
7342
7330
|
channelId: payment.channelId,
|
|
7343
7331
|
requestedAt: Date.now(),
|
|
7344
7332
|
// What the signature covers, not what the funding asked for. The exit's
|
|
7345
|
-
// exposure report uses this, and the two figures differ
|
|
7333
|
+
// exposure report uses this, and the two figures differ.
|
|
7346
7334
|
maxClaimableMicro: payment.maxClaimableMicro,
|
|
7347
7335
|
...payment.depositMicro !== void 0 ? { depositMicro: payment.depositMicro } : {},
|
|
7348
7336
|
...payment.authorizationValidBefore !== void 0 ? { authorizationValidBefore: payment.authorizationValidBefore } : {}
|
|
@@ -7386,13 +7374,8 @@ async function fundOverX402(args, fundId, resumed, corrected = false, locked = f
|
|
|
7386
7374
|
base,
|
|
7387
7375
|
result,
|
|
7388
7376
|
void 0,
|
|
7389
|
-
//
|
|
7390
|
-
//
|
|
7391
|
-
// requirement's own `accepted.network`. Keyed by channel id, so it is the
|
|
7392
|
-
// chain *this* funding rode rather than the wallet's pin — which is what
|
|
7393
|
-
// makes it survive a resume that crosses an `x402-network` re-pin, and
|
|
7394
|
-
// what keeps a re-pinned wallet from re-stating the credit's chain as
|
|
7395
|
-
// wherever it points today.
|
|
7377
|
+
// Record the accepted channel's chain, rather than a wallet pin that may have changed
|
|
7378
|
+
// during a replay.
|
|
7396
7379
|
findX402Channel({ channelId: pending.channelId })?.network
|
|
7397
7380
|
);
|
|
7398
7381
|
recordSpendOnce({
|
|
@@ -7544,7 +7527,7 @@ function x402BindingRefusalCopy(err, creditId) {
|
|
|
7544
7527
|
return {
|
|
7545
7528
|
display: "This prepaid balance was opened by a one-off x402 payment, so x402's reusable channel can't top it up. Nothing was credited.",
|
|
7546
7529
|
// The flavour is not the caller's to pick, but it is no longer the live
|
|
7547
|
-
// menu's either:
|
|
7530
|
+
// menu's either: records the binding this refusal just named, so
|
|
7548
7531
|
// the next top-up of this credit signs a one-off payment rather than
|
|
7549
7532
|
// another channel deposit. That makes the retry the fix wherever this DVM
|
|
7550
7533
|
// still takes one — and where it doesn't, the answer is refused locally
|
|
@@ -7628,7 +7611,7 @@ async function fundOverCashu(args, fundId) {
|
|
|
7628
7611
|
cashuP2pk: {
|
|
7629
7612
|
mints: args.cashuMint ? [args.cashuMint] : [...cashu.mints],
|
|
7630
7613
|
lock_pubkey: lockPubkey,
|
|
7631
|
-
//
|
|
7614
|
+
// refund clause on the funding outputs too — a top-up the DVM
|
|
7632
7615
|
// never confirms is the same stranded capital a per-call spend would be.
|
|
7633
7616
|
canonical_id: cashu.canonical_id,
|
|
7634
7617
|
min_locktime: cashu.min_locktime
|
|
@@ -7852,7 +7835,7 @@ async function fundOverMppCharge(args, fundId, resumed, locked = false) {
|
|
|
7852
7835
|
privateKey: account.privateKey,
|
|
7853
7836
|
// This funding's own intent is the basis the ceiling is measured against:
|
|
7854
7837
|
// the DVM authors the figure that gets signed, and a challenge more than
|
|
7855
|
-
// the shared tolerance above the ask is refused unsigned
|
|
7838
|
+
// the shared tolerance above the ask is refused unsigned.
|
|
7856
7839
|
basisMicro: args.amountMicro,
|
|
7857
7840
|
onError: "throw"
|
|
7858
7841
|
});
|
|
@@ -8493,7 +8476,7 @@ async function fundOverLightning(args, fundId, resumed) {
|
|
|
8493
8476
|
// it wrote none, its message appended to ours. A wallet that said "no
|
|
8494
8477
|
// route to the destination" is telling the caller something a generic
|
|
8495
8478
|
// "didn't go through" throws away, and this is the one funding failure a
|
|
8496
|
-
// human has to act on themselves
|
|
8479
|
+
// human has to act on themselves.
|
|
8497
8480
|
display: typeof mapped?.data?.display === "string" ? mapped.data.display : `The Lightning payment for this credit didn't go through${mapped ? ` (${mapped.code})` : ""}. The credit was not funded.${mapped?.message ? ` ${mapped.message}` : ""}`,
|
|
8498
8481
|
hint: belowKnownFloor ? `This amount is below the $${formatUsd((args.menu?.lightning_min_micro ?? 0) / 1e6)} minimum this DVM sets for Lightning, so no retry can pay it. Refill the agent's ecash pocket with 'dvm wallet fund' and fund with ecash instead.` : mapped?.hint
|
|
8499
8482
|
};
|
|
@@ -8594,13 +8577,13 @@ function settled(args, base, result, spentSats, x402ChannelNetwork) {
|
|
|
8594
8577
|
targetMicro: args.targetMicro ?? result.credit.remaining_micro,
|
|
8595
8578
|
// The rail is a pin, not a preference: every later top-up of this credit
|
|
8596
8579
|
// has to arrive on it or the DVM refuses. Within x402 the instrument is
|
|
8597
|
-
// pinned the same way and for the same reason
|
|
8580
|
+
// pinned the same way and for the same reason.
|
|
8598
8581
|
rail: base.rail,
|
|
8599
8582
|
...base.x402Flavour ? { x402Instrument: x402InstrumentForFlavour(base.x402Flavour) } : {},
|
|
8600
8583
|
...x402ChannelNetwork ? { x402ChannelNetwork } : {},
|
|
8601
8584
|
...args.menu ? { menu: args.menu } : {},
|
|
8602
8585
|
// Identity, so the offline headroom view can match a `trustOverrides`
|
|
8603
|
-
// pre-grant without re-describing the DVM
|
|
8586
|
+
// pre-grant without re-describing the DVM.
|
|
8604
8587
|
...args.providerInfo?.builder?.pubkey ? { builderPubkey: args.providerInfo.builder.pubkey } : {},
|
|
8605
8588
|
sequenced: result.replayed !== true
|
|
8606
8589
|
});
|
|
@@ -9322,9 +9305,6 @@ async function probeLightning(timeoutMs) {
|
|
|
9322
9305
|
error: {
|
|
9323
9306
|
code: mapped.code,
|
|
9324
9307
|
message: mapped.message,
|
|
9325
|
-
// The same drop fixed one branch down: `float_invalid_uri` knows to say
|
|
9326
|
-
// "reconnect with a URI copied whole", and the row was rendering the
|
|
9327
|
-
// generic rail hint over the top of it (internal-review).
|
|
9328
9308
|
...mapped.hint ? { hint: mapped.hint } : {},
|
|
9329
9309
|
...refusalFields(mapped.data)
|
|
9330
9310
|
}
|
|
@@ -9363,10 +9343,6 @@ async function probeLightning(timeoutMs) {
|
|
|
9363
9343
|
error: {
|
|
9364
9344
|
code: probe.error?.code ?? "float_wallet_offline",
|
|
9365
9345
|
message: probe.error?.message ?? "The Lightning wallet did not respond.",
|
|
9366
|
-
// Lightning was the one rail dropping the probe's own diagnosis here,
|
|
9367
|
-
// so every float failure rendered as the generic "re-connect" remedy —
|
|
9368
|
-
// the wrong move for a connection the wallet refused on a permission
|
|
9369
|
-
// (internal-review). x402 and Tempo already forward theirs via `classifyError`.
|
|
9370
9346
|
...probe.error?.hint ? { hint: probe.error.hint } : {},
|
|
9371
9347
|
...refusalFields(probe.error?.data)
|
|
9372
9348
|
}
|
|
@@ -9376,7 +9352,6 @@ async function probeLightning(timeoutMs) {
|
|
|
9376
9352
|
rail: "lightning",
|
|
9377
9353
|
configured: true,
|
|
9378
9354
|
reachable: true,
|
|
9379
|
-
// Left absent, never coerced to 0 — see `details.balance_unknown` above.
|
|
9380
9355
|
...probe.balanceMsats === void 0 ? {} : { balanceMsats: probe.balanceMsats },
|
|
9381
9356
|
details
|
|
9382
9357
|
};
|
|
@@ -9420,7 +9395,7 @@ async function probeX402(x402, timeoutMs) {
|
|
|
9420
9395
|
let network;
|
|
9421
9396
|
let address;
|
|
9422
9397
|
try {
|
|
9423
|
-
const { loadX402Wallet: loadX402Wallet2, getX402Balance: getX402Balance2, ensureAddress: ensureAddress2, usdcContractByCaip2: usdcContractByCaip22 } = await import("../x402-
|
|
9398
|
+
const { loadX402Wallet: loadX402Wallet2, getX402Balance: getX402Balance2, ensureAddress: ensureAddress2, usdcContractByCaip2: usdcContractByCaip22 } = await import("../x402-CI6PSHNO.js");
|
|
9424
9399
|
const wallet = loadX402Wallet2();
|
|
9425
9400
|
if (!wallet) {
|
|
9426
9401
|
const storedKey = x402.privateKey;
|
|
@@ -9450,16 +9425,10 @@ async function probeX402(x402, timeoutMs) {
|
|
|
9450
9425
|
configured: true,
|
|
9451
9426
|
reachable: true,
|
|
9452
9427
|
balanceUsdc: balance.usdc,
|
|
9453
|
-
// internal-review: record the contract the balance was actually read against —
|
|
9454
|
-
// a zero here only means "none of *this* token, on *this* chain". Map
|
|
9455
|
-
// lookup off the network already resolved; no second RPC.
|
|
9456
9428
|
details: {
|
|
9457
9429
|
address: w.address,
|
|
9458
9430
|
network: w.network,
|
|
9459
9431
|
token: usdcContractByCaip22(w.network),
|
|
9460
|
-
// internal-review: and the endpoint that answered, which the caller can
|
|
9461
|
-
// point elsewhere — a wrong one reads as a plausible $0.00 otherwise.
|
|
9462
|
-
// Redacted here, at the boundary where the URL becomes display.
|
|
9463
9432
|
...rpcDetails(balance.rpcUrlRedacted, balance.rpcSource)
|
|
9464
9433
|
}
|
|
9465
9434
|
};
|
|
@@ -9478,7 +9447,7 @@ async function probeMpp(mpp, timeoutMs) {
|
|
|
9478
9447
|
if (!mpp) return null;
|
|
9479
9448
|
if (mpp.method === "tempo") {
|
|
9480
9449
|
try {
|
|
9481
|
-
const { connectedTempoAccount: connectedTempoAccount2, getTempoUsdcBalance: getTempoUsdcBalance2, resolveTempoNetwork: resolveTempoNetwork2 } = await import("../tempo-wallet-
|
|
9450
|
+
const { connectedTempoAccount: connectedTempoAccount2, getTempoUsdcBalance: getTempoUsdcBalance2, resolveTempoNetwork: resolveTempoNetwork2 } = await import("../tempo-wallet-ZFNUDFVO.js");
|
|
9482
9451
|
const account = await connectedTempoAccount2();
|
|
9483
9452
|
if (!account) {
|
|
9484
9453
|
return {
|
|
@@ -9499,13 +9468,10 @@ async function probeMpp(mpp, timeoutMs) {
|
|
|
9499
9468
|
configured: true,
|
|
9500
9469
|
reachable: true,
|
|
9501
9470
|
balanceUsdc: balance.usdc,
|
|
9502
|
-
// internal-review: record the contract the balance was actually read
|
|
9503
|
-
// against — a zero here only means "none of *this* token".
|
|
9504
9471
|
details: {
|
|
9505
9472
|
address: account.address,
|
|
9506
9473
|
chain_id: balance.chainId,
|
|
9507
9474
|
token: balance.tokenAddress,
|
|
9508
|
-
// internal-review: as on x402 above — which endpoint the number came from.
|
|
9509
9475
|
...rpcDetails(balance.rpcUrlRedacted, balance.rpcSource)
|
|
9510
9476
|
}
|
|
9511
9477
|
};
|
|
@@ -1,41 +1,39 @@
|
|
|
1
1
|
import { FacilitatorConfig } from '@x402/core/server';
|
|
2
|
-
import { aj as PaymentPayload, ap as PaymentRequirementsV1, aq as PaymentRequirementsV2, aE as X402Config, av as SettleResponse, aC as VerifyResponse, bi as X402ExactVersionSupport, bj as X402Receipt, bk as TransactionalPayoutHook, bl as CashuMeltCompleted } from '../step-cache-
|
|
3
|
-
export { bm as CreditDepositPayload, bn as CreditDrainPayload, bo as FundingLot, bp as LotDebit, bq as LotDepletion, br as MppxServer, bs as NON_CHANNEL_BITCOIN_RAILS, bt as NonChannelBitcoinRail, bu as PayoutReporter, bv as PostgresTempoSessionStore, bw as RevenueReporter, bx as SIGNED_ENVELOPE_FIELDS, by as SIGNED_ENVELOPE_TYPES, bz as X402TrackedChannel, bA as _testing, bB as createDefaultReplayStore, bC as depleteLots, bD as fifoOrder, bE as inKindDrawMsats, bF as isInKindDepletion, bG as isNonChannelBitcoinRail, bH as lotOwedSats, bI as netOwedSats, bJ as wrapMppx } from '../step-cache-
|
|
2
|
+
import { aj as PaymentPayload, ap as PaymentRequirementsV1, aq as PaymentRequirementsV2, aE as X402Config, av as SettleResponse, aC as VerifyResponse, bi as X402ExactVersionSupport, bj as X402Receipt, bk as TransactionalPayoutHook, bl as CashuMeltCompleted } from '../step-cache-v2yhyhSZ.js';
|
|
3
|
+
export { bm as CreditDepositPayload, bn as CreditDrainPayload, bo as FundingLot, bp as LotDebit, bq as LotDepletion, br as MppxServer, bs as NON_CHANNEL_BITCOIN_RAILS, bt as NonChannelBitcoinRail, bu as PayoutReporter, bv as PostgresTempoSessionStore, bw as RevenueReporter, bx as SIGNED_ENVELOPE_FIELDS, by as SIGNED_ENVELOPE_TYPES, bz as X402TrackedChannel, bA as _testing, bB as createDefaultReplayStore, bC as depleteLots, bD as fifoOrder, bE as inKindDrawMsats, bF as isInKindDepletion, bG as isNonChannelBitcoinRail, bH as lotOwedSats, bI as netOwedSats, bJ as wrapMppx } from '../step-cache-v2yhyhSZ.js';
|
|
4
4
|
import { Hono } from 'hono';
|
|
5
5
|
import { Env, BlankSchema } from 'hono/types';
|
|
6
6
|
import { Pool } from 'pg';
|
|
7
7
|
export { Pool } from 'pg';
|
|
8
|
-
import { g as getWallet } from '../wallet-
|
|
9
|
-
import { A as AccumulatorPool, a as AccumulatorQuerier, C as ConsumedCredentialStore } from '../credit-menu-
|
|
10
|
-
export { b as AppEnv, c as CreditFundingReport, F as FiatDenomination, d as FiatDenominationFailure, e as FundOnlyRequest, I as IncomingPaymentOpts, J as JobCancelledError, M as MintHealthTracker, P as PAYMENT_PROOF_KEYS, f as PaymentErrorCode, g as PaymentErrorDetail, h as PaymentInfo, R as ReporterBannerOpts, i as ResolvedFx, j as RevenueBootCheckOpts, S as SDKServerOpts, k as ServerJob, l as ShortPayForfeit, T as TempoChannelReport, m as TempoObserverHealth, n as TempoSessionChannelMismatchError, U as UpfrontPaymentOpts, V as VerifiedIncomingPayment, o as VerifyIncomingSnapshot, X as X402BatchChannelObservation, p as X402FacilitatorHealth, q as X402SettlementEvidenceOutcome, r as X402SettlementRepair, s as X402SettlementRepairRefusal, t as X402SettlementRepaired, u as X402WedgedSettlement, v as X402WedgedSettlementPage, w as X402_BATCH_SETTLEMENT_MAINNET_NETWORK, x as abortJob, y as applyPaymentInfoToJob, z as assertRevenueReporterReady, B as buildPaymentErrorResponse, D as clearAccumulatorForDvm, E as createDVMServer, G as creditDepositPayload, H as derivedFundCreditId, K as devModeSkipsPaymentVerification, L as fromJobRecord, N as fundedMicroFor, O as hasPaymentProof, Q as hashLockKey, W as implicitCreditId, Y as initWalletAccumulatorTable, Z as insertAccumulatorRows, _ as isDerivedCreditId, $ as isTerminal, a0 as isYieldMessage, a1 as issueUpfrontChallenges, a2 as msatsToFiatMicro, a3 as paymentErrorBody, a4 as pinAskFiat, a5 as priceFiatMicro, a6 as processIncomingPayment, a7 as providerMessage, a8 as repairX402ExactSettlementEffect, a9 as resolveFxSnapshot, aa as resolvePriceFiat, ab as revenueReporterBannerState, ac as toCreditTerms, ad as toJobRecord, ae as unknownRouteNotFound, af as verifyIncomingPayment, ag as verifyTempoSessionManagementCredential, ah as verifyUpfrontPayment, ai as x402RequiredUsdcMicro, aj as x402SettledShare } from '../credit-menu-
|
|
11
|
-
import { g as LockPubkey } from '../lightning-backend-
|
|
12
|
-
export { t as lockPubkeyStoreToLockPubkey } from '../lightning-backend-
|
|
13
|
-
export { O as OutgoingMessage, S as StaleJobReapable, i as isStaleJobReapable } from '../job-store-
|
|
8
|
+
import { g as getWallet } from '../wallet-Dwjs5n_M.js';
|
|
9
|
+
import { A as AccumulatorPool, a as AccumulatorQuerier, C as ConsumedCredentialStore } from '../credit-menu-kDA9RVzD.js';
|
|
10
|
+
export { b as AppEnv, c as CreditFundingReport, F as FiatDenomination, d as FiatDenominationFailure, e as FundOnlyRequest, I as IncomingPaymentOpts, J as JobCancelledError, M as MintHealthTracker, P as PAYMENT_PROOF_KEYS, f as PaymentErrorCode, g as PaymentErrorDetail, h as PaymentInfo, R as ReporterBannerOpts, i as ResolvedFx, j as RevenueBootCheckOpts, S as SDKServerOpts, k as ServerJob, l as ShortPayForfeit, T as TempoChannelReport, m as TempoObserverHealth, n as TempoSessionChannelMismatchError, U as UpfrontPaymentOpts, V as VerifiedIncomingPayment, o as VerifyIncomingSnapshot, X as X402BatchChannelObservation, p as X402FacilitatorHealth, q as X402SettlementEvidenceOutcome, r as X402SettlementRepair, s as X402SettlementRepairRefusal, t as X402SettlementRepaired, u as X402WedgedSettlement, v as X402WedgedSettlementPage, w as X402_BATCH_SETTLEMENT_MAINNET_NETWORK, x as abortJob, y as applyPaymentInfoToJob, z as assertRevenueReporterReady, B as buildPaymentErrorResponse, D as clearAccumulatorForDvm, E as createDVMServer, G as creditDepositPayload, H as derivedFundCreditId, K as devModeSkipsPaymentVerification, L as fromJobRecord, N as fundedMicroFor, O as hasPaymentProof, Q as hashLockKey, W as implicitCreditId, Y as initWalletAccumulatorTable, Z as insertAccumulatorRows, _ as isDerivedCreditId, $ as isTerminal, a0 as isYieldMessage, a1 as issueUpfrontChallenges, a2 as msatsToFiatMicro, a3 as paymentErrorBody, a4 as pinAskFiat, a5 as priceFiatMicro, a6 as processIncomingPayment, a7 as providerMessage, a8 as repairX402ExactSettlementEffect, a9 as resolveFxSnapshot, aa as resolvePriceFiat, ab as revenueReporterBannerState, ac as toCreditTerms, ad as toJobRecord, ae as unknownRouteNotFound, af as verifyIncomingPayment, ag as verifyTempoSessionManagementCredential, ah as verifyUpfrontPayment, ai as x402RequiredUsdcMicro, aj as x402SettledShare } from '../credit-menu-kDA9RVzD.js';
|
|
11
|
+
import { g as LockPubkey } from '../lightning-backend-BhsyrBLa.js';
|
|
12
|
+
export { t as lockPubkeyStoreToLockPubkey } from '../lightning-backend-BhsyrBLa.js';
|
|
13
|
+
export { O as OutgoingMessage, S as StaleJobReapable, i as isStaleJobReapable } from '../job-store-D3CcZp_g.js';
|
|
14
14
|
import { Store } from 'mppx';
|
|
15
15
|
import { z } from 'zod';
|
|
16
16
|
import '@x402/evm/batch-settlement/server';
|
|
17
17
|
import 'viem';
|
|
18
18
|
import '@x402/core/types';
|
|
19
19
|
import '@cashu/cashu-ts';
|
|
20
|
-
import '../fx-
|
|
20
|
+
import '../fx-DhyT1Cjh.js';
|
|
21
21
|
|
|
22
|
-
/** POST a verify request to the configured facilitator. */
|
|
23
22
|
declare function verifyWithFacilitator(payload: PaymentPayload, requirements: PaymentRequirementsV1 | PaymentRequirementsV2, config?: Pick<X402Config, "facilitator" | "facilitatorAuth">, createAuthHeaders?: FacilitatorConfig["createAuthHeaders"] | undefined): Promise<VerifyResponse>;
|
|
24
|
-
/** POST a settlement request to the configured facilitator. */
|
|
25
23
|
declare function settleWithFacilitator(payload: PaymentPayload, requirements: PaymentRequirementsV1 | PaymentRequirementsV2, config?: Pick<X402Config, "facilitator" | "facilitatorAuth">, createAuthHeaders?: FacilitatorConfig["createAuthHeaders"] | undefined): Promise<SettleResponse>;
|
|
26
24
|
|
|
27
25
|
/**
|
|
28
|
-
* Verify an x402 `X-PAYMENT` header per the x402 spec
|
|
26
|
+
* Verify an x402 `X-PAYMENT` header per the x402 spec.
|
|
29
27
|
*
|
|
30
28
|
* Flow:
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
29
|
+
* 1. Decode the base64 `PaymentPayload`
|
|
30
|
+
* 2. Rebuild the `PaymentRequirements` the server advertised on the 402 — the
|
|
31
|
+
* facilitator deep-equals these against the payload's authorization, so a
|
|
32
|
+
* credential bought against any other set fails verification.
|
|
33
|
+
* 3. Call the facilitator's `/verify`
|
|
34
|
+
* 4. On valid, call the facilitator's `/settle` to broadcast the EIP-3009
|
|
35
|
+
* `transferWithAuthorization`. The on-chain tx hash flows through to the
|
|
36
|
+
* receipt and into `X-PAYMENT-RESPONSE` for the client.
|
|
39
37
|
*
|
|
40
38
|
* A positive `btcUsdRate` converts the settled USDC back to msats. Zero means
|
|
41
39
|
* the requirement was already stated exactly in USD and no rate was needed;
|
|
@@ -48,8 +46,8 @@ declare function verifyX402Payment(paymentHeader: string, config: X402Config, re
|
|
|
48
46
|
/**
|
|
49
47
|
* Snapshot of a DVM's published lock-pubkey state at a point in time. `current`
|
|
50
48
|
* is what the SDK advertises as `cashu.lock_pubkeys[0]`; `retired` are the
|
|
51
|
-
* pubkeys
|
|
52
|
-
*
|
|
49
|
+
* pubkeys inside the rotation grace window plus legacy sentinel-0 entries
|
|
50
|
+
* kept until explicitly cleaned up. Both halves are needed by the
|
|
53
51
|
* receive path (accept proofs locked to any entry) and the admin auth verifier
|
|
54
52
|
* (accept signatures from any entry during grace).
|
|
55
53
|
*/
|
|
@@ -67,10 +65,6 @@ interface LockPubkeyState {
|
|
|
67
65
|
* a process restart.
|
|
68
66
|
*/
|
|
69
67
|
type LockPubkeyStateLoader = () => Promise<LockPubkeyState>;
|
|
70
|
-
/**
|
|
71
|
-
* Subset of pg.Pool used by the lock-pubkey store. Sharing `AccumulatorPool`
|
|
72
|
-
* keeps the SDK's "pass me a Postgres pool" surface uniform across stores.
|
|
73
|
-
*/
|
|
74
68
|
type LockPubkeyPool = AccumulatorPool;
|
|
75
69
|
/**
|
|
76
70
|
* Create the `dvm_lock_pubkeys` table if absent. Each row is one entry in a
|
|
@@ -90,20 +84,16 @@ declare function initLockPubkeyTable(db: LockPubkeyPool): Promise<void>;
|
|
|
90
84
|
* Also backfills any distinct `lock_pubkey` values found in
|
|
91
85
|
* `wallet_accumulator` for this DVM that aren't yet in `dvm_lock_pubkeys`,
|
|
92
86
|
* inserting them as retired rows with `retired_at_ms = 0` — the
|
|
93
|
-
* "long-retired-still-meltable" sentinel. This handles
|
|
87
|
+
* "long-retired-still-meltable" sentinel. This handles legacy batches
|
|
94
88
|
* that would otherwise trip the monitor's `orphan_lock_pubkey` alarm every
|
|
95
89
|
* tick. Sentinel-0 rows are exempt from grace-window filtering and
|
|
96
90
|
* `pruneRetired` so they stay visible until the operator melts the legacy
|
|
97
91
|
* batches and the receive path keeps accepting in-flight tokens locked to
|
|
98
92
|
* them.
|
|
99
93
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* first-boot window. Closed the same way, with `ON CONFLICT DO NOTHING` on
|
|
104
|
-
* that partial index: the boot lock (internal-review) serializes the cross-machine
|
|
105
|
-
* half, but two callers on one pool share its acquisition (a fire-and-forget
|
|
106
|
-
* hydrate overlapping boot's), so the guard has to hold without it.
|
|
94
|
+
* `ON CONFLICT DO NOTHING` protects concurrent seeds invoked reentrantly from
|
|
95
|
+
* one guarded callback. Nested calls bypass the queue to avoid deadlock, so
|
|
96
|
+
* both inserts can pass `WHERE NOT EXISTS` before either commits.
|
|
107
97
|
*/
|
|
108
98
|
declare function seedLockPubkeyState(db: LockPubkeyPool, dvmId: string, pubkey: string, now?: number): Promise<void>;
|
|
109
99
|
/**
|
|
@@ -137,27 +127,20 @@ declare function rotateLockPubkey(db: LockPubkeyPool, dvmId: string, newPubkey:
|
|
|
137
127
|
*/
|
|
138
128
|
declare function pruneRetired(db: AccumulatorQuerier, dvmId: string, graceMs: number, now?: number): Promise<number>;
|
|
139
129
|
/**
|
|
140
|
-
* Default rotation grace window
|
|
141
|
-
*
|
|
130
|
+
* Default rotation grace window in seconds. Override through
|
|
131
|
+
* `SDKServerOpts.lockPubkeyGraceSeconds`.
|
|
142
132
|
*/
|
|
143
133
|
declare const DEFAULT_LOCK_PUBKEY_GRACE_SECONDS = 86400;
|
|
144
|
-
/**
|
|
145
|
-
* Lift a single pubkey + grace-filtered retired list into the flat array the
|
|
146
|
-
* accept path checks against. Convenience for call sites that don't care
|
|
147
|
-
* about the retired-row structure.
|
|
148
|
-
*/
|
|
149
134
|
declare function activePubkeySet(state: LockPubkeyState): LockPubkey[];
|
|
150
135
|
|
|
151
|
-
/** Options for `installAdminCashuRoutes`. */
|
|
152
136
|
interface InstallAdminCashuRoutesOpts {
|
|
153
|
-
/** Pool against the SDK's accumulator DB. */
|
|
154
137
|
db: Pool;
|
|
155
138
|
/** Identifier of this DVM — bound into every signed admin challenge. */
|
|
156
139
|
dvmId: string;
|
|
157
140
|
/**
|
|
158
141
|
* Live lock-pubkey state loader. Auth accepts a signature from the current
|
|
159
142
|
* pubkey or any retired pubkey still within the rotation grace window
|
|
160
|
-
*
|
|
143
|
+
* The `/admin/cashu/rotate-lock-pubkey` route narrows that to
|
|
161
144
|
* current-only.
|
|
162
145
|
*/
|
|
163
146
|
getLockPubkeyState: LockPubkeyStateLoader;
|
|
@@ -165,25 +148,15 @@ interface InstallAdminCashuRoutesOpts {
|
|
|
165
148
|
graceSeconds: number;
|
|
166
149
|
/** Replay-protection store keyed by nonce. */
|
|
167
150
|
nonceStore: ConsumedCredentialStore;
|
|
168
|
-
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* melt is a landed payout, and its report commits with the mark or not at
|
|
172
|
-
* all. `enqueue` throwing rolls the mark back and fails the call — the CLI's
|
|
173
|
-
* recovery re-posts `mark-melted` on its next run, where a melt marked with
|
|
174
|
-
* no row would understate paid-out forever. `committed` runs after.
|
|
175
|
-
*/
|
|
151
|
+
/** Runs after mint checkstate reports the proofs SPENT, inside the transaction that
|
|
152
|
+
* records the caller-reported melt audit and marks rows melted. Enqueue failure
|
|
153
|
+
* rolls the mark back for recovery; committed runs only after commit. */
|
|
176
154
|
onMelted?: TransactionalPayoutHook<CashuMeltCompleted>;
|
|
177
155
|
/** Override for cashu-ts wallet construction (tests). */
|
|
178
156
|
walletProvider?: typeof getWallet;
|
|
179
157
|
/** Override for the current time (tests). Returns ms since epoch. */
|
|
180
158
|
now?: () => number;
|
|
181
159
|
}
|
|
182
|
-
/**
|
|
183
|
-
* Register the four admin endpoints on the supplied Hono app. Idempotent at
|
|
184
|
-
* the call site — `app.ts` only invokes this when accumulator config is
|
|
185
|
-
* complete (`cashuMode === "p2pk-accumulator"`, `db`, `dvmId`, `lockPubkey`).
|
|
186
|
-
*/
|
|
187
160
|
declare function installAdminCashuRoutes<E extends Env = Env, S extends BlankSchema = BlankSchema>(app: Hono<E, S>, opts: InstallAdminCashuRoutesOpts): void;
|
|
188
161
|
/**
|
|
189
162
|
* Convenience constructor for the in-memory nonce store — exported so callers
|
|
@@ -194,7 +167,7 @@ declare function createAdminCashuNonceStore(): ConsumedCredentialStore;
|
|
|
194
167
|
|
|
195
168
|
/**
|
|
196
169
|
* The `fx_rate_unavailable` payment-error detail, shaped like every other flat
|
|
197
|
-
* payment error
|
|
170
|
+
* payment error: a flat machine `error` code plus `message` and the
|
|
198
171
|
* `display`/`hint`/`retryable` fields an agent relays verbatim and branches
|
|
199
172
|
* retries on — the shape the `paymentErrorBody` builder enforces for the sibling
|
|
200
173
|
* 503s (`mint_health_pending`, `cashu_mint_sick`) and the 402 family alike. This
|
|
@@ -211,11 +184,7 @@ declare function rateUnavailablePaymentError(): {
|
|
|
211
184
|
/**
|
|
212
185
|
* Create a fetch wrapper that emits `dvm.fetch` spans via `loggers.isolate`.
|
|
213
186
|
*
|
|
214
|
-
*
|
|
215
|
-
* status code. When observability is disabled, `loggers.isolate` is the no-op
|
|
216
|
-
* logger — `span()` calls `fn()` directly with zero overhead.
|
|
217
|
-
*
|
|
218
|
-
* `signal` (internal-review) is the job's cancellation signal. When supplied, every
|
|
187
|
+
* `signal` is the job's cancellation signal. When supplied, every
|
|
219
188
|
* request made through this fetch aborts on job cancel — that is what stops
|
|
220
189
|
* provider spend mid-job. It is *merged* with any caller-supplied
|
|
221
190
|
* `init.signal` rather than replacing it, so a per-request timeout (scrapfly,
|
|
@@ -232,7 +201,7 @@ interface JobCredentialRequest {
|
|
|
232
201
|
header(name: string): string | undefined;
|
|
233
202
|
}
|
|
234
203
|
/**
|
|
235
|
-
*
|
|
204
|
+
* the credential gate on a runtime's `/v1/job/:id/*` routes — the
|
|
236
205
|
* "did this request present anything?" predicate and the 401 body that answers
|
|
237
206
|
* when it didn't, built together so the copy can never describe a credential
|
|
238
207
|
* the predicate doesn't accept.
|
|
@@ -244,20 +213,20 @@ interface JobCredentialGate {
|
|
|
244
213
|
body(): Record<string, unknown>;
|
|
245
214
|
}
|
|
246
215
|
/**
|
|
247
|
-
*
|
|
216
|
+
* build the credential gate for one runtime.
|
|
248
217
|
*
|
|
249
218
|
* `acceptsBearer` is what separates them. The isolate tier derives
|
|
250
219
|
* `requesterId` from `Authorization: Bearer`, so a Bearer token really is a
|
|
251
220
|
* job credential there. The SDK server does not — its auth middleware pins
|
|
252
221
|
* `requesterId` to `anonymous`/`dev-anonymous`, so every SDK job is gated on
|
|
253
|
-
* the
|
|
222
|
+
* the `X-Job-Token` and a Bearer header proves nothing. Counting it
|
|
254
223
|
* anyway would send a stale client that happens to send one back to the
|
|
255
224
|
* opaque 404 this exists to eliminate.
|
|
256
225
|
*
|
|
257
226
|
* A request carrying no accepted credential can be refused before the job is
|
|
258
227
|
* ever looked up, which is what makes {@link JobCredentialGate.body} safe to
|
|
259
228
|
* be specific about — the 404-not-403 choice on a *failed* ownership check is
|
|
260
|
-
* deliberate (
|
|
229
|
+
* deliberate (a wrong credential must never confirm a job id exists),
|
|
261
230
|
* and that property is untouched here because this body is returned before any
|
|
262
231
|
* store lookup, identical whether or not the job exists.
|
|
263
232
|
*
|
|
@@ -268,7 +237,6 @@ declare function jobCredentialGate(opts: {
|
|
|
268
237
|
acceptsBearer: boolean;
|
|
269
238
|
}): JobCredentialGate;
|
|
270
239
|
|
|
271
|
-
/** Options for `PostgresTempoChargeStore`. */
|
|
272
240
|
interface PostgresTempoChargeStoreOpts {
|
|
273
241
|
/** Table name. Defaults to `"mpp_tempo_charge_replays"`. Must match `/^[a-zA-Z_][a-zA-Z0-9_]*$/`. */
|
|
274
242
|
tableName?: string;
|
|
@@ -288,7 +256,7 @@ interface PostgresTempoChargeStoreOpts {
|
|
|
288
256
|
}
|
|
289
257
|
/**
|
|
290
258
|
* Postgres implementation of the atomic store mppx's `tempo.charge` uses for
|
|
291
|
-
* replay protection
|
|
259
|
+
* replay protection.
|
|
292
260
|
*
|
|
293
261
|
* mppx refuses a charge credential whose transaction hash it has already taken
|
|
294
262
|
* (`markHashUsed`), and refuses a zero-dollar proof credential whose challenge
|
|
@@ -330,27 +298,15 @@ declare class PostgresTempoChargeStore implements Store.AtomicStore {
|
|
|
330
298
|
init(): Promise<void>;
|
|
331
299
|
/** Read one stored value, or `null` when absent — mppx's miss sentinel. */
|
|
332
300
|
get(key: string): Promise<unknown>;
|
|
333
|
-
/** Replace one stored value. */
|
|
334
301
|
put(key: string, value: unknown): Promise<void>;
|
|
335
302
|
/** Delete one stored value — mppx's compensating release on a failed broadcast. */
|
|
336
303
|
delete(key: string): Promise<void>;
|
|
337
304
|
/**
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
* write is the one that matters here: `FOR UPDATE` locks nothing when no row
|
|
342
|
-
* exists, so two machines marking one hash for the first time would both read
|
|
343
|
-
* `null` and both believe they won.
|
|
344
|
-
*
|
|
345
|
-
* Replay keys are unique per credential, so they never contend. The contended
|
|
346
|
-
* key is the fee-sponsor budget — one per `(chain, sponsor)`, read-modified
|
|
347
|
-
* several times per sponsored charge — and serializing it across machines is
|
|
348
|
-
* the point of sharing the store at all. The critical section is a SELECT and
|
|
349
|
-
* an upsert, so a queue of waiters clears in tens of milliseconds; a pooled
|
|
350
|
-
* connection is held for exactly that long and never across a chain call.
|
|
305
|
+
* Advisory locking covers the absent-row first write before the row lock.
|
|
306
|
+
* Both competing presentations of one credential and the shared sponsor
|
|
307
|
+
* budget need this serialization. The transaction contains no chain call.
|
|
351
308
|
*/
|
|
352
309
|
update<result>(key: string, fn: (current: unknown) => Store.Change<unknown, result>): Promise<result>;
|
|
353
|
-
/** The boot DDL itself — always runs under {@link withSdkInitLock} (internal-review). */
|
|
354
310
|
private createTables;
|
|
355
311
|
private maybeSweep;
|
|
356
312
|
}
|
|
@@ -373,7 +329,6 @@ declare const TEMPO_CLOSE_REQUESTED_TOPIC = "0xf5a36fc00a96cbb9cf1f8f59299165e1d
|
|
|
373
329
|
*/
|
|
374
330
|
declare const TEMPO_CLOSE_DB_RECOVERY_BUDGET_MS = 15000;
|
|
375
331
|
|
|
376
|
-
/** Humanised `{ message, hint }` derived from a ZodError for the `invalid_input`/`invalid_quote_data` envelope. */
|
|
377
332
|
interface HumanizedZodError {
|
|
378
333
|
message: string;
|
|
379
334
|
hint: string;
|
|
@@ -391,11 +346,6 @@ interface HumanizedZodError {
|
|
|
391
346
|
* that fit: a chunking hint is the one output that tells a caller what to
|
|
392
347
|
* actually do, and losing it because the oversized field sorted fourth is the
|
|
393
348
|
* same class of unhelpful answer this whole path exists to avoid.
|
|
394
|
-
*
|
|
395
|
-
* The `ZodError.message` field is itself a JSON-stringified array of issues
|
|
396
|
-
* (per Zod's default Error contract). Using it raw — as the SDK previously
|
|
397
|
-
* did — leaks the unstructured array into the agent-facing response, which
|
|
398
|
-
* is what internal-review fixes.
|
|
399
349
|
*/
|
|
400
350
|
declare function humanizeZodError(err: z.ZodError, opts: {
|
|
401
351
|
schemaUrl: string;
|