@inversealtruism/cairn-sdk 0.3.2 → 0.4.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/board.cjs +1 -1
- package/dist/board.js +2 -2
- package/dist/{chunk-JKC5K253.js → chunk-2L5QNDAE.js} +1 -1
- package/dist/{chunk-CZWDA3A5.js → chunk-2ZML7IKV.js} +1 -1
- package/dist/{chunk-AGU6K5EZ.js → chunk-GTTLMWGY.js} +1 -1
- package/dist/{chunk-FMXNJQWL.js → chunk-MREZG2HN.js} +2 -2
- package/dist/{chunk-BN3PFJDY.js → chunk-RKR3JMIA.js} +34 -16
- package/dist/connect.cjs +34 -17
- package/dist/connect.d.cts +7 -1
- package/dist/connect.d.ts +7 -1
- package/dist/connect.js +2 -2
- package/dist/content.cjs +1 -1
- package/dist/content.js +2 -2
- package/dist/controller.cjs +34 -17
- package/dist/controller.js +3 -3
- package/dist/index.cjs +157 -31
- package/dist/index.d.cts +39 -13
- package/dist/index.d.ts +39 -13
- package/dist/index.js +134 -19
- package/dist/react.cjs +34 -17
- package/dist/react.js +3 -3
- package/package.json +18 -25
package/dist/index.cjs
CHANGED
|
@@ -46,16 +46,21 @@ __export(index_exports, {
|
|
|
46
46
|
discoverProviders: () => discoverProviders,
|
|
47
47
|
errorCode: () => errorCode,
|
|
48
48
|
feeBpsAt: () => import_cairnx_core2.feeBpsAt,
|
|
49
|
+
fillEndorsement: () => import_cairnx_core2.fillEndorsement,
|
|
50
|
+
fillIsSafe: () => import_cairnx_core2.fillIsSafe,
|
|
51
|
+
fillOutputPlan: () => import_cairnx_core2.fillOutputPlan,
|
|
49
52
|
getWallet: () => getWallet,
|
|
50
53
|
isInstalled: () => isInstalled,
|
|
51
54
|
mapProviderError: () => mapProviderError,
|
|
52
55
|
mapSubmitResultError: () => mapSubmitResultError,
|
|
53
|
-
preverifyOffer: () => preverifyOffer
|
|
56
|
+
preverifyOffer: () => preverifyOffer,
|
|
57
|
+
previewFill: () => import_cairnx_core2.previewFill,
|
|
58
|
+
requiredFillOutputs: () => import_cairnx_core2.requiredFillOutputs
|
|
54
59
|
});
|
|
55
60
|
module.exports = __toCommonJS(index_exports);
|
|
56
61
|
|
|
57
62
|
// src/errors.ts
|
|
58
|
-
var SDK_VERSION = "0.
|
|
63
|
+
var SDK_VERSION = "0.4.0";
|
|
59
64
|
var DOCS_BASE = "https://cairn-substrate.com/docs/sdk";
|
|
60
65
|
var CairnError = class extends Error {
|
|
61
66
|
/** Stable machine code for programmatic branching. */
|
|
@@ -147,7 +152,7 @@ var SubmitInFlightError = class extends CairnError {
|
|
|
147
152
|
this.txid = txid3;
|
|
148
153
|
}
|
|
149
154
|
};
|
|
150
|
-
var NATIVE_CODES = /* @__PURE__ */ new Set(["
|
|
155
|
+
var NATIVE_CODES = /* @__PURE__ */ new Set(["FIRST_PARTY_ONLY", "RATE_LIMITED", "FORBIDDEN", "INTERNAL"]);
|
|
151
156
|
var NESTED_TRANSIENT = /* @__PURE__ */ new Set(["VERIFY_UNAVAILABLE", "OFFER_UNKNOWN"]);
|
|
152
157
|
var NESTED_TERMINAL = /* @__PURE__ */ new Set([
|
|
153
158
|
"FILL_UNSAFE",
|
|
@@ -1015,6 +1020,7 @@ var NamesClient = class {
|
|
|
1015
1020
|
};
|
|
1016
1021
|
|
|
1017
1022
|
// src/connect.ts
|
|
1023
|
+
var DEFAULT_PROVIDER_TIMEOUT_MS = 10 * 6e4;
|
|
1018
1024
|
function discoverProviders(opts = {}) {
|
|
1019
1025
|
const timeoutMs = opts.timeoutMs ?? 1e3;
|
|
1020
1026
|
return new Promise((resolve) => {
|
|
@@ -1094,8 +1100,24 @@ function unwrapWrite(reply) {
|
|
|
1094
1100
|
var WalletConnection = class {
|
|
1095
1101
|
provider;
|
|
1096
1102
|
_addr = null;
|
|
1097
|
-
|
|
1103
|
+
/** B7c: per-call provider timeout (ms). GENEROUS by default so it never rejects an in-flight human
|
|
1104
|
+
* approval; 0 disables it. Every provider call (writes especially) races against it. */
|
|
1105
|
+
_timeoutMs;
|
|
1106
|
+
constructor(provider, opts = {}) {
|
|
1098
1107
|
this.provider = provider;
|
|
1108
|
+
this._timeoutMs = opts.timeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS;
|
|
1109
|
+
}
|
|
1110
|
+
// B7c: race a provider call against the per-call timeout. On timeout, throw a fail-closed CairnError
|
|
1111
|
+
// (retryable:false: a write may already have reached the wallet, so never invite a blind auto-retry). The
|
|
1112
|
+
// genuine wallet resolves quickly once the user acts; this only fires on a truly hung/absent response.
|
|
1113
|
+
call(op, label) {
|
|
1114
|
+
const ms = this._timeoutMs;
|
|
1115
|
+
if (!Number.isFinite(ms) || ms <= 0) return Promise.resolve(op());
|
|
1116
|
+
let timer;
|
|
1117
|
+
const timeout = new Promise((_, reject) => {
|
|
1118
|
+
timer = setTimeout(() => reject(new CairnError(`the wallet did not respond to ${label} within ${ms}ms`, { retryable: false })), ms);
|
|
1119
|
+
});
|
|
1120
|
+
return Promise.race([Promise.resolve(op()), timeout]).finally(() => clearTimeout(timer));
|
|
1099
1121
|
}
|
|
1100
1122
|
/** The wallet's version string (e.g. "0.2.x"). */
|
|
1101
1123
|
get version() {
|
|
@@ -1107,13 +1129,13 @@ var WalletConnection = class {
|
|
|
1107
1129
|
}
|
|
1108
1130
|
/** Request connection. First time per origin prompts the user; afterwards may be silent. */
|
|
1109
1131
|
async connect() {
|
|
1110
|
-
const { addr } = unwrap(await this.provider.connect());
|
|
1132
|
+
const { addr } = unwrap(await this.call(() => this.provider.connect(), "connect"));
|
|
1111
1133
|
this._addr = addr;
|
|
1112
1134
|
return addr;
|
|
1113
1135
|
}
|
|
1114
1136
|
/** Get the connected address (does not force a new connection prompt if already consented). */
|
|
1115
1137
|
async getAddress() {
|
|
1116
|
-
const { addr } = unwrap(await this.provider.getAddress());
|
|
1138
|
+
const { addr } = unwrap(await this.call(() => this.provider.getAddress(), "getAddress"));
|
|
1117
1139
|
this._addr = addr;
|
|
1118
1140
|
return addr;
|
|
1119
1141
|
}
|
|
@@ -1126,7 +1148,7 @@ var WalletConnection = class {
|
|
|
1126
1148
|
if (typeof this.provider.signIn !== "function") {
|
|
1127
1149
|
return Promise.reject(new UnsupportedMethodError("this wallet does not expose signIn()"));
|
|
1128
1150
|
}
|
|
1129
|
-
return
|
|
1151
|
+
return this.call(() => this.provider.signIn(), "signIn").then(unwrap);
|
|
1130
1152
|
}
|
|
1131
1153
|
/**
|
|
1132
1154
|
* Audience-bound "Sign in with CSD" (SIWC) — the secure, replay-resistant third-party login.
|
|
@@ -1142,7 +1164,7 @@ var WalletConnection = class {
|
|
|
1142
1164
|
if (typeof this.provider.signInWithCsd !== "function") {
|
|
1143
1165
|
return Promise.reject(new UnsupportedMethodError("this wallet predates Sign-in-with-CSD \u2014 ask the user to update the Cairn Wallet"));
|
|
1144
1166
|
}
|
|
1145
|
-
return
|
|
1167
|
+
return this.call(() => this.provider.signInWithCsd(params), "signInWithCsd").then(unwrap);
|
|
1146
1168
|
}
|
|
1147
1169
|
/** True if this wallet supports audience-bound SIWC (safe to call `signInWithCsd`). */
|
|
1148
1170
|
get supportsSiwc() {
|
|
@@ -1152,7 +1174,7 @@ var WalletConnection = class {
|
|
|
1152
1174
|
async getCapabilities() {
|
|
1153
1175
|
if (typeof this.provider.getCapabilities !== "function") return null;
|
|
1154
1176
|
try {
|
|
1155
|
-
return await this.provider.getCapabilities();
|
|
1177
|
+
return await this.call(() => this.provider.getCapabilities(), "getCapabilities");
|
|
1156
1178
|
} catch {
|
|
1157
1179
|
return null;
|
|
1158
1180
|
}
|
|
@@ -1168,24 +1190,24 @@ var WalletConnection = class {
|
|
|
1168
1190
|
if (typeof this.provider.fillOffer !== "function") {
|
|
1169
1191
|
return Promise.reject(new UnsupportedMethodError("this wallet predates fillOffer() \u2014 ask the user to update the Cairn Wallet"));
|
|
1170
1192
|
}
|
|
1171
|
-
return
|
|
1193
|
+
return this.call(() => this.provider.fillOffer(params), "fillOffer").then(unwrapWrite);
|
|
1172
1194
|
}
|
|
1173
1195
|
/** This origin's current permission grant (EIP-2255-style). Silent; [] if none / unsupported. */
|
|
1174
1196
|
async getPermissions() {
|
|
1175
1197
|
if (typeof this.provider.getPermissions !== "function") return [];
|
|
1176
|
-
return unwrap(await this.provider.getPermissions());
|
|
1198
|
+
return unwrap(await this.call(() => this.provider.getPermissions(), "getPermissions"));
|
|
1177
1199
|
}
|
|
1178
1200
|
/** Explicitly request permission to see the address (prompts, like connect). */
|
|
1179
1201
|
requestPermissions() {
|
|
1180
1202
|
if (typeof this.provider.requestPermissions !== "function") {
|
|
1181
1203
|
return Promise.reject(new UnsupportedMethodError("this wallet predates requestPermissions \u2014 use connect()"));
|
|
1182
1204
|
}
|
|
1183
|
-
return
|
|
1205
|
+
return this.call(() => this.provider.requestPermissions(), "requestPermissions").then(unwrap);
|
|
1184
1206
|
}
|
|
1185
1207
|
/** Revoke THIS origin's own access (silent). Returns { revoked }. Safe no-op on older wallets. */
|
|
1186
1208
|
async revokePermissions() {
|
|
1187
1209
|
if (typeof this.provider.revokePermissions !== "function") return { revoked: false };
|
|
1188
|
-
return unwrap(await this.provider.revokePermissions());
|
|
1210
|
+
return unwrap(await this.call(() => this.provider.revokePermissions(), "revokePermissions"));
|
|
1189
1211
|
}
|
|
1190
1212
|
/**
|
|
1191
1213
|
* Subscribe to provider events. `accountsChanged` fires with `[]` when this site loses access
|
|
@@ -1201,26 +1223,26 @@ var WalletConnection = class {
|
|
|
1201
1223
|
}
|
|
1202
1224
|
/** Send CSD (always prompts with clear-signing; wallet picks inputs + returns change to itself). */
|
|
1203
1225
|
send(params) {
|
|
1204
|
-
return
|
|
1226
|
+
return this.call(() => this.provider.send(params), "send").then(unwrapWrite);
|
|
1205
1227
|
}
|
|
1206
1228
|
/** Low-level Propose (always prompts). Prefer `cairn.board.propose()` which computes the hash/uri/expiry. */
|
|
1207
1229
|
propose(params) {
|
|
1208
|
-
return
|
|
1230
|
+
return this.call(() => this.provider.propose(params), "propose").then(unwrapWrite);
|
|
1209
1231
|
}
|
|
1210
1232
|
/** Attest/support a proposal (always prompts). */
|
|
1211
1233
|
attest(params) {
|
|
1212
|
-
return
|
|
1234
|
+
return this.call(() => this.provider.attest(params), "attest").then(unwrapWrite);
|
|
1213
1235
|
}
|
|
1214
1236
|
/** Seal a commit-reveal claim (always prompts; salt stays inside the wallet). */
|
|
1215
1237
|
sealClaim(params) {
|
|
1216
|
-
return
|
|
1238
|
+
return this.call(() => this.provider.sealClaim(params), "sealClaim").then(unwrapWrite);
|
|
1217
1239
|
}
|
|
1218
1240
|
/** Reveal a previously sealed claim by its sealing txid (always prompts). */
|
|
1219
1241
|
revealClaim(txid3) {
|
|
1220
1242
|
if (typeof txid3 !== "string" || !txid3) {
|
|
1221
1243
|
return Promise.reject(new UnsupportedMethodError("revealClaim requires the sealing txid"));
|
|
1222
1244
|
}
|
|
1223
|
-
return
|
|
1245
|
+
return this.call(() => this.provider.revealClaim(txid3), "revealClaim").then(unwrapWrite);
|
|
1224
1246
|
}
|
|
1225
1247
|
};
|
|
1226
1248
|
async function getWallet(opts = {}) {
|
|
@@ -1239,6 +1261,23 @@ var import_cairnx_core2 = require("@inversealtruism/cairnx-core");
|
|
|
1239
1261
|
var ADDR = /^0x[0-9a-f]{40}$/;
|
|
1240
1262
|
var HASH = /^0x[0-9a-f]{64}$/;
|
|
1241
1263
|
var COINBASE = "0x" + "00".repeat(32);
|
|
1264
|
+
function bindPlannedSums(planned, proven) {
|
|
1265
|
+
const provenMap = new Map(proven.map((o) => [o.to.toLowerCase(), o.value]));
|
|
1266
|
+
const plannedMap = /* @__PURE__ */ new Map();
|
|
1267
|
+
try {
|
|
1268
|
+
for (const [a, v] of Object.entries(planned)) {
|
|
1269
|
+
const k = String(a).toLowerCase();
|
|
1270
|
+
plannedMap.set(k, (plannedMap.get(k) ?? 0n) + BigInt(v));
|
|
1271
|
+
}
|
|
1272
|
+
} catch {
|
|
1273
|
+
return "invalid plannedOutputs (amounts must be base-unit integers)";
|
|
1274
|
+
}
|
|
1275
|
+
for (const k of /* @__PURE__ */ new Set([...provenMap.keys(), ...plannedMap.keys()])) {
|
|
1276
|
+
if ((provenMap.get(k) ?? 0n) !== (plannedMap.get(k) ?? 0n))
|
|
1277
|
+
return `your planned payment doesn't match the proven fill outputs (${k}: planned ${(plannedMap.get(k) ?? 0n).toString()}, proven ${(provenMap.get(k) ?? 0n).toString()}) - refusing (an overpay past the proven amount is unrecoverable, and a missing or low leg is a doomed underpay)`;
|
|
1278
|
+
}
|
|
1279
|
+
return void 0;
|
|
1280
|
+
}
|
|
1242
1281
|
async function provenAuthor(client, provenTx) {
|
|
1243
1282
|
const in0 = provenTx.inputs?.[0];
|
|
1244
1283
|
if (!in0 || String(in0.prevTxid).toLowerCase() === COINBASE && Number(in0.vout) === 4294967295) return null;
|
|
@@ -1294,17 +1333,35 @@ async function preverifyOffer(opts) {
|
|
|
1294
1333
|
return { ok: false, trust: "unverified", reason: "the offer record doesn't match the on-chain (merkle-proven) commitment" };
|
|
1295
1334
|
const seller = await provenAuthor(opts.client, provenTx);
|
|
1296
1335
|
if (!seller) return { ok: false, trust: "verified", transient: true, blockHeight, reason: "couldn't prove the offer's on-chain author yet; the chain view may be catching up, try again" };
|
|
1336
|
+
const offerRec = rec;
|
|
1297
1337
|
const w = rec.want ?? {};
|
|
1298
1338
|
const payto = w.payto && ADDR.test(String(w.payto).toLowerCase()) ? String(w.payto).toLowerCase() : seller;
|
|
1299
|
-
const terms =
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1339
|
+
const terms = (0, import_cairnx_core2.provenOfferTerms)(offerRec, blockHeight);
|
|
1340
|
+
let outputPlan;
|
|
1341
|
+
let sumsMismatch;
|
|
1342
|
+
if (opts.pay !== void 0 && opts.pay !== null && !(0, import_cairnx_core2.isTokenWant)(offerRec.want) && offerRec.min === void 0) {
|
|
1343
|
+
const provenState = {
|
|
1344
|
+
id,
|
|
1345
|
+
seller,
|
|
1346
|
+
give: offerRec.give,
|
|
1347
|
+
want: offerRec.want,
|
|
1348
|
+
taker: offerRec.taker,
|
|
1349
|
+
bid: offerRec.bid,
|
|
1350
|
+
status: "open",
|
|
1351
|
+
expiresEpoch: 0,
|
|
1352
|
+
height: blockHeight,
|
|
1353
|
+
feeBps: terms.feeBps
|
|
1354
|
+
};
|
|
1355
|
+
const plan = (0, import_cairnx_core2.fillOutputPlan)(provenState, opts.pay);
|
|
1356
|
+
if (plan.kind === "csd-outputs") {
|
|
1357
|
+
outputPlan = plan.outputs;
|
|
1358
|
+
if (opts.plannedOutputs !== void 0 && opts.plannedOutputs !== null)
|
|
1359
|
+
sumsMismatch = bindPlannedSums(opts.plannedOutputs, plan.outputs);
|
|
1360
|
+
} else if (plan.kind === "undeliverable") {
|
|
1361
|
+
sumsMismatch = `this pay would not deliver against the proven offer (${plan.reason}) - refusing (the CSD would be lost)`;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
const base = { payto, seller, terms, blockHeight, ...outputPlan ? { outputPlan } : {} };
|
|
1308
1365
|
if (opts.servedOffer !== void 0 && opts.servedOffer !== null) {
|
|
1309
1366
|
const so = opts.servedOffer;
|
|
1310
1367
|
const servedPayto = so?.want?.payto !== void 0 && so?.want?.payto !== null ? String(so.want.payto).toLowerCase() : "";
|
|
@@ -1312,9 +1369,10 @@ async function preverifyOffer(opts) {
|
|
|
1312
1369
|
return { ok: false, trust: "verified", reason: "the served payment recipient doesn't match the offer's on-chain author/record", ...base };
|
|
1313
1370
|
if (so?.seller !== void 0 && so?.seller !== null && String(so.seller).toLowerCase() !== seller)
|
|
1314
1371
|
return { ok: false, trust: "verified", reason: "the served seller doesn't match the offer's on-chain author (a lying resolver may be redirecting your payment)", ...base };
|
|
1315
|
-
if ((0, import_cairnx_core2.bindOfferTerms)(opts.servedOffer, terms))
|
|
1316
|
-
return { ok: false, trust: "verified", reason: "the served
|
|
1372
|
+
if ((0, import_cairnx_core2.bindOfferTerms)(opts.servedOffer, terms, { give: true, wantType: true }))
|
|
1373
|
+
return { ok: false, trust: "verified", reason: "the served terms don't match the offer's on-chain record (fee, rebate, partial sizing, the give, or the want type - a lying resolver could mis-size or re-route the fill, redirecting or burning your payment)", ...base };
|
|
1317
1374
|
}
|
|
1375
|
+
if (sumsMismatch) return { ok: false, trust: "verified", reason: sumsMismatch, ...base };
|
|
1318
1376
|
return { ok: true, trust: "verified", ...base };
|
|
1319
1377
|
}
|
|
1320
1378
|
|
|
@@ -1410,6 +1468,10 @@ var CairnController = class {
|
|
|
1410
1468
|
// src/index.ts
|
|
1411
1469
|
var DEFAULT_SPV_CHECKPOINT = { height: 38142, hash: "0x00000000000140f023cc0ee1457a40833f2fcb4de44291b9d373e50f17b97232" };
|
|
1412
1470
|
var DEFAULT_CAIRN = "https://cairn-substrate.com";
|
|
1471
|
+
var SPV_HTTP_TIMEOUT_MS = 15e3;
|
|
1472
|
+
var SPV_HTTP_MAX_RETRIES = 4;
|
|
1473
|
+
var spvSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
1474
|
+
var spvRetryDelayMs = (attempt, retryAfterSecs) => Math.min(4e3, Math.max(700 * (attempt + 1), retryAfterSecs * 1e3));
|
|
1413
1475
|
var Cairn = class {
|
|
1414
1476
|
config;
|
|
1415
1477
|
chain;
|
|
@@ -1425,6 +1487,8 @@ var Cairn = class {
|
|
|
1425
1487
|
_spvLight = null;
|
|
1426
1488
|
_spvSeeded = false;
|
|
1427
1489
|
_spvCp;
|
|
1490
|
+
// W12: the cairn base the SPV header-batch provider fetches /api/headers from (same base the rest of the SDK uses).
|
|
1491
|
+
_cairnBase;
|
|
1428
1492
|
constructor(config = {}) {
|
|
1429
1493
|
this.config = config;
|
|
1430
1494
|
const fetch = config.fetch;
|
|
@@ -1433,6 +1497,7 @@ var Cairn = class {
|
|
|
1433
1497
|
const rpc = config.baseUrls?.rpc ?? `${cairn}/api/rpc`;
|
|
1434
1498
|
const indexer = (config.baseUrls?.indexer ?? `${cairn}/explorer/api`).replace(/\/+$/, "");
|
|
1435
1499
|
this.cairnHttp = new Http({ baseUrl: cairn, fetch, timeoutMs });
|
|
1500
|
+
this._cairnBase = cairn;
|
|
1436
1501
|
const indexerHttp = new Http({ baseUrl: indexer, fetch, timeoutMs });
|
|
1437
1502
|
const swarmHttp = config.baseUrls?.swarm ? new Http({ baseUrl: config.baseUrls.swarm.replace(/\/+$/, ""), fetch, timeoutMs }) : void 0;
|
|
1438
1503
|
this._spvCp = config.spvCheckpoint ?? DEFAULT_SPV_CHECKPOINT;
|
|
@@ -1469,13 +1534,69 @@ var Cairn = class {
|
|
|
1469
1534
|
/** The PoW-verifying SPV light client, seeded ONCE from the pinned checkpoint (shared by the M3 header-merkle
|
|
1470
1535
|
* bind and the F13 offer pre-verify). Reused across calls; the first call near tip syncs the post-checkpoint span. */
|
|
1471
1536
|
async seededSpvLight() {
|
|
1472
|
-
if (!this._spvLight) this._spvLight = new import_csd_light.LightClient({
|
|
1537
|
+
if (!this._spvLight) this._spvLight = new import_csd_light.LightClient({
|
|
1538
|
+
client: this.chain.client,
|
|
1539
|
+
checkpoints: { [this._spvCp.height]: this._spvCp.hash },
|
|
1540
|
+
headersBatchProvider: (from, count) => this.fetchHeadersBatch(from, count)
|
|
1541
|
+
});
|
|
1473
1542
|
if (!this._spvSeeded) {
|
|
1474
1543
|
await this._spvLight.syncFromCheckpoint(this._spvCp.height, this._spvCp.hash);
|
|
1544
|
+
try {
|
|
1545
|
+
const tipHeight = Number((await this.chain.tip()).height);
|
|
1546
|
+
const have = this._spvLight.baseHeight + this._spvLight.chain.length - 1;
|
|
1547
|
+
if (Number.isFinite(tipHeight) && tipHeight > have) await this._spvLight.sync(tipHeight);
|
|
1548
|
+
} catch {
|
|
1549
|
+
}
|
|
1475
1550
|
this._spvSeeded = true;
|
|
1476
1551
|
}
|
|
1477
1552
|
return this._spvLight;
|
|
1478
1553
|
}
|
|
1554
|
+
/**
|
|
1555
|
+
* W12 batch header transport for the checkpoint..tip forward sync, backed by the cairn server's
|
|
1556
|
+
* `/api/headers/:from/:count`. Carries ZERO trust: the LightClient re-verifies every header's PoW /
|
|
1557
|
+
* prev-link / LWMA, so a forged or stale row fails closed and retrying transport proves nothing new.
|
|
1558
|
+
* Retry budget: a 429 (per-IP header budget) or 502/503 (a height past the lagging indexer, or the
|
|
1559
|
+
* server's 10s deadline) is a transient data-availability hiccup; back off (honouring Retry-After) a
|
|
1560
|
+
* bounded number of times, then THROW so `sync()` fails closed. A non-dense range is rejected.
|
|
1561
|
+
*
|
|
1562
|
+
* B7d / F6 DEPENDENCY: `/api/headers` serves no Access-Control-Allow-Origin today (`corsPublic` is
|
|
1563
|
+
* mounted on `/explorer/api`, `/trade/api` and `/api/rpc`, not here). A SAME-ORIGIN dApp (hosted on the
|
|
1564
|
+
* cairn base) reaches it now; a CROSS-ORIGIN third-party dApp cannot until B7d adds the CORS mount and
|
|
1565
|
+
* restarts the cairn service. This code is correct as written; it becomes reachable cross-origin only
|
|
1566
|
+
* once B7d ships. This is a recorded dependency, not a blocker for authoring/testing.
|
|
1567
|
+
*/
|
|
1568
|
+
async fetchHeadersBatch(from, count) {
|
|
1569
|
+
const g = this.config.fetch ?? globalThis.fetch;
|
|
1570
|
+
if (!g) throw new Error("No fetch available for SPV header sync - pass `fetch` in the SDK options.");
|
|
1571
|
+
const doFetch = this.config.fetch ? this.config.fetch : g.bind(globalThis);
|
|
1572
|
+
const url = `${this._cairnBase}/api/headers/${from}/${count}`;
|
|
1573
|
+
for (let attempt = 0; ; attempt++) {
|
|
1574
|
+
let res;
|
|
1575
|
+
const ctrl = new AbortController();
|
|
1576
|
+
const timer = setTimeout(() => ctrl.abort(), SPV_HTTP_TIMEOUT_MS);
|
|
1577
|
+
try {
|
|
1578
|
+
res = await doFetch(url, { signal: ctrl.signal });
|
|
1579
|
+
} catch (e) {
|
|
1580
|
+
if (attempt >= SPV_HTTP_MAX_RETRIES) throw e;
|
|
1581
|
+
await spvSleep(spvRetryDelayMs(attempt, 0));
|
|
1582
|
+
continue;
|
|
1583
|
+
} finally {
|
|
1584
|
+
clearTimeout(timer);
|
|
1585
|
+
}
|
|
1586
|
+
if (res.ok) {
|
|
1587
|
+
const rows = (await res.json())?.headers;
|
|
1588
|
+
if (!Array.isArray(rows) || rows.length !== count) throw new Error(`/api/headers: non-dense range (${from}/${count})`);
|
|
1589
|
+
return rows.map((r) => ({ header: r.header, hash: r.hash }));
|
|
1590
|
+
}
|
|
1591
|
+
if ((res.status === 429 || res.status === 502 || res.status === 503) && attempt < SPV_HTTP_MAX_RETRIES) {
|
|
1592
|
+
res.body?.cancel?.().catch(() => {
|
|
1593
|
+
});
|
|
1594
|
+
await spvSleep(spvRetryDelayMs(attempt, Number(res.headers.get("retry-after")) || 0));
|
|
1595
|
+
continue;
|
|
1596
|
+
}
|
|
1597
|
+
throw new Error(`/api/headers ${res.status}`);
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1479
1600
|
/**
|
|
1480
1601
|
* F13 — corroborate an offer ON-CHAIN before building a `fillOffer` payment's `outputs`. Merkle-proves the
|
|
1481
1602
|
* offer into the PoW-verified header chain (from the pinned SPV checkpoint), binds the record to its on-chain
|
|
@@ -1539,9 +1660,14 @@ var Cairn = class {
|
|
|
1539
1660
|
discoverProviders,
|
|
1540
1661
|
errorCode,
|
|
1541
1662
|
feeBpsAt,
|
|
1663
|
+
fillEndorsement,
|
|
1664
|
+
fillIsSafe,
|
|
1665
|
+
fillOutputPlan,
|
|
1542
1666
|
getWallet,
|
|
1543
1667
|
isInstalled,
|
|
1544
1668
|
mapProviderError,
|
|
1545
1669
|
mapSubmitResultError,
|
|
1546
|
-
preverifyOffer
|
|
1670
|
+
preverifyOffer,
|
|
1671
|
+
previewFill,
|
|
1672
|
+
requiredFillOutputs
|
|
1547
1673
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -10,9 +10,10 @@ export { ContentClientOptions, PreparedContent } from './content.cjs';
|
|
|
10
10
|
import { RegistryClient } from './registry.cjs';
|
|
11
11
|
import { WalletConnection, DetectOptions } from './connect.cjs';
|
|
12
12
|
export { AttestParams, CairnProvider, ConnectResult, FillParams, ProposeParams, ProviderDetail, ProviderInfo, SealClaimParams, SendParams, SignInResult, SiwcParams, SiwcResult, TxResult, WalletCapabilities, WalletPermission, connect, detectProvider, discoverProviders, getWallet, isInstalled } from './connect.cjs';
|
|
13
|
+
import { ProvenOfferTerms } from '@inversealtruism/cairnx-core';
|
|
14
|
+
export { FillEndorsement, FillOutputPlan, FillPreview, FillSafety, ProvenOfferTerms, bindOfferTerms, feeBpsAt, fillEndorsement, fillIsSafe, fillOutputPlan, previewFill, requiredFillOutputs } from '@inversealtruism/cairnx-core';
|
|
13
15
|
import { InclusionResult } from '@inversealtruism/csd-light';
|
|
14
16
|
export { CairnController, CairnControllerOptions, CairnState } from './controller.cjs';
|
|
15
|
-
export { bindOfferTerms, feeBpsAt } from '@inversealtruism/cairnx-core';
|
|
16
17
|
import '@inversealtruism/csd-client';
|
|
17
18
|
import '@inversealtruism/csd-tx';
|
|
18
19
|
import '@inversealtruism/csd-codec';
|
|
@@ -105,15 +106,6 @@ declare class NamesClient {
|
|
|
105
106
|
state(): Promise<unknown>;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
/** The fee/rebate-relevant fields of an offer, derived from the MERKLE-PROVEN offer (never a served object). */
|
|
109
|
-
interface ProvenOfferTerms {
|
|
110
|
-
height: number;
|
|
111
|
-
feeBps: number;
|
|
112
|
-
value?: string;
|
|
113
|
-
taker?: string;
|
|
114
|
-
bid?: string;
|
|
115
|
-
min?: string;
|
|
116
|
-
}
|
|
117
109
|
/** The trust-labeled verdict. `ok:false` + `transient:true` = a retryable chain-catching-up soft-fail (NOT a
|
|
118
110
|
* proven mismatch). `payto`/`seller`/`terms` are populated whenever they could be merkle-derived. */
|
|
119
111
|
interface OfferFillCheck {
|
|
@@ -127,6 +119,15 @@ interface OfferFillCheck {
|
|
|
127
119
|
seller?: string;
|
|
128
120
|
terms?: ProvenOfferTerms;
|
|
129
121
|
blockHeight?: number;
|
|
122
|
+
/** B7b (REBIND W3/M1): the PROVEN CSD outputs to build for `pay` (a WHOLE fill of a non-partial offer),
|
|
123
|
+
* sized from the merkle-proven offer by the single-sourced `fillOutputPlan`. Present only when `pay` was
|
|
124
|
+
* passed and the offer could be sized. Build EXACTLY these; never the resolver-served outputs a lying
|
|
125
|
+
* resolver could redirect. A partial (min-bearing) offer is left unsized (its running paid/delivered is
|
|
126
|
+
* not provable at this corroboration layer; the wallet's fill-SPV is the payment-grade sizer). */
|
|
127
|
+
outputPlan?: {
|
|
128
|
+
to: string;
|
|
129
|
+
value: bigint;
|
|
130
|
+
}[];
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
/**
|
|
@@ -144,11 +145,20 @@ declare function preverifyOffer(opts: {
|
|
|
144
145
|
};
|
|
145
146
|
offerId: string;
|
|
146
147
|
servedOffer?: unknown;
|
|
148
|
+
/** B7b (REBIND W3/M1): the CSD base units you intend to pay. When given, the result carries `outputPlan`
|
|
149
|
+
* (the PROVEN CSD outputs to build for a WHOLE fill of a non-partial offer, sized by the single-sourced
|
|
150
|
+
* `fillOutputPlan`) and, if you also pass `plannedOutputs`, binds them EXACTLY to that proven plan.
|
|
151
|
+
* A partial (min-bearing) offer is left unsized here; the wallet's fill-SPV is its payment-grade sizer. */
|
|
152
|
+
pay?: bigint | string | number;
|
|
153
|
+
/** B7b: your planned per-address CSD sums (the outputs you WILL build), bound both ways to `outputPlan`.
|
|
154
|
+
* Requires `pay`. A missing/low leg is a doomed underpay; an extra/high leg is a W3 overpay or an N26
|
|
155
|
+
* smuggled output - both refused. */
|
|
156
|
+
plannedOutputs?: Record<string, bigint | string | number>;
|
|
147
157
|
}): Promise<OfferFillCheck>;
|
|
148
158
|
|
|
149
159
|
/** Stable machine-readable error codes (branch on these, not the message text). */
|
|
150
160
|
type CairnErrorCode = "NOT_INSTALLED" | "USER_REJECTED" | "WALLET_LOCKED" | "UNSUPPORTED_METHOD" | "HTTP_ERROR" | "CONTENT_VERIFICATION" | "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" | "UNKNOWN";
|
|
151
|
-
declare const SDK_VERSION = "0.
|
|
161
|
+
declare const SDK_VERSION = "0.4.0";
|
|
152
162
|
interface CairnErrorOptions {
|
|
153
163
|
code?: CairnErrorCode;
|
|
154
164
|
docsPath?: string;
|
|
@@ -168,7 +178,7 @@ declare class CairnError extends Error {
|
|
|
168
178
|
/** Relative docs path (under the SDK docs base), if any. */
|
|
169
179
|
readonly docsPath?: string;
|
|
170
180
|
/** The cairn-sdk version that produced this error. */
|
|
171
|
-
readonly version = "0.
|
|
181
|
+
readonly version = "0.4.0";
|
|
172
182
|
/**
|
|
173
183
|
* Whether a dApp may safely AUTO-retry this failure. `false` for fund-safety refusals and user-intent
|
|
174
184
|
* declines (the default); `true` only for provably transient infra faults where nothing was signed.
|
|
@@ -309,6 +319,7 @@ declare class Cairn {
|
|
|
309
319
|
private _spvLight;
|
|
310
320
|
private _spvSeeded;
|
|
311
321
|
private readonly _spvCp;
|
|
322
|
+
private readonly _cairnBase;
|
|
312
323
|
constructor(config?: CairnConfig);
|
|
313
324
|
/**
|
|
314
325
|
* PoW-VERIFIED header merkle at a height (audit M3 — the no-PoW half). Lazily seeds a light
|
|
@@ -322,6 +333,21 @@ declare class Cairn {
|
|
|
322
333
|
/** The PoW-verifying SPV light client, seeded ONCE from the pinned checkpoint (shared by the M3 header-merkle
|
|
323
334
|
* bind and the F13 offer pre-verify). Reused across calls; the first call near tip syncs the post-checkpoint span. */
|
|
324
335
|
private seededSpvLight;
|
|
336
|
+
/**
|
|
337
|
+
* W12 batch header transport for the checkpoint..tip forward sync, backed by the cairn server's
|
|
338
|
+
* `/api/headers/:from/:count`. Carries ZERO trust: the LightClient re-verifies every header's PoW /
|
|
339
|
+
* prev-link / LWMA, so a forged or stale row fails closed and retrying transport proves nothing new.
|
|
340
|
+
* Retry budget: a 429 (per-IP header budget) or 502/503 (a height past the lagging indexer, or the
|
|
341
|
+
* server's 10s deadline) is a transient data-availability hiccup; back off (honouring Retry-After) a
|
|
342
|
+
* bounded number of times, then THROW so `sync()` fails closed. A non-dense range is rejected.
|
|
343
|
+
*
|
|
344
|
+
* B7d / F6 DEPENDENCY: `/api/headers` serves no Access-Control-Allow-Origin today (`corsPublic` is
|
|
345
|
+
* mounted on `/explorer/api`, `/trade/api` and `/api/rpc`, not here). A SAME-ORIGIN dApp (hosted on the
|
|
346
|
+
* cairn base) reaches it now; a CROSS-ORIGIN third-party dApp cannot until B7d adds the CORS mount and
|
|
347
|
+
* restarts the cairn service. This code is correct as written; it becomes reachable cross-origin only
|
|
348
|
+
* once B7d ships. This is a recorded dependency, not a blocker for authoring/testing.
|
|
349
|
+
*/
|
|
350
|
+
private fetchHeadersBatch;
|
|
325
351
|
/**
|
|
326
352
|
* F13 — corroborate an offer ON-CHAIN before building a `fillOffer` payment's `outputs`. Merkle-proves the
|
|
327
353
|
* offer into the PoW-verified header chain (from the pinned SPV checkpoint), binds the record to its on-chain
|
|
@@ -346,4 +372,4 @@ declare class Cairn {
|
|
|
346
372
|
get connected(): boolean;
|
|
347
373
|
}
|
|
348
374
|
|
|
349
|
-
export { BoardClient, Cairn, type CairnBaseUrls, type CairnConfig, CairnError, type CairnErrorCode, type CairnErrorOptions, Chain, ContentClient, ContentVerificationError, DEFAULT_SPV_CHECKPOINT, DetectOptions, FetchLike, Http, HttpError, IndexerClient, type NameDetail, type NameResolution, NamesClient, NotInstalledError, type OfferFillCheck, type PrimaryName,
|
|
375
|
+
export { BoardClient, Cairn, type CairnBaseUrls, type CairnConfig, CairnError, type CairnErrorCode, type CairnErrorOptions, Chain, ContentClient, ContentVerificationError, DEFAULT_SPV_CHECKPOINT, DetectOptions, FetchLike, Http, HttpError, IndexerClient, type NameDetail, type NameResolution, NamesClient, NotInstalledError, type OfferFillCheck, type PrimaryName, RegistryClient, SDK_VERSION, SubmitInFlightError, type TokenInfo, UnsupportedMethodError, UserRejectedError, WalletConnection, WalletLockedError, errorCode, mapProviderError, mapSubmitResultError, preverifyOffer };
|
package/dist/index.d.ts
CHANGED
|
@@ -10,9 +10,10 @@ export { ContentClientOptions, PreparedContent } from './content.js';
|
|
|
10
10
|
import { RegistryClient } from './registry.js';
|
|
11
11
|
import { WalletConnection, DetectOptions } from './connect.js';
|
|
12
12
|
export { AttestParams, CairnProvider, ConnectResult, FillParams, ProposeParams, ProviderDetail, ProviderInfo, SealClaimParams, SendParams, SignInResult, SiwcParams, SiwcResult, TxResult, WalletCapabilities, WalletPermission, connect, detectProvider, discoverProviders, getWallet, isInstalled } from './connect.js';
|
|
13
|
+
import { ProvenOfferTerms } from '@inversealtruism/cairnx-core';
|
|
14
|
+
export { FillEndorsement, FillOutputPlan, FillPreview, FillSafety, ProvenOfferTerms, bindOfferTerms, feeBpsAt, fillEndorsement, fillIsSafe, fillOutputPlan, previewFill, requiredFillOutputs } from '@inversealtruism/cairnx-core';
|
|
13
15
|
import { InclusionResult } from '@inversealtruism/csd-light';
|
|
14
16
|
export { CairnController, CairnControllerOptions, CairnState } from './controller.js';
|
|
15
|
-
export { bindOfferTerms, feeBpsAt } from '@inversealtruism/cairnx-core';
|
|
16
17
|
import '@inversealtruism/csd-client';
|
|
17
18
|
import '@inversealtruism/csd-tx';
|
|
18
19
|
import '@inversealtruism/csd-codec';
|
|
@@ -105,15 +106,6 @@ declare class NamesClient {
|
|
|
105
106
|
state(): Promise<unknown>;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
|
-
/** The fee/rebate-relevant fields of an offer, derived from the MERKLE-PROVEN offer (never a served object). */
|
|
109
|
-
interface ProvenOfferTerms {
|
|
110
|
-
height: number;
|
|
111
|
-
feeBps: number;
|
|
112
|
-
value?: string;
|
|
113
|
-
taker?: string;
|
|
114
|
-
bid?: string;
|
|
115
|
-
min?: string;
|
|
116
|
-
}
|
|
117
109
|
/** The trust-labeled verdict. `ok:false` + `transient:true` = a retryable chain-catching-up soft-fail (NOT a
|
|
118
110
|
* proven mismatch). `payto`/`seller`/`terms` are populated whenever they could be merkle-derived. */
|
|
119
111
|
interface OfferFillCheck {
|
|
@@ -127,6 +119,15 @@ interface OfferFillCheck {
|
|
|
127
119
|
seller?: string;
|
|
128
120
|
terms?: ProvenOfferTerms;
|
|
129
121
|
blockHeight?: number;
|
|
122
|
+
/** B7b (REBIND W3/M1): the PROVEN CSD outputs to build for `pay` (a WHOLE fill of a non-partial offer),
|
|
123
|
+
* sized from the merkle-proven offer by the single-sourced `fillOutputPlan`. Present only when `pay` was
|
|
124
|
+
* passed and the offer could be sized. Build EXACTLY these; never the resolver-served outputs a lying
|
|
125
|
+
* resolver could redirect. A partial (min-bearing) offer is left unsized (its running paid/delivered is
|
|
126
|
+
* not provable at this corroboration layer; the wallet's fill-SPV is the payment-grade sizer). */
|
|
127
|
+
outputPlan?: {
|
|
128
|
+
to: string;
|
|
129
|
+
value: bigint;
|
|
130
|
+
}[];
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
/**
|
|
@@ -144,11 +145,20 @@ declare function preverifyOffer(opts: {
|
|
|
144
145
|
};
|
|
145
146
|
offerId: string;
|
|
146
147
|
servedOffer?: unknown;
|
|
148
|
+
/** B7b (REBIND W3/M1): the CSD base units you intend to pay. When given, the result carries `outputPlan`
|
|
149
|
+
* (the PROVEN CSD outputs to build for a WHOLE fill of a non-partial offer, sized by the single-sourced
|
|
150
|
+
* `fillOutputPlan`) and, if you also pass `plannedOutputs`, binds them EXACTLY to that proven plan.
|
|
151
|
+
* A partial (min-bearing) offer is left unsized here; the wallet's fill-SPV is its payment-grade sizer. */
|
|
152
|
+
pay?: bigint | string | number;
|
|
153
|
+
/** B7b: your planned per-address CSD sums (the outputs you WILL build), bound both ways to `outputPlan`.
|
|
154
|
+
* Requires `pay`. A missing/low leg is a doomed underpay; an extra/high leg is a W3 overpay or an N26
|
|
155
|
+
* smuggled output - both refused. */
|
|
156
|
+
plannedOutputs?: Record<string, bigint | string | number>;
|
|
147
157
|
}): Promise<OfferFillCheck>;
|
|
148
158
|
|
|
149
159
|
/** Stable machine-readable error codes (branch on these, not the message text). */
|
|
150
160
|
type CairnErrorCode = "NOT_INSTALLED" | "USER_REJECTED" | "WALLET_LOCKED" | "UNSUPPORTED_METHOD" | "HTTP_ERROR" | "CONTENT_VERIFICATION" | "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" | "UNKNOWN";
|
|
151
|
-
declare const SDK_VERSION = "0.
|
|
161
|
+
declare const SDK_VERSION = "0.4.0";
|
|
152
162
|
interface CairnErrorOptions {
|
|
153
163
|
code?: CairnErrorCode;
|
|
154
164
|
docsPath?: string;
|
|
@@ -168,7 +178,7 @@ declare class CairnError extends Error {
|
|
|
168
178
|
/** Relative docs path (under the SDK docs base), if any. */
|
|
169
179
|
readonly docsPath?: string;
|
|
170
180
|
/** The cairn-sdk version that produced this error. */
|
|
171
|
-
readonly version = "0.
|
|
181
|
+
readonly version = "0.4.0";
|
|
172
182
|
/**
|
|
173
183
|
* Whether a dApp may safely AUTO-retry this failure. `false` for fund-safety refusals and user-intent
|
|
174
184
|
* declines (the default); `true` only for provably transient infra faults where nothing was signed.
|
|
@@ -309,6 +319,7 @@ declare class Cairn {
|
|
|
309
319
|
private _spvLight;
|
|
310
320
|
private _spvSeeded;
|
|
311
321
|
private readonly _spvCp;
|
|
322
|
+
private readonly _cairnBase;
|
|
312
323
|
constructor(config?: CairnConfig);
|
|
313
324
|
/**
|
|
314
325
|
* PoW-VERIFIED header merkle at a height (audit M3 — the no-PoW half). Lazily seeds a light
|
|
@@ -322,6 +333,21 @@ declare class Cairn {
|
|
|
322
333
|
/** The PoW-verifying SPV light client, seeded ONCE from the pinned checkpoint (shared by the M3 header-merkle
|
|
323
334
|
* bind and the F13 offer pre-verify). Reused across calls; the first call near tip syncs the post-checkpoint span. */
|
|
324
335
|
private seededSpvLight;
|
|
336
|
+
/**
|
|
337
|
+
* W12 batch header transport for the checkpoint..tip forward sync, backed by the cairn server's
|
|
338
|
+
* `/api/headers/:from/:count`. Carries ZERO trust: the LightClient re-verifies every header's PoW /
|
|
339
|
+
* prev-link / LWMA, so a forged or stale row fails closed and retrying transport proves nothing new.
|
|
340
|
+
* Retry budget: a 429 (per-IP header budget) or 502/503 (a height past the lagging indexer, or the
|
|
341
|
+
* server's 10s deadline) is a transient data-availability hiccup; back off (honouring Retry-After) a
|
|
342
|
+
* bounded number of times, then THROW so `sync()` fails closed. A non-dense range is rejected.
|
|
343
|
+
*
|
|
344
|
+
* B7d / F6 DEPENDENCY: `/api/headers` serves no Access-Control-Allow-Origin today (`corsPublic` is
|
|
345
|
+
* mounted on `/explorer/api`, `/trade/api` and `/api/rpc`, not here). A SAME-ORIGIN dApp (hosted on the
|
|
346
|
+
* cairn base) reaches it now; a CROSS-ORIGIN third-party dApp cannot until B7d adds the CORS mount and
|
|
347
|
+
* restarts the cairn service. This code is correct as written; it becomes reachable cross-origin only
|
|
348
|
+
* once B7d ships. This is a recorded dependency, not a blocker for authoring/testing.
|
|
349
|
+
*/
|
|
350
|
+
private fetchHeadersBatch;
|
|
325
351
|
/**
|
|
326
352
|
* F13 — corroborate an offer ON-CHAIN before building a `fillOffer` payment's `outputs`. Merkle-proves the
|
|
327
353
|
* offer into the PoW-verified header chain (from the pinned SPV checkpoint), binds the record to its on-chain
|
|
@@ -346,4 +372,4 @@ declare class Cairn {
|
|
|
346
372
|
get connected(): boolean;
|
|
347
373
|
}
|
|
348
374
|
|
|
349
|
-
export { BoardClient, Cairn, type CairnBaseUrls, type CairnConfig, CairnError, type CairnErrorCode, type CairnErrorOptions, Chain, ContentClient, ContentVerificationError, DEFAULT_SPV_CHECKPOINT, DetectOptions, FetchLike, Http, HttpError, IndexerClient, type NameDetail, type NameResolution, NamesClient, NotInstalledError, type OfferFillCheck, type PrimaryName,
|
|
375
|
+
export { BoardClient, Cairn, type CairnBaseUrls, type CairnConfig, CairnError, type CairnErrorCode, type CairnErrorOptions, Chain, ContentClient, ContentVerificationError, DEFAULT_SPV_CHECKPOINT, DetectOptions, FetchLike, Http, HttpError, IndexerClient, type NameDetail, type NameResolution, NamesClient, NotInstalledError, type OfferFillCheck, type PrimaryName, RegistryClient, SDK_VERSION, SubmitInFlightError, type TokenInfo, UnsupportedMethodError, UserRejectedError, WalletConnection, WalletLockedError, errorCode, mapProviderError, mapSubmitResultError, preverifyOffer };
|