@inversealtruism/cairn-sdk 0.8.0 → 0.8.2
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 +3 -3
- package/dist/chain.cjs +83 -3
- package/dist/chain.d.cts +9 -4
- package/dist/chain.d.ts +9 -4
- package/dist/chain.js +6 -1
- package/dist/{chunk-DTPADO7N.js → chunk-2RR4ZJPQ.js} +1 -1
- package/dist/{chunk-UAPWZZQK.js → chunk-37OHCH7R.js} +20 -8
- package/dist/{chunk-JXBO4LV6.js → chunk-AHPXOYCC.js} +1 -1
- package/dist/{chunk-WWO3FXHG.js → chunk-EVEBQSDK.js} +19 -14
- package/dist/{chunk-C452UODV.js → chunk-IPBMMJ3Z.js} +26 -4
- package/dist/{chunk-CI7YODPP.js → chunk-NRCTL7OI.js} +43 -3
- package/dist/connect.cjs +34 -20
- package/dist/connect.js +2 -2
- package/dist/content.cjs +1 -1
- package/dist/content.js +2 -2
- package/dist/controller.cjs +34 -20
- package/dist/controller.js +3 -3
- package/dist/index.cjs +268 -99
- package/dist/index.d.cts +77 -32
- package/dist/index.d.ts +77 -32
- package/dist/index.js +190 -82
- package/dist/indexer.cjs +98 -3
- package/dist/indexer.d.cts +5 -1
- package/dist/indexer.d.ts +5 -1
- package/dist/indexer.js +2 -1
- package/dist/react.cjs +34 -20
- package/dist/react.js +3 -3
- package/package.json +10 -7
package/dist/index.d.cts
CHANGED
|
@@ -11,8 +11,8 @@ import { WalletConnection, DetectOptions } from './connect.cjs';
|
|
|
11
11
|
export { AttestParams, CairnProvider, ConnectResult, FillParams, ProposeParams, ProviderDetail, ProviderInfo, SealClaimParams, SendParams, SignInResult, SiwcParams, SiwcResult, TxResult, WalletCapabilities, WalletPermission, connect, detectProvider, discoverProviders, getWallet, isInstalled } from './connect.cjs';
|
|
12
12
|
import { InclusionResult } from '@inversealtruism/csd-light';
|
|
13
13
|
export { CairnController, CairnControllerOptions, CairnState } from './controller.cjs';
|
|
14
|
+
import { NodeTxJson } from '@inversealtruism/csd-tx';
|
|
14
15
|
import '@inversealtruism/csd-client';
|
|
15
|
-
import '@inversealtruism/csd-tx';
|
|
16
16
|
import '@inversealtruism/csd-codec';
|
|
17
17
|
import '@inversealtruism/csd-crypto';
|
|
18
18
|
|
|
@@ -138,6 +138,9 @@ declare class NamesClient {
|
|
|
138
138
|
/** The trust-labeled verdict. `ok:false` + `transient:true` = a retryable chain-catching-up soft-fail (NOT a
|
|
139
139
|
* proven mismatch). `payto`/`seller`/`terms` are populated whenever they could be merkle-derived. */
|
|
140
140
|
interface OfferFillCheck {
|
|
141
|
+
/** `true`: the offer record is proven and no check refused. Without `me` and `tip` it does not say the offer
|
|
142
|
+
* is fillable by you now (it may be bound to another taker, held by someone else's live claim or
|
|
143
|
+
* reservation, or too close to its expiry), and with `sized: false` it does not size your fill. */
|
|
141
144
|
ok: boolean;
|
|
142
145
|
/** "verified" = merkle-proven inclusion + on-chain author; "proof-consistent" = a proof that folds but the
|
|
143
146
|
* header could not be PoW-verified (indexer-trusted); "unverified" = could not prove. */
|
|
@@ -149,17 +152,37 @@ interface OfferFillCheck {
|
|
|
149
152
|
/** Minted by cairnx-core's `provenOfferTerms`, so it can be passed back to `bindOfferTerms` without the opt-out. */
|
|
150
153
|
terms?: MintedProvenOfferTerms;
|
|
151
154
|
blockHeight?: number;
|
|
155
|
+
/** The proven Propose's `expires_epoch`. */
|
|
156
|
+
expiresEpoch?: number;
|
|
157
|
+
/** The first block height at which CairnX treats the offer as expired (cairnx-core `offerExpiryHeightOf` over the
|
|
158
|
+
* proven expiry and anchor). A fill must be mined below it; with `me` and `tip` a fill with less than
|
|
159
|
+
* cairnx-core's `FILL_TIP_MARGIN` blocks of cushion is refused, without them compare it with your tip. */
|
|
160
|
+
expiresAt?: number;
|
|
152
161
|
/** B7b (REBIND W3/M1): the PROVEN CSD outputs to build for `pay` (a WHOLE fill of a non-partial offer),
|
|
153
162
|
* sized from the merkle-proven offer by the single-sourced `fillOutputPlan`. Present only when `pay` was
|
|
154
|
-
* passed, the served offer carried a `status
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
163
|
+
* passed, the served offer carried a `status`, the offer could be sized, and neither the served status, the
|
|
164
|
+
* endorsement nor the expiry cushion refuses the fill (other refusals keep the proven plan; branch on `ok`).
|
|
165
|
+
* Build EXACTLY these; never the resolver-served outputs a lying resolver could redirect. A partial
|
|
166
|
+
* (min-bearing) offer is left unsized (its running paid/delivered is not provable at this corroboration layer;
|
|
167
|
+
* the wallet's fill-SPV is the payment-grade sizer). Liveness is never proven here: the plan is sized only
|
|
168
|
+
* for the status the resolver served, so an offer with no served status gets no plan. */
|
|
159
169
|
outputPlan?: {
|
|
160
170
|
to: string;
|
|
161
171
|
value: bigint;
|
|
162
172
|
}[];
|
|
173
|
+
/** Present when `pay` was passed: `true` when `outputPlan` holds the proven outputs for this pay, `false` when
|
|
174
|
+
* the fill could not be sized from proven data (`planReason` says why). `ok: true` with `sized: false` is a
|
|
175
|
+
* verdict on the offer record, not on this fill. */
|
|
176
|
+
sized?: boolean;
|
|
177
|
+
/** Present when `me` and `tip` were passed: cairnx-core's `fillEndorsement` over the served state after the
|
|
178
|
+
* binds. "refused" answers `ok: false`; "not-endorsable" (a token-priced want) is not a refusal. */
|
|
179
|
+
endorsement?: {
|
|
180
|
+
verdict: "endorsed" | "refused" | "not-endorsable";
|
|
181
|
+
reason: string;
|
|
182
|
+
};
|
|
183
|
+
/** Present with `endorsement`: the proposal id the fill's attest must target at `tip` (cairnx-core
|
|
184
|
+
* `fillTargetId`: the offer id, or the fclaim txid while a live reservation routes the offer). */
|
|
185
|
+
fillTarget?: string;
|
|
163
186
|
/** Present when `plannedOutputs` was passed: `true` when they were bound to `outputPlan` (a mismatch
|
|
164
187
|
* refuses with `ok: false`), `false` when there was no proven plan to bind them to (`planReason` says why).
|
|
165
188
|
* `ok: true` with `planBound: false` means your planned outputs were NOT checked. */
|
|
@@ -174,7 +197,7 @@ interface OfferFillCheck {
|
|
|
174
197
|
* for the prevout-owner author bind. Pass `servedOffer` (the resolver's offer object) to also bind its
|
|
175
198
|
* payto/seller/terms to the proven values. The FULL object is required: a served offer missing want.payto
|
|
176
199
|
* or seller is refused (P75-5). A token-priced offer's served want.ticker/want.amount are bound verbatim to
|
|
177
|
-
* the record. See the module header for the trust posture.
|
|
200
|
+
* the record. A served status other than open refuses. See the module header for the trust posture.
|
|
178
201
|
*/
|
|
179
202
|
declare function preverifyOffer(opts: {
|
|
180
203
|
light: {
|
|
@@ -188,17 +211,27 @@ declare function preverifyOffer(opts: {
|
|
|
188
211
|
/** B7b (REBIND W3/M1): the CSD base units you intend to pay. When given, the result carries `outputPlan`
|
|
189
212
|
* (the PROVEN CSD outputs to build for a WHOLE fill of a non-partial offer, sized by the single-sourced
|
|
190
213
|
* `fillOutputPlan`) and, if you also pass `plannedOutputs`, binds them EXACTLY to that proven plan.
|
|
191
|
-
* A partial (min-bearing) offer is left unsized here; the
|
|
214
|
+
* A partial (min-bearing) offer is left unsized here (`sized: false`); with the served offer, a pay its
|
|
215
|
+
* served progress says delivers nothing (below the minimum) is refused. The wallet's fill-SPV sizes it. */
|
|
192
216
|
pay?: bigint | string | number;
|
|
193
217
|
/** B7b: your planned per-address CSD sums (the outputs you WILL build), bound both ways to `outputPlan`.
|
|
194
218
|
* Requires `pay`. A missing/low leg is a doomed underpay; an extra/high leg is a W3 overpay or an N26
|
|
195
|
-
* smuggled output - both refused. */
|
|
219
|
+
* smuggled output - both refused. On a token-priced offer any positive CSD leg is refused. */
|
|
196
220
|
plannedOutputs?: Record<string, bigint | string | number>;
|
|
221
|
+
/** Your address, the one that signs the fill. With `tip` (and `pay`), the result carries cairnx-core's
|
|
222
|
+
* `fillEndorsement` over the served state: a taker bound to another address, an open CSD offer you hold no
|
|
223
|
+
* live claim or reservation on, or an attest target the offer's routing rejects is refused, and so is a fill
|
|
224
|
+
* that cairnx-core's `offerFillTooLate` says is too close to the offer's expiry. */
|
|
225
|
+
me?: string;
|
|
226
|
+
/** The chain tip height you sign at (for example `(await cairn.chain.tip()).height`). Goes with `me`. */
|
|
227
|
+
tip?: number;
|
|
228
|
+
/** The proposal id your attest will target: the offer id, or the fclaim txid while your reservation routes it. */
|
|
229
|
+
fillTargetId?: string;
|
|
197
230
|
}): Promise<OfferFillCheck>;
|
|
198
231
|
|
|
199
232
|
/** Stable machine-readable error codes (branch on these, not the message text). */
|
|
200
|
-
type CairnErrorCode = "NOT_INSTALLED" | "USER_REJECTED" | "WALLET_LOCKED" | "UNSUPPORTED_METHOD" | "HTTP_ERROR" | "CONTENT_VERIFICATION" | "CONTENT_NOT_JSON" | "ACCOUNT_CHANGED" | "FIRST_PARTY_ONLY" | "RATE_LIMITED" | "APPROVAL_CLOSED" | "FORBIDDEN" | "INTERNAL" | "GHOST_INPUTS_SKIPPED" | "VERIFY_UNAVAILABLE" | "VERIFY_TAMPER" | "INSUFFICIENT" | "TOO_MANY_INPUTS" | "FEE_TOO_LOW" | "FEE_CAP" | "BAD_FEE" | "ZERO_ADDR_REFUSED" | "BAD_OUTPUTS" | "NO_OUTPUTS" | "BAD_REQUEST" | "OFFER_UNKNOWN" | "FILL_UNSAFE" | "FILL_WRONG_TARGET" | "SOURCE_DIVERGENCE" | "SUBMIT_REJECTED" | "SUBMIT_MAYBE_INFLIGHT" | "SUBMIT_DUPLICATE" | "NOTHING_TO_CONSOLIDATE" | "OFFER_SOURCE_CONFLICT" | "FILL_LEGACY_SUNSET" | "VERIFY_HORIZON" | "VERIFY_UNREPRESENTABLE" | "WALLET_UNAVAILABLE" | "REVIEW_REQUIRED" | "UNKNOWN";
|
|
201
|
-
declare const SDK_VERSION = "0.8.
|
|
233
|
+
type CairnErrorCode = "NOT_INSTALLED" | "USER_REJECTED" | "WALLET_LOCKED" | "UNSUPPORTED_METHOD" | "HTTP_ERROR" | "CONTENT_VERIFICATION" | "CONTENT_NOT_JSON" | "ACCOUNT_CHANGED" | "FIRST_PARTY_ONLY" | "RATE_LIMITED" | "APPROVAL_CLOSED" | "FORBIDDEN" | "INTERNAL" | "GHOST_INPUTS_SKIPPED" | "VERIFY_UNAVAILABLE" | "VERIFY_TAMPER" | "INSUFFICIENT" | "TOO_MANY_INPUTS" | "FEE_TOO_LOW" | "FEE_CAP" | "BAD_FEE" | "ZERO_ADDR_REFUSED" | "BAD_OUTPUTS" | "NO_OUTPUTS" | "BAD_REQUEST" | "OFFER_UNKNOWN" | "FILL_UNSAFE" | "FILL_WRONG_TARGET" | "SOURCE_DIVERGENCE" | "SUBMIT_REJECTED" | "SUBMIT_MAYBE_INFLIGHT" | "SUBMIT_DUPLICATE" | "NOTHING_TO_CONSOLIDATE" | "OFFER_SOURCE_CONFLICT" | "FILL_LEGACY_SUNSET" | "VERIFY_HORIZON" | "VERIFY_UNREPRESENTABLE" | "WALLET_UNAVAILABLE" | "REVIEW_REQUIRED" | "SEAL_NOT_MINED" | "RESERVATION_DENIED" | "RPC_BLOCK_MISMATCH" | "WALLET_TIMEOUT" | "UNKNOWN";
|
|
234
|
+
declare const SDK_VERSION = "0.8.2";
|
|
202
235
|
interface CairnErrorOptions {
|
|
203
236
|
code?: CairnErrorCode;
|
|
204
237
|
docsPath?: string;
|
|
@@ -218,7 +251,7 @@ declare class CairnError extends Error {
|
|
|
218
251
|
/** Relative docs path (under the SDK docs base), if any. */
|
|
219
252
|
readonly docsPath?: string;
|
|
220
253
|
/** The cairn-sdk version that produced this error. */
|
|
221
|
-
readonly version = "0.8.
|
|
254
|
+
readonly version = "0.8.2";
|
|
222
255
|
/**
|
|
223
256
|
* Whether a dApp may safely AUTO-retry this failure. `false` for fund-safety refusals and user-intent
|
|
224
257
|
* declines (the default); `true` only for provably transient infra faults where nothing was signed.
|
|
@@ -261,20 +294,28 @@ declare class ContentVerificationError extends CairnError {
|
|
|
261
294
|
constructor(expected: string);
|
|
262
295
|
}
|
|
263
296
|
/**
|
|
264
|
-
* The
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
297
|
+
* The outcome of a write is AMBIGUOUS: the tx MAY already be in the mempool. Thrown by the write wrappers for
|
|
298
|
+
* the nested `SUBMIT_MAYBE_INFLIGHT` (request threw / timed out / 5xx gateway / unreadable body) and
|
|
299
|
+
* `SUBMIT_DUPLICATE` (node answered "already present or mempool conflict") codes, for `WALLET_UNAVAILABLE` on a
|
|
300
|
+
* write (the page lost the wallet's reply, which may come after the submit), for `WALLET_TIMEOUT` (the call
|
|
301
|
+
* outlasted the connection timeout while the request stays open in the wallet), and by `Chain.send` when the
|
|
302
|
+
* submit request fails after signing without a 4xx answer (a 4xx is `SUBMIT_REJECTED`). It CARRIES the
|
|
303
|
+
* locally-computed consensus `txid` when one is known so a dApp can RECONCILE (check the explorer / balance)
|
|
304
|
+
* instead of blindly re-broadcasting, which would re-invite the double-broadcast this contract exists to prevent
|
|
305
|
+
* (F14). It is NOT retryable (`retryable === false`);
|
|
306
|
+
* `maybeSent === true` distinguishes it from a definitely-not-sent terminal refusal. See WALLET-ERROR-CODES.md
|
|
307
|
+
* in the cairn-wallet repo.
|
|
271
308
|
*/
|
|
272
309
|
declare class SubmitInFlightError extends CairnError {
|
|
273
|
-
/** The locally-computed consensus txid to reconcile against the chain (
|
|
310
|
+
/** The locally-computed consensus txid to reconcile against the chain (undefined when it is not known). */
|
|
274
311
|
readonly txid?: string;
|
|
275
|
-
/**
|
|
312
|
+
/** The signed transaction, set only when `Chain.send` threw this (a wallet write keeps it in the wallet).
|
|
313
|
+
* `chain.submit(nodeJson)` resends it unchanged: the same coins under the same txid, so it cannot pay twice,
|
|
314
|
+
* where a new send may select other coins. */
|
|
315
|
+
readonly nodeJson?: NodeTxJson;
|
|
316
|
+
/** Always true: the tx MAY be in the mempool. Reconcile via `txid` or the balance; never blind-retry. */
|
|
276
317
|
readonly maybeSent = true;
|
|
277
|
-
constructor(message: string, code: "SUBMIT_MAYBE_INFLIGHT" | "SUBMIT_DUPLICATE", txid?: string);
|
|
318
|
+
constructor(message: string, code: "SUBMIT_MAYBE_INFLIGHT" | "SUBMIT_DUPLICATE" | "WALLET_UNAVAILABLE" | "WALLET_TIMEOUT", txid?: string, cause?: unknown, nodeJson?: NodeTxJson);
|
|
278
319
|
}
|
|
279
320
|
declare function mapProviderError(error: string, code?: string): CairnError;
|
|
280
321
|
/**
|
|
@@ -282,9 +323,10 @@ declare function mapProviderError(error: string, code?: string): CairnError;
|
|
|
282
323
|
* onto a typed error the write wrappers THROW. Without this a fund-safety refusal would RESOLVE with a phantom
|
|
283
324
|
* `txid:undefined`, so a dApp doing `const { txid } = await fillOffer(...); markPaid(txid)` marks a REFUSED
|
|
284
325
|
* fill as paid. Three buckets:
|
|
285
|
-
* - AMBIGUOUS-INFLIGHT (`SUBMIT_MAYBE_INFLIGHT` / `SUBMIT_DUPLICATE`
|
|
286
|
-
* the locally-computed `txid` to reconcile (never blind-retry).
|
|
287
|
-
* - TRANSIENT (`VERIFY_UNAVAILABLE` / `OFFER_UNKNOWN`): `retryable === true` (nothing
|
|
326
|
+
* - AMBIGUOUS-INFLIGHT (`SUBMIT_MAYBE_INFLIGHT` / `SUBMIT_DUPLICATE` / `WALLET_UNAVAILABLE`): a
|
|
327
|
+
* `SubmitInFlightError` that CARRIES the locally-computed `txid` when given, to reconcile (never blind-retry).
|
|
328
|
+
* - TRANSIENT (`VERIFY_UNAVAILABLE` / `OFFER_UNKNOWN` / `REVIEW_REQUIRED`): `retryable === true` (nothing sent;
|
|
329
|
+
* retry shortly).
|
|
288
330
|
* - DEFINITIVE fund-safety refusal (everything else, incl. an unknown / absent code): `retryable === false`.
|
|
289
331
|
* Fail-closed: an explicit `ok:false` with no recognized code still throws a non-retryable refusal.
|
|
290
332
|
*/
|
|
@@ -350,6 +392,7 @@ declare class Cairn {
|
|
|
350
392
|
private readonly cairnHttp;
|
|
351
393
|
private _spvLight;
|
|
352
394
|
private _spvSeedInflight;
|
|
395
|
+
private _spvReseedInflight;
|
|
353
396
|
private readonly _spvCp;
|
|
354
397
|
private readonly _cairnBase;
|
|
355
398
|
constructor(config?: CairnConfig);
|
|
@@ -386,11 +429,7 @@ declare class Cairn {
|
|
|
386
429
|
* data-availability hiccup; back off (honouring Retry-After) a bounded number of times, then THROW so
|
|
387
430
|
* `sync()` fails closed. A non-dense range is rejected terminally (never retried).
|
|
388
431
|
*
|
|
389
|
-
*
|
|
390
|
-
* mounted on `/explorer/api`, `/trade/api` and `/api/rpc`, not here). A SAME-ORIGIN dApp (hosted on the
|
|
391
|
-
* cairn base) reaches it now; a CROSS-ORIGIN third-party dApp cannot until B7d adds the CORS mount and
|
|
392
|
-
* restarts the cairn service. This code is correct as written; it becomes reachable cross-origin only
|
|
393
|
-
* once B7d ships. This is a recorded dependency, not a blocker for authoring/testing.
|
|
432
|
+
* Cross-origin reach depends on the server's CORS mount on `/api/headers` (the cairn server mounts one).
|
|
394
433
|
*/
|
|
395
434
|
private fetchHeadersBatch;
|
|
396
435
|
/**
|
|
@@ -399,7 +438,8 @@ declare class Cairn {
|
|
|
399
438
|
* commitment, derives the payment recipient + seller from the offer's on-chain AUTHOR (the funding input's
|
|
400
439
|
* prevout owner, txid-committed, NOT the malleable scriptSig), and, if you pass the resolver-SERVED `offer`
|
|
401
440
|
* object, binds its payto/seller + fee/rebate/partial terms to the proven ones. Returns a TRUST-LABELED result
|
|
402
|
-
* (fail-closed on a positive mismatch
|
|
441
|
+
* (fail-closed on a positive mismatch; `transient` on a lagging chain view; final, naming the anchor, for an
|
|
442
|
+
* offer mined below the SPV checkpoint).
|
|
403
443
|
*
|
|
404
444
|
* This is best-effort corroboration, NOT the payment-grade boundary: the Cairn Wallet's OWN on-device
|
|
405
445
|
* fill-SPV (0.2.60+, fails-closed before signing) is that. A dApp settling real value should still clear this
|
|
@@ -407,11 +447,16 @@ declare class Cairn {
|
|
|
407
447
|
*
|
|
408
448
|
* Pass opts.pay (the CSD base units you intend to pay) to receive the PROVEN outputPlan for a whole fill of a
|
|
409
449
|
* non-partial offer, and opts.plannedOutputs to bind your planned per-address sums to it before signing; build
|
|
410
|
-
* EXACTLY the outputPlan, never resolver-served outputs.
|
|
450
|
+
* EXACTLY the outputPlan, never resolver-served outputs. Pass opts.me (your address) and opts.tip (the chain tip
|
|
451
|
+
* height) with pay to have cairnx-core's fillEndorsement and offerFillTooLate judge the fill for you at that tip; without them `ok`
|
|
452
|
+
* says the offer record is proven, not that you can fill it now.
|
|
411
453
|
*/
|
|
412
454
|
verifyOfferForFill(offerId: string, servedOffer?: unknown, opts?: {
|
|
413
455
|
pay?: bigint | string | number;
|
|
414
456
|
plannedOutputs?: Record<string, bigint | string | number>;
|
|
457
|
+
me?: string;
|
|
458
|
+
tip?: number;
|
|
459
|
+
fillTargetId?: string;
|
|
415
460
|
}): Promise<OfferFillCheck>;
|
|
416
461
|
/**
|
|
417
462
|
* Detect + connect the Cairn Wallet (browser only) and attach it as `cairn.wallet`.
|
package/dist/index.d.ts
CHANGED
|
@@ -11,8 +11,8 @@ import { WalletConnection, DetectOptions } from './connect.js';
|
|
|
11
11
|
export { AttestParams, CairnProvider, ConnectResult, FillParams, ProposeParams, ProviderDetail, ProviderInfo, SealClaimParams, SendParams, SignInResult, SiwcParams, SiwcResult, TxResult, WalletCapabilities, WalletPermission, connect, detectProvider, discoverProviders, getWallet, isInstalled } from './connect.js';
|
|
12
12
|
import { InclusionResult } from '@inversealtruism/csd-light';
|
|
13
13
|
export { CairnController, CairnControllerOptions, CairnState } from './controller.js';
|
|
14
|
+
import { NodeTxJson } from '@inversealtruism/csd-tx';
|
|
14
15
|
import '@inversealtruism/csd-client';
|
|
15
|
-
import '@inversealtruism/csd-tx';
|
|
16
16
|
import '@inversealtruism/csd-codec';
|
|
17
17
|
import '@inversealtruism/csd-crypto';
|
|
18
18
|
|
|
@@ -138,6 +138,9 @@ declare class NamesClient {
|
|
|
138
138
|
/** The trust-labeled verdict. `ok:false` + `transient:true` = a retryable chain-catching-up soft-fail (NOT a
|
|
139
139
|
* proven mismatch). `payto`/`seller`/`terms` are populated whenever they could be merkle-derived. */
|
|
140
140
|
interface OfferFillCheck {
|
|
141
|
+
/** `true`: the offer record is proven and no check refused. Without `me` and `tip` it does not say the offer
|
|
142
|
+
* is fillable by you now (it may be bound to another taker, held by someone else's live claim or
|
|
143
|
+
* reservation, or too close to its expiry), and with `sized: false` it does not size your fill. */
|
|
141
144
|
ok: boolean;
|
|
142
145
|
/** "verified" = merkle-proven inclusion + on-chain author; "proof-consistent" = a proof that folds but the
|
|
143
146
|
* header could not be PoW-verified (indexer-trusted); "unverified" = could not prove. */
|
|
@@ -149,17 +152,37 @@ interface OfferFillCheck {
|
|
|
149
152
|
/** Minted by cairnx-core's `provenOfferTerms`, so it can be passed back to `bindOfferTerms` without the opt-out. */
|
|
150
153
|
terms?: MintedProvenOfferTerms;
|
|
151
154
|
blockHeight?: number;
|
|
155
|
+
/** The proven Propose's `expires_epoch`. */
|
|
156
|
+
expiresEpoch?: number;
|
|
157
|
+
/** The first block height at which CairnX treats the offer as expired (cairnx-core `offerExpiryHeightOf` over the
|
|
158
|
+
* proven expiry and anchor). A fill must be mined below it; with `me` and `tip` a fill with less than
|
|
159
|
+
* cairnx-core's `FILL_TIP_MARGIN` blocks of cushion is refused, without them compare it with your tip. */
|
|
160
|
+
expiresAt?: number;
|
|
152
161
|
/** B7b (REBIND W3/M1): the PROVEN CSD outputs to build for `pay` (a WHOLE fill of a non-partial offer),
|
|
153
162
|
* sized from the merkle-proven offer by the single-sourced `fillOutputPlan`. Present only when `pay` was
|
|
154
|
-
* passed, the served offer carried a `status
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
163
|
+
* passed, the served offer carried a `status`, the offer could be sized, and neither the served status, the
|
|
164
|
+
* endorsement nor the expiry cushion refuses the fill (other refusals keep the proven plan; branch on `ok`).
|
|
165
|
+
* Build EXACTLY these; never the resolver-served outputs a lying resolver could redirect. A partial
|
|
166
|
+
* (min-bearing) offer is left unsized (its running paid/delivered is not provable at this corroboration layer;
|
|
167
|
+
* the wallet's fill-SPV is the payment-grade sizer). Liveness is never proven here: the plan is sized only
|
|
168
|
+
* for the status the resolver served, so an offer with no served status gets no plan. */
|
|
159
169
|
outputPlan?: {
|
|
160
170
|
to: string;
|
|
161
171
|
value: bigint;
|
|
162
172
|
}[];
|
|
173
|
+
/** Present when `pay` was passed: `true` when `outputPlan` holds the proven outputs for this pay, `false` when
|
|
174
|
+
* the fill could not be sized from proven data (`planReason` says why). `ok: true` with `sized: false` is a
|
|
175
|
+
* verdict on the offer record, not on this fill. */
|
|
176
|
+
sized?: boolean;
|
|
177
|
+
/** Present when `me` and `tip` were passed: cairnx-core's `fillEndorsement` over the served state after the
|
|
178
|
+
* binds. "refused" answers `ok: false`; "not-endorsable" (a token-priced want) is not a refusal. */
|
|
179
|
+
endorsement?: {
|
|
180
|
+
verdict: "endorsed" | "refused" | "not-endorsable";
|
|
181
|
+
reason: string;
|
|
182
|
+
};
|
|
183
|
+
/** Present with `endorsement`: the proposal id the fill's attest must target at `tip` (cairnx-core
|
|
184
|
+
* `fillTargetId`: the offer id, or the fclaim txid while a live reservation routes the offer). */
|
|
185
|
+
fillTarget?: string;
|
|
163
186
|
/** Present when `plannedOutputs` was passed: `true` when they were bound to `outputPlan` (a mismatch
|
|
164
187
|
* refuses with `ok: false`), `false` when there was no proven plan to bind them to (`planReason` says why).
|
|
165
188
|
* `ok: true` with `planBound: false` means your planned outputs were NOT checked. */
|
|
@@ -174,7 +197,7 @@ interface OfferFillCheck {
|
|
|
174
197
|
* for the prevout-owner author bind. Pass `servedOffer` (the resolver's offer object) to also bind its
|
|
175
198
|
* payto/seller/terms to the proven values. The FULL object is required: a served offer missing want.payto
|
|
176
199
|
* or seller is refused (P75-5). A token-priced offer's served want.ticker/want.amount are bound verbatim to
|
|
177
|
-
* the record. See the module header for the trust posture.
|
|
200
|
+
* the record. A served status other than open refuses. See the module header for the trust posture.
|
|
178
201
|
*/
|
|
179
202
|
declare function preverifyOffer(opts: {
|
|
180
203
|
light: {
|
|
@@ -188,17 +211,27 @@ declare function preverifyOffer(opts: {
|
|
|
188
211
|
/** B7b (REBIND W3/M1): the CSD base units you intend to pay. When given, the result carries `outputPlan`
|
|
189
212
|
* (the PROVEN CSD outputs to build for a WHOLE fill of a non-partial offer, sized by the single-sourced
|
|
190
213
|
* `fillOutputPlan`) and, if you also pass `plannedOutputs`, binds them EXACTLY to that proven plan.
|
|
191
|
-
* A partial (min-bearing) offer is left unsized here; the
|
|
214
|
+
* A partial (min-bearing) offer is left unsized here (`sized: false`); with the served offer, a pay its
|
|
215
|
+
* served progress says delivers nothing (below the minimum) is refused. The wallet's fill-SPV sizes it. */
|
|
192
216
|
pay?: bigint | string | number;
|
|
193
217
|
/** B7b: your planned per-address CSD sums (the outputs you WILL build), bound both ways to `outputPlan`.
|
|
194
218
|
* Requires `pay`. A missing/low leg is a doomed underpay; an extra/high leg is a W3 overpay or an N26
|
|
195
|
-
* smuggled output - both refused. */
|
|
219
|
+
* smuggled output - both refused. On a token-priced offer any positive CSD leg is refused. */
|
|
196
220
|
plannedOutputs?: Record<string, bigint | string | number>;
|
|
221
|
+
/** Your address, the one that signs the fill. With `tip` (and `pay`), the result carries cairnx-core's
|
|
222
|
+
* `fillEndorsement` over the served state: a taker bound to another address, an open CSD offer you hold no
|
|
223
|
+
* live claim or reservation on, or an attest target the offer's routing rejects is refused, and so is a fill
|
|
224
|
+
* that cairnx-core's `offerFillTooLate` says is too close to the offer's expiry. */
|
|
225
|
+
me?: string;
|
|
226
|
+
/** The chain tip height you sign at (for example `(await cairn.chain.tip()).height`). Goes with `me`. */
|
|
227
|
+
tip?: number;
|
|
228
|
+
/** The proposal id your attest will target: the offer id, or the fclaim txid while your reservation routes it. */
|
|
229
|
+
fillTargetId?: string;
|
|
197
230
|
}): Promise<OfferFillCheck>;
|
|
198
231
|
|
|
199
232
|
/** Stable machine-readable error codes (branch on these, not the message text). */
|
|
200
|
-
type CairnErrorCode = "NOT_INSTALLED" | "USER_REJECTED" | "WALLET_LOCKED" | "UNSUPPORTED_METHOD" | "HTTP_ERROR" | "CONTENT_VERIFICATION" | "CONTENT_NOT_JSON" | "ACCOUNT_CHANGED" | "FIRST_PARTY_ONLY" | "RATE_LIMITED" | "APPROVAL_CLOSED" | "FORBIDDEN" | "INTERNAL" | "GHOST_INPUTS_SKIPPED" | "VERIFY_UNAVAILABLE" | "VERIFY_TAMPER" | "INSUFFICIENT" | "TOO_MANY_INPUTS" | "FEE_TOO_LOW" | "FEE_CAP" | "BAD_FEE" | "ZERO_ADDR_REFUSED" | "BAD_OUTPUTS" | "NO_OUTPUTS" | "BAD_REQUEST" | "OFFER_UNKNOWN" | "FILL_UNSAFE" | "FILL_WRONG_TARGET" | "SOURCE_DIVERGENCE" | "SUBMIT_REJECTED" | "SUBMIT_MAYBE_INFLIGHT" | "SUBMIT_DUPLICATE" | "NOTHING_TO_CONSOLIDATE" | "OFFER_SOURCE_CONFLICT" | "FILL_LEGACY_SUNSET" | "VERIFY_HORIZON" | "VERIFY_UNREPRESENTABLE" | "WALLET_UNAVAILABLE" | "REVIEW_REQUIRED" | "UNKNOWN";
|
|
201
|
-
declare const SDK_VERSION = "0.8.
|
|
233
|
+
type CairnErrorCode = "NOT_INSTALLED" | "USER_REJECTED" | "WALLET_LOCKED" | "UNSUPPORTED_METHOD" | "HTTP_ERROR" | "CONTENT_VERIFICATION" | "CONTENT_NOT_JSON" | "ACCOUNT_CHANGED" | "FIRST_PARTY_ONLY" | "RATE_LIMITED" | "APPROVAL_CLOSED" | "FORBIDDEN" | "INTERNAL" | "GHOST_INPUTS_SKIPPED" | "VERIFY_UNAVAILABLE" | "VERIFY_TAMPER" | "INSUFFICIENT" | "TOO_MANY_INPUTS" | "FEE_TOO_LOW" | "FEE_CAP" | "BAD_FEE" | "ZERO_ADDR_REFUSED" | "BAD_OUTPUTS" | "NO_OUTPUTS" | "BAD_REQUEST" | "OFFER_UNKNOWN" | "FILL_UNSAFE" | "FILL_WRONG_TARGET" | "SOURCE_DIVERGENCE" | "SUBMIT_REJECTED" | "SUBMIT_MAYBE_INFLIGHT" | "SUBMIT_DUPLICATE" | "NOTHING_TO_CONSOLIDATE" | "OFFER_SOURCE_CONFLICT" | "FILL_LEGACY_SUNSET" | "VERIFY_HORIZON" | "VERIFY_UNREPRESENTABLE" | "WALLET_UNAVAILABLE" | "REVIEW_REQUIRED" | "SEAL_NOT_MINED" | "RESERVATION_DENIED" | "RPC_BLOCK_MISMATCH" | "WALLET_TIMEOUT" | "UNKNOWN";
|
|
234
|
+
declare const SDK_VERSION = "0.8.2";
|
|
202
235
|
interface CairnErrorOptions {
|
|
203
236
|
code?: CairnErrorCode;
|
|
204
237
|
docsPath?: string;
|
|
@@ -218,7 +251,7 @@ declare class CairnError extends Error {
|
|
|
218
251
|
/** Relative docs path (under the SDK docs base), if any. */
|
|
219
252
|
readonly docsPath?: string;
|
|
220
253
|
/** The cairn-sdk version that produced this error. */
|
|
221
|
-
readonly version = "0.8.
|
|
254
|
+
readonly version = "0.8.2";
|
|
222
255
|
/**
|
|
223
256
|
* Whether a dApp may safely AUTO-retry this failure. `false` for fund-safety refusals and user-intent
|
|
224
257
|
* declines (the default); `true` only for provably transient infra faults where nothing was signed.
|
|
@@ -261,20 +294,28 @@ declare class ContentVerificationError extends CairnError {
|
|
|
261
294
|
constructor(expected: string);
|
|
262
295
|
}
|
|
263
296
|
/**
|
|
264
|
-
* The
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
297
|
+
* The outcome of a write is AMBIGUOUS: the tx MAY already be in the mempool. Thrown by the write wrappers for
|
|
298
|
+
* the nested `SUBMIT_MAYBE_INFLIGHT` (request threw / timed out / 5xx gateway / unreadable body) and
|
|
299
|
+
* `SUBMIT_DUPLICATE` (node answered "already present or mempool conflict") codes, for `WALLET_UNAVAILABLE` on a
|
|
300
|
+
* write (the page lost the wallet's reply, which may come after the submit), for `WALLET_TIMEOUT` (the call
|
|
301
|
+
* outlasted the connection timeout while the request stays open in the wallet), and by `Chain.send` when the
|
|
302
|
+
* submit request fails after signing without a 4xx answer (a 4xx is `SUBMIT_REJECTED`). It CARRIES the
|
|
303
|
+
* locally-computed consensus `txid` when one is known so a dApp can RECONCILE (check the explorer / balance)
|
|
304
|
+
* instead of blindly re-broadcasting, which would re-invite the double-broadcast this contract exists to prevent
|
|
305
|
+
* (F14). It is NOT retryable (`retryable === false`);
|
|
306
|
+
* `maybeSent === true` distinguishes it from a definitely-not-sent terminal refusal. See WALLET-ERROR-CODES.md
|
|
307
|
+
* in the cairn-wallet repo.
|
|
271
308
|
*/
|
|
272
309
|
declare class SubmitInFlightError extends CairnError {
|
|
273
|
-
/** The locally-computed consensus txid to reconcile against the chain (
|
|
310
|
+
/** The locally-computed consensus txid to reconcile against the chain (undefined when it is not known). */
|
|
274
311
|
readonly txid?: string;
|
|
275
|
-
/**
|
|
312
|
+
/** The signed transaction, set only when `Chain.send` threw this (a wallet write keeps it in the wallet).
|
|
313
|
+
* `chain.submit(nodeJson)` resends it unchanged: the same coins under the same txid, so it cannot pay twice,
|
|
314
|
+
* where a new send may select other coins. */
|
|
315
|
+
readonly nodeJson?: NodeTxJson;
|
|
316
|
+
/** Always true: the tx MAY be in the mempool. Reconcile via `txid` or the balance; never blind-retry. */
|
|
276
317
|
readonly maybeSent = true;
|
|
277
|
-
constructor(message: string, code: "SUBMIT_MAYBE_INFLIGHT" | "SUBMIT_DUPLICATE", txid?: string);
|
|
318
|
+
constructor(message: string, code: "SUBMIT_MAYBE_INFLIGHT" | "SUBMIT_DUPLICATE" | "WALLET_UNAVAILABLE" | "WALLET_TIMEOUT", txid?: string, cause?: unknown, nodeJson?: NodeTxJson);
|
|
278
319
|
}
|
|
279
320
|
declare function mapProviderError(error: string, code?: string): CairnError;
|
|
280
321
|
/**
|
|
@@ -282,9 +323,10 @@ declare function mapProviderError(error: string, code?: string): CairnError;
|
|
|
282
323
|
* onto a typed error the write wrappers THROW. Without this a fund-safety refusal would RESOLVE with a phantom
|
|
283
324
|
* `txid:undefined`, so a dApp doing `const { txid } = await fillOffer(...); markPaid(txid)` marks a REFUSED
|
|
284
325
|
* fill as paid. Three buckets:
|
|
285
|
-
* - AMBIGUOUS-INFLIGHT (`SUBMIT_MAYBE_INFLIGHT` / `SUBMIT_DUPLICATE`
|
|
286
|
-
* the locally-computed `txid` to reconcile (never blind-retry).
|
|
287
|
-
* - TRANSIENT (`VERIFY_UNAVAILABLE` / `OFFER_UNKNOWN`): `retryable === true` (nothing
|
|
326
|
+
* - AMBIGUOUS-INFLIGHT (`SUBMIT_MAYBE_INFLIGHT` / `SUBMIT_DUPLICATE` / `WALLET_UNAVAILABLE`): a
|
|
327
|
+
* `SubmitInFlightError` that CARRIES the locally-computed `txid` when given, to reconcile (never blind-retry).
|
|
328
|
+
* - TRANSIENT (`VERIFY_UNAVAILABLE` / `OFFER_UNKNOWN` / `REVIEW_REQUIRED`): `retryable === true` (nothing sent;
|
|
329
|
+
* retry shortly).
|
|
288
330
|
* - DEFINITIVE fund-safety refusal (everything else, incl. an unknown / absent code): `retryable === false`.
|
|
289
331
|
* Fail-closed: an explicit `ok:false` with no recognized code still throws a non-retryable refusal.
|
|
290
332
|
*/
|
|
@@ -350,6 +392,7 @@ declare class Cairn {
|
|
|
350
392
|
private readonly cairnHttp;
|
|
351
393
|
private _spvLight;
|
|
352
394
|
private _spvSeedInflight;
|
|
395
|
+
private _spvReseedInflight;
|
|
353
396
|
private readonly _spvCp;
|
|
354
397
|
private readonly _cairnBase;
|
|
355
398
|
constructor(config?: CairnConfig);
|
|
@@ -386,11 +429,7 @@ declare class Cairn {
|
|
|
386
429
|
* data-availability hiccup; back off (honouring Retry-After) a bounded number of times, then THROW so
|
|
387
430
|
* `sync()` fails closed. A non-dense range is rejected terminally (never retried).
|
|
388
431
|
*
|
|
389
|
-
*
|
|
390
|
-
* mounted on `/explorer/api`, `/trade/api` and `/api/rpc`, not here). A SAME-ORIGIN dApp (hosted on the
|
|
391
|
-
* cairn base) reaches it now; a CROSS-ORIGIN third-party dApp cannot until B7d adds the CORS mount and
|
|
392
|
-
* restarts the cairn service. This code is correct as written; it becomes reachable cross-origin only
|
|
393
|
-
* once B7d ships. This is a recorded dependency, not a blocker for authoring/testing.
|
|
432
|
+
* Cross-origin reach depends on the server's CORS mount on `/api/headers` (the cairn server mounts one).
|
|
394
433
|
*/
|
|
395
434
|
private fetchHeadersBatch;
|
|
396
435
|
/**
|
|
@@ -399,7 +438,8 @@ declare class Cairn {
|
|
|
399
438
|
* commitment, derives the payment recipient + seller from the offer's on-chain AUTHOR (the funding input's
|
|
400
439
|
* prevout owner, txid-committed, NOT the malleable scriptSig), and, if you pass the resolver-SERVED `offer`
|
|
401
440
|
* object, binds its payto/seller + fee/rebate/partial terms to the proven ones. Returns a TRUST-LABELED result
|
|
402
|
-
* (fail-closed on a positive mismatch
|
|
441
|
+
* (fail-closed on a positive mismatch; `transient` on a lagging chain view; final, naming the anchor, for an
|
|
442
|
+
* offer mined below the SPV checkpoint).
|
|
403
443
|
*
|
|
404
444
|
* This is best-effort corroboration, NOT the payment-grade boundary: the Cairn Wallet's OWN on-device
|
|
405
445
|
* fill-SPV (0.2.60+, fails-closed before signing) is that. A dApp settling real value should still clear this
|
|
@@ -407,11 +447,16 @@ declare class Cairn {
|
|
|
407
447
|
*
|
|
408
448
|
* Pass opts.pay (the CSD base units you intend to pay) to receive the PROVEN outputPlan for a whole fill of a
|
|
409
449
|
* non-partial offer, and opts.plannedOutputs to bind your planned per-address sums to it before signing; build
|
|
410
|
-
* EXACTLY the outputPlan, never resolver-served outputs.
|
|
450
|
+
* EXACTLY the outputPlan, never resolver-served outputs. Pass opts.me (your address) and opts.tip (the chain tip
|
|
451
|
+
* height) with pay to have cairnx-core's fillEndorsement and offerFillTooLate judge the fill for you at that tip; without them `ok`
|
|
452
|
+
* says the offer record is proven, not that you can fill it now.
|
|
411
453
|
*/
|
|
412
454
|
verifyOfferForFill(offerId: string, servedOffer?: unknown, opts?: {
|
|
413
455
|
pay?: bigint | string | number;
|
|
414
456
|
plannedOutputs?: Record<string, bigint | string | number>;
|
|
457
|
+
me?: string;
|
|
458
|
+
tip?: number;
|
|
459
|
+
fillTargetId?: string;
|
|
415
460
|
}): Promise<OfferFillCheck>;
|
|
416
461
|
/**
|
|
417
462
|
* Detect + connect the Cairn Wallet (browser only) and attach it as `cairn.wallet`.
|