@chipi-stack/backend 14.13.0 → 14.14.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.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { shortString, hash, CallData, ec, RpcProvider, Account, num, CairoCustomEnum, CairoOption, CairoOptionVariant, cairo, typedData, uint256 } from 'starknet';
2
- import { SHHH_KIND_GAS_OVERHEAD, isValidApiKey, ChipiAuthError, STARKNET_NETWORKS, API_VERSIONING, validateErrorResponse, ChipiApiError, handleApiError, getWalletTypeFromClassHash, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, SHHH_VERIFIER_CLASS_HASHES, API_ENDPOINTS, ChipiTransactionError, formatAmount, SKU_CONTRACTS, CARRIER_IDS, SERVICE_TYPES, ChipiSessionError, SESSION_ERRORS, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, withRpcFallback, CONTRACT_ADDRESSES, TOKEN_DECIMALS } from '@chipi-stack/shared';
2
+ import { SHHH_KIND_GAS_OVERHEAD, isValidApiKey, ChipiAuthError, STARKNET_NETWORKS, API_VERSIONING, validateErrorResponse, ChipiApiError, handleApiError, getWalletTypeFromClassHash, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, SHHH_VERIFIER_CLASS_HASHES, API_ENDPOINTS, ChipiTransactionError, formatAmount, SKU_CONTRACTS, CARRIER_IDS, SERVICE_TYPES, ChipiSessionError, SESSION_ERRORS, SESSION_ENTRYPOINTS, SESSION_DEFAULTS, withRpcFallback, CONTRACT_ADDRESSES, TOKEN_DECIMALS } from '@chipi-stack/shared';
3
3
  import CryptoES from 'crypto-es';
4
4
  import { randomBytes } from 'crypto';
5
5
  import { STARKNET_CONTRACTS, Chain } from '@chipi-stack/types';
@@ -84,7 +84,7 @@ function hashCall(call) {
84
84
  return poseidonSpan([
85
85
  CALL_TYPE_HASH_REV1,
86
86
  toBigInt(call.contractAddress),
87
- toBigInt(hash.getSelectorFromName(call.entrypoint)),
87
+ toBigInt(hash.getSelector(call.entrypoint)),
88
88
  calldataHash
89
89
  ]);
90
90
  }
@@ -567,7 +567,7 @@ function serializeExecuteFromOutsideV2Calldata(params) {
567
567
  out.push(BigInt(oe.calls.length));
568
568
  for (const call of oe.calls) {
569
569
  out.push(BigInt(call.contractAddress));
570
- out.push(BigInt(hash.getSelectorFromName(call.entrypoint)));
570
+ out.push(BigInt(hash.getSelector(call.entrypoint)));
571
571
  const callData = Array.isArray(call.calldata) ? call.calldata : [];
572
572
  out.push(BigInt(callData.length));
573
573
  for (const datum of callData) {
@@ -1947,14 +1947,14 @@ var ChipiTransactions = class {
1947
1947
  /**
1948
1948
  * Get on-chain transaction status
1949
1949
  */
1950
- async getTransactionStatus(hash9, bearerToken) {
1950
+ async getTransactionStatus(hash11, bearerToken) {
1951
1951
  return this.client.get({
1952
- endpoint: `${API_ENDPOINTS.TRANSACTIONS}/${hash9}/status`,
1952
+ endpoint: `${API_ENDPOINTS.TRANSACTIONS}/${hash11}/status`,
1953
1953
  bearerToken
1954
1954
  });
1955
1955
  }
1956
1956
  /**
1957
- * Sync on-chain transfers from Voyager into the DB (read-through cache).
1957
+ * Sync on-chain transfers (Starknet Transfer events) into the DB (read-through cache).
1958
1958
  * Discovers transactions not made through the SDK (e.g., external USDC receives).
1959
1959
  * After sync, getTransactionList returns the newly discovered transactions.
1960
1960
  */
@@ -2119,6 +2119,144 @@ var ChipiSkus = class {
2119
2119
 
2120
2120
  // src/sessions.ts
2121
2121
  init_encryption2();
2122
+ var FIELD_PRIME = 2n ** 251n + 17n * 2n ** 192n + 1n;
2123
+ var HEX_FELT = /^0x[0-9a-fA-F]{1,64}$/;
2124
+ var DECIMAL_FELT = /^\d+$/;
2125
+ var CAIRO_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
2126
+ function normalizeEntrypoints(entrypoints) {
2127
+ return entrypoints.map((entry) => {
2128
+ const value = String(entry).trim();
2129
+ if (HEX_FELT.test(value) || DECIMAL_FELT.test(value)) {
2130
+ const felt = BigInt(value);
2131
+ if (felt >= FIELD_PRIME) {
2132
+ throw new ChipiSessionError(
2133
+ `Session entrypoint ${value} is not a valid felt (>= field prime).`,
2134
+ SESSION_ERRORS.SESSION_ENTRYPOINT_NOT_ALLOWED
2135
+ );
2136
+ }
2137
+ return num.toHex(felt);
2138
+ }
2139
+ if (CAIRO_IDENTIFIER.test(value)) {
2140
+ return hash.getSelectorFromName(value);
2141
+ }
2142
+ throw new ChipiSessionError(
2143
+ `Session entrypoint "${value}" is neither a selector (0x\u2026) nor a function name.`,
2144
+ SESSION_ERRORS.SESSION_ENTRYPOINT_NOT_ALLOWED
2145
+ );
2146
+ });
2147
+ }
2148
+ function decodeSessionData(result, nowSeconds) {
2149
+ const validUntil = Number(BigInt(result[0]));
2150
+ const maxCalls = Number(BigInt(result[1]));
2151
+ const callsUsed = Number(BigInt(result[2]));
2152
+ const remainingCalls = Math.max(maxCalls - callsUsed, 0);
2153
+ const isActive = validUntil !== 0 && nowSeconds <= validUntil && remainingCalls > 0;
2154
+ return { isActive, validUntil, remainingCalls, allowedEntrypoints: [] };
2155
+ }
2156
+ var U128_MASK = (1n << 128n) - 1n;
2157
+ var U256_MAX = (1n << 256n) - 1n;
2158
+ var U64_MAX = (1n << 64n) - 1n;
2159
+ function splitU256(value) {
2160
+ return [num.toHex(value & U128_MASK), num.toHex(value >> 128n)];
2161
+ }
2162
+ function buildAddSessionKeyCall(walletAddress, sessionConfig) {
2163
+ const allowedEntrypoints = normalizeEntrypoints(sessionConfig.allowedEntrypoints);
2164
+ return {
2165
+ contractAddress: walletAddress,
2166
+ entrypoint: SESSION_ENTRYPOINTS.ADD_OR_UPDATE,
2167
+ calldata: [
2168
+ sessionConfig.sessionPublicKey,
2169
+ num.toHex(sessionConfig.validUntil),
2170
+ num.toHex(sessionConfig.maxCalls),
2171
+ num.toHex(allowedEntrypoints.length),
2172
+ ...allowedEntrypoints
2173
+ ]
2174
+ };
2175
+ }
2176
+ function buildRevokeSessionKeyCall(walletAddress, sessionPublicKey) {
2177
+ return {
2178
+ contractAddress: walletAddress,
2179
+ entrypoint: SESSION_ENTRYPOINTS.REVOKE,
2180
+ calldata: [sessionPublicKey]
2181
+ };
2182
+ }
2183
+ function validateSpendingPolicyConfig(config) {
2184
+ const { token, maxPerCall, maxPerWindow, windowSeconds } = config;
2185
+ if (!token || token.trim().length === 0) {
2186
+ throw new ChipiSessionError(
2187
+ `Invalid token address for spending policy: "${token}"`,
2188
+ SESSION_ERRORS.INVALID_SPENDING_POLICY
2189
+ );
2190
+ }
2191
+ if (typeof windowSeconds !== "number" || !Number.isFinite(windowSeconds) || !Number.isInteger(windowSeconds) || windowSeconds <= 0 || BigInt(windowSeconds) > U64_MAX) {
2192
+ throw new ChipiSessionError(
2193
+ `Invalid window duration: ${windowSeconds}. Must be a positive integer within u64 range.`,
2194
+ SESSION_ERRORS.INVALID_SPENDING_POLICY
2195
+ );
2196
+ }
2197
+ if (maxPerCall < 0n || maxPerCall > U256_MAX) {
2198
+ throw new ChipiSessionError(
2199
+ `Invalid maxPerCall: must be >= 0 and <= 2^256 - 1`,
2200
+ SESSION_ERRORS.INVALID_SPENDING_POLICY
2201
+ );
2202
+ }
2203
+ if (maxPerWindow < 0n || maxPerWindow > U256_MAX) {
2204
+ throw new ChipiSessionError(
2205
+ `Invalid maxPerWindow: must be >= 0 and <= 2^256 - 1`,
2206
+ SESSION_ERRORS.INVALID_SPENDING_POLICY
2207
+ );
2208
+ }
2209
+ if (maxPerWindow > 0n && maxPerCall > maxPerWindow) {
2210
+ throw new ChipiSessionError(
2211
+ `Invalid spending policy: maxPerCall (${maxPerCall}) cannot exceed maxPerWindow (${maxPerWindow})`,
2212
+ SESSION_ERRORS.INVALID_SPENDING_POLICY
2213
+ );
2214
+ }
2215
+ }
2216
+ function buildSetSpendingPolicyCall(walletAddress, config) {
2217
+ validateSpendingPolicyConfig(config);
2218
+ const [maxPerCallLow, maxPerCallHigh] = splitU256(config.maxPerCall);
2219
+ const [maxPerWindowLow, maxPerWindowHigh] = splitU256(config.maxPerWindow);
2220
+ return {
2221
+ contractAddress: walletAddress,
2222
+ entrypoint: SESSION_ENTRYPOINTS.SET_SPENDING_POLICY,
2223
+ calldata: [
2224
+ config.sessionPublicKey,
2225
+ config.token,
2226
+ maxPerCallLow,
2227
+ maxPerCallHigh,
2228
+ maxPerWindowLow,
2229
+ maxPerWindowHigh,
2230
+ num.toHex(config.windowSeconds)
2231
+ ]
2232
+ };
2233
+ }
2234
+ function buildRemoveSpendingPolicyCall(walletAddress, sessionPublicKey, token) {
2235
+ if (!token || token.trim().length === 0) {
2236
+ throw new ChipiSessionError(
2237
+ `Invalid token address for spending policy removal: "${token}"`,
2238
+ SESSION_ERRORS.INVALID_SPENDING_POLICY
2239
+ );
2240
+ }
2241
+ return {
2242
+ contractAddress: walletAddress,
2243
+ entrypoint: SESSION_ENTRYPOINTS.REMOVE_SPENDING_POLICY,
2244
+ calldata: [sessionPublicKey, token]
2245
+ };
2246
+ }
2247
+ function buildSessionSetupCalls(walletAddress, sessionConfig, spendingPolicies = []) {
2248
+ return [
2249
+ buildAddSessionKeyCall(walletAddress, sessionConfig),
2250
+ ...spendingPolicies.map(
2251
+ (policy) => buildSetSpendingPolicyCall(walletAddress, {
2252
+ ...policy,
2253
+ sessionPublicKey: sessionConfig.sessionPublicKey
2254
+ })
2255
+ )
2256
+ ];
2257
+ }
2258
+
2259
+ // src/sessions.ts
2122
2260
  var ChipiSessions = class {
2123
2261
  constructor(client) {
2124
2262
  this.client = client;
@@ -2258,25 +2396,12 @@ var ChipiSessions = class {
2258
2396
  maxCalls: sessionConfig.maxCalls,
2259
2397
  allowedEntrypoints: sessionConfig.allowedEntrypoints.length
2260
2398
  });
2261
- const calldata = [
2262
- sessionConfig.sessionPublicKey,
2263
- num.toHex(sessionConfig.validUntil),
2264
- num.toHex(sessionConfig.maxCalls),
2265
- // Array: first element is length, then elements
2266
- num.toHex(sessionConfig.allowedEntrypoints.length),
2267
- ...sessionConfig.allowedEntrypoints
2268
- ];
2399
+ const addCall = buildAddSessionKeyCall(wallet.publicKey, sessionConfig);
2269
2400
  const txHash = await executePaymasterTransaction({
2270
2401
  params: {
2271
2402
  encryptKey,
2272
2403
  wallet,
2273
- calls: [
2274
- {
2275
- contractAddress: wallet.publicKey,
2276
- entrypoint: SESSION_ENTRYPOINTS.ADD_OR_UPDATE,
2277
- calldata
2278
- }
2279
- ],
2404
+ calls: [addCall],
2280
2405
  saveToDatabase: false
2281
2406
  // Don't record session management txs
2282
2407
  },
@@ -2300,6 +2425,54 @@ var ChipiSessions = class {
2300
2425
  throw error;
2301
2426
  }
2302
2427
  }
2428
+ /**
2429
+ * Register a session and its spending policies in ONE owner-signed transaction.
2430
+ *
2431
+ * Equivalent to `addSessionKeyToContract` followed by one `setSpendingPolicy`
2432
+ * per token, but the owner signs once (one passkey prompt) and the session
2433
+ * never exists on-chain without its caps.
2434
+ *
2435
+ * @example
2436
+ * ```typescript
2437
+ * const txHash = await sdk.sessions.setupSession({
2438
+ * encryptKey,
2439
+ * wallet,
2440
+ * sessionConfig: {
2441
+ * sessionPublicKey: session.publicKey,
2442
+ * validUntil: session.validUntil,
2443
+ * maxCalls: 500,
2444
+ * allowedEntrypoints: ["transfer", "approve"],
2445
+ * },
2446
+ * spendingPolicies: [
2447
+ * { token: USDC, maxPerCall: 5_000_000n, maxPerWindow: 20_000_000n, windowSeconds: 86400 },
2448
+ * ],
2449
+ * }, bearerToken);
2450
+ * ```
2451
+ */
2452
+ async setupSession(params, bearerToken) {
2453
+ const { encryptKey, wallet, sessionConfig, spendingPolicies = [] } = params;
2454
+ this.validateWalletSupportsSessions(wallet.walletType, "Setup", wallet.publicKey);
2455
+ const calls = buildSessionSetupCalls(wallet.publicKey, sessionConfig, spendingPolicies);
2456
+ console.log("[ChipiSDK:Session:Setup] Registering session with spending policies", {
2457
+ walletAddress: wallet.publicKey.slice(0, 15) + "...",
2458
+ sessionPubKey: sessionConfig.sessionPublicKey.slice(0, 15) + "...",
2459
+ validUntil: new Date(sessionConfig.validUntil * 1e3).toISOString(),
2460
+ maxCalls: sessionConfig.maxCalls,
2461
+ allowedEntrypoints: sessionConfig.allowedEntrypoints.length,
2462
+ spendingPolicies: spendingPolicies.length
2463
+ });
2464
+ return executePaymasterTransaction({
2465
+ params: {
2466
+ encryptKey,
2467
+ wallet,
2468
+ calls,
2469
+ saveToDatabase: false
2470
+ // Don't record session management txs
2471
+ },
2472
+ bearerToken,
2473
+ client: this.client
2474
+ });
2475
+ }
2303
2476
  /**
2304
2477
  * Revoke a session key from the smart contract.
2305
2478
  *
@@ -2333,13 +2506,7 @@ var ChipiSessions = class {
2333
2506
  params: {
2334
2507
  encryptKey,
2335
2508
  wallet,
2336
- calls: [
2337
- {
2338
- contractAddress: wallet.publicKey,
2339
- entrypoint: SESSION_ENTRYPOINTS.REVOKE,
2340
- calldata: [sessionPublicKey]
2341
- }
2342
- ],
2509
+ calls: [buildRevokeSessionKeyCall(wallet.publicKey, sessionPublicKey)],
2343
2510
  saveToDatabase: false
2344
2511
  // Don't record session management txs
2345
2512
  },
@@ -2414,11 +2581,10 @@ var ChipiSessions = class {
2414
2581
  allowedEntrypoints: []
2415
2582
  };
2416
2583
  }
2417
- const isActive = resultArray[0] === "0x1";
2418
- const validUntil = Number(BigInt(resultArray[1]));
2419
- const remainingCalls = Number(BigInt(resultArray[2]));
2420
- const entrypointsLen = Number(BigInt(resultArray[3]));
2421
- const allowedEntrypoints = resultArray.slice(4, 4 + entrypointsLen);
2584
+ const { isActive, validUntil, remainingCalls, allowedEntrypoints } = decodeSessionData(
2585
+ resultArray,
2586
+ Math.floor(Date.now() / 1e3)
2587
+ );
2422
2588
  const sessionData = {
2423
2589
  isActive,
2424
2590
  validUntil,
@@ -2429,7 +2595,8 @@ var ChipiSessions = class {
2429
2595
  isActive,
2430
2596
  validUntil: new Date(validUntil * 1e3).toISOString(),
2431
2597
  remainingCalls,
2432
- allowedEntrypointsCount: allowedEntrypoints.length
2598
+ // The struct carries the whitelist length, not the selectors.
2599
+ allowedEntrypointsLen: Number(BigInt(resultArray[3]))
2433
2600
  });
2434
2601
  return sessionData;
2435
2602
  } catch (error) {
@@ -2529,13 +2696,6 @@ var ChipiSessions = class {
2529
2696
  // Wraps ISessionSpendingPolicy contract interface.
2530
2697
  // Spending policies enforce per-token limits on ERC-20 operations
2531
2698
  // (transfer, approve, increase_allowance) executed by session keys.
2532
- /**
2533
- * Split a bigint into Cairo u256 representation (low u128, high u128).
2534
- */
2535
- splitU256(value) {
2536
- const mask = (1n << 128n) - 1n;
2537
- return [num.toHex(value & mask), num.toHex(value >> 128n)];
2538
- }
2539
2699
  /**
2540
2700
  * Reconstruct a bigint from Cairo u256 (low, high) hex strings.
2541
2701
  */
@@ -2580,38 +2740,7 @@ var ChipiSessions = class {
2580
2740
  SESSION_ERRORS.INVALID_WALLET_TYPE_FOR_SESSION
2581
2741
  );
2582
2742
  }
2583
- const U256_MAX = (1n << 256n) - 1n;
2584
- const U64_MAX = (1n << 64n) - 1n;
2585
- if (!token || token.trim().length === 0) {
2586
- throw new ChipiSessionError(
2587
- `Invalid token address for spending policy: "${token}"`,
2588
- SESSION_ERRORS.INVALID_SPENDING_POLICY
2589
- );
2590
- }
2591
- if (typeof windowSeconds !== "number" || !Number.isFinite(windowSeconds) || !Number.isInteger(windowSeconds) || windowSeconds <= 0 || BigInt(windowSeconds) > U64_MAX) {
2592
- throw new ChipiSessionError(
2593
- `Invalid window duration: ${windowSeconds}. Must be a positive integer within u64 range.`,
2594
- SESSION_ERRORS.INVALID_SPENDING_POLICY
2595
- );
2596
- }
2597
- if (maxPerCall < 0n || maxPerCall > U256_MAX) {
2598
- throw new ChipiSessionError(
2599
- `Invalid maxPerCall: must be >= 0 and <= 2^256 - 1`,
2600
- SESSION_ERRORS.INVALID_SPENDING_POLICY
2601
- );
2602
- }
2603
- if (maxPerWindow < 0n || maxPerWindow > U256_MAX) {
2604
- throw new ChipiSessionError(
2605
- `Invalid maxPerWindow: must be >= 0 and <= 2^256 - 1`,
2606
- SESSION_ERRORS.INVALID_SPENDING_POLICY
2607
- );
2608
- }
2609
- if (maxPerWindow > 0n && maxPerCall > maxPerWindow) {
2610
- throw new ChipiSessionError(
2611
- `Invalid spending policy: maxPerCall (${maxPerCall}) cannot exceed maxPerWindow (${maxPerWindow})`,
2612
- SESSION_ERRORS.INVALID_SPENDING_POLICY
2613
- );
2614
- }
2743
+ validateSpendingPolicyConfig(spendingPolicyConfig);
2615
2744
  try {
2616
2745
  console.log("[ChipiSDK:Session:SetSpendingPolicy] Setting spending policy", {
2617
2746
  walletAddress: wallet.publicKey.slice(0, 15) + "...",
@@ -2621,28 +2750,12 @@ var ChipiSessions = class {
2621
2750
  maxPerWindow: maxPerWindow.toString(),
2622
2751
  windowSeconds
2623
2752
  });
2624
- const [maxPerCallLow, maxPerCallHigh] = this.splitU256(maxPerCall);
2625
- const [maxPerWindowLow, maxPerWindowHigh] = this.splitU256(maxPerWindow);
2626
- const calldata = [
2627
- sessionPublicKey,
2628
- token,
2629
- maxPerCallLow,
2630
- maxPerCallHigh,
2631
- maxPerWindowLow,
2632
- maxPerWindowHigh,
2633
- num.toHex(windowSeconds)
2634
- ];
2753
+ const setPolicyCall = buildSetSpendingPolicyCall(wallet.publicKey, spendingPolicyConfig);
2635
2754
  const txHash = await executePaymasterTransaction({
2636
2755
  params: {
2637
2756
  encryptKey,
2638
2757
  wallet,
2639
- calls: [
2640
- {
2641
- contractAddress: wallet.publicKey,
2642
- entrypoint: SESSION_ENTRYPOINTS.SET_SPENDING_POLICY,
2643
- calldata
2644
- }
2645
- ],
2758
+ calls: [setPolicyCall],
2646
2759
  saveToDatabase: false
2647
2760
  },
2648
2761
  bearerToken,
@@ -2809,18 +2922,12 @@ var ChipiSessions = class {
2809
2922
  sessionPubKey: sessionPublicKey.slice(0, 15) + "...",
2810
2923
  token: token.slice(0, 15) + "..."
2811
2924
  });
2812
- const calldata = [sessionPublicKey, token];
2925
+ const removeCall = buildRemoveSpendingPolicyCall(wallet.publicKey, sessionPublicKey, token);
2813
2926
  const txHash = await executePaymasterTransaction({
2814
2927
  params: {
2815
2928
  encryptKey,
2816
2929
  wallet,
2817
- calls: [
2818
- {
2819
- contractAddress: wallet.publicKey,
2820
- entrypoint: SESSION_ENTRYPOINTS.REMOVE_SPENDING_POLICY,
2821
- calldata
2822
- }
2823
- ],
2930
+ calls: [removeCall],
2824
2931
  saveToDatabase: false
2825
2932
  },
2826
2933
  bearerToken,
@@ -3001,6 +3108,105 @@ var ChipiTreasury = class {
3001
3108
  };
3002
3109
  }
3003
3110
  };
3111
+ var AI_BASE = "/ai";
3112
+ var THINK_ACTIONS = /* @__PURE__ */ new Set(["swap", "supply", "withdraw", "hold"]);
3113
+ function isThinkDecision(decision) {
3114
+ if (!decision || typeof decision !== "object") return false;
3115
+ const d = decision;
3116
+ if (typeof d.action !== "string" || !THINK_ACTIONS.has(d.action)) return false;
3117
+ if (typeof d.reason !== "string") return false;
3118
+ if (d.amount !== void 0 && (typeof d.amount !== "number" || !Number.isFinite(d.amount)))
3119
+ return false;
3120
+ if (d.confidence !== void 0 && typeof d.confidence !== "number") return false;
3121
+ if (d.from !== void 0 && typeof d.from !== "string") return false;
3122
+ if (d.to !== void 0 && typeof d.to !== "string") return false;
3123
+ return true;
3124
+ }
3125
+ var ChipiAi = class {
3126
+ constructor(client, apiSecretKey) {
3127
+ this.client = client;
3128
+ this.apiSecretKey = apiSecretKey;
3129
+ }
3130
+ secret() {
3131
+ const key = this.apiSecretKey;
3132
+ if (!key || !key.startsWith("sk_")) {
3133
+ throw new ChipiAuthError(
3134
+ "sdk.ai needs a secret key (sk_): configure the SDK with apiSecretKey and call it from a server, never the browser."
3135
+ );
3136
+ }
3137
+ return key;
3138
+ }
3139
+ /**
3140
+ * `GET /v1/ai/signals`: technical signals per token, market sentiment and
3141
+ * DeFi yields. Free up to a monthly quota per organization, then billed per call.
3142
+ */
3143
+ async signals(params = {}) {
3144
+ const query = {};
3145
+ if (params.tokens?.length) query.tokens = params.tokens.join(",");
3146
+ if (params.chain) query.chain = params.chain;
3147
+ return this.client.get({
3148
+ endpoint: `${AI_BASE}/signals`,
3149
+ params: query,
3150
+ bearerToken: this.secret()
3151
+ });
3152
+ }
3153
+ /**
3154
+ * `POST /v1/ai/think`: one DeFi decision for a portfolio, with the latest
3155
+ * signals and your risk parameters injected into the prompt.
3156
+ *
3157
+ * The decision is advice, not an order: check it with `isThinkDecision` and
3158
+ * enforce your own limits before executing anything.
3159
+ */
3160
+ async think(params) {
3161
+ return this.client.post({
3162
+ endpoint: `${AI_BASE}/think`,
3163
+ bearerToken: this.secret(),
3164
+ body: params
3165
+ });
3166
+ }
3167
+ /**
3168
+ * `POST /v1/ai/execute`: unsigned AVNU swap calls (approve + swap) for
3169
+ * `walletAddress`. Nothing is submitted; sign the calls with a session key
3170
+ * or the owner's key.
3171
+ */
3172
+ async execute(params) {
3173
+ return this.client.post({
3174
+ endpoint: `${AI_BASE}/execute`,
3175
+ bearerToken: this.secret(),
3176
+ body: params
3177
+ });
3178
+ }
3179
+ /** `POST /v1/ai/chat`: general-purpose chat, billed per token. */
3180
+ async chat(params) {
3181
+ return this.client.post({
3182
+ endpoint: `${AI_BASE}/chat`,
3183
+ bearerToken: this.secret(),
3184
+ body: params
3185
+ });
3186
+ }
3187
+ /**
3188
+ * `GET /v1/ai/prices`: USD prices and 1h / 24h / 7d changes, refreshed about
3189
+ * every 30 seconds. No credits are charged, but like every `sdk.ai` method it
3190
+ * needs the SDK's secret key (`sk_`).
3191
+ */
3192
+ async prices(params = {}) {
3193
+ const query = {};
3194
+ if (params.tokens?.length) query.tokens = params.tokens.join(",");
3195
+ if (params.chain) query.chain = params.chain;
3196
+ return this.client.get({
3197
+ endpoint: `${AI_BASE}/prices`,
3198
+ params: query,
3199
+ bearerToken: this.secret()
3200
+ });
3201
+ }
3202
+ /** `GET /v1/ai/models`: available models, prices and limits. */
3203
+ async models() {
3204
+ return this.client.get({
3205
+ endpoint: `${AI_BASE}/models`,
3206
+ bearerToken: this.secret()
3207
+ });
3208
+ }
3209
+ };
3004
3210
  var InMemoryNonceStore = class {
3005
3211
  constructor() {
3006
3212
  this.used = /* @__PURE__ */ new Set();
@@ -3318,6 +3524,7 @@ var ChipiSDK = class {
3318
3524
  this.sessions = new ChipiSessions(this.client);
3319
3525
  this.exchanges = new ChipiExchanges(this.client);
3320
3526
  this.treasury = new ChipiTreasury(this.client, config.apiSecretKey);
3527
+ this.ai = new ChipiAi(this.client, config.apiSecretKey);
3321
3528
  this.executeTransaction = this.executeTransaction.bind(this);
3322
3529
  this.executeTransactionWithSession = this.executeTransactionWithSession.bind(this);
3323
3530
  this.transfer = this.transfer.bind(this);
@@ -3581,8 +3788,8 @@ var ChipiSDK = class {
3581
3788
  /**
3582
3789
  * Get on-chain transaction status (supports polling for confirmation)
3583
3790
  */
3584
- async getTransactionStatus(hash9, bearerToken) {
3585
- return this.transactions.getTransactionStatus(hash9, this.resolveBearerToken(bearerToken));
3791
+ async getTransactionStatus(hash11, bearerToken) {
3792
+ return this.transactions.getTransactionStatus(hash11, this.resolveBearerToken(bearerToken));
3586
3793
  }
3587
3794
  /**
3588
3795
  * Prepare a wallet upgrade (e.g., READY → CHIPI or CHIPI v29 → v33).
@@ -3997,6 +4204,79 @@ function x402Middleware(config) {
3997
4204
  next();
3998
4205
  };
3999
4206
  }
4207
+ var InMemoryTxHashStore = class {
4208
+ constructor() {
4209
+ this.used = /* @__PURE__ */ new Set();
4210
+ }
4211
+ consume(transactionHash) {
4212
+ if (this.used.has(transactionHash)) return false;
4213
+ this.used.add(transactionHash);
4214
+ return true;
4215
+ }
4216
+ };
4217
+ var TRANSFER_SELECTOR = BigInt(hash.getSelectorFromName("Transfer"));
4218
+ function toBigInt2(value) {
4219
+ if (value === void 0) return void 0;
4220
+ try {
4221
+ return BigInt(value);
4222
+ } catch {
4223
+ return void 0;
4224
+ }
4225
+ }
4226
+ function decodeTransfer(event) {
4227
+ if (toBigInt2(event.keys[0]) !== TRANSFER_SELECTOR) return void 0;
4228
+ const [from, to, low, high] = event.keys.length >= 3 ? [event.keys[1], event.keys[2], event.data[0], event.data[1]] : [event.data[0], event.data[1], event.data[2], event.data[3]];
4229
+ const values = [from, to, low, high].map(toBigInt2);
4230
+ if (values.some((v) => v === void 0)) return void 0;
4231
+ const [f, t, l, h] = values;
4232
+ return { from: f, to: t, amount: l + (h << 128n) };
4233
+ }
4234
+ var SessionTxVerifier = class {
4235
+ constructor(config = {}) {
4236
+ const { txHashStore, getReceipt, ...receiptOptions } = config;
4237
+ this.store = txHashStore ?? new InMemoryTxHashStore();
4238
+ this.getReceipt = getReceipt ?? waitForTransaction;
4239
+ this.receiptOptions = receiptOptions;
4240
+ }
4241
+ async verifyTransfer(params) {
4242
+ const { transactionHash, token, from, to, minAmount } = params;
4243
+ const receipt = await this.getReceipt(transactionHash, this.receiptOptions);
4244
+ if (!receipt.success) {
4245
+ return { valid: false, transactionHash, reason: "REVERTED", detail: receipt.revertReason };
4246
+ }
4247
+ const tokenAddress = BigInt(token);
4248
+ const fromAddress = BigInt(from);
4249
+ const toAddress = BigInt(to);
4250
+ let best;
4251
+ for (const event of receipt.events) {
4252
+ if (toBigInt2(event.from_address) !== tokenAddress) continue;
4253
+ const transfer = decodeTransfer(event);
4254
+ if (!transfer || transfer.from !== fromAddress || transfer.to !== toAddress) continue;
4255
+ if (best === void 0 || transfer.amount > best) best = transfer.amount;
4256
+ }
4257
+ if (best === void 0) {
4258
+ return { valid: false, transactionHash, reason: "TRANSFER_NOT_FOUND" };
4259
+ }
4260
+ if (best < minAmount) {
4261
+ return {
4262
+ valid: false,
4263
+ transactionHash,
4264
+ reason: "AMOUNT_TOO_LOW",
4265
+ detail: `paid ${best}, expected at least ${minAmount}`
4266
+ };
4267
+ }
4268
+ const key = "0x" + BigInt(transactionHash).toString(16);
4269
+ if (!await this.store.consume(key)) {
4270
+ return { valid: false, transactionHash, reason: "ALREADY_USED" };
4271
+ }
4272
+ return {
4273
+ valid: true,
4274
+ transactionHash,
4275
+ amount: best,
4276
+ ...receipt.blockNumber !== void 0 ? { blockNumber: receipt.blockNumber } : {}
4277
+ };
4278
+ }
4279
+ };
4000
4280
 
4001
4281
  // src/shhh/index.ts
4002
4282
  init_snip12_hash();
@@ -4402,7 +4682,7 @@ var JWT_APPLE_SUB_KIND_TAG = "JWT_ES256_APPLE_SUB";
4402
4682
  var JWT_APPLE_SUB_KIND_TAG_FELT = BigInt(shortString.encodeShortString(JWT_APPLE_SUB_KIND_TAG));
4403
4683
  var APPLE_ISSUER = "https://appleid.apple.com";
4404
4684
  var NONCE_B64URL_LEN = 43;
4405
- var U128_MASK = (1n << 128n) - 1n;
4685
+ var U128_MASK2 = (1n << 128n) - 1n;
4406
4686
  function assertBytes3(name, b, len) {
4407
4687
  if (b.length !== len) {
4408
4688
  throw new Error(`${name} must be exactly ${len} bytes; got ${b.length}.`);
@@ -4412,7 +4692,7 @@ function bytesBeToU2563(b) {
4412
4692
  assertBytes3("secp256r1 32B value", b, 32);
4413
4693
  let x = 0n;
4414
4694
  for (let i = 0; i < b.length; i++) x = x << 8n | BigInt(b[i]);
4415
- return { low: x & U128_MASK, high: x >> 128n };
4695
+ return { low: x & U128_MASK2, high: x >> 128n };
4416
4696
  }
4417
4697
  function jwtAppleSubHash(sub) {
4418
4698
  const bytes = new TextEncoder().encode(sub);
@@ -4547,9 +4827,9 @@ function buildEnvelopePayload(fields) {
4547
4827
  BigInt(fields.issOffset),
4548
4828
  BigInt(fields.subOffset),
4549
4829
  BigInt(fields.subLen),
4550
- fields.r & U128_MASK,
4830
+ fields.r & U128_MASK2,
4551
4831
  fields.r >> 128n,
4552
- fields.s & U128_MASK,
4832
+ fields.s & U128_MASK2,
4553
4833
  fields.s >> 128n,
4554
4834
  BigInt(fields.yParity)
4555
4835
  ];
@@ -4895,6 +5175,6 @@ function submitViaAccount(funded) {
4895
5175
  };
4896
5176
  }
4897
5177
 
4898
- export { ANY_CALLER_FELT, APPLE_ISSUER, BOOTSTRAP_DOMAIN_SEPARATOR, ChipiBrowserSDK, ChipiClient, ChipiPaymasterAdapter, ChipiSDK, ChipiServerSDK, ChipiSessions, ChipiSkuPurchases, ChipiSkus, ChipiTransactions, ChipiTreasury, ChipiWallets, DEFAULT_OP_EXPIRY_SECONDS, ISIGNER_CANONICAL_LABEL, ISIGNER_ID, ISRC9_V2_ID, MAX_OE_VALIDITY_WINDOW_SECONDS, MIN_THRESHOLD_OWNERS, OE_DOMAIN_NAME, OE_DOMAIN_REVISION, OE_DOMAIN_VERSION, OP_ADD_OWNER, OP_REMOVE_OWNER, OP_ROTATE_OWNER, OP_SET_THRESHOLD, ROLE_GUARDIAN, ROLE_OWNER, SIG_VERSION_V1_HEX_ASCII, SIG_VERSION_V2_SNIP12, SIG_VERSION_V2_THRESHOLD, STARKNET_MESSAGE_PREFIX, ShhhAccount, TIMELOCK_SECONDS, VIEW_SELECTORS, X402Facilitator, X402ShhhClient, assertValidV2Snip12Envelope, buildBootstrapSignedCall, buildCancelPendingOpCall, buildCancelRecoveryCall, buildEd25519Envelope, buildEd25519EnvelopeFromSignature, buildEip191EnvelopeFromPrivateKey, buildEip191EnvelopeFromSignature, buildExecuteAddOwnerCall, buildExecuteRemoveOwnerCall, buildExecuteRotateOwnerCall, buildExecuteSetThresholdCall, buildFinalizeRecoveryCall, buildInitiateRecoveryCall, buildJwtAppleSubEnvelopeFromTestKey, buildJwtAppleSubEnvelopeFromTokenResponse, buildMigrationCalls, buildOutsideExecution, buildProposeAddOwnerCall, buildProposeRemoveOwnerCall, buildProposeRotateOwnerCall, buildProposeSetThresholdCall, buildStarkEnvelope, buildThresholdEnvelope, buildWebAuthnEnvelopeFromAssertion, buildWebAuthnEnvelopeFromPrivateKey, byteArrayToFelts, computeAddressSalt, computeBootstrapMessage, computeISignerId, computeOeHash, computeShhhAddress, computeSnip12Hash, decryptPrivateKey, ed25519OwnerId, ed25519OwnerPubkeyParam, ed25519PubkeyFelts, ed25519SignedBytes, eip191OwnerId, eip191OwnerPubkeyParam, eip191PubkeyFelts, encryptPrivateKey, estimateThresholdGasOverhead, executeShhhSponsoredRaw, hashCall, hashCalls, hashOutsideExecutionStruct, hashStarknetDomain, isReadyToExecute, jwtAppleSubHash, jwtAppleSubOwnerId, jwtAppleSubPubkeyFelts, labelToFelt, locateSubClaim, messageHashToNonceB64url, migrateChipiWalletToShhh, ownerCommitment, parseAppleIdToken, parseDerEcdsaSignature, parseEip191Signature, parseThresholdEnvelope, resolveShhhChainId, secondsUntilExecutable, serializeExecuteFromOutsideV2Calldata, signBootstrapMessage, signTypedData, signTypedDataArray, snip12HashToHexAsciiBytes, starkOwnerId, starkPubkeyFelts, submitViaAccount, waitForTransaction, webauthnOwnerId, webauthnOwnerPubkeyParam, webauthnPubkeyFelts, wrapV2Snip12Envelope, wrapV2ThresholdEnvelope, x402Middleware };
5178
+ export { ANY_CALLER_FELT, APPLE_ISSUER, BOOTSTRAP_DOMAIN_SEPARATOR, ChipiAi, ChipiBrowserSDK, ChipiClient, ChipiPaymasterAdapter, ChipiSDK, ChipiServerSDK, ChipiSessions, ChipiSkuPurchases, ChipiSkus, ChipiTransactions, ChipiTreasury, ChipiWallets, DEFAULT_OP_EXPIRY_SECONDS, ISIGNER_CANONICAL_LABEL, ISIGNER_ID, ISRC9_V2_ID, MAX_OE_VALIDITY_WINDOW_SECONDS, MIN_THRESHOLD_OWNERS, OE_DOMAIN_NAME, OE_DOMAIN_REVISION, OE_DOMAIN_VERSION, OP_ADD_OWNER, OP_REMOVE_OWNER, OP_ROTATE_OWNER, OP_SET_THRESHOLD, ROLE_GUARDIAN, ROLE_OWNER, SIG_VERSION_V1_HEX_ASCII, SIG_VERSION_V2_SNIP12, SIG_VERSION_V2_THRESHOLD, STARKNET_MESSAGE_PREFIX, SessionTxVerifier, ShhhAccount, TIMELOCK_SECONDS, VIEW_SELECTORS, X402Facilitator, X402ShhhClient, assertValidV2Snip12Envelope, buildAddSessionKeyCall, buildBootstrapSignedCall, buildCancelPendingOpCall, buildCancelRecoveryCall, buildEd25519Envelope, buildEd25519EnvelopeFromSignature, buildEip191EnvelopeFromPrivateKey, buildEip191EnvelopeFromSignature, buildExecuteAddOwnerCall, buildExecuteRemoveOwnerCall, buildExecuteRotateOwnerCall, buildExecuteSetThresholdCall, buildFinalizeRecoveryCall, buildInitiateRecoveryCall, buildJwtAppleSubEnvelopeFromTestKey, buildJwtAppleSubEnvelopeFromTokenResponse, buildMigrationCalls, buildOutsideExecution, buildProposeAddOwnerCall, buildProposeRemoveOwnerCall, buildProposeRotateOwnerCall, buildProposeSetThresholdCall, buildRemoveSpendingPolicyCall, buildRevokeSessionKeyCall, buildSessionSetupCalls, buildSetSpendingPolicyCall, buildStarkEnvelope, buildThresholdEnvelope, buildWebAuthnEnvelopeFromAssertion, buildWebAuthnEnvelopeFromPrivateKey, byteArrayToFelts, computeAddressSalt, computeBootstrapMessage, computeISignerId, computeOeHash, computeShhhAddress, computeSnip12Hash, decryptPrivateKey, ed25519OwnerId, ed25519OwnerPubkeyParam, ed25519PubkeyFelts, ed25519SignedBytes, eip191OwnerId, eip191OwnerPubkeyParam, eip191PubkeyFelts, encryptPrivateKey, estimateThresholdGasOverhead, executeShhhSponsoredRaw, hashCall, hashCalls, hashOutsideExecutionStruct, hashStarknetDomain, isReadyToExecute, isThinkDecision, jwtAppleSubHash, jwtAppleSubOwnerId, jwtAppleSubPubkeyFelts, labelToFelt, locateSubClaim, messageHashToNonceB64url, migrateChipiWalletToShhh, normalizeEntrypoints, ownerCommitment, parseAppleIdToken, parseDerEcdsaSignature, parseEip191Signature, parseThresholdEnvelope, resolveShhhChainId, secondsUntilExecutable, serializeExecuteFromOutsideV2Calldata, signBootstrapMessage, signTypedData, signTypedDataArray, snip12HashToHexAsciiBytes, starkOwnerId, starkPubkeyFelts, submitViaAccount, validateSpendingPolicyConfig, waitForTransaction, webauthnOwnerId, webauthnOwnerPubkeyParam, webauthnPubkeyFelts, wrapV2Snip12Envelope, wrapV2ThresholdEnvelope, x402Middleware };
4899
5179
  //# sourceMappingURL=index.mjs.map
4900
5180
  //# sourceMappingURL=index.mjs.map