@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.d.mts +245 -6
- package/dist/index.d.ts +245 -6
- package/dist/index.js +394 -104
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +386 -106
- package/dist/index.mjs.map +1 -1
- package/dist/skuPurchases.js +3 -3
- package/dist/skuPurchases.js.map +1 -1
- package/dist/skuPurchases.mjs +3 -3
- package/dist/skuPurchases.mjs.map +1 -1
- package/dist/transactions.d.mts +1 -1
- package/dist/transactions.d.ts +1 -1
- package/dist/transactions.js +3 -3
- package/dist/transactions.js.map +1 -1
- package/dist/transactions.mjs +3 -3
- package/dist/transactions.mjs.map +1 -1
- package/dist/wallets.js +2 -2
- package/dist/wallets.js.map +1 -1
- package/dist/wallets.mjs +2 -2
- package/dist/wallets.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -89,7 +89,7 @@ function hashCall(call) {
|
|
|
89
89
|
return poseidonSpan([
|
|
90
90
|
CALL_TYPE_HASH_REV1,
|
|
91
91
|
toBigInt(call.contractAddress),
|
|
92
|
-
toBigInt(starknet.hash.
|
|
92
|
+
toBigInt(starknet.hash.getSelector(call.entrypoint)),
|
|
93
93
|
calldataHash
|
|
94
94
|
]);
|
|
95
95
|
}
|
|
@@ -572,7 +572,7 @@ function serializeExecuteFromOutsideV2Calldata(params) {
|
|
|
572
572
|
out.push(BigInt(oe.calls.length));
|
|
573
573
|
for (const call of oe.calls) {
|
|
574
574
|
out.push(BigInt(call.contractAddress));
|
|
575
|
-
out.push(BigInt(starknet.hash.
|
|
575
|
+
out.push(BigInt(starknet.hash.getSelector(call.entrypoint)));
|
|
576
576
|
const callData = Array.isArray(call.calldata) ? call.calldata : [];
|
|
577
577
|
out.push(BigInt(callData.length));
|
|
578
578
|
for (const datum of callData) {
|
|
@@ -1952,14 +1952,14 @@ var ChipiTransactions = class {
|
|
|
1952
1952
|
/**
|
|
1953
1953
|
* Get on-chain transaction status
|
|
1954
1954
|
*/
|
|
1955
|
-
async getTransactionStatus(
|
|
1955
|
+
async getTransactionStatus(hash11, bearerToken) {
|
|
1956
1956
|
return this.client.get({
|
|
1957
|
-
endpoint: `${shared.API_ENDPOINTS.TRANSACTIONS}/${
|
|
1957
|
+
endpoint: `${shared.API_ENDPOINTS.TRANSACTIONS}/${hash11}/status`,
|
|
1958
1958
|
bearerToken
|
|
1959
1959
|
});
|
|
1960
1960
|
}
|
|
1961
1961
|
/**
|
|
1962
|
-
* Sync on-chain transfers
|
|
1962
|
+
* Sync on-chain transfers (Starknet Transfer events) into the DB (read-through cache).
|
|
1963
1963
|
* Discovers transactions not made through the SDK (e.g., external USDC receives).
|
|
1964
1964
|
* After sync, getTransactionList returns the newly discovered transactions.
|
|
1965
1965
|
*/
|
|
@@ -2124,6 +2124,144 @@ var ChipiSkus = class {
|
|
|
2124
2124
|
|
|
2125
2125
|
// src/sessions.ts
|
|
2126
2126
|
init_encryption2();
|
|
2127
|
+
var FIELD_PRIME = 2n ** 251n + 17n * 2n ** 192n + 1n;
|
|
2128
|
+
var HEX_FELT = /^0x[0-9a-fA-F]{1,64}$/;
|
|
2129
|
+
var DECIMAL_FELT = /^\d+$/;
|
|
2130
|
+
var CAIRO_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
2131
|
+
function normalizeEntrypoints(entrypoints) {
|
|
2132
|
+
return entrypoints.map((entry) => {
|
|
2133
|
+
const value = String(entry).trim();
|
|
2134
|
+
if (HEX_FELT.test(value) || DECIMAL_FELT.test(value)) {
|
|
2135
|
+
const felt = BigInt(value);
|
|
2136
|
+
if (felt >= FIELD_PRIME) {
|
|
2137
|
+
throw new shared.ChipiSessionError(
|
|
2138
|
+
`Session entrypoint ${value} is not a valid felt (>= field prime).`,
|
|
2139
|
+
shared.SESSION_ERRORS.SESSION_ENTRYPOINT_NOT_ALLOWED
|
|
2140
|
+
);
|
|
2141
|
+
}
|
|
2142
|
+
return starknet.num.toHex(felt);
|
|
2143
|
+
}
|
|
2144
|
+
if (CAIRO_IDENTIFIER.test(value)) {
|
|
2145
|
+
return starknet.hash.getSelectorFromName(value);
|
|
2146
|
+
}
|
|
2147
|
+
throw new shared.ChipiSessionError(
|
|
2148
|
+
`Session entrypoint "${value}" is neither a selector (0x\u2026) nor a function name.`,
|
|
2149
|
+
shared.SESSION_ERRORS.SESSION_ENTRYPOINT_NOT_ALLOWED
|
|
2150
|
+
);
|
|
2151
|
+
});
|
|
2152
|
+
}
|
|
2153
|
+
function decodeSessionData(result, nowSeconds) {
|
|
2154
|
+
const validUntil = Number(BigInt(result[0]));
|
|
2155
|
+
const maxCalls = Number(BigInt(result[1]));
|
|
2156
|
+
const callsUsed = Number(BigInt(result[2]));
|
|
2157
|
+
const remainingCalls = Math.max(maxCalls - callsUsed, 0);
|
|
2158
|
+
const isActive = validUntil !== 0 && nowSeconds <= validUntil && remainingCalls > 0;
|
|
2159
|
+
return { isActive, validUntil, remainingCalls, allowedEntrypoints: [] };
|
|
2160
|
+
}
|
|
2161
|
+
var U128_MASK = (1n << 128n) - 1n;
|
|
2162
|
+
var U256_MAX = (1n << 256n) - 1n;
|
|
2163
|
+
var U64_MAX = (1n << 64n) - 1n;
|
|
2164
|
+
function splitU256(value) {
|
|
2165
|
+
return [starknet.num.toHex(value & U128_MASK), starknet.num.toHex(value >> 128n)];
|
|
2166
|
+
}
|
|
2167
|
+
function buildAddSessionKeyCall(walletAddress, sessionConfig) {
|
|
2168
|
+
const allowedEntrypoints = normalizeEntrypoints(sessionConfig.allowedEntrypoints);
|
|
2169
|
+
return {
|
|
2170
|
+
contractAddress: walletAddress,
|
|
2171
|
+
entrypoint: shared.SESSION_ENTRYPOINTS.ADD_OR_UPDATE,
|
|
2172
|
+
calldata: [
|
|
2173
|
+
sessionConfig.sessionPublicKey,
|
|
2174
|
+
starknet.num.toHex(sessionConfig.validUntil),
|
|
2175
|
+
starknet.num.toHex(sessionConfig.maxCalls),
|
|
2176
|
+
starknet.num.toHex(allowedEntrypoints.length),
|
|
2177
|
+
...allowedEntrypoints
|
|
2178
|
+
]
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2181
|
+
function buildRevokeSessionKeyCall(walletAddress, sessionPublicKey) {
|
|
2182
|
+
return {
|
|
2183
|
+
contractAddress: walletAddress,
|
|
2184
|
+
entrypoint: shared.SESSION_ENTRYPOINTS.REVOKE,
|
|
2185
|
+
calldata: [sessionPublicKey]
|
|
2186
|
+
};
|
|
2187
|
+
}
|
|
2188
|
+
function validateSpendingPolicyConfig(config) {
|
|
2189
|
+
const { token, maxPerCall, maxPerWindow, windowSeconds } = config;
|
|
2190
|
+
if (!token || token.trim().length === 0) {
|
|
2191
|
+
throw new shared.ChipiSessionError(
|
|
2192
|
+
`Invalid token address for spending policy: "${token}"`,
|
|
2193
|
+
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2194
|
+
);
|
|
2195
|
+
}
|
|
2196
|
+
if (typeof windowSeconds !== "number" || !Number.isFinite(windowSeconds) || !Number.isInteger(windowSeconds) || windowSeconds <= 0 || BigInt(windowSeconds) > U64_MAX) {
|
|
2197
|
+
throw new shared.ChipiSessionError(
|
|
2198
|
+
`Invalid window duration: ${windowSeconds}. Must be a positive integer within u64 range.`,
|
|
2199
|
+
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2200
|
+
);
|
|
2201
|
+
}
|
|
2202
|
+
if (maxPerCall < 0n || maxPerCall > U256_MAX) {
|
|
2203
|
+
throw new shared.ChipiSessionError(
|
|
2204
|
+
`Invalid maxPerCall: must be >= 0 and <= 2^256 - 1`,
|
|
2205
|
+
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2206
|
+
);
|
|
2207
|
+
}
|
|
2208
|
+
if (maxPerWindow < 0n || maxPerWindow > U256_MAX) {
|
|
2209
|
+
throw new shared.ChipiSessionError(
|
|
2210
|
+
`Invalid maxPerWindow: must be >= 0 and <= 2^256 - 1`,
|
|
2211
|
+
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2212
|
+
);
|
|
2213
|
+
}
|
|
2214
|
+
if (maxPerWindow > 0n && maxPerCall > maxPerWindow) {
|
|
2215
|
+
throw new shared.ChipiSessionError(
|
|
2216
|
+
`Invalid spending policy: maxPerCall (${maxPerCall}) cannot exceed maxPerWindow (${maxPerWindow})`,
|
|
2217
|
+
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
function buildSetSpendingPolicyCall(walletAddress, config) {
|
|
2222
|
+
validateSpendingPolicyConfig(config);
|
|
2223
|
+
const [maxPerCallLow, maxPerCallHigh] = splitU256(config.maxPerCall);
|
|
2224
|
+
const [maxPerWindowLow, maxPerWindowHigh] = splitU256(config.maxPerWindow);
|
|
2225
|
+
return {
|
|
2226
|
+
contractAddress: walletAddress,
|
|
2227
|
+
entrypoint: shared.SESSION_ENTRYPOINTS.SET_SPENDING_POLICY,
|
|
2228
|
+
calldata: [
|
|
2229
|
+
config.sessionPublicKey,
|
|
2230
|
+
config.token,
|
|
2231
|
+
maxPerCallLow,
|
|
2232
|
+
maxPerCallHigh,
|
|
2233
|
+
maxPerWindowLow,
|
|
2234
|
+
maxPerWindowHigh,
|
|
2235
|
+
starknet.num.toHex(config.windowSeconds)
|
|
2236
|
+
]
|
|
2237
|
+
};
|
|
2238
|
+
}
|
|
2239
|
+
function buildRemoveSpendingPolicyCall(walletAddress, sessionPublicKey, token) {
|
|
2240
|
+
if (!token || token.trim().length === 0) {
|
|
2241
|
+
throw new shared.ChipiSessionError(
|
|
2242
|
+
`Invalid token address for spending policy removal: "${token}"`,
|
|
2243
|
+
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2244
|
+
);
|
|
2245
|
+
}
|
|
2246
|
+
return {
|
|
2247
|
+
contractAddress: walletAddress,
|
|
2248
|
+
entrypoint: shared.SESSION_ENTRYPOINTS.REMOVE_SPENDING_POLICY,
|
|
2249
|
+
calldata: [sessionPublicKey, token]
|
|
2250
|
+
};
|
|
2251
|
+
}
|
|
2252
|
+
function buildSessionSetupCalls(walletAddress, sessionConfig, spendingPolicies = []) {
|
|
2253
|
+
return [
|
|
2254
|
+
buildAddSessionKeyCall(walletAddress, sessionConfig),
|
|
2255
|
+
...spendingPolicies.map(
|
|
2256
|
+
(policy) => buildSetSpendingPolicyCall(walletAddress, {
|
|
2257
|
+
...policy,
|
|
2258
|
+
sessionPublicKey: sessionConfig.sessionPublicKey
|
|
2259
|
+
})
|
|
2260
|
+
)
|
|
2261
|
+
];
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
// src/sessions.ts
|
|
2127
2265
|
var ChipiSessions = class {
|
|
2128
2266
|
constructor(client) {
|
|
2129
2267
|
this.client = client;
|
|
@@ -2263,25 +2401,12 @@ var ChipiSessions = class {
|
|
|
2263
2401
|
maxCalls: sessionConfig.maxCalls,
|
|
2264
2402
|
allowedEntrypoints: sessionConfig.allowedEntrypoints.length
|
|
2265
2403
|
});
|
|
2266
|
-
const
|
|
2267
|
-
sessionConfig.sessionPublicKey,
|
|
2268
|
-
starknet.num.toHex(sessionConfig.validUntil),
|
|
2269
|
-
starknet.num.toHex(sessionConfig.maxCalls),
|
|
2270
|
-
// Array: first element is length, then elements
|
|
2271
|
-
starknet.num.toHex(sessionConfig.allowedEntrypoints.length),
|
|
2272
|
-
...sessionConfig.allowedEntrypoints
|
|
2273
|
-
];
|
|
2404
|
+
const addCall = buildAddSessionKeyCall(wallet.publicKey, sessionConfig);
|
|
2274
2405
|
const txHash = await executePaymasterTransaction({
|
|
2275
2406
|
params: {
|
|
2276
2407
|
encryptKey,
|
|
2277
2408
|
wallet,
|
|
2278
|
-
calls: [
|
|
2279
|
-
{
|
|
2280
|
-
contractAddress: wallet.publicKey,
|
|
2281
|
-
entrypoint: shared.SESSION_ENTRYPOINTS.ADD_OR_UPDATE,
|
|
2282
|
-
calldata
|
|
2283
|
-
}
|
|
2284
|
-
],
|
|
2409
|
+
calls: [addCall],
|
|
2285
2410
|
saveToDatabase: false
|
|
2286
2411
|
// Don't record session management txs
|
|
2287
2412
|
},
|
|
@@ -2305,6 +2430,54 @@ var ChipiSessions = class {
|
|
|
2305
2430
|
throw error;
|
|
2306
2431
|
}
|
|
2307
2432
|
}
|
|
2433
|
+
/**
|
|
2434
|
+
* Register a session and its spending policies in ONE owner-signed transaction.
|
|
2435
|
+
*
|
|
2436
|
+
* Equivalent to `addSessionKeyToContract` followed by one `setSpendingPolicy`
|
|
2437
|
+
* per token, but the owner signs once (one passkey prompt) and the session
|
|
2438
|
+
* never exists on-chain without its caps.
|
|
2439
|
+
*
|
|
2440
|
+
* @example
|
|
2441
|
+
* ```typescript
|
|
2442
|
+
* const txHash = await sdk.sessions.setupSession({
|
|
2443
|
+
* encryptKey,
|
|
2444
|
+
* wallet,
|
|
2445
|
+
* sessionConfig: {
|
|
2446
|
+
* sessionPublicKey: session.publicKey,
|
|
2447
|
+
* validUntil: session.validUntil,
|
|
2448
|
+
* maxCalls: 500,
|
|
2449
|
+
* allowedEntrypoints: ["transfer", "approve"],
|
|
2450
|
+
* },
|
|
2451
|
+
* spendingPolicies: [
|
|
2452
|
+
* { token: USDC, maxPerCall: 5_000_000n, maxPerWindow: 20_000_000n, windowSeconds: 86400 },
|
|
2453
|
+
* ],
|
|
2454
|
+
* }, bearerToken);
|
|
2455
|
+
* ```
|
|
2456
|
+
*/
|
|
2457
|
+
async setupSession(params, bearerToken) {
|
|
2458
|
+
const { encryptKey, wallet, sessionConfig, spendingPolicies = [] } = params;
|
|
2459
|
+
this.validateWalletSupportsSessions(wallet.walletType, "Setup", wallet.publicKey);
|
|
2460
|
+
const calls = buildSessionSetupCalls(wallet.publicKey, sessionConfig, spendingPolicies);
|
|
2461
|
+
console.log("[ChipiSDK:Session:Setup] Registering session with spending policies", {
|
|
2462
|
+
walletAddress: wallet.publicKey.slice(0, 15) + "...",
|
|
2463
|
+
sessionPubKey: sessionConfig.sessionPublicKey.slice(0, 15) + "...",
|
|
2464
|
+
validUntil: new Date(sessionConfig.validUntil * 1e3).toISOString(),
|
|
2465
|
+
maxCalls: sessionConfig.maxCalls,
|
|
2466
|
+
allowedEntrypoints: sessionConfig.allowedEntrypoints.length,
|
|
2467
|
+
spendingPolicies: spendingPolicies.length
|
|
2468
|
+
});
|
|
2469
|
+
return executePaymasterTransaction({
|
|
2470
|
+
params: {
|
|
2471
|
+
encryptKey,
|
|
2472
|
+
wallet,
|
|
2473
|
+
calls,
|
|
2474
|
+
saveToDatabase: false
|
|
2475
|
+
// Don't record session management txs
|
|
2476
|
+
},
|
|
2477
|
+
bearerToken,
|
|
2478
|
+
client: this.client
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2308
2481
|
/**
|
|
2309
2482
|
* Revoke a session key from the smart contract.
|
|
2310
2483
|
*
|
|
@@ -2338,13 +2511,7 @@ var ChipiSessions = class {
|
|
|
2338
2511
|
params: {
|
|
2339
2512
|
encryptKey,
|
|
2340
2513
|
wallet,
|
|
2341
|
-
calls: [
|
|
2342
|
-
{
|
|
2343
|
-
contractAddress: wallet.publicKey,
|
|
2344
|
-
entrypoint: shared.SESSION_ENTRYPOINTS.REVOKE,
|
|
2345
|
-
calldata: [sessionPublicKey]
|
|
2346
|
-
}
|
|
2347
|
-
],
|
|
2514
|
+
calls: [buildRevokeSessionKeyCall(wallet.publicKey, sessionPublicKey)],
|
|
2348
2515
|
saveToDatabase: false
|
|
2349
2516
|
// Don't record session management txs
|
|
2350
2517
|
},
|
|
@@ -2419,11 +2586,10 @@ var ChipiSessions = class {
|
|
|
2419
2586
|
allowedEntrypoints: []
|
|
2420
2587
|
};
|
|
2421
2588
|
}
|
|
2422
|
-
const isActive
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
const allowedEntrypoints = resultArray.slice(4, 4 + entrypointsLen);
|
|
2589
|
+
const { isActive, validUntil, remainingCalls, allowedEntrypoints } = decodeSessionData(
|
|
2590
|
+
resultArray,
|
|
2591
|
+
Math.floor(Date.now() / 1e3)
|
|
2592
|
+
);
|
|
2427
2593
|
const sessionData = {
|
|
2428
2594
|
isActive,
|
|
2429
2595
|
validUntil,
|
|
@@ -2434,7 +2600,8 @@ var ChipiSessions = class {
|
|
|
2434
2600
|
isActive,
|
|
2435
2601
|
validUntil: new Date(validUntil * 1e3).toISOString(),
|
|
2436
2602
|
remainingCalls,
|
|
2437
|
-
|
|
2603
|
+
// The struct carries the whitelist length, not the selectors.
|
|
2604
|
+
allowedEntrypointsLen: Number(BigInt(resultArray[3]))
|
|
2438
2605
|
});
|
|
2439
2606
|
return sessionData;
|
|
2440
2607
|
} catch (error) {
|
|
@@ -2534,13 +2701,6 @@ var ChipiSessions = class {
|
|
|
2534
2701
|
// Wraps ISessionSpendingPolicy contract interface.
|
|
2535
2702
|
// Spending policies enforce per-token limits on ERC-20 operations
|
|
2536
2703
|
// (transfer, approve, increase_allowance) executed by session keys.
|
|
2537
|
-
/**
|
|
2538
|
-
* Split a bigint into Cairo u256 representation (low u128, high u128).
|
|
2539
|
-
*/
|
|
2540
|
-
splitU256(value) {
|
|
2541
|
-
const mask = (1n << 128n) - 1n;
|
|
2542
|
-
return [starknet.num.toHex(value & mask), starknet.num.toHex(value >> 128n)];
|
|
2543
|
-
}
|
|
2544
2704
|
/**
|
|
2545
2705
|
* Reconstruct a bigint from Cairo u256 (low, high) hex strings.
|
|
2546
2706
|
*/
|
|
@@ -2585,38 +2745,7 @@ var ChipiSessions = class {
|
|
|
2585
2745
|
shared.SESSION_ERRORS.INVALID_WALLET_TYPE_FOR_SESSION
|
|
2586
2746
|
);
|
|
2587
2747
|
}
|
|
2588
|
-
|
|
2589
|
-
const U64_MAX = (1n << 64n) - 1n;
|
|
2590
|
-
if (!token || token.trim().length === 0) {
|
|
2591
|
-
throw new shared.ChipiSessionError(
|
|
2592
|
-
`Invalid token address for spending policy: "${token}"`,
|
|
2593
|
-
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2594
|
-
);
|
|
2595
|
-
}
|
|
2596
|
-
if (typeof windowSeconds !== "number" || !Number.isFinite(windowSeconds) || !Number.isInteger(windowSeconds) || windowSeconds <= 0 || BigInt(windowSeconds) > U64_MAX) {
|
|
2597
|
-
throw new shared.ChipiSessionError(
|
|
2598
|
-
`Invalid window duration: ${windowSeconds}. Must be a positive integer within u64 range.`,
|
|
2599
|
-
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2600
|
-
);
|
|
2601
|
-
}
|
|
2602
|
-
if (maxPerCall < 0n || maxPerCall > U256_MAX) {
|
|
2603
|
-
throw new shared.ChipiSessionError(
|
|
2604
|
-
`Invalid maxPerCall: must be >= 0 and <= 2^256 - 1`,
|
|
2605
|
-
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2606
|
-
);
|
|
2607
|
-
}
|
|
2608
|
-
if (maxPerWindow < 0n || maxPerWindow > U256_MAX) {
|
|
2609
|
-
throw new shared.ChipiSessionError(
|
|
2610
|
-
`Invalid maxPerWindow: must be >= 0 and <= 2^256 - 1`,
|
|
2611
|
-
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2612
|
-
);
|
|
2613
|
-
}
|
|
2614
|
-
if (maxPerWindow > 0n && maxPerCall > maxPerWindow) {
|
|
2615
|
-
throw new shared.ChipiSessionError(
|
|
2616
|
-
`Invalid spending policy: maxPerCall (${maxPerCall}) cannot exceed maxPerWindow (${maxPerWindow})`,
|
|
2617
|
-
shared.SESSION_ERRORS.INVALID_SPENDING_POLICY
|
|
2618
|
-
);
|
|
2619
|
-
}
|
|
2748
|
+
validateSpendingPolicyConfig(spendingPolicyConfig);
|
|
2620
2749
|
try {
|
|
2621
2750
|
console.log("[ChipiSDK:Session:SetSpendingPolicy] Setting spending policy", {
|
|
2622
2751
|
walletAddress: wallet.publicKey.slice(0, 15) + "...",
|
|
@@ -2626,28 +2755,12 @@ var ChipiSessions = class {
|
|
|
2626
2755
|
maxPerWindow: maxPerWindow.toString(),
|
|
2627
2756
|
windowSeconds
|
|
2628
2757
|
});
|
|
2629
|
-
const
|
|
2630
|
-
const [maxPerWindowLow, maxPerWindowHigh] = this.splitU256(maxPerWindow);
|
|
2631
|
-
const calldata = [
|
|
2632
|
-
sessionPublicKey,
|
|
2633
|
-
token,
|
|
2634
|
-
maxPerCallLow,
|
|
2635
|
-
maxPerCallHigh,
|
|
2636
|
-
maxPerWindowLow,
|
|
2637
|
-
maxPerWindowHigh,
|
|
2638
|
-
starknet.num.toHex(windowSeconds)
|
|
2639
|
-
];
|
|
2758
|
+
const setPolicyCall = buildSetSpendingPolicyCall(wallet.publicKey, spendingPolicyConfig);
|
|
2640
2759
|
const txHash = await executePaymasterTransaction({
|
|
2641
2760
|
params: {
|
|
2642
2761
|
encryptKey,
|
|
2643
2762
|
wallet,
|
|
2644
|
-
calls: [
|
|
2645
|
-
{
|
|
2646
|
-
contractAddress: wallet.publicKey,
|
|
2647
|
-
entrypoint: shared.SESSION_ENTRYPOINTS.SET_SPENDING_POLICY,
|
|
2648
|
-
calldata
|
|
2649
|
-
}
|
|
2650
|
-
],
|
|
2763
|
+
calls: [setPolicyCall],
|
|
2651
2764
|
saveToDatabase: false
|
|
2652
2765
|
},
|
|
2653
2766
|
bearerToken,
|
|
@@ -2814,18 +2927,12 @@ var ChipiSessions = class {
|
|
|
2814
2927
|
sessionPubKey: sessionPublicKey.slice(0, 15) + "...",
|
|
2815
2928
|
token: token.slice(0, 15) + "..."
|
|
2816
2929
|
});
|
|
2817
|
-
const
|
|
2930
|
+
const removeCall = buildRemoveSpendingPolicyCall(wallet.publicKey, sessionPublicKey, token);
|
|
2818
2931
|
const txHash = await executePaymasterTransaction({
|
|
2819
2932
|
params: {
|
|
2820
2933
|
encryptKey,
|
|
2821
2934
|
wallet,
|
|
2822
|
-
calls: [
|
|
2823
|
-
{
|
|
2824
|
-
contractAddress: wallet.publicKey,
|
|
2825
|
-
entrypoint: shared.SESSION_ENTRYPOINTS.REMOVE_SPENDING_POLICY,
|
|
2826
|
-
calldata
|
|
2827
|
-
}
|
|
2828
|
-
],
|
|
2935
|
+
calls: [removeCall],
|
|
2829
2936
|
saveToDatabase: false
|
|
2830
2937
|
},
|
|
2831
2938
|
bearerToken,
|
|
@@ -3006,6 +3113,105 @@ var ChipiTreasury = class {
|
|
|
3006
3113
|
};
|
|
3007
3114
|
}
|
|
3008
3115
|
};
|
|
3116
|
+
var AI_BASE = "/ai";
|
|
3117
|
+
var THINK_ACTIONS = /* @__PURE__ */ new Set(["swap", "supply", "withdraw", "hold"]);
|
|
3118
|
+
function isThinkDecision(decision) {
|
|
3119
|
+
if (!decision || typeof decision !== "object") return false;
|
|
3120
|
+
const d = decision;
|
|
3121
|
+
if (typeof d.action !== "string" || !THINK_ACTIONS.has(d.action)) return false;
|
|
3122
|
+
if (typeof d.reason !== "string") return false;
|
|
3123
|
+
if (d.amount !== void 0 && (typeof d.amount !== "number" || !Number.isFinite(d.amount)))
|
|
3124
|
+
return false;
|
|
3125
|
+
if (d.confidence !== void 0 && typeof d.confidence !== "number") return false;
|
|
3126
|
+
if (d.from !== void 0 && typeof d.from !== "string") return false;
|
|
3127
|
+
if (d.to !== void 0 && typeof d.to !== "string") return false;
|
|
3128
|
+
return true;
|
|
3129
|
+
}
|
|
3130
|
+
var ChipiAi = class {
|
|
3131
|
+
constructor(client, apiSecretKey) {
|
|
3132
|
+
this.client = client;
|
|
3133
|
+
this.apiSecretKey = apiSecretKey;
|
|
3134
|
+
}
|
|
3135
|
+
secret() {
|
|
3136
|
+
const key = this.apiSecretKey;
|
|
3137
|
+
if (!key || !key.startsWith("sk_")) {
|
|
3138
|
+
throw new shared.ChipiAuthError(
|
|
3139
|
+
"sdk.ai needs a secret key (sk_): configure the SDK with apiSecretKey and call it from a server, never the browser."
|
|
3140
|
+
);
|
|
3141
|
+
}
|
|
3142
|
+
return key;
|
|
3143
|
+
}
|
|
3144
|
+
/**
|
|
3145
|
+
* `GET /v1/ai/signals`: technical signals per token, market sentiment and
|
|
3146
|
+
* DeFi yields. Free up to a monthly quota per organization, then billed per call.
|
|
3147
|
+
*/
|
|
3148
|
+
async signals(params = {}) {
|
|
3149
|
+
const query = {};
|
|
3150
|
+
if (params.tokens?.length) query.tokens = params.tokens.join(",");
|
|
3151
|
+
if (params.chain) query.chain = params.chain;
|
|
3152
|
+
return this.client.get({
|
|
3153
|
+
endpoint: `${AI_BASE}/signals`,
|
|
3154
|
+
params: query,
|
|
3155
|
+
bearerToken: this.secret()
|
|
3156
|
+
});
|
|
3157
|
+
}
|
|
3158
|
+
/**
|
|
3159
|
+
* `POST /v1/ai/think`: one DeFi decision for a portfolio, with the latest
|
|
3160
|
+
* signals and your risk parameters injected into the prompt.
|
|
3161
|
+
*
|
|
3162
|
+
* The decision is advice, not an order: check it with `isThinkDecision` and
|
|
3163
|
+
* enforce your own limits before executing anything.
|
|
3164
|
+
*/
|
|
3165
|
+
async think(params) {
|
|
3166
|
+
return this.client.post({
|
|
3167
|
+
endpoint: `${AI_BASE}/think`,
|
|
3168
|
+
bearerToken: this.secret(),
|
|
3169
|
+
body: params
|
|
3170
|
+
});
|
|
3171
|
+
}
|
|
3172
|
+
/**
|
|
3173
|
+
* `POST /v1/ai/execute`: unsigned AVNU swap calls (approve + swap) for
|
|
3174
|
+
* `walletAddress`. Nothing is submitted; sign the calls with a session key
|
|
3175
|
+
* or the owner's key.
|
|
3176
|
+
*/
|
|
3177
|
+
async execute(params) {
|
|
3178
|
+
return this.client.post({
|
|
3179
|
+
endpoint: `${AI_BASE}/execute`,
|
|
3180
|
+
bearerToken: this.secret(),
|
|
3181
|
+
body: params
|
|
3182
|
+
});
|
|
3183
|
+
}
|
|
3184
|
+
/** `POST /v1/ai/chat`: general-purpose chat, billed per token. */
|
|
3185
|
+
async chat(params) {
|
|
3186
|
+
return this.client.post({
|
|
3187
|
+
endpoint: `${AI_BASE}/chat`,
|
|
3188
|
+
bearerToken: this.secret(),
|
|
3189
|
+
body: params
|
|
3190
|
+
});
|
|
3191
|
+
}
|
|
3192
|
+
/**
|
|
3193
|
+
* `GET /v1/ai/prices`: USD prices and 1h / 24h / 7d changes, refreshed about
|
|
3194
|
+
* every 30 seconds. No credits are charged, but like every `sdk.ai` method it
|
|
3195
|
+
* needs the SDK's secret key (`sk_`).
|
|
3196
|
+
*/
|
|
3197
|
+
async prices(params = {}) {
|
|
3198
|
+
const query = {};
|
|
3199
|
+
if (params.tokens?.length) query.tokens = params.tokens.join(",");
|
|
3200
|
+
if (params.chain) query.chain = params.chain;
|
|
3201
|
+
return this.client.get({
|
|
3202
|
+
endpoint: `${AI_BASE}/prices`,
|
|
3203
|
+
params: query,
|
|
3204
|
+
bearerToken: this.secret()
|
|
3205
|
+
});
|
|
3206
|
+
}
|
|
3207
|
+
/** `GET /v1/ai/models`: available models, prices and limits. */
|
|
3208
|
+
async models() {
|
|
3209
|
+
return this.client.get({
|
|
3210
|
+
endpoint: `${AI_BASE}/models`,
|
|
3211
|
+
bearerToken: this.secret()
|
|
3212
|
+
});
|
|
3213
|
+
}
|
|
3214
|
+
};
|
|
3009
3215
|
var InMemoryNonceStore = class {
|
|
3010
3216
|
constructor() {
|
|
3011
3217
|
this.used = /* @__PURE__ */ new Set();
|
|
@@ -3323,6 +3529,7 @@ var ChipiSDK = class {
|
|
|
3323
3529
|
this.sessions = new ChipiSessions(this.client);
|
|
3324
3530
|
this.exchanges = new ChipiExchanges(this.client);
|
|
3325
3531
|
this.treasury = new ChipiTreasury(this.client, config.apiSecretKey);
|
|
3532
|
+
this.ai = new ChipiAi(this.client, config.apiSecretKey);
|
|
3326
3533
|
this.executeTransaction = this.executeTransaction.bind(this);
|
|
3327
3534
|
this.executeTransactionWithSession = this.executeTransactionWithSession.bind(this);
|
|
3328
3535
|
this.transfer = this.transfer.bind(this);
|
|
@@ -3586,8 +3793,8 @@ var ChipiSDK = class {
|
|
|
3586
3793
|
/**
|
|
3587
3794
|
* Get on-chain transaction status (supports polling for confirmation)
|
|
3588
3795
|
*/
|
|
3589
|
-
async getTransactionStatus(
|
|
3590
|
-
return this.transactions.getTransactionStatus(
|
|
3796
|
+
async getTransactionStatus(hash11, bearerToken) {
|
|
3797
|
+
return this.transactions.getTransactionStatus(hash11, this.resolveBearerToken(bearerToken));
|
|
3591
3798
|
}
|
|
3592
3799
|
/**
|
|
3593
3800
|
* Prepare a wallet upgrade (e.g., READY → CHIPI or CHIPI v29 → v33).
|
|
@@ -4002,6 +4209,79 @@ function x402Middleware(config) {
|
|
|
4002
4209
|
next();
|
|
4003
4210
|
};
|
|
4004
4211
|
}
|
|
4212
|
+
var InMemoryTxHashStore = class {
|
|
4213
|
+
constructor() {
|
|
4214
|
+
this.used = /* @__PURE__ */ new Set();
|
|
4215
|
+
}
|
|
4216
|
+
consume(transactionHash) {
|
|
4217
|
+
if (this.used.has(transactionHash)) return false;
|
|
4218
|
+
this.used.add(transactionHash);
|
|
4219
|
+
return true;
|
|
4220
|
+
}
|
|
4221
|
+
};
|
|
4222
|
+
var TRANSFER_SELECTOR = BigInt(starknet.hash.getSelectorFromName("Transfer"));
|
|
4223
|
+
function toBigInt2(value) {
|
|
4224
|
+
if (value === void 0) return void 0;
|
|
4225
|
+
try {
|
|
4226
|
+
return BigInt(value);
|
|
4227
|
+
} catch {
|
|
4228
|
+
return void 0;
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
function decodeTransfer(event) {
|
|
4232
|
+
if (toBigInt2(event.keys[0]) !== TRANSFER_SELECTOR) return void 0;
|
|
4233
|
+
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]];
|
|
4234
|
+
const values = [from, to, low, high].map(toBigInt2);
|
|
4235
|
+
if (values.some((v) => v === void 0)) return void 0;
|
|
4236
|
+
const [f, t, l, h] = values;
|
|
4237
|
+
return { from: f, to: t, amount: l + (h << 128n) };
|
|
4238
|
+
}
|
|
4239
|
+
var SessionTxVerifier = class {
|
|
4240
|
+
constructor(config = {}) {
|
|
4241
|
+
const { txHashStore, getReceipt, ...receiptOptions } = config;
|
|
4242
|
+
this.store = txHashStore ?? new InMemoryTxHashStore();
|
|
4243
|
+
this.getReceipt = getReceipt ?? waitForTransaction;
|
|
4244
|
+
this.receiptOptions = receiptOptions;
|
|
4245
|
+
}
|
|
4246
|
+
async verifyTransfer(params) {
|
|
4247
|
+
const { transactionHash, token, from, to, minAmount } = params;
|
|
4248
|
+
const receipt = await this.getReceipt(transactionHash, this.receiptOptions);
|
|
4249
|
+
if (!receipt.success) {
|
|
4250
|
+
return { valid: false, transactionHash, reason: "REVERTED", detail: receipt.revertReason };
|
|
4251
|
+
}
|
|
4252
|
+
const tokenAddress = BigInt(token);
|
|
4253
|
+
const fromAddress = BigInt(from);
|
|
4254
|
+
const toAddress = BigInt(to);
|
|
4255
|
+
let best;
|
|
4256
|
+
for (const event of receipt.events) {
|
|
4257
|
+
if (toBigInt2(event.from_address) !== tokenAddress) continue;
|
|
4258
|
+
const transfer = decodeTransfer(event);
|
|
4259
|
+
if (!transfer || transfer.from !== fromAddress || transfer.to !== toAddress) continue;
|
|
4260
|
+
if (best === void 0 || transfer.amount > best) best = transfer.amount;
|
|
4261
|
+
}
|
|
4262
|
+
if (best === void 0) {
|
|
4263
|
+
return { valid: false, transactionHash, reason: "TRANSFER_NOT_FOUND" };
|
|
4264
|
+
}
|
|
4265
|
+
if (best < minAmount) {
|
|
4266
|
+
return {
|
|
4267
|
+
valid: false,
|
|
4268
|
+
transactionHash,
|
|
4269
|
+
reason: "AMOUNT_TOO_LOW",
|
|
4270
|
+
detail: `paid ${best}, expected at least ${minAmount}`
|
|
4271
|
+
};
|
|
4272
|
+
}
|
|
4273
|
+
const key = "0x" + BigInt(transactionHash).toString(16);
|
|
4274
|
+
if (!await this.store.consume(key)) {
|
|
4275
|
+
return { valid: false, transactionHash, reason: "ALREADY_USED" };
|
|
4276
|
+
}
|
|
4277
|
+
return {
|
|
4278
|
+
valid: true,
|
|
4279
|
+
transactionHash,
|
|
4280
|
+
amount: best,
|
|
4281
|
+
...receipt.blockNumber !== void 0 ? { blockNumber: receipt.blockNumber } : {}
|
|
4282
|
+
};
|
|
4283
|
+
}
|
|
4284
|
+
};
|
|
4005
4285
|
|
|
4006
4286
|
// src/shhh/index.ts
|
|
4007
4287
|
init_snip12_hash();
|
|
@@ -4407,7 +4687,7 @@ var JWT_APPLE_SUB_KIND_TAG = "JWT_ES256_APPLE_SUB";
|
|
|
4407
4687
|
var JWT_APPLE_SUB_KIND_TAG_FELT = BigInt(starknet.shortString.encodeShortString(JWT_APPLE_SUB_KIND_TAG));
|
|
4408
4688
|
var APPLE_ISSUER = "https://appleid.apple.com";
|
|
4409
4689
|
var NONCE_B64URL_LEN = 43;
|
|
4410
|
-
var
|
|
4690
|
+
var U128_MASK2 = (1n << 128n) - 1n;
|
|
4411
4691
|
function assertBytes3(name, b, len) {
|
|
4412
4692
|
if (b.length !== len) {
|
|
4413
4693
|
throw new Error(`${name} must be exactly ${len} bytes; got ${b.length}.`);
|
|
@@ -4417,7 +4697,7 @@ function bytesBeToU2563(b) {
|
|
|
4417
4697
|
assertBytes3("secp256r1 32B value", b, 32);
|
|
4418
4698
|
let x = 0n;
|
|
4419
4699
|
for (let i = 0; i < b.length; i++) x = x << 8n | BigInt(b[i]);
|
|
4420
|
-
return { low: x &
|
|
4700
|
+
return { low: x & U128_MASK2, high: x >> 128n };
|
|
4421
4701
|
}
|
|
4422
4702
|
function jwtAppleSubHash(sub) {
|
|
4423
4703
|
const bytes = new TextEncoder().encode(sub);
|
|
@@ -4552,9 +4832,9 @@ function buildEnvelopePayload(fields) {
|
|
|
4552
4832
|
BigInt(fields.issOffset),
|
|
4553
4833
|
BigInt(fields.subOffset),
|
|
4554
4834
|
BigInt(fields.subLen),
|
|
4555
|
-
fields.r &
|
|
4835
|
+
fields.r & U128_MASK2,
|
|
4556
4836
|
fields.r >> 128n,
|
|
4557
|
-
fields.s &
|
|
4837
|
+
fields.s & U128_MASK2,
|
|
4558
4838
|
fields.s >> 128n,
|
|
4559
4839
|
BigInt(fields.yParity)
|
|
4560
4840
|
];
|
|
@@ -4914,6 +5194,7 @@ Object.defineProperty(exports, "Currency", {
|
|
|
4914
5194
|
});
|
|
4915
5195
|
exports.APPLE_ISSUER = APPLE_ISSUER;
|
|
4916
5196
|
exports.BOOTSTRAP_DOMAIN_SEPARATOR = BOOTSTRAP_DOMAIN_SEPARATOR;
|
|
5197
|
+
exports.ChipiAi = ChipiAi;
|
|
4917
5198
|
exports.ChipiBrowserSDK = ChipiBrowserSDK;
|
|
4918
5199
|
exports.ChipiClient = ChipiClient;
|
|
4919
5200
|
exports.ChipiPaymasterAdapter = ChipiPaymasterAdapter;
|
|
@@ -4932,12 +5213,14 @@ exports.OP_ROTATE_OWNER = OP_ROTATE_OWNER;
|
|
|
4932
5213
|
exports.OP_SET_THRESHOLD = OP_SET_THRESHOLD;
|
|
4933
5214
|
exports.ROLE_GUARDIAN = ROLE_GUARDIAN;
|
|
4934
5215
|
exports.ROLE_OWNER = ROLE_OWNER;
|
|
5216
|
+
exports.SessionTxVerifier = SessionTxVerifier;
|
|
4935
5217
|
exports.ShhhAccount = ShhhAccount;
|
|
4936
5218
|
exports.TIMELOCK_SECONDS = TIMELOCK_SECONDS;
|
|
4937
5219
|
exports.VIEW_SELECTORS = VIEW_SELECTORS;
|
|
4938
5220
|
exports.X402Facilitator = X402Facilitator;
|
|
4939
5221
|
exports.X402ShhhClient = X402ShhhClient;
|
|
4940
5222
|
exports.assertValidV2Snip12Envelope = assertValidV2Snip12Envelope;
|
|
5223
|
+
exports.buildAddSessionKeyCall = buildAddSessionKeyCall;
|
|
4941
5224
|
exports.buildBootstrapSignedCall = buildBootstrapSignedCall;
|
|
4942
5225
|
exports.buildCancelPendingOpCall = buildCancelPendingOpCall;
|
|
4943
5226
|
exports.buildCancelRecoveryCall = buildCancelRecoveryCall;
|
|
@@ -4959,6 +5242,10 @@ exports.buildProposeAddOwnerCall = buildProposeAddOwnerCall;
|
|
|
4959
5242
|
exports.buildProposeRemoveOwnerCall = buildProposeRemoveOwnerCall;
|
|
4960
5243
|
exports.buildProposeRotateOwnerCall = buildProposeRotateOwnerCall;
|
|
4961
5244
|
exports.buildProposeSetThresholdCall = buildProposeSetThresholdCall;
|
|
5245
|
+
exports.buildRemoveSpendingPolicyCall = buildRemoveSpendingPolicyCall;
|
|
5246
|
+
exports.buildRevokeSessionKeyCall = buildRevokeSessionKeyCall;
|
|
5247
|
+
exports.buildSessionSetupCalls = buildSessionSetupCalls;
|
|
5248
|
+
exports.buildSetSpendingPolicyCall = buildSetSpendingPolicyCall;
|
|
4962
5249
|
exports.buildStarkEnvelope = buildStarkEnvelope;
|
|
4963
5250
|
exports.buildThresholdEnvelope = buildThresholdEnvelope;
|
|
4964
5251
|
exports.buildWebAuthnEnvelopeFromAssertion = buildWebAuthnEnvelopeFromAssertion;
|
|
@@ -4984,6 +5271,7 @@ exports.hashCalls = hashCalls;
|
|
|
4984
5271
|
exports.hashOutsideExecutionStruct = hashOutsideExecutionStruct;
|
|
4985
5272
|
exports.hashStarknetDomain = hashStarknetDomain;
|
|
4986
5273
|
exports.isReadyToExecute = isReadyToExecute;
|
|
5274
|
+
exports.isThinkDecision = isThinkDecision;
|
|
4987
5275
|
exports.jwtAppleSubHash = jwtAppleSubHash;
|
|
4988
5276
|
exports.jwtAppleSubOwnerId = jwtAppleSubOwnerId;
|
|
4989
5277
|
exports.jwtAppleSubPubkeyFelts = jwtAppleSubPubkeyFelts;
|
|
@@ -4991,6 +5279,7 @@ exports.labelToFelt = labelToFelt;
|
|
|
4991
5279
|
exports.locateSubClaim = locateSubClaim;
|
|
4992
5280
|
exports.messageHashToNonceB64url = messageHashToNonceB64url;
|
|
4993
5281
|
exports.migrateChipiWalletToShhh = migrateChipiWalletToShhh;
|
|
5282
|
+
exports.normalizeEntrypoints = normalizeEntrypoints;
|
|
4994
5283
|
exports.ownerCommitment = ownerCommitment;
|
|
4995
5284
|
exports.parseAppleIdToken = parseAppleIdToken;
|
|
4996
5285
|
exports.parseDerEcdsaSignature = parseDerEcdsaSignature;
|
|
@@ -5006,6 +5295,7 @@ exports.snip12HashToHexAsciiBytes = snip12HashToHexAsciiBytes;
|
|
|
5006
5295
|
exports.starkOwnerId = starkOwnerId;
|
|
5007
5296
|
exports.starkPubkeyFelts = starkPubkeyFelts;
|
|
5008
5297
|
exports.submitViaAccount = submitViaAccount;
|
|
5298
|
+
exports.validateSpendingPolicyConfig = validateSpendingPolicyConfig;
|
|
5009
5299
|
exports.waitForTransaction = waitForTransaction;
|
|
5010
5300
|
exports.webauthnOwnerId = webauthnOwnerId;
|
|
5011
5301
|
exports.webauthnOwnerPubkeyParam = webauthnOwnerPubkeyParam;
|