@elisym/sdk 0.22.0 → 0.24.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/agent-store.cjs +22 -0
- package/dist/agent-store.cjs.map +1 -1
- package/dist/agent-store.d.cts +9 -1
- package/dist/agent-store.d.ts +9 -1
- package/dist/agent-store.js +23 -2
- package/dist/agent-store.js.map +1 -1
- package/dist/{global-schema-CddHP2nk.d.cts → global-schema-BsVFDtkt.d.cts} +8 -8
- package/dist/{global-schema-CddHP2nk.d.ts → global-schema-BsVFDtkt.d.ts} +8 -8
- package/dist/index.cjs +177 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +223 -8
- package/dist/index.d.ts +223 -8
- package/dist/index.js +174 -28
- package/dist/index.js.map +1 -1
- package/dist/llm-health.cjs +11 -0
- package/dist/llm-health.cjs.map +1 -1
- package/dist/llm-health.d.cts +2 -2
- package/dist/llm-health.d.ts +2 -2
- package/dist/llm-health.js +11 -1
- package/dist/llm-health.js.map +1 -1
- package/dist/node.cjs +181 -1
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +47 -2
- package/dist/node.d.ts +47 -2
- package/dist/node.js +181 -2
- package/dist/node.js.map +1 -1
- package/dist/skills.cjs +183 -38
- package/dist/skills.cjs.map +1 -1
- package/dist/skills.d.cts +49 -1
- package/dist/skills.d.ts +49 -1
- package/dist/skills.js +185 -40
- package/dist/skills.js.map +1 -1
- package/dist/{types-COvV499T.d.cts → types-Cdscy9kY.d.cts} +13 -1
- package/dist/{types-COvV499T.d.ts → types-Cdscy9kY.d.ts} +13 -1
- package/package.json +4 -1
package/dist/index.cjs
CHANGED
|
@@ -93,10 +93,35 @@ var DEFAULTS = {
|
|
|
93
93
|
RESULT_RETRY_COUNT: 3,
|
|
94
94
|
RESULT_RETRY_BASE_MS: 1e3,
|
|
95
95
|
QUERY_MAX_CONCURRENCY: 6,
|
|
96
|
-
VERIFY_SIGNATURE_LIMIT: 25
|
|
96
|
+
VERIFY_SIGNATURE_LIMIT: 25,
|
|
97
|
+
// Default ceiling for a single iroh file transfer (seed/fetch). A tunable
|
|
98
|
+
// default, not a protocol constant - the transfer is resumable and its own
|
|
99
|
+
// budget, decoupled from the result-wait window.
|
|
100
|
+
IROH_FETCH_TIMEOUT_MS: 3e5
|
|
97
101
|
};
|
|
98
102
|
var LIMITS = {
|
|
99
103
|
MAX_INPUT_LENGTH: 1e5,
|
|
104
|
+
// NIP-44 v2 hard cap on encrypted plaintext: the pad() length prefix is a u16,
|
|
105
|
+
// so the plaintext can be at most 65_535 BYTES (not chars). Encrypting anything
|
|
106
|
+
// larger throws `invalid plaintext size` inside nip44Encrypt. This is the binding
|
|
107
|
+
// limit for TARGETED (encrypted) jobs - lower than every relay's NIP-11 cap.
|
|
108
|
+
NIP44_MAX_PLAINTEXT_BYTES: 65535,
|
|
109
|
+
// Spill threshold for encrypted content: above this many UTF-8 bytes, callers
|
|
110
|
+
// route the text through iroh out-of-band instead of inlining it. A non-spilled
|
|
111
|
+
// job is encrypted RAW (no envelope - see marketplace.submitJobRequest), so a
|
|
112
|
+
// 60_000-byte input is a 60_000-byte plaintext; the ~5.5KB gap under the hard cap
|
|
113
|
+
// is plain slack, and NIP44_MAX_PLAINTEXT_BYTES is the SDK backstop.
|
|
114
|
+
MAX_ENCRYPTED_INLINE_BYTES: 6e4,
|
|
115
|
+
// Ceiling above which a text/* attachment is NOT materialized back into a string
|
|
116
|
+
// (re-inlined into SkillInput.data) - the consumer gets a filePath / explicit
|
|
117
|
+
// fetch instead. Also bounds the in-memory git-diff buffer (memory-DoS guard).
|
|
118
|
+
MAX_REINLINE_TEXT_BYTES: 4194304,
|
|
119
|
+
// 4 MiB
|
|
120
|
+
// Hard safety cap on a single file transferred via iroh, enforced on the
|
|
121
|
+
// actual streamed bytes (never the sender-declared `size`). A tunable default;
|
|
122
|
+
// providers may lower it per deployment.
|
|
123
|
+
MAX_FILE_SIZE: 1073741824,
|
|
124
|
+
// 1 GiB
|
|
100
125
|
MAX_TIMEOUT_SECS: 600,
|
|
101
126
|
// Upper bound for execution budgets (`max_execution_secs` / `execution_timeout_secs`).
|
|
102
127
|
// Distinct from MAX_TIMEOUT_SECS (the result-wait cap): execution budgets may be
|
|
@@ -114,6 +139,10 @@ var LIMITS = {
|
|
|
114
139
|
MAX_POLICY_SUMMARY_LENGTH: 280,
|
|
115
140
|
MAX_POLICY_VERSION_LENGTH: 32
|
|
116
141
|
};
|
|
142
|
+
var UTF8_ENCODER = new TextEncoder();
|
|
143
|
+
function utf8ByteLength(value) {
|
|
144
|
+
return UTF8_ENCODER.encode(value).length;
|
|
145
|
+
}
|
|
117
146
|
function getConfigDecoder() {
|
|
118
147
|
return kit.getStructDecoder([
|
|
119
148
|
["discriminator", kit.fixDecoderSize(kit.getBytesDecoder(), 8)],
|
|
@@ -1237,6 +1266,12 @@ function parseCapabilityEvent(event, network) {
|
|
|
1237
1266
|
if (card.payment && (typeof card.payment.chain !== "string" || typeof card.payment.network !== "string" || typeof card.payment.address !== "string")) {
|
|
1238
1267
|
return null;
|
|
1239
1268
|
}
|
|
1269
|
+
if (card.payment && (card.payment.token !== void 0 && typeof card.payment.token !== "string" || card.payment.symbol !== void 0 && typeof card.payment.symbol !== "string" || card.payment.mint !== void 0 && typeof card.payment.mint !== "string")) {
|
|
1270
|
+
return null;
|
|
1271
|
+
}
|
|
1272
|
+
if (card.inputMime !== void 0 && (typeof card.inputMime !== "string" || card.inputMime.length > 255) || card.outputMime !== void 0 && (typeof card.outputMime !== "string" || card.outputMime.length > 255)) {
|
|
1273
|
+
return null;
|
|
1274
|
+
}
|
|
1240
1275
|
if (card.payment?.job_price !== null && card.payment?.job_price !== void 0 && (!Number.isInteger(card.payment.job_price) || card.payment.job_price < 0)) {
|
|
1241
1276
|
return null;
|
|
1242
1277
|
}
|
|
@@ -1497,6 +1532,7 @@ var DiscoveryService = class {
|
|
|
1497
1532
|
return agents;
|
|
1498
1533
|
}
|
|
1499
1534
|
const deliveredJobsByProvider = /* @__PURE__ */ new Map();
|
|
1535
|
+
const customerByJob = /* @__PURE__ */ new Map();
|
|
1500
1536
|
for (const ev of resultEvents) {
|
|
1501
1537
|
if (!nostrTools.verifyEvent(ev)) {
|
|
1502
1538
|
continue;
|
|
@@ -1516,8 +1552,13 @@ var DiscoveryService = class {
|
|
|
1516
1552
|
deliveredJobsByProvider.set(ev.pubkey, delivered);
|
|
1517
1553
|
}
|
|
1518
1554
|
delivered.add(jobEventId);
|
|
1555
|
+
const customerPubkey = ev.tags.find((tag) => tag[0] === "p")?.[1];
|
|
1556
|
+
if (customerPubkey) {
|
|
1557
|
+
customerByJob.set(jobEventId, customerPubkey);
|
|
1558
|
+
}
|
|
1519
1559
|
}
|
|
1520
1560
|
}
|
|
1561
|
+
const countedRatings = /* @__PURE__ */ new Set();
|
|
1521
1562
|
for (const ev of feedbackEvents) {
|
|
1522
1563
|
if (!nostrTools.verifyEvent(ev)) {
|
|
1523
1564
|
continue;
|
|
@@ -1533,19 +1574,25 @@ var DiscoveryService = class {
|
|
|
1533
1574
|
if (ev.created_at > agent.lastSeen) {
|
|
1534
1575
|
agent.lastSeen = ev.created_at;
|
|
1535
1576
|
}
|
|
1577
|
+
const jobEventId = ev.tags.find((tag) => tag[0] === "e")?.[1];
|
|
1578
|
+
const hasDeliveredResult = jobEventId !== void 0 && deliveredJobsByProvider.get(targetPubkey)?.has(jobEventId) === true;
|
|
1579
|
+
const jobCustomer = jobEventId !== void 0 ? customerByJob.get(jobEventId) : void 0;
|
|
1580
|
+
const authoredByCustomer = jobCustomer !== void 0 && ev.pubkey === jobCustomer;
|
|
1536
1581
|
const rating = ev.tags.find((tag) => tag[0] === "rating")?.[1];
|
|
1537
|
-
if (rating === "1" || rating === "0") {
|
|
1538
|
-
|
|
1539
|
-
if (
|
|
1540
|
-
|
|
1582
|
+
if ((rating === "1" || rating === "0") && hasDeliveredResult && authoredByCustomer) {
|
|
1583
|
+
const ratingKey = `${ev.pubkey}:${jobEventId}`;
|
|
1584
|
+
if (!countedRatings.has(ratingKey)) {
|
|
1585
|
+
countedRatings.add(ratingKey);
|
|
1586
|
+
agent.totalRatingCount = (agent.totalRatingCount ?? 0) + 1;
|
|
1587
|
+
if (rating === "1") {
|
|
1588
|
+
agent.positiveCount = (agent.positiveCount ?? 0) + 1;
|
|
1589
|
+
}
|
|
1541
1590
|
}
|
|
1542
1591
|
}
|
|
1543
1592
|
const status = ev.tags.find((tag) => tag[0] === "status")?.[1];
|
|
1544
1593
|
const txTag = ev.tags.find((tag) => tag[0] === "tx");
|
|
1545
1594
|
const txSignature = txTag?.[1];
|
|
1546
|
-
|
|
1547
|
-
const hasDeliveredResult = jobEventId !== void 0 && deliveredJobsByProvider.get(targetPubkey)?.has(jobEventId) === true;
|
|
1548
|
-
if (status === "payment-completed" && typeof txSignature === "string" && txSignature && hasDeliveredResult) {
|
|
1595
|
+
if (status === "payment-completed" && typeof txSignature === "string" && txSignature && hasDeliveredResult && authoredByCustomer) {
|
|
1549
1596
|
if (!agent.lastPaidJobAt || ev.created_at > agent.lastPaidJobAt) {
|
|
1550
1597
|
agent.lastPaidJobAt = ev.created_at;
|
|
1551
1598
|
agent.lastPaidJobTx = txSignature;
|
|
@@ -1801,6 +1848,67 @@ function nip44Decrypt(ciphertext, receiverSk, senderPubkey) {
|
|
|
1801
1848
|
const conversationKey = nip44__namespace.v2.utils.getConversationKey(receiverSk, senderPubkey);
|
|
1802
1849
|
return nip44__namespace.v2.decrypt(ciphertext, conversationKey);
|
|
1803
1850
|
}
|
|
1851
|
+
var ENVELOPE_VERSION = "elisym-job/1";
|
|
1852
|
+
var ENVELOPE_NAMESPACE_PREFIX = "elisym-job/";
|
|
1853
|
+
var MAX_TICKET_LENGTH = 4096;
|
|
1854
|
+
var FileTransportSchema = zod.z.discriminatedUnion("kind", [
|
|
1855
|
+
zod.z.object({
|
|
1856
|
+
kind: zod.z.literal("iroh"),
|
|
1857
|
+
/** Opaque iroh `BlobTicket` string. Parsed into a real ticket only at fetch time. */
|
|
1858
|
+
ticket: zod.z.string().min(1).max(MAX_TICKET_LENGTH)
|
|
1859
|
+
})
|
|
1860
|
+
]);
|
|
1861
|
+
var FileAttachmentSchema = zod.z.object({
|
|
1862
|
+
/** Display name only. Never used to derive a filesystem path (callers sanitize). */
|
|
1863
|
+
name: zod.z.string().min(1).max(255),
|
|
1864
|
+
/** Declared size in bytes (display/hint only; enforcement is on actual streamed bytes). */
|
|
1865
|
+
size: zod.z.number().int().nonnegative(),
|
|
1866
|
+
mime: zod.z.string().min(1).max(255),
|
|
1867
|
+
/** Ordered by sender preference; at least one. */
|
|
1868
|
+
transports: zod.z.array(FileTransportSchema).min(1),
|
|
1869
|
+
/** Optional provider hint (unix seconds) for when seeding may stop. */
|
|
1870
|
+
seedingExpiresAt: zod.z.number().int().nonnegative().optional()
|
|
1871
|
+
});
|
|
1872
|
+
var JobPayloadEnvelopeSchema = zod.z.object({
|
|
1873
|
+
v: zod.z.literal(ENVELOPE_VERSION),
|
|
1874
|
+
text: zod.z.string().optional(),
|
|
1875
|
+
attachment: FileAttachmentSchema.optional()
|
|
1876
|
+
});
|
|
1877
|
+
function encodeJobPayload(payload) {
|
|
1878
|
+
const envelope = { v: ENVELOPE_VERSION };
|
|
1879
|
+
if (payload.text !== void 0) {
|
|
1880
|
+
envelope.text = payload.text;
|
|
1881
|
+
}
|
|
1882
|
+
if (payload.attachment !== void 0) {
|
|
1883
|
+
envelope.attachment = payload.attachment;
|
|
1884
|
+
}
|
|
1885
|
+
return JSON.stringify(envelope);
|
|
1886
|
+
}
|
|
1887
|
+
function decodeJobPayload(content) {
|
|
1888
|
+
if (content.length > LIMITS.MAX_INPUT_LENGTH) {
|
|
1889
|
+
return { text: content };
|
|
1890
|
+
}
|
|
1891
|
+
let parsed;
|
|
1892
|
+
try {
|
|
1893
|
+
parsed = JSON.parse(content);
|
|
1894
|
+
} catch {
|
|
1895
|
+
return { text: content };
|
|
1896
|
+
}
|
|
1897
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
1898
|
+
return { text: content };
|
|
1899
|
+
}
|
|
1900
|
+
const version = parsed.v;
|
|
1901
|
+
if (typeof version !== "string" || !version.startsWith(ENVELOPE_NAMESPACE_PREFIX)) {
|
|
1902
|
+
return { text: content };
|
|
1903
|
+
}
|
|
1904
|
+
const result = JobPayloadEnvelopeSchema.safeParse(parsed);
|
|
1905
|
+
if (!result.success) {
|
|
1906
|
+
throw new Error(
|
|
1907
|
+
`Invalid elisym job payload (v=${JSON.stringify(version)}): ${result.error.message}`
|
|
1908
|
+
);
|
|
1909
|
+
}
|
|
1910
|
+
return { text: result.data.text, attachment: result.data.attachment };
|
|
1911
|
+
}
|
|
1804
1912
|
|
|
1805
1913
|
// src/services/marketplace.ts
|
|
1806
1914
|
function isEncrypted(event) {
|
|
@@ -1833,7 +1941,8 @@ var MarketplaceService = class {
|
|
|
1833
1941
|
}
|
|
1834
1942
|
/** Submit a job request with NIP-44 encrypted input. Returns the event ID. */
|
|
1835
1943
|
async submitJobRequest(identity, options) {
|
|
1836
|
-
|
|
1944
|
+
const hasAttachment = options.attachment !== void 0;
|
|
1945
|
+
if (!options.input && !hasAttachment) {
|
|
1837
1946
|
throw new Error("Job input must not be empty.");
|
|
1838
1947
|
}
|
|
1839
1948
|
if (options.input.length > LIMITS.MAX_INPUT_LENGTH) {
|
|
@@ -1847,7 +1956,15 @@ var MarketplaceService = class {
|
|
|
1847
1956
|
if (options.providerPubkey && !/^[0-9a-f]{64}$/.test(options.providerPubkey)) {
|
|
1848
1957
|
throw new Error("Invalid provider pubkey: expected 64 hex characters.");
|
|
1849
1958
|
}
|
|
1850
|
-
const plaintext = options.input;
|
|
1959
|
+
const plaintext = hasAttachment ? encodeJobPayload({ text: options.input || void 0, attachment: options.attachment }) : options.input;
|
|
1960
|
+
if (options.providerPubkey) {
|
|
1961
|
+
const plaintextBytes = utf8ByteLength(plaintext);
|
|
1962
|
+
if (plaintextBytes > LIMITS.NIP44_MAX_PLAINTEXT_BYTES) {
|
|
1963
|
+
throw new Error(
|
|
1964
|
+
`Encrypted job input too large: ${plaintextBytes} bytes (max ${LIMITS.NIP44_MAX_PLAINTEXT_BYTES}). Send large input as a file/iroh attachment instead.`
|
|
1965
|
+
);
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1851
1968
|
const encrypted = options.providerPubkey ? nip44Encrypt(plaintext, identity.secretKey, options.providerPubkey) : plaintext;
|
|
1852
1969
|
const tags = [
|
|
1853
1970
|
["i", options.providerPubkey ? "encrypted" : "text", "text"],
|
|
@@ -1941,9 +2058,15 @@ var MarketplaceService = class {
|
|
|
1941
2058
|
if (content === null) {
|
|
1942
2059
|
return;
|
|
1943
2060
|
}
|
|
2061
|
+
let decoded;
|
|
2062
|
+
try {
|
|
2063
|
+
decoded = decodeJobPayload(content);
|
|
2064
|
+
} catch {
|
|
2065
|
+
return;
|
|
2066
|
+
}
|
|
1944
2067
|
resultDelivered = true;
|
|
1945
2068
|
try {
|
|
1946
|
-
cb.onResult?.(
|
|
2069
|
+
cb.onResult?.(decoded.text ?? "", ev.id, decoded.attachment);
|
|
1947
2070
|
} catch {
|
|
1948
2071
|
} finally {
|
|
1949
2072
|
done();
|
|
@@ -2107,8 +2230,9 @@ var MarketplaceService = class {
|
|
|
2107
2230
|
);
|
|
2108
2231
|
}
|
|
2109
2232
|
/** Submit a job result with NIP-44 encrypted content. Result kind is derived from the request kind. */
|
|
2110
|
-
async submitJobResult(identity, requestEvent, content, amount) {
|
|
2111
|
-
|
|
2233
|
+
async submitJobResult(identity, requestEvent, content, amount, attachment) {
|
|
2234
|
+
const hasAttachment = attachment !== void 0;
|
|
2235
|
+
if (!content && !hasAttachment) {
|
|
2112
2236
|
throw new Error("Job result content must not be empty.");
|
|
2113
2237
|
}
|
|
2114
2238
|
if (!Number.isInteger(requestEvent.kind)) {
|
|
@@ -2121,7 +2245,16 @@ var MarketplaceService = class {
|
|
|
2121
2245
|
);
|
|
2122
2246
|
}
|
|
2123
2247
|
const shouldEncrypt = isEncrypted(requestEvent);
|
|
2124
|
-
const
|
|
2248
|
+
const payload = hasAttachment ? encodeJobPayload({ text: content || void 0, attachment }) : content;
|
|
2249
|
+
if (shouldEncrypt) {
|
|
2250
|
+
const payloadBytes = utf8ByteLength(payload);
|
|
2251
|
+
if (payloadBytes > LIMITS.NIP44_MAX_PLAINTEXT_BYTES) {
|
|
2252
|
+
throw new Error(
|
|
2253
|
+
`Encrypted job result too large: ${payloadBytes} bytes (max ${LIMITS.NIP44_MAX_PLAINTEXT_BYTES}). Deliver large results as a file/iroh attachment instead.`
|
|
2254
|
+
);
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
const resultContent = shouldEncrypt ? nip44Encrypt(payload, identity.secretKey, requestEvent.pubkey) : payload;
|
|
2125
2258
|
const resultKind = KIND_JOB_RESULT_BASE + offset;
|
|
2126
2259
|
const tags = [
|
|
2127
2260
|
["e", requestEvent.id],
|
|
@@ -2153,11 +2286,11 @@ var MarketplaceService = class {
|
|
|
2153
2286
|
* With maxAttempts=3: try, ~1s, try, ~2s, try, throw.
|
|
2154
2287
|
* Jitter: 0.5x-1.0x of calculated delay.
|
|
2155
2288
|
*/
|
|
2156
|
-
async submitJobResultWithRetry(identity, requestEvent, content, amount, maxAttempts = DEFAULTS.RESULT_RETRY_COUNT, baseDelayMs = DEFAULTS.RESULT_RETRY_BASE_MS) {
|
|
2289
|
+
async submitJobResultWithRetry(identity, requestEvent, content, amount, maxAttempts = DEFAULTS.RESULT_RETRY_COUNT, baseDelayMs = DEFAULTS.RESULT_RETRY_BASE_MS, attachment) {
|
|
2157
2290
|
const attempts = Math.max(1, maxAttempts);
|
|
2158
2291
|
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
2159
2292
|
try {
|
|
2160
|
-
return await this.submitJobResult(identity, requestEvent, content, amount);
|
|
2293
|
+
return await this.submitJobResult(identity, requestEvent, content, amount, attachment);
|
|
2161
2294
|
} catch (e) {
|
|
2162
2295
|
if (attempt >= attempts - 1) {
|
|
2163
2296
|
throw e;
|
|
@@ -3429,35 +3562,43 @@ function formatNetworkBaseline(estimate) {
|
|
|
3429
3562
|
return `Estimated network gas: ${total} SOL (${parts.join(" + ")}).`;
|
|
3430
3563
|
}
|
|
3431
3564
|
var NEGATIVE_CACHE_TTL_MS = 6e4;
|
|
3565
|
+
var MAX_CACHE_ENTRIES = 5e3;
|
|
3432
3566
|
var verifyCache = /* @__PURE__ */ new Map();
|
|
3433
3567
|
function clearQuickVerifyCache() {
|
|
3434
3568
|
verifyCache.clear();
|
|
3435
3569
|
}
|
|
3436
3570
|
async function verifyJobPaymentQuick(rpc, txSignature, expectedRecipient) {
|
|
3437
3571
|
if (!txSignature) {
|
|
3438
|
-
return {
|
|
3572
|
+
return { receivedFunds: false, txSignature: "", reason: "invalid_input" };
|
|
3439
3573
|
}
|
|
3440
3574
|
if (!expectedRecipient || !kit.isAddress(expectedRecipient)) {
|
|
3441
|
-
return {
|
|
3575
|
+
return { receivedFunds: false, txSignature, reason: "invalid_input" };
|
|
3442
3576
|
}
|
|
3443
3577
|
const cacheKey2 = `${txSignature}:${expectedRecipient}`;
|
|
3444
3578
|
const cached = verifyCache.get(cacheKey2);
|
|
3445
3579
|
if (cached) {
|
|
3446
|
-
if (cached.result.
|
|
3580
|
+
if (cached.result.receivedFunds) {
|
|
3447
3581
|
return cached.result;
|
|
3448
3582
|
}
|
|
3449
3583
|
if (Date.now() - cached.cachedAt < NEGATIVE_CACHE_TTL_MS) {
|
|
3450
3584
|
return cached.result;
|
|
3451
3585
|
}
|
|
3586
|
+
verifyCache.delete(cacheKey2);
|
|
3452
3587
|
}
|
|
3453
3588
|
const result = await doVerifyOnce(rpc, txSignature, expectedRecipient);
|
|
3589
|
+
if (verifyCache.size >= MAX_CACHE_ENTRIES) {
|
|
3590
|
+
const oldest = verifyCache.keys().next().value;
|
|
3591
|
+
if (oldest !== void 0) {
|
|
3592
|
+
verifyCache.delete(oldest);
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3454
3595
|
verifyCache.set(cacheKey2, { result, cachedAt: Date.now() });
|
|
3455
3596
|
return result;
|
|
3456
3597
|
}
|
|
3457
3598
|
async function doVerifyOnce(rpc, txSignature, expectedRecipient) {
|
|
3458
3599
|
const sigStr = txSignature;
|
|
3459
3600
|
if (!rpc || typeof rpc.getTransaction !== "function") {
|
|
3460
|
-
return {
|
|
3601
|
+
return { receivedFunds: false, txSignature: sigStr, reason: "rpc_error" };
|
|
3461
3602
|
}
|
|
3462
3603
|
let tx;
|
|
3463
3604
|
try {
|
|
@@ -3467,13 +3608,13 @@ async function doVerifyOnce(rpc, txSignature, expectedRecipient) {
|
|
|
3467
3608
|
maxSupportedTransactionVersion: 0
|
|
3468
3609
|
}).send();
|
|
3469
3610
|
} catch {
|
|
3470
|
-
return {
|
|
3611
|
+
return { receivedFunds: false, txSignature: sigStr, reason: "rpc_error" };
|
|
3471
3612
|
}
|
|
3472
3613
|
if (!tx) {
|
|
3473
|
-
return {
|
|
3614
|
+
return { receivedFunds: false, txSignature: sigStr, reason: "not_found" };
|
|
3474
3615
|
}
|
|
3475
3616
|
if (!tx.meta || tx.meta.err) {
|
|
3476
|
-
return {
|
|
3617
|
+
return { receivedFunds: false, txSignature: sigStr, reason: "tx_failed" };
|
|
3477
3618
|
}
|
|
3478
3619
|
const accountKeys = tx.transaction.message.accountKeys;
|
|
3479
3620
|
const recipientStr = expectedRecipient;
|
|
@@ -3487,7 +3628,7 @@ async function doVerifyOnce(rpc, txSignature, expectedRecipient) {
|
|
|
3487
3628
|
if (pre !== void 0 && post !== void 0) {
|
|
3488
3629
|
const delta = BigInt(post) - BigInt(pre);
|
|
3489
3630
|
if (delta > 0n) {
|
|
3490
|
-
return {
|
|
3631
|
+
return { receivedFunds: true, txSignature: sigStr };
|
|
3491
3632
|
}
|
|
3492
3633
|
}
|
|
3493
3634
|
}
|
|
@@ -3505,11 +3646,11 @@ async function doVerifyOnce(rpc, txSignature, expectedRecipient) {
|
|
|
3505
3646
|
const preAmount = pre ? BigInt(pre.uiTokenAmount.amount) : 0n;
|
|
3506
3647
|
const postAmount = BigInt(post.uiTokenAmount.amount);
|
|
3507
3648
|
if (postAmount > preAmount) {
|
|
3508
|
-
return {
|
|
3649
|
+
return { receivedFunds: true, txSignature: sigStr };
|
|
3509
3650
|
}
|
|
3510
3651
|
}
|
|
3511
3652
|
}
|
|
3512
|
-
return {
|
|
3653
|
+
return { receivedFunds: false, txSignature: sigStr, reason: "recipient_mismatch" };
|
|
3513
3654
|
}
|
|
3514
3655
|
var DEFAULT_LIMIT = 1e3;
|
|
3515
3656
|
var NATIVE_KEY = "native";
|
|
@@ -3604,7 +3745,12 @@ var SessionSpendLimitEntrySchema = zod.z.object({
|
|
|
3604
3745
|
chain: zod.z.enum(["solana"]),
|
|
3605
3746
|
token: zod.z.string().min(1).max(16).regex(/^[a-z0-9]+$/, "token must be lowercase alphanumeric"),
|
|
3606
3747
|
mint: zod.z.string().min(1).max(64).optional(),
|
|
3607
|
-
|
|
3748
|
+
// Stored as a string to preserve the operator's exact decimal text (avoids
|
|
3749
|
+
// Number round-tripping to scientific notation). Legacy configs persisted a
|
|
3750
|
+
// number; accept both and normalize to a positive-decimal string.
|
|
3751
|
+
amount: zod.z.union([zod.z.string(), zod.z.number()]).transform((value) => typeof value === "number" ? String(value) : value.trim()).refine((value) => /^\d+(?:\.\d+)?$/.test(value) && /[1-9]/.test(value), {
|
|
3752
|
+
message: 'amount must be a positive decimal (e.g. "0.5", "1")'
|
|
3753
|
+
})
|
|
3608
3754
|
}).strict();
|
|
3609
3755
|
var GlobalConfigSchema = zod.z.object({
|
|
3610
3756
|
session_spend_limits: zod.z.array(SessionSpendLimitEntrySchema).max(16).optional()
|
|
@@ -3810,6 +3956,7 @@ exports.DEFAULT_KIND_OFFSET = DEFAULT_KIND_OFFSET;
|
|
|
3810
3956
|
exports.DEFAULT_REDACT_PATHS = DEFAULT_REDACT_PATHS;
|
|
3811
3957
|
exports.DiscoveryService = DiscoveryService;
|
|
3812
3958
|
exports.ELISYM_PROTOCOL_TAG = ELISYM_PROTOCOL_TAG;
|
|
3959
|
+
exports.ENVELOPE_VERSION = ENVELOPE_VERSION;
|
|
3813
3960
|
exports.ElisymClient = ElisymClient;
|
|
3814
3961
|
exports.ElisymIdentity = ElisymIdentity;
|
|
3815
3962
|
exports.GlobalConfigSchema = GlobalConfigSchema;
|
|
@@ -3858,6 +4005,8 @@ exports.compareAgentsByRank = compareAgentsByRank;
|
|
|
3858
4005
|
exports.computeRankKey = computeRankKey;
|
|
3859
4006
|
exports.createPaymentRequestWithOnchainConfig = createPaymentRequestWithOnchainConfig;
|
|
3860
4007
|
exports.createSlidingWindowLimiter = createSlidingWindowLimiter;
|
|
4008
|
+
exports.decodeJobPayload = decodeJobPayload;
|
|
4009
|
+
exports.encodeJobPayload = encodeJobPayload;
|
|
3861
4010
|
exports.estimateNetworkBaseline = estimateNetworkBaseline;
|
|
3862
4011
|
exports.estimatePriorityFeeMicroLamports = estimatePriorityFeeMicroLamports;
|
|
3863
4012
|
exports.estimateSolFeeLamports = estimateSolFeeLamports;
|
|
@@ -3881,6 +4030,7 @@ exports.resolveKnownAsset = resolveKnownAsset;
|
|
|
3881
4030
|
exports.timeAgo = timeAgo;
|
|
3882
4031
|
exports.toDTag = toDTag;
|
|
3883
4032
|
exports.truncateKey = truncateKey;
|
|
4033
|
+
exports.utf8ByteLength = utf8ByteLength;
|
|
3884
4034
|
exports.validateAgentName = validateAgentName;
|
|
3885
4035
|
exports.validateExpiry = validateExpiry;
|
|
3886
4036
|
exports.verifyJobPaymentQuick = verifyJobPaymentQuick;
|