@elisym/sdk 0.5.0 → 0.7.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/index.cjs +282 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +231 -9
- package/dist/index.d.ts +231 -9
- package/dist/index.js +274 -23
- package/dist/index.js.map +1 -1
- package/dist/runtime.cjs +200 -0
- package/dist/runtime.cjs.map +1 -0
- package/dist/runtime.d.cts +116 -0
- package/dist/runtime.d.ts +116 -0
- package/dist/runtime.js +193 -0
- package/dist/runtime.js.map +1 -0
- package/dist/skills.cjs +673 -0
- package/dist/skills.cjs.map +1 -0
- package/dist/skills.d.cts +172 -0
- package/dist/skills.d.ts +172 -0
- package/dist/skills.js +660 -0
- package/dist/skills.js.map +1 -0
- package/package.json +21 -1
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var system = require('@solana-program/system');
|
|
4
4
|
var kit = require('@solana/kit');
|
|
5
5
|
var Decimal2 = require('decimal.js-light');
|
|
6
|
+
var zod = require('zod');
|
|
6
7
|
var nostrTools = require('nostr-tools');
|
|
7
8
|
var nip44 = require('nostr-tools/nip44');
|
|
8
9
|
|
|
@@ -215,7 +216,118 @@ function assertExpiry(createdAt, expirySecs) {
|
|
|
215
216
|
}
|
|
216
217
|
}
|
|
217
218
|
|
|
219
|
+
// src/payment/priorityFee.ts
|
|
220
|
+
var PRIORITY_FEE_FLOOR_MICROLAMPORTS = 1000n;
|
|
221
|
+
var DEFAULT_PERCENTILE = 75;
|
|
222
|
+
var DEFAULT_CACHE_TTL_MS = 1e4;
|
|
223
|
+
var cache2 = /* @__PURE__ */ new Map();
|
|
224
|
+
async function estimatePriorityFeeMicroLamports(rpc, options) {
|
|
225
|
+
const percentile = clampPercentile(options?.percentile ?? DEFAULT_PERCENTILE);
|
|
226
|
+
const ttl = options?.ttlMs ?? DEFAULT_CACHE_TTL_MS;
|
|
227
|
+
const accounts = options?.accounts ?? [];
|
|
228
|
+
const key = cacheKey(percentile, accounts);
|
|
229
|
+
const now = Date.now();
|
|
230
|
+
const cached = cache2.get(key);
|
|
231
|
+
if (cached && now < cached.expires) {
|
|
232
|
+
return cached.microLamports;
|
|
233
|
+
}
|
|
234
|
+
const samples = await rpc.getRecentPrioritizationFees(accounts).send();
|
|
235
|
+
const fee = pickPercentileFee(samples, percentile);
|
|
236
|
+
cache2.set(key, { microLamports: fee, expires: now + ttl });
|
|
237
|
+
return fee;
|
|
238
|
+
}
|
|
239
|
+
function clearPriorityFeeCache() {
|
|
240
|
+
cache2.clear();
|
|
241
|
+
}
|
|
242
|
+
function pickPercentileFee(samples, percentile) {
|
|
243
|
+
if (samples.length === 0) {
|
|
244
|
+
return PRIORITY_FEE_FLOOR_MICROLAMPORTS;
|
|
245
|
+
}
|
|
246
|
+
const sorted = samples.map((sample) => BigInt(sample.prioritizationFee)).sort(compareBigInt);
|
|
247
|
+
const clamped = clampPercentile(percentile);
|
|
248
|
+
const indexFloat = clamped / 100 * (sorted.length - 1) | 0;
|
|
249
|
+
const value = sorted[indexFloat];
|
|
250
|
+
return value > PRIORITY_FEE_FLOOR_MICROLAMPORTS ? value : PRIORITY_FEE_FLOOR_MICROLAMPORTS;
|
|
251
|
+
}
|
|
252
|
+
function clampPercentile(value) {
|
|
253
|
+
if (!Number.isFinite(value)) {
|
|
254
|
+
return DEFAULT_PERCENTILE;
|
|
255
|
+
}
|
|
256
|
+
if (value < 0) {
|
|
257
|
+
return 0;
|
|
258
|
+
}
|
|
259
|
+
if (value > 100) {
|
|
260
|
+
return 100;
|
|
261
|
+
}
|
|
262
|
+
return value;
|
|
263
|
+
}
|
|
264
|
+
function compareBigInt(left, right) {
|
|
265
|
+
if (left < right) {
|
|
266
|
+
return -1;
|
|
267
|
+
}
|
|
268
|
+
if (left > right) {
|
|
269
|
+
return 1;
|
|
270
|
+
}
|
|
271
|
+
return 0;
|
|
272
|
+
}
|
|
273
|
+
function cacheKey(percentile, accounts) {
|
|
274
|
+
if (accounts.length === 0) {
|
|
275
|
+
return `p:${percentile}`;
|
|
276
|
+
}
|
|
277
|
+
return `p:${percentile}:${[...accounts].sort().join(",")}`;
|
|
278
|
+
}
|
|
279
|
+
var MAX_DESCRIPTION_LENGTH = LIMITS.MAX_DESCRIPTION_LENGTH;
|
|
280
|
+
var MAX_SAFE_LAMPORTS = Number.MAX_SAFE_INTEGER;
|
|
281
|
+
var MAX_EXPIRY_SECS_SCHEMA = 86400;
|
|
282
|
+
var BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]+$/;
|
|
283
|
+
var SOLANA_ADDRESS_LENGTH_RE = /^.{32,44}$/;
|
|
284
|
+
var lamportsSchema = zod.z.number().int().positive().max(MAX_SAFE_LAMPORTS, `amount must be <= ${MAX_SAFE_LAMPORTS}`);
|
|
285
|
+
var feeAmountSchema = zod.z.number().int().nonnegative().max(MAX_SAFE_LAMPORTS, `fee_amount must be <= ${MAX_SAFE_LAMPORTS}`);
|
|
286
|
+
var solanaAddressSchema = zod.z.string().regex(BASE58_RE, "must be base58").regex(SOLANA_ADDRESS_LENGTH_RE, "must be 32-44 base58 chars");
|
|
287
|
+
var PaymentRequestSchema = zod.z.object({
|
|
288
|
+
recipient: solanaAddressSchema,
|
|
289
|
+
amount: lamportsSchema,
|
|
290
|
+
reference: solanaAddressSchema,
|
|
291
|
+
description: zod.z.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
292
|
+
fee_address: solanaAddressSchema.optional(),
|
|
293
|
+
fee_amount: feeAmountSchema.optional(),
|
|
294
|
+
created_at: zod.z.number().int().positive(),
|
|
295
|
+
expiry_secs: zod.z.number().int().positive().max(MAX_EXPIRY_SECS_SCHEMA, `expiry_secs must be <= ${MAX_EXPIRY_SECS_SCHEMA}`)
|
|
296
|
+
});
|
|
297
|
+
function parsePaymentRequest(input, options) {
|
|
298
|
+
let parsed;
|
|
299
|
+
try {
|
|
300
|
+
parsed = JSON.parse(input);
|
|
301
|
+
} catch (e) {
|
|
302
|
+
return {
|
|
303
|
+
ok: false,
|
|
304
|
+
error: { code: "invalid_json", message: `Invalid payment request JSON: ${e}` }
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
const result = PaymentRequestSchema.safeParse(parsed);
|
|
308
|
+
if (!result.success) {
|
|
309
|
+
return {
|
|
310
|
+
ok: false,
|
|
311
|
+
error: { code: "schema", message: result.error.message }
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
if (options?.maxAmountLamports !== void 0) {
|
|
315
|
+
if (BigInt(result.data.amount) > options.maxAmountLamports) {
|
|
316
|
+
return {
|
|
317
|
+
ok: false,
|
|
318
|
+
error: {
|
|
319
|
+
code: "amount_exceeds_max",
|
|
320
|
+
message: `Payment amount ${result.data.amount} lamports exceeds approved max ${options.maxAmountLamports}.`
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return { ok: true, data: result.data };
|
|
326
|
+
}
|
|
327
|
+
|
|
218
328
|
// src/payment/solana.ts
|
|
329
|
+
var DEFAULT_COMPUTE_UNIT_LIMIT = 2e5;
|
|
330
|
+
var DEFAULT_PRIORITY_FEE_PERCENTILE = 75;
|
|
219
331
|
var REFERENCE_BYTE_LENGTH = 32;
|
|
220
332
|
function isValidSolanaAddress(value) {
|
|
221
333
|
return kit.isAddress(value);
|
|
@@ -272,32 +384,27 @@ var SolanaPaymentStrategy = class {
|
|
|
272
384
|
expiry_secs: expirySecs
|
|
273
385
|
};
|
|
274
386
|
}
|
|
275
|
-
validatePaymentRequest(requestJson, config, expectedRecipient) {
|
|
387
|
+
validatePaymentRequest(requestJson, config, expectedRecipient, options) {
|
|
276
388
|
assertConfig(config);
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
code: "invalid_amount",
|
|
286
|
-
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
if (typeof data.recipient !== "string" || !data.recipient) {
|
|
290
|
-
return { code: "missing_recipient", message: "Missing recipient in payment request" };
|
|
389
|
+
const parsed = parsePaymentRequest(requestJson, {
|
|
390
|
+
maxAmountLamports: options?.maxAmountLamports
|
|
391
|
+
});
|
|
392
|
+
if (!parsed.ok) {
|
|
393
|
+
if (parsed.error.code === "invalid_json") {
|
|
394
|
+
return { code: "invalid_json", message: parsed.error.message };
|
|
395
|
+
}
|
|
396
|
+
if (parsed.error.code === "amount_exceeds_max") {
|
|
397
|
+
return { code: "invalid_amount", message: parsed.error.message };
|
|
398
|
+
}
|
|
399
|
+
return { code: "invalid_amount", message: parsed.error.message };
|
|
291
400
|
}
|
|
401
|
+
const data = parsed.data;
|
|
292
402
|
if (!isValidSolanaAddress(data.recipient)) {
|
|
293
403
|
return {
|
|
294
404
|
code: "invalid_recipient_address",
|
|
295
405
|
message: `Invalid Solana address for recipient: ${data.recipient}`
|
|
296
406
|
};
|
|
297
407
|
}
|
|
298
|
-
if (typeof data.reference !== "string" || !data.reference) {
|
|
299
|
-
return { code: "missing_reference", message: "Missing reference in payment request" };
|
|
300
|
-
}
|
|
301
408
|
if (!isValidSolanaAddress(data.reference)) {
|
|
302
409
|
return {
|
|
303
410
|
code: "invalid_reference_address",
|
|
@@ -357,7 +464,7 @@ var SolanaPaymentStrategy = class {
|
|
|
357
464
|
* read-only, non-signer account so providers can detect the payment via
|
|
358
465
|
* `getSignaturesForAddress(reference)`.
|
|
359
466
|
*/
|
|
360
|
-
async buildTransaction(paymentRequest, payerSigner, rpc, config) {
|
|
467
|
+
async buildTransaction(paymentRequest, payerSigner, rpc, config, options) {
|
|
361
468
|
assertConfig(config);
|
|
362
469
|
assertLamports(paymentRequest.amount, "payment amount");
|
|
363
470
|
if (paymentRequest.amount === 0) {
|
|
@@ -376,14 +483,23 @@ var SolanaPaymentStrategy = class {
|
|
|
376
483
|
`Invalid fee address: expected ${treasury}, got ${paymentRequest.fee_address}. Cannot build transaction with redirected fees.`
|
|
377
484
|
);
|
|
378
485
|
}
|
|
379
|
-
const
|
|
486
|
+
const computeUnitLimit = options?.computeUnitLimit ?? DEFAULT_COMPUTE_UNIT_LIMIT;
|
|
487
|
+
if (!Number.isInteger(computeUnitLimit) || computeUnitLimit <= 0) {
|
|
488
|
+
throw new Error(`Invalid computeUnitLimit: ${computeUnitLimit}. Must be a positive integer.`);
|
|
489
|
+
}
|
|
490
|
+
const paymentInstructions = buildPaymentInstructions(paymentRequest, payerSigner);
|
|
491
|
+
const priorityFeeMicroLamports = options?.priorityFeeMicroLamports ?? await estimatePriorityFeeMicroLamports(rpc, {
|
|
492
|
+
percentile: options?.priorityFeePercentile ?? DEFAULT_PRIORITY_FEE_PERCENTILE
|
|
493
|
+
});
|
|
380
494
|
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
|
|
381
495
|
const message = kit.pipe(
|
|
382
496
|
kit.createTransactionMessage({ version: 0 }),
|
|
383
497
|
(m) => kit.setTransactionMessageFeePayerSigner(payerSigner, m),
|
|
384
498
|
(m) => kit.setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
|
|
499
|
+
(m) => kit.setTransactionMessageComputeUnitLimit(computeUnitLimit, m),
|
|
500
|
+
(m) => kit.setTransactionMessageComputeUnitPrice(priorityFeeMicroLamports, m),
|
|
385
501
|
(m) => kit.appendTransactionMessageInstructions(
|
|
386
|
-
|
|
502
|
+
paymentInstructions,
|
|
387
503
|
m
|
|
388
504
|
)
|
|
389
505
|
);
|
|
@@ -2296,12 +2412,149 @@ function validateAgentName(name) {
|
|
|
2296
2412
|
}
|
|
2297
2413
|
}
|
|
2298
2414
|
|
|
2415
|
+
// src/primitives/rateLimiter.ts
|
|
2416
|
+
function createSlidingWindowLimiter(options) {
|
|
2417
|
+
const { windowMs, maxPerWindow, maxKeys } = options;
|
|
2418
|
+
if (windowMs <= 0) {
|
|
2419
|
+
throw new RangeError("windowMs must be > 0");
|
|
2420
|
+
}
|
|
2421
|
+
if (maxPerWindow <= 0) {
|
|
2422
|
+
throw new RangeError("maxPerWindow must be > 0");
|
|
2423
|
+
}
|
|
2424
|
+
if (maxKeys <= 0) {
|
|
2425
|
+
throw new RangeError("maxKeys must be > 0");
|
|
2426
|
+
}
|
|
2427
|
+
const entries = /* @__PURE__ */ new Map();
|
|
2428
|
+
function evictIfNeeded() {
|
|
2429
|
+
while (entries.size > maxKeys) {
|
|
2430
|
+
const oldestKey = entries.keys().next().value;
|
|
2431
|
+
if (oldestKey === void 0) {
|
|
2432
|
+
return;
|
|
2433
|
+
}
|
|
2434
|
+
entries.delete(oldestKey);
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
return {
|
|
2438
|
+
peek(key, now = Date.now()) {
|
|
2439
|
+
const entry = entries.get(key);
|
|
2440
|
+
if (!entry) {
|
|
2441
|
+
return { allowed: true, resetAt: now + windowMs, count: 0 };
|
|
2442
|
+
}
|
|
2443
|
+
const cutoff = now - windowMs;
|
|
2444
|
+
const fresh = entry.hits.filter((timestamp) => timestamp > cutoff);
|
|
2445
|
+
return {
|
|
2446
|
+
allowed: fresh.length < maxPerWindow,
|
|
2447
|
+
resetAt: (fresh[0] ?? now) + windowMs,
|
|
2448
|
+
count: fresh.length
|
|
2449
|
+
};
|
|
2450
|
+
},
|
|
2451
|
+
check(key, now = Date.now()) {
|
|
2452
|
+
const entry = entries.get(key) ?? { hits: [] };
|
|
2453
|
+
const cutoff = now - windowMs;
|
|
2454
|
+
const fresh = entry.hits.filter((timestamp) => timestamp > cutoff);
|
|
2455
|
+
if (fresh.length >= maxPerWindow) {
|
|
2456
|
+
entries.delete(key);
|
|
2457
|
+
entries.set(key, { hits: fresh });
|
|
2458
|
+
return {
|
|
2459
|
+
allowed: false,
|
|
2460
|
+
resetAt: (fresh[0] ?? now) + windowMs,
|
|
2461
|
+
count: fresh.length
|
|
2462
|
+
};
|
|
2463
|
+
}
|
|
2464
|
+
fresh.push(now);
|
|
2465
|
+
entries.delete(key);
|
|
2466
|
+
entries.set(key, { hits: fresh });
|
|
2467
|
+
evictIfNeeded();
|
|
2468
|
+
return {
|
|
2469
|
+
allowed: true,
|
|
2470
|
+
resetAt: (fresh[0] ?? now) + windowMs,
|
|
2471
|
+
count: fresh.length
|
|
2472
|
+
};
|
|
2473
|
+
},
|
|
2474
|
+
prune(now = Date.now()) {
|
|
2475
|
+
const cutoff = now - windowMs;
|
|
2476
|
+
for (const [key, entry] of entries) {
|
|
2477
|
+
const fresh = entry.hits.filter((timestamp) => timestamp > cutoff);
|
|
2478
|
+
if (fresh.length === 0) {
|
|
2479
|
+
entries.delete(key);
|
|
2480
|
+
} else if (fresh.length !== entry.hits.length) {
|
|
2481
|
+
entry.hits = fresh;
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
},
|
|
2485
|
+
size() {
|
|
2486
|
+
return entries.size;
|
|
2487
|
+
},
|
|
2488
|
+
reset() {
|
|
2489
|
+
entries.clear();
|
|
2490
|
+
}
|
|
2491
|
+
};
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
// src/primitives/logRedact.ts
|
|
2495
|
+
var SECRET_REDACT_PATHS = [
|
|
2496
|
+
"*.ELISYM_NOSTR_PRIVATE_KEY",
|
|
2497
|
+
"*.ELISYM_SOLANA_PRIVATE_KEY",
|
|
2498
|
+
"*.nostrPrivateKeyHex",
|
|
2499
|
+
"*.solanaPrivateKeyBase58",
|
|
2500
|
+
"*.secretKey",
|
|
2501
|
+
"*.secret",
|
|
2502
|
+
"ELISYM_NOSTR_PRIVATE_KEY",
|
|
2503
|
+
"ELISYM_SOLANA_PRIVATE_KEY",
|
|
2504
|
+
// Canonical on-disk `.secrets.json` field names. Logging the whole
|
|
2505
|
+
// `secrets` object, or any single field directly, must not leak.
|
|
2506
|
+
"llm_api_key",
|
|
2507
|
+
"nostr_secret_key",
|
|
2508
|
+
"solana_secret_key",
|
|
2509
|
+
"*.llm_api_key",
|
|
2510
|
+
"*.nostr_secret_key",
|
|
2511
|
+
"*.solana_secret_key",
|
|
2512
|
+
"secrets",
|
|
2513
|
+
"*.secrets"
|
|
2514
|
+
];
|
|
2515
|
+
var INPUT_REDACT_PATHS = [
|
|
2516
|
+
"content",
|
|
2517
|
+
"input",
|
|
2518
|
+
"prompt",
|
|
2519
|
+
"*.content",
|
|
2520
|
+
"*.input",
|
|
2521
|
+
"*.prompt",
|
|
2522
|
+
"event.content",
|
|
2523
|
+
"*.event.content",
|
|
2524
|
+
// JobLedger entries carry the raw Nostr event JSON (which embeds
|
|
2525
|
+
// `event.content`) and the full LLM `resultContent` - both are
|
|
2526
|
+
// customer-confidential and must never land in a structured log.
|
|
2527
|
+
"rawEventJson",
|
|
2528
|
+
"resultContent",
|
|
2529
|
+
"*.rawEventJson",
|
|
2530
|
+
"*.resultContent"
|
|
2531
|
+
];
|
|
2532
|
+
var DEFAULT_REDACT_PATHS = [...SECRET_REDACT_PATHS, ...INPUT_REDACT_PATHS];
|
|
2533
|
+
var INPUT_REDACT_LEAVES = /* @__PURE__ */ new Set([
|
|
2534
|
+
"content",
|
|
2535
|
+
"input",
|
|
2536
|
+
"prompt",
|
|
2537
|
+
"rawEventJson",
|
|
2538
|
+
"resultContent"
|
|
2539
|
+
]);
|
|
2540
|
+
function makeCensor() {
|
|
2541
|
+
return (_value, path) => {
|
|
2542
|
+
const last = path[path.length - 1];
|
|
2543
|
+
if (last !== void 0 && INPUT_REDACT_LEAVES.has(last)) {
|
|
2544
|
+
return "[INPUT REDACTED]";
|
|
2545
|
+
}
|
|
2546
|
+
return "[REDACTED]";
|
|
2547
|
+
};
|
|
2548
|
+
}
|
|
2549
|
+
|
|
2299
2550
|
exports.BoundedSet = BoundedSet;
|
|
2300
2551
|
exports.DEFAULTS = DEFAULTS;
|
|
2301
2552
|
exports.DEFAULT_KIND_OFFSET = DEFAULT_KIND_OFFSET;
|
|
2553
|
+
exports.DEFAULT_REDACT_PATHS = DEFAULT_REDACT_PATHS;
|
|
2302
2554
|
exports.DiscoveryService = DiscoveryService;
|
|
2303
2555
|
exports.ElisymClient = ElisymClient;
|
|
2304
2556
|
exports.ElisymIdentity = ElisymIdentity;
|
|
2557
|
+
exports.INPUT_REDACT_PATHS = INPUT_REDACT_PATHS;
|
|
2305
2558
|
exports.KIND_APP_HANDLER = KIND_APP_HANDLER;
|
|
2306
2559
|
exports.KIND_JOB_FEEDBACK = KIND_JOB_FEEDBACK;
|
|
2307
2560
|
exports.KIND_JOB_REQUEST = KIND_JOB_REQUEST;
|
|
@@ -2318,22 +2571,30 @@ exports.NostrPool = NostrPool;
|
|
|
2318
2571
|
exports.PROTOCOL_FEE_BPS = PROTOCOL_FEE_BPS;
|
|
2319
2572
|
exports.PROTOCOL_PROGRAM_ID_DEVNET = PROTOCOL_PROGRAM_ID_DEVNET;
|
|
2320
2573
|
exports.PROTOCOL_TREASURY = PROTOCOL_TREASURY;
|
|
2574
|
+
exports.PaymentRequestSchema = PaymentRequestSchema;
|
|
2321
2575
|
exports.PingService = PingService;
|
|
2322
2576
|
exports.RELAYS = RELAYS;
|
|
2577
|
+
exports.SECRET_REDACT_PATHS = SECRET_REDACT_PATHS;
|
|
2323
2578
|
exports.SolanaPaymentStrategy = SolanaPaymentStrategy;
|
|
2324
2579
|
exports.assertExpiry = assertExpiry;
|
|
2325
2580
|
exports.assertLamports = assertLamports;
|
|
2326
2581
|
exports.buildPaymentInstructions = buildPaymentInstructions;
|
|
2327
2582
|
exports.calculateProtocolFee = calculateProtocolFee;
|
|
2583
|
+
exports.clearPriorityFeeCache = clearPriorityFeeCache;
|
|
2328
2584
|
exports.clearProtocolConfigCache = clearProtocolConfigCache;
|
|
2329
2585
|
exports.createPaymentRequestWithOnchainConfig = createPaymentRequestWithOnchainConfig;
|
|
2586
|
+
exports.createSlidingWindowLimiter = createSlidingWindowLimiter;
|
|
2587
|
+
exports.estimatePriorityFeeMicroLamports = estimatePriorityFeeMicroLamports;
|
|
2330
2588
|
exports.formatSol = formatSol;
|
|
2331
2589
|
exports.getProtocolConfig = getProtocolConfig;
|
|
2332
2590
|
exports.getProtocolProgramId = getProtocolProgramId;
|
|
2333
2591
|
exports.jobRequestKind = jobRequestKind;
|
|
2334
2592
|
exports.jobResultKind = jobResultKind;
|
|
2593
|
+
exports.makeCensor = makeCensor;
|
|
2335
2594
|
exports.nip44Decrypt = nip44Decrypt;
|
|
2336
2595
|
exports.nip44Encrypt = nip44Encrypt;
|
|
2596
|
+
exports.parsePaymentRequest = parsePaymentRequest;
|
|
2597
|
+
exports.pickPercentileFee = pickPercentileFee;
|
|
2337
2598
|
exports.timeAgo = timeAgo;
|
|
2338
2599
|
exports.toDTag = toDTag;
|
|
2339
2600
|
exports.truncateKey = truncateKey;
|