@chipi-stack/backend 14.15.1 → 14.17.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/README.md +48 -0
- package/dist/index.d.mts +543 -65
- package/dist/index.d.ts +543 -65
- package/dist/index.js +1026 -317
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +997 -319
- package/dist/index.mjs.map +1 -1
- package/dist/skuPurchases.js +16 -2
- package/dist/skuPurchases.js.map +1 -1
- package/dist/skuPurchases.mjs +16 -2
- package/dist/skuPurchases.mjs.map +1 -1
- package/dist/transactions.js +16 -2
- package/dist/transactions.js.map +1 -1
- package/dist/transactions.mjs +16 -2
- package/dist/transactions.mjs.map +1 -1
- package/dist/wallets.js +25 -3
- package/dist/wallets.js.map +1 -1
- package/dist/wallets.mjs +25 -3
- package/dist/wallets.mjs.map +1 -1
- package/package.json +4 -4
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,
|
|
2
|
+
import { SHHH_VERIFIER_CLASS_HASHES, SHHH_KIND_GAS_OVERHEAD, isValidApiKey, ChipiAuthError, STARKNET_NETWORKS, API_VERSIONING, validateErrorResponse, ChipiApiError, handleApiError, getWalletTypeFromClassHash, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, 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';
|
|
@@ -168,9 +168,9 @@ function assertValidV2Snip12Envelope(envelope) {
|
|
|
168
168
|
}
|
|
169
169
|
return envelope[1];
|
|
170
170
|
}
|
|
171
|
-
function _tryDecodeShortString(
|
|
171
|
+
function _tryDecodeShortString(felt2) {
|
|
172
172
|
try {
|
|
173
|
-
return shortString.decodeShortString("0x" +
|
|
173
|
+
return shortString.decodeShortString("0x" + felt2.toString(16));
|
|
174
174
|
} catch {
|
|
175
175
|
return null;
|
|
176
176
|
}
|
|
@@ -194,14 +194,20 @@ function buildThresholdEnvelope(args) {
|
|
|
194
194
|
);
|
|
195
195
|
}
|
|
196
196
|
seenOwners.add(key);
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
if (env.length < 3) {
|
|
198
|
+
throw new Error(
|
|
199
|
+
`THRESH: inner envelope ${i} must have at least [tag, owner_id, kind_tag]; got ${env.length} felts`
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
const frame = env.slice(1);
|
|
203
|
+
out.push(BigInt(frame.length));
|
|
204
|
+
for (const felt2 of frame) {
|
|
205
|
+
if (felt2 < 0n) {
|
|
200
206
|
throw new RangeError(
|
|
201
207
|
`THRESH: envelope ${i} contains negative felt (cannot serialize as felt252)`
|
|
202
208
|
);
|
|
203
209
|
}
|
|
204
|
-
out.push(
|
|
210
|
+
out.push(felt2);
|
|
205
211
|
}
|
|
206
212
|
}
|
|
207
213
|
return out;
|
|
@@ -234,15 +240,26 @@ function parseThresholdEnvelope(envelope) {
|
|
|
234
240
|
`THRESH: inner ${i} would overflow envelope (env_len ${envLen}, cursor ${cursor}, total ${envelope.length})`
|
|
235
241
|
);
|
|
236
242
|
}
|
|
237
|
-
const
|
|
238
|
-
for (const
|
|
239
|
-
if (
|
|
243
|
+
const frame = envelope.slice(cursor, cursor + envLen);
|
|
244
|
+
for (const felt2 of frame) {
|
|
245
|
+
if (felt2 < 0n) {
|
|
240
246
|
throw new RangeError(
|
|
241
247
|
`THRESH: inner ${i} contains negative felt (cannot serialize as felt252)`
|
|
242
248
|
);
|
|
243
249
|
}
|
|
244
250
|
}
|
|
245
|
-
const ownerId =
|
|
251
|
+
const ownerId = frame[0];
|
|
252
|
+
if (ownerId >= 0x100000000n) {
|
|
253
|
+
if (ownerId === V2_THRESHOLD_TAG) {
|
|
254
|
+
throw new Error(
|
|
255
|
+
`THRESH: inner ${i}: nested threshold envelopes are not allowed; inner frames are [owner_id, kind_tag, ...payload]`
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
throw new Error(
|
|
259
|
+
`THRESH: inner ${i} owner_id 0x${ownerId.toString(16)} is not a u32; inner frames are [owner_id, kind_tag, ...payload] with no V2_SNIP12 tag`
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
const inner = [V2_SNIP12_TAG, ...frame];
|
|
246
263
|
const key = ownerId.toString();
|
|
247
264
|
if (seenOwners.has(key)) {
|
|
248
265
|
throw new Error(
|
|
@@ -545,6 +562,7 @@ var init_stark = __esm({
|
|
|
545
562
|
var execute_paymaster_raw_exports = {};
|
|
546
563
|
__export(execute_paymaster_raw_exports, {
|
|
547
564
|
executeShhhSponsoredRaw: () => executeShhhSponsoredRaw,
|
|
565
|
+
newOeNonce: () => newOeNonce,
|
|
548
566
|
resolveShhhChainId: () => resolveShhhChainId,
|
|
549
567
|
serializeExecuteFromOutsideV2Calldata: () => serializeExecuteFromOutsideV2Calldata
|
|
550
568
|
});
|
|
@@ -882,13 +900,26 @@ function unwrapPrepareResponse(response) {
|
|
|
882
900
|
apiMessage ?? "Invalid response from /transactions/prepare-typed-data: typedData is missing"
|
|
883
901
|
);
|
|
884
902
|
}
|
|
903
|
+
function feltEquals(value, expected) {
|
|
904
|
+
try {
|
|
905
|
+
return BigInt(value) === expected;
|
|
906
|
+
} catch {
|
|
907
|
+
return false;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
885
910
|
function normalizeSignature(signature) {
|
|
886
911
|
if (Array.isArray(signature)) {
|
|
887
912
|
if (signature.length < 2) {
|
|
888
913
|
throw new Error(`Array signature must have at least 2 elements, got ${signature.length}`);
|
|
889
914
|
}
|
|
890
|
-
const
|
|
891
|
-
|
|
915
|
+
const isArgentSingle = signature.length === 5 && feltEquals(signature[0], 1n) && feltEquals(signature[1], 0n);
|
|
916
|
+
if (signature.length !== 2 && !isArgentSingle) {
|
|
917
|
+
throw new Error(
|
|
918
|
+
`Unsupported ${signature.length}-felt signature: expected [r, s] or Argent [1, 0, pubkey, r, s].`
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
const r = isArgentSingle ? signature[3] : signature[0];
|
|
922
|
+
const s = isArgentSingle ? signature[4] : signature[1];
|
|
892
923
|
if (r == null || s == null) {
|
|
893
924
|
throw new Error(`Signature elements must not be null/undefined. Got r=${r}, s=${s}`);
|
|
894
925
|
}
|
|
@@ -1603,7 +1634,10 @@ var ChipiWallets = class {
|
|
|
1603
1634
|
publicKey,
|
|
1604
1635
|
walletType,
|
|
1605
1636
|
starkKeyPubAX,
|
|
1606
|
-
|
|
1637
|
+
// The class the address above was computed with. SHHH always
|
|
1638
|
+
// names it: chipi-back's default for clients that name none is
|
|
1639
|
+
// the class SDKs up to 14.16 used (V8.4), not ours.
|
|
1640
|
+
...(customClassHash || isShhh) && { classHash: accountClassHash },
|
|
1607
1641
|
// SHHH: tell chipi-back which signer kind + pubkey felts
|
|
1608
1642
|
// produced this deployment so it can validate against the
|
|
1609
1643
|
// expected SHHH constructor shape and populate the new
|
|
@@ -1615,6 +1649,11 @@ var ChipiWallets = class {
|
|
|
1615
1649
|
}
|
|
1616
1650
|
});
|
|
1617
1651
|
const { typedData: typedData2, accountClassHash: accountClassHashResponse } = typedDataResponse;
|
|
1652
|
+
if (isShhh && (!accountClassHashResponse || BigInt(accountClassHashResponse) !== BigInt(accountClassHash))) {
|
|
1653
|
+
throw new Error(
|
|
1654
|
+
`prepare-creation returned class ${accountClassHashResponse ?? "(none)"}, but the wallet address was computed with ${accountClassHash}. Not deploying.`
|
|
1655
|
+
);
|
|
1656
|
+
}
|
|
1618
1657
|
let userSignaturePayload;
|
|
1619
1658
|
if (isShhh) {
|
|
1620
1659
|
userSignaturePayload = {
|
|
@@ -1953,9 +1992,9 @@ var ChipiTransactions = class {
|
|
|
1953
1992
|
/**
|
|
1954
1993
|
* Get on-chain transaction status
|
|
1955
1994
|
*/
|
|
1956
|
-
async getTransactionStatus(
|
|
1995
|
+
async getTransactionStatus(hash13, bearerToken) {
|
|
1957
1996
|
return this.client.get({
|
|
1958
|
-
endpoint: `${API_ENDPOINTS.TRANSACTIONS}/${
|
|
1997
|
+
endpoint: `${API_ENDPOINTS.TRANSACTIONS}/${hash13}/status`,
|
|
1959
1998
|
bearerToken
|
|
1960
1999
|
});
|
|
1961
2000
|
}
|
|
@@ -2133,14 +2172,14 @@ function normalizeEntrypoints(entrypoints) {
|
|
|
2133
2172
|
return entrypoints.map((entry) => {
|
|
2134
2173
|
const value = String(entry).trim();
|
|
2135
2174
|
if (HEX_FELT.test(value) || DECIMAL_FELT.test(value)) {
|
|
2136
|
-
const
|
|
2137
|
-
if (
|
|
2175
|
+
const felt2 = BigInt(value);
|
|
2176
|
+
if (felt2 >= FIELD_PRIME) {
|
|
2138
2177
|
throw new ChipiSessionError(
|
|
2139
2178
|
`Session entrypoint ${value} is not a valid felt (>= field prime).`,
|
|
2140
2179
|
SESSION_ERRORS.SESSION_ENTRYPOINT_NOT_ALLOWED
|
|
2141
2180
|
);
|
|
2142
2181
|
}
|
|
2143
|
-
return num.toHex(
|
|
2182
|
+
return num.toHex(felt2);
|
|
2144
2183
|
}
|
|
2145
2184
|
if (CAIRO_IDENTIFIER.test(value)) {
|
|
2146
2185
|
return hash.getSelectorFromName(value);
|
|
@@ -3542,6 +3581,122 @@ var ChipiAi = class {
|
|
|
3542
3581
|
});
|
|
3543
3582
|
}
|
|
3544
3583
|
};
|
|
3584
|
+
var STARKNET_SIGNATURE_VALID = "0x56414c4944";
|
|
3585
|
+
function toFeltHex(value) {
|
|
3586
|
+
return num.toHex(BigInt(value));
|
|
3587
|
+
}
|
|
3588
|
+
function normalizeStarknetAddress(address) {
|
|
3589
|
+
return `0x${BigInt(address).toString(16).padStart(64, "0")}`;
|
|
3590
|
+
}
|
|
3591
|
+
function isContractNotFound(err) {
|
|
3592
|
+
const e = err;
|
|
3593
|
+
if (e?.baseError?.code === 20 || e?.code === 20) return true;
|
|
3594
|
+
return /contract not found/i.test(e?.message ?? String(err));
|
|
3595
|
+
}
|
|
3596
|
+
async function isValidStarknetSignature(provider, accountAddress, messageHash, signature) {
|
|
3597
|
+
try {
|
|
3598
|
+
const sig = signature.map(toFeltHex);
|
|
3599
|
+
const result = await provider.callContract({
|
|
3600
|
+
contractAddress: normalizeStarknetAddress(accountAddress),
|
|
3601
|
+
entrypoint: "is_valid_signature",
|
|
3602
|
+
calldata: [toFeltHex(messageHash), toFeltHex(sig.length), ...sig]
|
|
3603
|
+
});
|
|
3604
|
+
const first = result?.[0];
|
|
3605
|
+
if (first !== void 0 && BigInt(first) === BigInt(STARKNET_SIGNATURE_VALID)) {
|
|
3606
|
+
return { valid: true };
|
|
3607
|
+
}
|
|
3608
|
+
return { valid: false, reason: "INVALID_SIGNATURE" };
|
|
3609
|
+
} catch (err) {
|
|
3610
|
+
if (isContractNotFound(err)) return { valid: false, reason: "ACCOUNT_NOT_DEPLOYED" };
|
|
3611
|
+
return {
|
|
3612
|
+
valid: false,
|
|
3613
|
+
reason: "INVALID_SIGNATURE",
|
|
3614
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
3615
|
+
};
|
|
3616
|
+
}
|
|
3617
|
+
}
|
|
3618
|
+
var COUNTERFACTUAL_ACCOUNT_CLASSES = {
|
|
3619
|
+
/** OpenZeppelin AccountUpgradeable 3.0 (Bramble's default account). */
|
|
3620
|
+
OPENZEPPELIN_V3: "0x01d1777db36cdd06dd62cfde77b1b6ae06412af95d57a13dc40ac77b8a702381",
|
|
3621
|
+
/** Argent X / Ready 0.4 (`WALLET_CLASS_HASHES.READY`). */
|
|
3622
|
+
ARGENT_V0_4: "0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f"
|
|
3623
|
+
};
|
|
3624
|
+
function starkVerify(r, s, messageHash, publicKey) {
|
|
3625
|
+
const x = BigInt(publicKey).toString(16).padStart(64, "0");
|
|
3626
|
+
const sig = new ec.starkCurve.Signature(BigInt(r), BigInt(s));
|
|
3627
|
+
for (const prefix of ["02", "03"]) {
|
|
3628
|
+
try {
|
|
3629
|
+
if (ec.starkCurve.verify(sig, toFeltHex(messageHash), prefix + x)) return true;
|
|
3630
|
+
} catch {
|
|
3631
|
+
}
|
|
3632
|
+
}
|
|
3633
|
+
return false;
|
|
3634
|
+
}
|
|
3635
|
+
function verifyUndeployedStarknetSignature(deployment, messageHash, signature) {
|
|
3636
|
+
const classHash = normalizeStarknetAddress(deployment.class_hash);
|
|
3637
|
+
const calldata = deployment.calldata.map(toFeltHex);
|
|
3638
|
+
const sig = signature.map(toFeltHex);
|
|
3639
|
+
let publicKey;
|
|
3640
|
+
let r;
|
|
3641
|
+
let s;
|
|
3642
|
+
if (classHash === COUNTERFACTUAL_ACCOUNT_CLASSES.OPENZEPPELIN_V3) {
|
|
3643
|
+
if (calldata.length !== 1 || sig.length !== 2) {
|
|
3644
|
+
return { valid: false, reason: "INVALID_SIGNATURE" };
|
|
3645
|
+
}
|
|
3646
|
+
[publicKey] = calldata;
|
|
3647
|
+
[r, s] = sig;
|
|
3648
|
+
} else if (classHash === COUNTERFACTUAL_ACCOUNT_CLASSES.ARGENT_V0_4) {
|
|
3649
|
+
if (calldata.length !== 3 || BigInt(calldata[0]) !== 0n || BigInt(calldata[2]) !== 1n) {
|
|
3650
|
+
return { valid: false, reason: "UNSUPPORTED_ACCOUNT_CLASS" };
|
|
3651
|
+
}
|
|
3652
|
+
if (sig.length !== 5 || BigInt(sig[0]) !== 1n || BigInt(sig[1]) !== 0n) {
|
|
3653
|
+
return { valid: false, reason: "INVALID_SIGNATURE" };
|
|
3654
|
+
}
|
|
3655
|
+
if (BigInt(sig[2]) !== BigInt(calldata[1])) {
|
|
3656
|
+
return { valid: false, reason: "INVALID_SIGNATURE" };
|
|
3657
|
+
}
|
|
3658
|
+
publicKey = calldata[1];
|
|
3659
|
+
[, , , r, s] = sig;
|
|
3660
|
+
} else {
|
|
3661
|
+
return { valid: false, reason: "UNSUPPORTED_ACCOUNT_CLASS" };
|
|
3662
|
+
}
|
|
3663
|
+
const expected = hash.calculateContractAddressFromHash(
|
|
3664
|
+
toFeltHex(deployment.salt),
|
|
3665
|
+
classHash,
|
|
3666
|
+
calldata,
|
|
3667
|
+
0
|
|
3668
|
+
);
|
|
3669
|
+
if (normalizeStarknetAddress(expected) !== normalizeStarknetAddress(deployment.address)) {
|
|
3670
|
+
return { valid: false, reason: "ADDRESS_MISMATCH" };
|
|
3671
|
+
}
|
|
3672
|
+
return starkVerify(r, s, messageHash, publicKey) ? { valid: true } : { valid: false, reason: "INVALID_SIGNATURE" };
|
|
3673
|
+
}
|
|
3674
|
+
|
|
3675
|
+
// src/x402/facilitator.ts
|
|
3676
|
+
var TRANSFER_SELECTOR2 = BigInt(hash.getSelectorFromName("transfer"));
|
|
3677
|
+
function shhhTransferMatches(oeCalldata, payload) {
|
|
3678
|
+
try {
|
|
3679
|
+
const felts = oeCalldata.map((v) => BigInt(v));
|
|
3680
|
+
const [, , , executeBefore, callsLen] = felts;
|
|
3681
|
+
if (callsLen !== 1n) return { ok: false, reason: "SHHH payment must be exactly one transfer" };
|
|
3682
|
+
const [to, selector, len, recipient, low, high] = felts.slice(5, 11);
|
|
3683
|
+
if (to !== BigInt(payload.asset) || selector !== TRANSFER_SELECTOR2 || len !== 3n) {
|
|
3684
|
+
return { ok: false, reason: "SHHH payment call is not a transfer of the payment asset" };
|
|
3685
|
+
}
|
|
3686
|
+
if (recipient !== BigInt(payload.toAddress)) {
|
|
3687
|
+
return { ok: false, reason: "SHHH payment pays a different recipient" };
|
|
3688
|
+
}
|
|
3689
|
+
if (low + (high << 128n) !== BigInt(payload.amount)) {
|
|
3690
|
+
return { ok: false, reason: "SHHH payment amount differs from the declared amount" };
|
|
3691
|
+
}
|
|
3692
|
+
if (executeBefore <= BigInt(Math.floor(Date.now() / 1e3))) {
|
|
3693
|
+
return { ok: false, reason: "SHHH payment has expired (execute_before in the past)" };
|
|
3694
|
+
}
|
|
3695
|
+
return { ok: true };
|
|
3696
|
+
} catch {
|
|
3697
|
+
return { ok: false, reason: "Malformed SHHH oeCalldata" };
|
|
3698
|
+
}
|
|
3699
|
+
}
|
|
3545
3700
|
var InMemoryNonceStore = class {
|
|
3546
3701
|
constructor() {
|
|
3547
3702
|
this.used = /* @__PURE__ */ new Set();
|
|
@@ -3584,11 +3739,18 @@ var X402Facilitator = class _X402Facilitator {
|
|
|
3584
3739
|
* Verify a payment signature is valid (doesn't execute the transfer).
|
|
3585
3740
|
*
|
|
3586
3741
|
* Checks:
|
|
3587
|
-
* 1.
|
|
3588
|
-
* 2.
|
|
3589
|
-
* 3.
|
|
3590
|
-
* 4.
|
|
3591
|
-
* 5.
|
|
3742
|
+
* 1. x402 version is 1
|
|
3743
|
+
* 2. Network is starknet-mainnet
|
|
3744
|
+
* 3. Nonce has not been used (replay protection)
|
|
3745
|
+
* 4. Payment has not expired (validUntil > now)
|
|
3746
|
+
* 5. Asset is USDC mainnet
|
|
3747
|
+
* 6. Amount is positive
|
|
3748
|
+
* 7. Addresses are non-empty
|
|
3749
|
+
* 8. Signature: with a `provider`, the payer account's `is_valid_signature`
|
|
3750
|
+
* must return 'VALID'. Without one, only its presence is checked (not a
|
|
3751
|
+
* cryptographic check). SHHH payloads must sign exactly one transfer
|
|
3752
|
+
* of `amount` of `asset` to `toAddress`; their signature is checked
|
|
3753
|
+
* on-chain at settle.
|
|
3592
3754
|
*/
|
|
3593
3755
|
async verify(payment) {
|
|
3594
3756
|
const { payload } = payment;
|
|
@@ -3644,6 +3806,8 @@ var X402Facilitator = class _X402Facilitator {
|
|
|
3644
3806
|
if (!Array.isArray(oeCalldata) || oeCalldata.length === 0) {
|
|
3645
3807
|
return { valid: false, reason: "Missing SHHH oeCalldata" };
|
|
3646
3808
|
}
|
|
3809
|
+
const bound = shhhTransferMatches(oeCalldata, payment.payload);
|
|
3810
|
+
if (!bound.ok) return { valid: false, reason: bound.reason };
|
|
3647
3811
|
return { valid: true };
|
|
3648
3812
|
}
|
|
3649
3813
|
if (!this.provider) {
|
|
@@ -3664,22 +3828,25 @@ var X402Facilitator = class _X402Facilitator {
|
|
|
3664
3828
|
valid_until: String(payload.validUntil),
|
|
3665
3829
|
nonce: payload.nonce
|
|
3666
3830
|
});
|
|
3667
|
-
|
|
3831
|
+
let msgHash;
|
|
3668
3832
|
try {
|
|
3669
|
-
|
|
3670
|
-
contractAddress: payload.fromAddress,
|
|
3671
|
-
entrypoint: "is_valid_signature",
|
|
3672
|
-
calldata: [msgHash, "2", payload.signature.r, payload.signature.s]
|
|
3673
|
-
});
|
|
3674
|
-
const VALID = "0x56414c4944";
|
|
3675
|
-
if (result[0] === VALID || result[0] === BigInt(VALID).toString()) {
|
|
3676
|
-
return { valid: true };
|
|
3677
|
-
}
|
|
3678
|
-
return { valid: false, reason: "Invalid SNIP-12 signature" };
|
|
3833
|
+
msgHash = typedData.getMessageHash(paymentTypedData, payload.fromAddress);
|
|
3679
3834
|
} catch (err) {
|
|
3680
3835
|
const message = err instanceof Error ? err.message : String(err);
|
|
3681
|
-
return { valid: false, reason: `
|
|
3836
|
+
return { valid: false, reason: `Malformed payment: ${message}` };
|
|
3837
|
+
}
|
|
3838
|
+
const check = await isValidStarknetSignature(this.provider, payload.fromAddress, msgHash, [
|
|
3839
|
+
payload.signature.r,
|
|
3840
|
+
payload.signature.s
|
|
3841
|
+
]);
|
|
3842
|
+
if (check.valid) return { valid: true };
|
|
3843
|
+
if (check.reason === "ACCOUNT_NOT_DEPLOYED") {
|
|
3844
|
+
return { valid: false, reason: "Payer account is not deployed" };
|
|
3682
3845
|
}
|
|
3846
|
+
return {
|
|
3847
|
+
valid: false,
|
|
3848
|
+
reason: check.detail ? `Signature verification failed: ${check.detail}` : "Invalid SNIP-12 signature"
|
|
3849
|
+
};
|
|
3683
3850
|
}
|
|
3684
3851
|
/**
|
|
3685
3852
|
* Settle a verified payment by executing the USDC transfer via paymaster.
|
|
@@ -3808,7 +3975,7 @@ var signTypedData = async ({
|
|
|
3808
3975
|
throw error;
|
|
3809
3976
|
}
|
|
3810
3977
|
};
|
|
3811
|
-
function
|
|
3978
|
+
function toFeltHex2(x) {
|
|
3812
3979
|
return "0x" + x.toString(16).padStart(64, "0");
|
|
3813
3980
|
}
|
|
3814
3981
|
var signTypedDataArray = async ({
|
|
@@ -3838,7 +4005,7 @@ var signTypedDataArray = async ({
|
|
|
3838
4005
|
messageHash,
|
|
3839
4006
|
ownerIndex: 0n
|
|
3840
4007
|
});
|
|
3841
|
-
return envelope.map(
|
|
4008
|
+
return envelope.map(toFeltHex2);
|
|
3842
4009
|
}
|
|
3843
4010
|
const provider = new RpcProvider({ nodeUrl: WALLET_RPC_ENDPOINTS[walletType] });
|
|
3844
4011
|
const account = new Account({ provider, address: wallet.publicKey, signer: privateKeyDecrypted });
|
|
@@ -3846,144 +4013,643 @@ var signTypedDataArray = async ({
|
|
|
3846
4013
|
return [r, s];
|
|
3847
4014
|
};
|
|
3848
4015
|
|
|
3849
|
-
// src/
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
4016
|
+
// src/shhh/execute-external-owner.ts
|
|
4017
|
+
init_oe();
|
|
4018
|
+
init_execute_paymaster_raw();
|
|
4019
|
+
init_stark();
|
|
4020
|
+
|
|
4021
|
+
// src/shhh/signers/stark-snip12.ts
|
|
4022
|
+
init_compute_wallet_address();
|
|
4023
|
+
init_oe();
|
|
4024
|
+
var ROLE_OWNER = BigInt(shortString.encodeShortString("OWNER"));
|
|
4025
|
+
var ROLE_GUARDIAN = BigInt(shortString.encodeShortString("GUARDIAN"));
|
|
4026
|
+
var OP_ADD_OWNER = BigInt(shortString.encodeShortString("ADD_OWNER"));
|
|
4027
|
+
var OP_REMOVE_OWNER = BigInt(shortString.encodeShortString("REMOVE_OWNER"));
|
|
4028
|
+
var OP_ROTATE_OWNER = BigInt(shortString.encodeShortString("ROTATE_OWNER"));
|
|
4029
|
+
var OP_SET_THRESHOLD = BigInt(shortString.encodeShortString("SET_THRESHOLD"));
|
|
4030
|
+
var OP_ADD_VERIFIER_CLASS = BigInt(shortString.encodeShortString("ADD_VERIFIER"));
|
|
4031
|
+
var TIMELOCK_SECONDS = {
|
|
4032
|
+
ADD_OWNER: 172800,
|
|
4033
|
+
// 48h
|
|
4034
|
+
REMOVE_OWNER: 86400,
|
|
4035
|
+
// 24h
|
|
4036
|
+
ROTATE_OWNER: 86400,
|
|
4037
|
+
// 24h
|
|
4038
|
+
SET_THRESHOLD: 172800,
|
|
4039
|
+
// 48h
|
|
4040
|
+
ADD_VERIFIER: 172800,
|
|
4041
|
+
// 48h
|
|
4042
|
+
REMOVE_VERIFIER: 86400,
|
|
4043
|
+
// 24h
|
|
4044
|
+
ADD_GUARDIAN: 86400,
|
|
4045
|
+
// 24h
|
|
4046
|
+
REMOVE_GUARDIAN: 86400,
|
|
4047
|
+
// 24h
|
|
4048
|
+
RECOVERY: 604800
|
|
4049
|
+
// 7d — `TIMELOCK_RECOVERY`, the headline UX gate
|
|
4050
|
+
};
|
|
4051
|
+
var DEFAULT_OP_EXPIRY_SECONDS = 1209600;
|
|
4052
|
+
function _felt2(x, field = "felt") {
|
|
4053
|
+
const v = typeof x === "bigint" ? x : BigInt(x);
|
|
4054
|
+
if (v < 0n) {
|
|
4055
|
+
throw new RangeError(`${field} must be a non-negative felt; got ${v.toString()}`);
|
|
3876
4056
|
}
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
4057
|
+
return v;
|
|
4058
|
+
}
|
|
4059
|
+
function _encodeOwnerInput(input) {
|
|
4060
|
+
if (input.weight < 0) {
|
|
4061
|
+
throw new RangeError(`NewOwnerInput.weight must be non-negative; got ${input.weight}`);
|
|
4062
|
+
}
|
|
4063
|
+
const kindFelt = _felt2(BigInt(shortString.encodeShortString(input.kind)), "kind");
|
|
4064
|
+
const roleFelt = input.role === "OWNER" ? ROLE_OWNER : ROLE_GUARDIAN;
|
|
4065
|
+
const pubkey = input.pubkeyBytes.map((p, i) => _felt2(p, `pubkeyBytes[${i}]`));
|
|
4066
|
+
return [
|
|
4067
|
+
kindFelt,
|
|
4068
|
+
BigInt(pubkey.length),
|
|
4069
|
+
...pubkey,
|
|
4070
|
+
roleFelt,
|
|
4071
|
+
BigInt(input.weight),
|
|
4072
|
+
_felt2(BigInt(shortString.encodeShortString(input.label)), "label")
|
|
4073
|
+
];
|
|
4074
|
+
}
|
|
4075
|
+
function _call(walletAddress, entrypoint, calldata) {
|
|
4076
|
+
for (let i = 0; i < calldata.length; i++) {
|
|
4077
|
+
if (calldata[i] < 0n) {
|
|
4078
|
+
throw new RangeError(
|
|
4079
|
+
`calldata[${i}] must be a non-negative felt; got ${calldata[i].toString()}`
|
|
3885
4080
|
);
|
|
3886
4081
|
}
|
|
3887
|
-
return token;
|
|
3888
|
-
}
|
|
3889
|
-
/**
|
|
3890
|
-
* Create a PaymasterAdapter for use with TxBuilder.sendSponsored().
|
|
3891
|
-
*
|
|
3892
|
-
* @example
|
|
3893
|
-
* ```typescript
|
|
3894
|
-
* const sdk = new ChipiServerSDK({ apiPublicKey: "pk_...", apiSecretKey: "sk_..." });
|
|
3895
|
-
* const paymaster = sdk.createPaymasterAdapter();
|
|
3896
|
-
*
|
|
3897
|
-
* const txHash = await new TxBuilder(account, { paymaster })
|
|
3898
|
-
* .transfer(USDC, [{ to, amount }])
|
|
3899
|
-
* .sendSponsored(); // gasless!
|
|
3900
|
-
* ```
|
|
3901
|
-
*/
|
|
3902
|
-
createPaymasterAdapter(bearerToken) {
|
|
3903
|
-
const token = this.resolveBearerToken(bearerToken);
|
|
3904
|
-
return new ChipiPaymasterAdapter(this.client, token);
|
|
3905
|
-
}
|
|
3906
|
-
/**
|
|
3907
|
-
* Create an X402Facilitator for verifying and settling x402 payments.
|
|
3908
|
-
*
|
|
3909
|
-
* @example
|
|
3910
|
-
* ```typescript
|
|
3911
|
-
* const facilitator = sdk.createX402Facilitator();
|
|
3912
|
-
*
|
|
3913
|
-
* // With custom nonce store (Redis)
|
|
3914
|
-
* const facilitator = sdk.createX402Facilitator(bearerToken, {
|
|
3915
|
-
* nonceStore: {
|
|
3916
|
-
* has: async (nonce) => (await redis.sismember("x402:nonces", nonce)) === 1,
|
|
3917
|
-
* consume: async (nonce) => (await redis.sadd("x402:nonces", nonce)) === 1,
|
|
3918
|
-
* },
|
|
3919
|
-
* });
|
|
3920
|
-
* ```
|
|
3921
|
-
*/
|
|
3922
|
-
createX402Facilitator(bearerToken, config) {
|
|
3923
|
-
const token = this.resolveBearerToken(bearerToken);
|
|
3924
|
-
return new X402Facilitator(this.client, token, config);
|
|
3925
|
-
}
|
|
3926
|
-
/**
|
|
3927
|
-
* Execute a gasless transaction
|
|
3928
|
-
*/
|
|
3929
|
-
async executeTransaction({
|
|
3930
|
-
params,
|
|
3931
|
-
bearerToken
|
|
3932
|
-
}) {
|
|
3933
|
-
return this.transactions.executeTransaction({
|
|
3934
|
-
params,
|
|
3935
|
-
bearerToken: this.resolveBearerToken(bearerToken)
|
|
3936
|
-
});
|
|
3937
|
-
}
|
|
3938
|
-
/**
|
|
3939
|
-
* Execute a gasless transaction using a session key.
|
|
3940
|
-
*
|
|
3941
|
-
* This uses the 4-element session signature format instead of owner signature.
|
|
3942
|
-
* The session must be:
|
|
3943
|
-
* 1. Generated via `sessions.createSessionKey()`
|
|
3944
|
-
* 2. Registered on-chain via `sessions.addSessionKeyToContract()`
|
|
3945
|
-
*
|
|
3946
|
-
* CHIPI wallets only - will throw if wallet type is not CHIPI.
|
|
3947
|
-
*
|
|
3948
|
-
* @example
|
|
3949
|
-
* ```typescript
|
|
3950
|
-
* // 1. Create session key (store externally)
|
|
3951
|
-
* const session = sdk.sessions.createSessionKey({ encryptKey });
|
|
3952
|
-
*
|
|
3953
|
-
* // 2. Register on contract (one-time)
|
|
3954
|
-
* await sdk.sessions.addSessionKeyToContract({
|
|
3955
|
-
* encryptKey,
|
|
3956
|
-
* wallet,
|
|
3957
|
-
* sessionConfig: {
|
|
3958
|
-
* sessionPublicKey: session.publicKey,
|
|
3959
|
-
* validUntil: session.validUntil,
|
|
3960
|
-
* maxCalls: 1000,
|
|
3961
|
-
* allowedEntrypoints: []
|
|
3962
|
-
* }
|
|
3963
|
-
* }, bearerToken);
|
|
3964
|
-
*
|
|
3965
|
-
* // 3. Execute transactions with session (no owner key needed)
|
|
3966
|
-
* const txHash = await sdk.executeTransactionWithSession({
|
|
3967
|
-
* params: { encryptKey, wallet, session, calls },
|
|
3968
|
-
* bearerToken
|
|
3969
|
-
* });
|
|
3970
|
-
* ```
|
|
3971
|
-
*/
|
|
3972
|
-
async executeTransactionWithSession({
|
|
3973
|
-
params,
|
|
3974
|
-
bearerToken
|
|
3975
|
-
}) {
|
|
3976
|
-
return this.sessions.executeTransactionWithSession(
|
|
3977
|
-
params,
|
|
3978
|
-
this.resolveBearerToken(bearerToken)
|
|
3979
|
-
);
|
|
3980
4082
|
}
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
4083
|
+
return {
|
|
4084
|
+
contractAddress: typeof walletAddress === "bigint" ? "0x" + walletAddress.toString(16) : walletAddress,
|
|
4085
|
+
entrypoint,
|
|
4086
|
+
calldata: calldata.map((v) => "0x" + v.toString(16))
|
|
4087
|
+
};
|
|
4088
|
+
}
|
|
4089
|
+
function buildProposeAddOwnerCall(args) {
|
|
4090
|
+
const calldata = [BigInt(args.proposer), ..._encodeOwnerInput(args.newOwner)];
|
|
4091
|
+
return _call(args.walletAddress, "propose_add_owner", calldata);
|
|
4092
|
+
}
|
|
4093
|
+
function buildExecuteAddOwnerCall(args) {
|
|
4094
|
+
const calldata = [_felt2(args.opId), ..._encodeOwnerInput(args.newOwner)];
|
|
4095
|
+
return _call(args.walletAddress, "execute_add_owner", calldata);
|
|
4096
|
+
}
|
|
4097
|
+
function buildProposeRemoveOwnerCall(args) {
|
|
4098
|
+
return _call(args.walletAddress, "propose_remove_owner", [
|
|
4099
|
+
BigInt(args.proposer),
|
|
4100
|
+
BigInt(args.ownerId)
|
|
4101
|
+
]);
|
|
4102
|
+
}
|
|
4103
|
+
function buildExecuteRemoveOwnerCall(args) {
|
|
4104
|
+
return _call(args.walletAddress, "execute_remove_owner", [
|
|
4105
|
+
_felt2(args.opId),
|
|
4106
|
+
BigInt(args.ownerId)
|
|
4107
|
+
]);
|
|
4108
|
+
}
|
|
4109
|
+
function buildProposeRotateOwnerCall(args) {
|
|
4110
|
+
return _call(args.walletAddress, "propose_rotate_owner", [
|
|
4111
|
+
BigInt(args.proposer),
|
|
4112
|
+
BigInt(args.ownerId),
|
|
4113
|
+
BigInt(args.newPubkeyBytes.length),
|
|
4114
|
+
...args.newPubkeyBytes
|
|
4115
|
+
]);
|
|
4116
|
+
}
|
|
4117
|
+
function buildExecuteRotateOwnerCall(args) {
|
|
4118
|
+
return _call(args.walletAddress, "execute_rotate_owner", [
|
|
4119
|
+
_felt2(args.opId),
|
|
4120
|
+
BigInt(args.ownerId),
|
|
4121
|
+
BigInt(args.newPubkeyBytes.length),
|
|
4122
|
+
...args.newPubkeyBytes
|
|
4123
|
+
]);
|
|
4124
|
+
}
|
|
4125
|
+
function buildProposeSetThresholdCall(args) {
|
|
4126
|
+
return _call(args.walletAddress, "propose_set_threshold", [
|
|
4127
|
+
BigInt(args.proposer),
|
|
4128
|
+
BigInt(args.newThreshold)
|
|
4129
|
+
]);
|
|
4130
|
+
}
|
|
4131
|
+
function buildExecuteSetThresholdCall(args) {
|
|
4132
|
+
return _call(args.walletAddress, "execute_set_threshold", [
|
|
4133
|
+
_felt2(args.opId),
|
|
4134
|
+
BigInt(args.newThreshold)
|
|
4135
|
+
]);
|
|
4136
|
+
}
|
|
4137
|
+
function buildCancelPendingOpCall(args) {
|
|
4138
|
+
return _call(args.walletAddress, "cancel_pending_op", [_felt2(args.opId)]);
|
|
4139
|
+
}
|
|
4140
|
+
function _verifierClassHash(kind, classHash) {
|
|
4141
|
+
const h = classHash ?? SHHH_VERIFIER_CLASS_HASHES[kind];
|
|
4142
|
+
if (!h) throw new Error(`No verifier class hash known for kind "${kind}".`);
|
|
4143
|
+
return _felt2(h, "classHash");
|
|
4144
|
+
}
|
|
4145
|
+
function buildProposeAddVerifierClassCall(args) {
|
|
4146
|
+
const kindFelt = BigInt(shortString.encodeShortString(args.kind));
|
|
4147
|
+
return _call(args.walletAddress, "propose_add_verifier_class", [
|
|
4148
|
+
BigInt(args.proposer),
|
|
4149
|
+
kindFelt,
|
|
4150
|
+
_verifierClassHash(args.kind, args.classHash)
|
|
4151
|
+
]);
|
|
4152
|
+
}
|
|
4153
|
+
function buildExecuteAddVerifierClassCall(args) {
|
|
4154
|
+
const kindFelt = BigInt(shortString.encodeShortString(args.kind));
|
|
4155
|
+
return _call(args.walletAddress, "execute_add_verifier_class", [
|
|
4156
|
+
_felt2(args.opId),
|
|
4157
|
+
kindFelt,
|
|
4158
|
+
_verifierClassHash(args.kind, args.classHash)
|
|
4159
|
+
]);
|
|
4160
|
+
}
|
|
4161
|
+
function buildInitiateRecoveryCall(args) {
|
|
4162
|
+
const calldata = [BigInt(args.proposer), ..._encodeOwnerInput(args.newOwner)];
|
|
4163
|
+
return _call(args.walletAddress, "initiate_recovery", calldata);
|
|
4164
|
+
}
|
|
4165
|
+
function buildCancelRecoveryCall(args) {
|
|
4166
|
+
return _call(args.walletAddress, "cancel_recovery", [BigInt(args.ownerId)]);
|
|
4167
|
+
}
|
|
4168
|
+
function buildFinalizeRecoveryCall(args) {
|
|
4169
|
+
return _call(args.walletAddress, "finalize_recovery", _encodeOwnerInput(args.newOwner));
|
|
4170
|
+
}
|
|
4171
|
+
var VIEW_SELECTORS = {
|
|
4172
|
+
get_pending_op: hash.getSelectorFromName("get_pending_op"),
|
|
4173
|
+
get_pending_recovery: hash.getSelectorFromName("get_pending_recovery"),
|
|
4174
|
+
get_owner: hash.getSelectorFromName("get_owner")
|
|
4175
|
+
};
|
|
4176
|
+
function _toSecondsBigInt(value, field) {
|
|
4177
|
+
if (typeof value === "bigint") return value;
|
|
4178
|
+
if (!Number.isFinite(value)) {
|
|
4179
|
+
throw new TypeError(`${field} must be a finite timestamp; got ${value}`);
|
|
4180
|
+
}
|
|
4181
|
+
return BigInt(Math.floor(value));
|
|
4182
|
+
}
|
|
4183
|
+
function isReadyToExecute(validAfterSecs, nowSecs) {
|
|
4184
|
+
return _toSecondsBigInt(nowSecs, "nowSecs") >= _toSecondsBigInt(validAfterSecs, "validAfterSecs");
|
|
4185
|
+
}
|
|
4186
|
+
function secondsUntilExecutable(validAfterSecs, nowSecs) {
|
|
4187
|
+
const remaining = _toSecondsBigInt(validAfterSecs, "validAfterSecs") - _toSecondsBigInt(nowSecs, "nowSecs");
|
|
4188
|
+
return remaining <= 0n ? 0 : Number(remaining);
|
|
4189
|
+
}
|
|
4190
|
+
function _decodeShort(value) {
|
|
4191
|
+
const v = BigInt(value);
|
|
4192
|
+
return v === 0n ? "" : shortString.decodeShortString(num.toHex(v));
|
|
4193
|
+
}
|
|
4194
|
+
function _view(provider, walletAddress, entrypoint, calldata = []) {
|
|
4195
|
+
return provider.callContract({
|
|
4196
|
+
contractAddress: typeof walletAddress === "bigint" ? num.toHex(walletAddress) : walletAddress,
|
|
4197
|
+
entrypoint,
|
|
4198
|
+
calldata: calldata.map((v) => num.toHex(BigInt(v)))
|
|
4199
|
+
});
|
|
4200
|
+
}
|
|
4201
|
+
async function readShhhOwners(provider, walletAddress) {
|
|
4202
|
+
const [countFelt] = await _view(provider, walletAddress, "owner_count");
|
|
4203
|
+
const count = Number(BigInt(countFelt));
|
|
4204
|
+
const owners = [];
|
|
4205
|
+
for (let id = 0; id < count; id++) {
|
|
4206
|
+
owners.push(decodeShhhOwnerRecord(id, await _view(provider, walletAddress, "get_owner", [id])));
|
|
4207
|
+
}
|
|
4208
|
+
return owners;
|
|
4209
|
+
}
|
|
4210
|
+
function decodeShhhOwnerRecord(ownerId, felts) {
|
|
4211
|
+
if (felts.length < 9) {
|
|
4212
|
+
throw new Error(`get_owner returned ${felts.length} felts; expected 9 (OwnerRecord).`);
|
|
4213
|
+
}
|
|
4214
|
+
return {
|
|
4215
|
+
ownerId,
|
|
4216
|
+
kind: _decodeShort(felts[0]),
|
|
4217
|
+
pubkeyHash: BigInt(felts[1]),
|
|
4218
|
+
role: _decodeShort(felts[4]),
|
|
4219
|
+
weight: Number(BigInt(felts[5])),
|
|
4220
|
+
addedAt: Number(BigInt(felts[6])),
|
|
4221
|
+
label: _decodeShort(felts[7]),
|
|
4222
|
+
revoked: BigInt(felts[8]) !== 0n
|
|
4223
|
+
};
|
|
4224
|
+
}
|
|
4225
|
+
async function readVerifierClass(provider, walletAddress, kind) {
|
|
4226
|
+
const [h] = await _view(provider, walletAddress, "get_verifier_class", [
|
|
4227
|
+
BigInt(shortString.encodeShortString(kind))
|
|
4228
|
+
]);
|
|
4229
|
+
return BigInt(h ?? 0);
|
|
4230
|
+
}
|
|
4231
|
+
async function readPendingRecovery(provider, walletAddress) {
|
|
4232
|
+
const r = await _view(provider, walletAddress, "get_pending_recovery");
|
|
4233
|
+
return {
|
|
4234
|
+
initiatedAt: Number(BigInt(r[0])),
|
|
4235
|
+
validAfter: Number(BigInt(r[1])),
|
|
4236
|
+
newOwnerHash: BigInt(r[2]),
|
|
4237
|
+
isActive: BigInt(r[3]) !== 0n
|
|
4238
|
+
};
|
|
4239
|
+
}
|
|
4240
|
+
var OP_PROPOSED_KEY = BigInt(hash.getSelectorFromName("OpProposed"));
|
|
4241
|
+
function parseOpProposedEvents(events, walletAddress) {
|
|
4242
|
+
const wallet = walletAddress === void 0 ? void 0 : BigInt(walletAddress);
|
|
4243
|
+
return events.filter(
|
|
4244
|
+
(e) => e.keys.length >= 3 && BigInt(e.keys[0]) === OP_PROPOSED_KEY && (wallet === void 0 || e.from_address !== void 0 && BigInt(e.from_address) === wallet)
|
|
4245
|
+
).map((e) => ({
|
|
4246
|
+
opId: BigInt(e.keys[1]),
|
|
4247
|
+
opKind: _decodeShort(e.keys[2]),
|
|
4248
|
+
proposer: Number(BigInt(e.data[0])),
|
|
4249
|
+
payload: BigInt(e.data[1]),
|
|
4250
|
+
validAfter: Number(BigInt(e.data[2])),
|
|
4251
|
+
expiresAt: Number(BigInt(e.data[3]))
|
|
4252
|
+
}));
|
|
4253
|
+
}
|
|
4254
|
+
|
|
4255
|
+
// src/shhh/signers/stark-snip12.ts
|
|
4256
|
+
var STARK_SNIP12_KIND_TAG = "STARK_SNIP12";
|
|
4257
|
+
var STARK_KIND_TAG_FELT2 = BigInt(shortString.encodeShortString("STARK"));
|
|
4258
|
+
var V2_SNIP12_FELT = BigInt(shortString.encodeShortString("V2_SNIP12"));
|
|
4259
|
+
function domainChainId(chainId) {
|
|
4260
|
+
if (typeof chainId === "string" && !chainId.startsWith("0x")) return chainId;
|
|
4261
|
+
return shortString.decodeShortString(toFeltHex(chainId));
|
|
4262
|
+
}
|
|
4263
|
+
function felt(value) {
|
|
4264
|
+
return BigInt(value);
|
|
4265
|
+
}
|
|
4266
|
+
function starkSnip12ApprovalTypedData(params) {
|
|
4267
|
+
return {
|
|
4268
|
+
types: {
|
|
4269
|
+
StarknetDomain: [
|
|
4270
|
+
{ name: "name", type: "shortstring" },
|
|
4271
|
+
{ name: "version", type: "shortstring" },
|
|
4272
|
+
{ name: "chainId", type: "shortstring" },
|
|
4273
|
+
{ name: "revision", type: "shortstring" }
|
|
4274
|
+
],
|
|
4275
|
+
Approval: [
|
|
4276
|
+
{ name: "Wallet", type: "ContractAddress" },
|
|
4277
|
+
{ name: "Hash", type: "felt" }
|
|
4278
|
+
]
|
|
4279
|
+
},
|
|
4280
|
+
primaryType: "Approval",
|
|
4281
|
+
domain: {
|
|
4282
|
+
name: "Shhh",
|
|
4283
|
+
version: "1",
|
|
4284
|
+
chainId: domainChainId(params.chainId ?? "SN_MAIN"),
|
|
4285
|
+
revision: "1"
|
|
4286
|
+
},
|
|
4287
|
+
message: {
|
|
4288
|
+
Wallet: normalizeStarknetAddress(params.walletAddress),
|
|
4289
|
+
Hash: toFeltHex(params.messageHash)
|
|
4290
|
+
}
|
|
4291
|
+
};
|
|
4292
|
+
}
|
|
4293
|
+
function starkSnip12ApprovalHash(params) {
|
|
4294
|
+
const td = starkSnip12ApprovalTypedData(params);
|
|
4295
|
+
return BigInt(typedData.getMessageHash(td, normalizeStarknetAddress(params.signerAddress)));
|
|
4296
|
+
}
|
|
4297
|
+
function starkSnip12PubkeyFelts(starkPubkey, signerAddress) {
|
|
4298
|
+
const pub = felt(starkPubkey);
|
|
4299
|
+
const account = BigInt(normalizeStarknetAddress(signerAddress));
|
|
4300
|
+
if (pub === 0n || account === 0n) {
|
|
4301
|
+
throw new Error("starkSnip12PubkeyFelts: the key and the account address must be non-zero.");
|
|
4302
|
+
}
|
|
4303
|
+
return [pub, account];
|
|
4304
|
+
}
|
|
4305
|
+
function starkSnip12OwnerCommitment(starkPubkey, signerAddress) {
|
|
4306
|
+
return ownerCommitment(
|
|
4307
|
+
BigInt(shortString.encodeShortString(STARK_SNIP12_KIND_TAG)),
|
|
4308
|
+
starkSnip12PubkeyFelts(starkPubkey, signerAddress)
|
|
4309
|
+
);
|
|
4310
|
+
}
|
|
4311
|
+
function parseStarknetWalletSignature(signature) {
|
|
4312
|
+
const sig = signature.map((v) => felt(v));
|
|
4313
|
+
if (sig.length === 2) return { r: sig[0], s: sig[1] };
|
|
4314
|
+
if (sig.length === 5 && sig[0] === 1n && sig[1] === 0n) {
|
|
4315
|
+
return { pubkey: sig[2], r: sig[3], s: sig[4] };
|
|
4316
|
+
}
|
|
4317
|
+
if (sig.length === 5 && sig[0] === V2_SNIP12_FELT && sig[2] === STARK_KIND_TAG_FELT2) {
|
|
4318
|
+
return { shhhOwnerId: sig[1], r: sig[3], s: sig[4] };
|
|
4319
|
+
}
|
|
4320
|
+
throw new Error(
|
|
4321
|
+
`This wallet returned a ${sig.length}-felt signature that isn't a single STARK key (multisig, hardware or passkey signers aren't supported as a SHHH co-owner yet).`
|
|
4322
|
+
);
|
|
4323
|
+
}
|
|
4324
|
+
function starkVerifyX(r, s, msgHash, pubkeyX) {
|
|
4325
|
+
const x = pubkeyX.toString(16).padStart(64, "0");
|
|
4326
|
+
const sig = new ec.starkCurve.Signature(r, s);
|
|
4327
|
+
for (const prefix of ["02", "03"]) {
|
|
4328
|
+
try {
|
|
4329
|
+
if (ec.starkCurve.verify(sig, toFeltHex(msgHash), prefix + x)) return true;
|
|
4330
|
+
} catch {
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
return false;
|
|
4334
|
+
}
|
|
4335
|
+
function verifyStarkSnip12Approval(params) {
|
|
4336
|
+
const { r, s } = parseStarknetWalletSignature(params.signature);
|
|
4337
|
+
const h = starkSnip12ApprovalHash(params);
|
|
4338
|
+
return starkVerifyX(r, s, h, felt(params.starkPubkey));
|
|
4339
|
+
}
|
|
4340
|
+
function buildStarkSnip12Envelope(params) {
|
|
4341
|
+
if (params.ownerIndex < 0n || params.ownerIndex >= 0x100000000n) {
|
|
4342
|
+
throw new Error(
|
|
4343
|
+
`buildStarkSnip12Envelope: ownerIndex ${params.ownerIndex} is out of u32 range. Pass the owner's index in the owner_set, not its commitment.`
|
|
4344
|
+
);
|
|
4345
|
+
}
|
|
4346
|
+
const { r, s } = parseStarknetWalletSignature(params.signature);
|
|
4347
|
+
return wrapV2Snip12Envelope({
|
|
4348
|
+
ownerId: params.ownerIndex,
|
|
4349
|
+
kindTag: STARK_SNIP12_KIND_TAG,
|
|
4350
|
+
payload: [r, s]
|
|
4351
|
+
});
|
|
4352
|
+
}
|
|
4353
|
+
function recoverStarkKeys(r, s, msgHash) {
|
|
4354
|
+
const out = [];
|
|
4355
|
+
for (const bit of [0, 1]) {
|
|
4356
|
+
try {
|
|
4357
|
+
const point = new ec.starkCurve.Signature(r, s).addRecoveryBit(bit).recoverPublicKey(msgHash.toString(16).padStart(64, "0"));
|
|
4358
|
+
out.push(point.toAffine().x);
|
|
4359
|
+
} catch {
|
|
4360
|
+
}
|
|
4361
|
+
}
|
|
4362
|
+
return out;
|
|
4363
|
+
}
|
|
4364
|
+
async function tryCall(provider, contractAddress, entrypoint, calldata = []) {
|
|
4365
|
+
try {
|
|
4366
|
+
return await provider.callContract({ contractAddress, entrypoint, calldata });
|
|
4367
|
+
} catch {
|
|
4368
|
+
return null;
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
async function resolveStarkSnip12Signer(params) {
|
|
4372
|
+
const signer = normalizeStarknetAddress(params.signerAddress);
|
|
4373
|
+
const parsed = parseStarknetWalletSignature(params.signature);
|
|
4374
|
+
const approvalHash = starkSnip12ApprovalHash(params);
|
|
4375
|
+
const candidates = [];
|
|
4376
|
+
if (parsed.pubkey !== void 0) candidates.push(parsed.pubkey);
|
|
4377
|
+
if (parsed.shhhOwnerId !== void 0) {
|
|
4378
|
+
const felts = await tryCall(params.provider, signer, "get_owner", [
|
|
4379
|
+
toFeltHex(parsed.shhhOwnerId)
|
|
4380
|
+
]);
|
|
4381
|
+
const record = felts && felts.length >= 9 ? decodeShhhOwnerRecord(0, felts) : null;
|
|
4382
|
+
if (record && !record.revoked && record.kind === "STARK" && record.role === "OWNER") {
|
|
4383
|
+
for (const key2 of recoverStarkKeys(parsed.r, parsed.s, approvalHash)) {
|
|
4384
|
+
if (ownerCommitment(STARK_KIND_TAG_FELT2, [key2]) === record.pubkeyHash) candidates.push(key2);
|
|
4385
|
+
}
|
|
4386
|
+
}
|
|
4387
|
+
if (candidates.length === 0) {
|
|
4388
|
+
throw new Error(
|
|
4389
|
+
`Couldn't confirm the Chipi wallet's signer: owner ${parsed.shhhOwnerId} of ${signer} is not an active STARK owner whose key made this signature.`
|
|
4390
|
+
);
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
if (params.deploymentData && normalizeStarknetAddress(params.deploymentData.address) === signer) {
|
|
4394
|
+
const cls = normalizeStarknetAddress(params.deploymentData.class_hash);
|
|
4395
|
+
const cd = params.deploymentData.calldata;
|
|
4396
|
+
if (cls === COUNTERFACTUAL_ACCOUNT_CLASSES.OPENZEPPELIN_V3 && cd.length === 1) {
|
|
4397
|
+
candidates.push(felt(cd[0]));
|
|
4398
|
+
}
|
|
4399
|
+
if (cls === COUNTERFACTUAL_ACCOUNT_CLASSES.ARGENT_V0_4 && cd.length === 3) {
|
|
4400
|
+
candidates.push(felt(cd[1]));
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4403
|
+
if (candidates.length === 0) {
|
|
4404
|
+
const oz = await tryCall(params.provider, signer, "get_public_key");
|
|
4405
|
+
if (oz && oz.length >= 1) candidates.push(felt(oz[0]));
|
|
4406
|
+
}
|
|
4407
|
+
if (candidates.length === 0) {
|
|
4408
|
+
const signers = await tryCall(params.provider, signer, "get_signers");
|
|
4409
|
+
if (signers && signers.length >= 1) {
|
|
4410
|
+
const starkLen = Number(BigInt(signers[0]));
|
|
4411
|
+
const rest = signers.slice(1 + starkLen);
|
|
4412
|
+
const onlyStark = rest.every((v) => BigInt(v) === 0n);
|
|
4413
|
+
if (starkLen === 1 && onlyStark) candidates.push(felt(signers[1]));
|
|
4414
|
+
}
|
|
4415
|
+
}
|
|
4416
|
+
const key = candidates.find((k) => starkVerifyX(parsed.r, parsed.s, approvalHash, k));
|
|
4417
|
+
if (key === void 0) {
|
|
4418
|
+
throw new Error(
|
|
4419
|
+
"Couldn't confirm which key signs for this wallet. It may use a hardware or passkey signer, a multisig, or an account type we don't read yet."
|
|
4420
|
+
);
|
|
4421
|
+
}
|
|
4422
|
+
return { starkPubkey: key, pubkeyFelts: starkSnip12PubkeyFelts(key, signer) };
|
|
4423
|
+
}
|
|
4424
|
+
|
|
4425
|
+
// src/shhh/execute-external-owner.ts
|
|
4426
|
+
function prepareExternalOwnerExecution(params) {
|
|
4427
|
+
const walletAddress = normalizeStarknetAddress(params.walletAddress);
|
|
4428
|
+
const outsideExecution = buildOutsideExecution({
|
|
4429
|
+
nonce: params.nonce ?? newOeNonce(),
|
|
4430
|
+
calls: params.calls,
|
|
4431
|
+
caller: ANY_CALLER_FELT
|
|
4432
|
+
});
|
|
4433
|
+
const chainId = resolveShhhChainId({ override: params.chainId });
|
|
4434
|
+
const messageHash = computeOeHash(outsideExecution, walletAddress, chainId);
|
|
4435
|
+
const typedData2 = starkSnip12ApprovalTypedData({ walletAddress, messageHash, chainId });
|
|
4436
|
+
return { walletAddress, outsideExecution, messageHash, typedData: typedData2, chainId };
|
|
4437
|
+
}
|
|
4438
|
+
async function submitExternalOwnerExecution(params) {
|
|
4439
|
+
const { prepared } = params;
|
|
4440
|
+
if (params.signer && !verifyStarkSnip12Approval({
|
|
4441
|
+
walletAddress: prepared.walletAddress,
|
|
4442
|
+
messageHash: prepared.messageHash,
|
|
4443
|
+
signerAddress: params.signer.address,
|
|
4444
|
+
starkPubkey: params.signer.starkPubkey,
|
|
4445
|
+
signature: params.signature,
|
|
4446
|
+
chainId: prepared.chainId
|
|
4447
|
+
})) {
|
|
4448
|
+
throw new Error(
|
|
4449
|
+
"The signature doesn't match this wallet's registered key. Sign with the same wallet and account you added."
|
|
4450
|
+
);
|
|
4451
|
+
}
|
|
4452
|
+
const envelope = buildStarkSnip12Envelope({
|
|
4453
|
+
signature: params.signature,
|
|
4454
|
+
ownerIndex: BigInt(params.ownerIndex)
|
|
4455
|
+
});
|
|
4456
|
+
const calldata = serializeExecuteFromOutsideV2Calldata({
|
|
4457
|
+
outsideExecution: prepared.outsideExecution,
|
|
4458
|
+
signature: envelope
|
|
4459
|
+
});
|
|
4460
|
+
const response = await params.client.post({
|
|
4461
|
+
endpoint: "/transactions/execute-sponsored-raw",
|
|
4462
|
+
bearerToken: params.bearerToken,
|
|
4463
|
+
body: {
|
|
4464
|
+
accountAddress: prepared.walletAddress,
|
|
4465
|
+
calldata,
|
|
4466
|
+
...params.externalUserId ? { externalUserId: params.externalUserId } : {}
|
|
4467
|
+
}
|
|
4468
|
+
});
|
|
4469
|
+
if (!response?.transactionHash) {
|
|
4470
|
+
throw new Error(
|
|
4471
|
+
"execute-sponsored-raw response missing transactionHash. Check the chipi-back logs for upstream paymaster errors."
|
|
4472
|
+
);
|
|
4473
|
+
}
|
|
4474
|
+
return response.transactionHash;
|
|
4475
|
+
}
|
|
4476
|
+
async function executeShhhWithExternalSigner(params) {
|
|
4477
|
+
const prepared = prepareExternalOwnerExecution(params);
|
|
4478
|
+
const signature = await params.signTypedData(prepared.typedData);
|
|
4479
|
+
return submitExternalOwnerExecution({ ...params, prepared, signature });
|
|
4480
|
+
}
|
|
4481
|
+
async function executeShhhWithStarkKey(params) {
|
|
4482
|
+
const walletAddress = normalizeStarknetAddress(params.walletAddress);
|
|
4483
|
+
const outsideExecution = buildOutsideExecution({
|
|
4484
|
+
nonce: params.nonce ?? newOeNonce(),
|
|
4485
|
+
calls: params.calls,
|
|
4486
|
+
caller: ANY_CALLER_FELT
|
|
4487
|
+
});
|
|
4488
|
+
const chainId = resolveShhhChainId({ override: params.chainId });
|
|
4489
|
+
const messageHash = computeOeHash(outsideExecution, walletAddress, chainId);
|
|
4490
|
+
const signature = buildStarkEnvelope({
|
|
4491
|
+
privateKey: params.privateKey,
|
|
4492
|
+
messageHash,
|
|
4493
|
+
ownerIndex: BigInt(params.ownerIndex)
|
|
4494
|
+
});
|
|
4495
|
+
const calldata = serializeExecuteFromOutsideV2Calldata({ outsideExecution, signature });
|
|
4496
|
+
const response = await params.client.post({
|
|
4497
|
+
endpoint: "/transactions/execute-sponsored-raw",
|
|
4498
|
+
bearerToken: params.bearerToken,
|
|
4499
|
+
body: {
|
|
4500
|
+
accountAddress: walletAddress,
|
|
4501
|
+
calldata,
|
|
4502
|
+
signerKind: "STARK",
|
|
4503
|
+
...params.externalUserId ? { externalUserId: params.externalUserId } : {}
|
|
4504
|
+
}
|
|
4505
|
+
});
|
|
4506
|
+
if (!response?.transactionHash) {
|
|
4507
|
+
throw new Error(
|
|
4508
|
+
"execute-sponsored-raw response missing transactionHash. Check the chipi-back logs for upstream paymaster errors."
|
|
4509
|
+
);
|
|
4510
|
+
}
|
|
4511
|
+
return response.transactionHash;
|
|
4512
|
+
}
|
|
4513
|
+
|
|
4514
|
+
// src/chipi-sdk.ts
|
|
4515
|
+
var ChipiSDK = class {
|
|
4516
|
+
constructor(config) {
|
|
4517
|
+
this.client = new ChipiClient(config);
|
|
4518
|
+
this.nodeUrl = config.nodeUrl || STARKNET_NETWORKS.MAINNET;
|
|
4519
|
+
this.apiSecretKey = config.apiSecretKey;
|
|
4520
|
+
this.wallets = new ChipiWallets(this.client);
|
|
4521
|
+
this.transactions = new ChipiTransactions(this.client);
|
|
4522
|
+
this.skuPurchases = new ChipiSkuPurchases(this.client);
|
|
4523
|
+
this.skus = new ChipiSkus(this.client);
|
|
4524
|
+
this.sessions = new ChipiSessions(this.client);
|
|
4525
|
+
this.exchanges = new ChipiExchanges(this.client);
|
|
4526
|
+
this.treasury = new ChipiTreasury(this.client, config.apiSecretKey);
|
|
4527
|
+
this.ai = new ChipiAi(this.client, config.apiSecretKey, this.sessions);
|
|
4528
|
+
this.executeTransaction = this.executeTransaction.bind(this);
|
|
4529
|
+
this.executeTransactionWithSession = this.executeTransactionWithSession.bind(this);
|
|
4530
|
+
this.transfer = this.transfer.bind(this);
|
|
4531
|
+
this.approve = this.approve.bind(this);
|
|
4532
|
+
this.callAnyContract = this.callAnyContract.bind(this);
|
|
4533
|
+
this.createWallet = this.createWallet.bind(this);
|
|
4534
|
+
this.recordSendTransaction = this.recordSendTransaction.bind(this);
|
|
4535
|
+
this.purchaseSku = this.purchaseSku.bind(this);
|
|
4536
|
+
this.getUsdAmount = this.getUsdAmount.bind(this);
|
|
4537
|
+
this.signTypedData = this.signTypedData.bind(this);
|
|
4538
|
+
this.signTypedDataArray = this.signTypedDataArray.bind(this);
|
|
4539
|
+
this.executeWithExternalSigner = this.executeWithExternalSigner.bind(this);
|
|
4540
|
+
this.createPaymasterAdapter = this.createPaymasterAdapter.bind(this);
|
|
4541
|
+
this.createX402Facilitator = this.createX402Facilitator.bind(this);
|
|
4542
|
+
}
|
|
4543
|
+
/**
|
|
4544
|
+
* Resolve bearer token - uses provided token or falls back to apiSecretKey
|
|
4545
|
+
*/
|
|
4546
|
+
resolveBearerToken(bearerToken) {
|
|
4547
|
+
const token = bearerToken ?? this.apiSecretKey;
|
|
4548
|
+
if (!token) {
|
|
4549
|
+
throw new Error(
|
|
4550
|
+
"Authentication required: either pass a bearerToken or configure the SDK with an apiSecretKey"
|
|
4551
|
+
);
|
|
4552
|
+
}
|
|
4553
|
+
return token;
|
|
4554
|
+
}
|
|
4555
|
+
/**
|
|
4556
|
+
* Create a PaymasterAdapter for use with TxBuilder.sendSponsored().
|
|
4557
|
+
*
|
|
4558
|
+
* @example
|
|
4559
|
+
* ```typescript
|
|
4560
|
+
* const sdk = new ChipiServerSDK({ apiPublicKey: "pk_...", apiSecretKey: "sk_..." });
|
|
4561
|
+
* const paymaster = sdk.createPaymasterAdapter();
|
|
4562
|
+
*
|
|
4563
|
+
* const txHash = await new TxBuilder(account, { paymaster })
|
|
4564
|
+
* .transfer(USDC, [{ to, amount }])
|
|
4565
|
+
* .sendSponsored(); // gasless!
|
|
4566
|
+
* ```
|
|
4567
|
+
*/
|
|
4568
|
+
createPaymasterAdapter(bearerToken) {
|
|
4569
|
+
const token = this.resolveBearerToken(bearerToken);
|
|
4570
|
+
return new ChipiPaymasterAdapter(this.client, token);
|
|
4571
|
+
}
|
|
4572
|
+
/**
|
|
4573
|
+
* Create an X402Facilitator for verifying and settling x402 payments.
|
|
4574
|
+
*
|
|
4575
|
+
* @example
|
|
4576
|
+
* ```typescript
|
|
4577
|
+
* const facilitator = sdk.createX402Facilitator();
|
|
4578
|
+
*
|
|
4579
|
+
* // With custom nonce store (Redis)
|
|
4580
|
+
* const facilitator = sdk.createX402Facilitator(bearerToken, {
|
|
4581
|
+
* nonceStore: {
|
|
4582
|
+
* has: async (nonce) => (await redis.sismember("x402:nonces", nonce)) === 1,
|
|
4583
|
+
* consume: async (nonce) => (await redis.sadd("x402:nonces", nonce)) === 1,
|
|
4584
|
+
* },
|
|
4585
|
+
* });
|
|
4586
|
+
* ```
|
|
4587
|
+
*/
|
|
4588
|
+
createX402Facilitator(bearerToken, config) {
|
|
4589
|
+
const token = this.resolveBearerToken(bearerToken);
|
|
4590
|
+
return new X402Facilitator(this.client, token, config);
|
|
4591
|
+
}
|
|
4592
|
+
/**
|
|
4593
|
+
* Execute a gasless transaction
|
|
4594
|
+
*/
|
|
4595
|
+
async executeTransaction({
|
|
4596
|
+
params,
|
|
4597
|
+
bearerToken
|
|
4598
|
+
}) {
|
|
4599
|
+
return this.transactions.executeTransaction({
|
|
4600
|
+
params,
|
|
4601
|
+
bearerToken: this.resolveBearerToken(bearerToken)
|
|
4602
|
+
});
|
|
4603
|
+
}
|
|
4604
|
+
/**
|
|
4605
|
+
* Execute a gasless transaction using a session key.
|
|
4606
|
+
*
|
|
4607
|
+
* This uses the 4-element session signature format instead of owner signature.
|
|
4608
|
+
* The session must be:
|
|
4609
|
+
* 1. Generated via `sessions.createSessionKey()`
|
|
4610
|
+
* 2. Registered on-chain via `sessions.addSessionKeyToContract()`
|
|
4611
|
+
*
|
|
4612
|
+
* CHIPI wallets only - will throw if wallet type is not CHIPI.
|
|
4613
|
+
*
|
|
4614
|
+
* @example
|
|
4615
|
+
* ```typescript
|
|
4616
|
+
* // 1. Create session key (store externally)
|
|
4617
|
+
* const session = sdk.sessions.createSessionKey({ encryptKey });
|
|
4618
|
+
*
|
|
4619
|
+
* // 2. Register on contract (one-time)
|
|
4620
|
+
* await sdk.sessions.addSessionKeyToContract({
|
|
4621
|
+
* encryptKey,
|
|
4622
|
+
* wallet,
|
|
4623
|
+
* sessionConfig: {
|
|
4624
|
+
* sessionPublicKey: session.publicKey,
|
|
4625
|
+
* validUntil: session.validUntil,
|
|
4626
|
+
* maxCalls: 1000,
|
|
4627
|
+
* allowedEntrypoints: []
|
|
4628
|
+
* }
|
|
4629
|
+
* }, bearerToken);
|
|
4630
|
+
*
|
|
4631
|
+
* // 3. Execute transactions with session (no owner key needed)
|
|
4632
|
+
* const txHash = await sdk.executeTransactionWithSession({
|
|
4633
|
+
* params: { encryptKey, wallet, session, calls },
|
|
4634
|
+
* bearerToken
|
|
4635
|
+
* });
|
|
4636
|
+
* ```
|
|
4637
|
+
*/
|
|
4638
|
+
async executeTransactionWithSession({
|
|
4639
|
+
params,
|
|
4640
|
+
bearerToken
|
|
4641
|
+
}) {
|
|
4642
|
+
return this.sessions.executeTransactionWithSession(
|
|
4643
|
+
params,
|
|
4644
|
+
this.resolveBearerToken(bearerToken)
|
|
4645
|
+
);
|
|
4646
|
+
}
|
|
4647
|
+
/**
|
|
4648
|
+
* Sign SNIP-12 typed data without executing a transaction.
|
|
4649
|
+
*
|
|
4650
|
+
* Purely local operation: decrypt private key → sign → return { r, s }.
|
|
4651
|
+
* No API calls are made. Useful for x402 payment signatures and other
|
|
4652
|
+
* off-chain signing flows.
|
|
3987
4653
|
*
|
|
3988
4654
|
* @example
|
|
3989
4655
|
* ```typescript
|
|
@@ -4007,6 +4673,39 @@ var ChipiSDK = class {
|
|
|
4007
4673
|
async signTypedDataArray({ params }) {
|
|
4008
4674
|
return signTypedDataArray({ params });
|
|
4009
4675
|
}
|
|
4676
|
+
/**
|
|
4677
|
+
* Run calls on a SHHH wallet, signed by an external Starknet wallet that is
|
|
4678
|
+
* one of its `STARK_SNIP12` owners (Bramble, Braavos, Ready/Argent, OZ, or
|
|
4679
|
+
* another Chipi wallet). The wallet signs an `Approval` typed data through
|
|
4680
|
+
* `signTypedData` (its `wallet_signTypedData`); Chipi's paymaster relays the
|
|
4681
|
+
* outside execution gaslessly. Returns the tx hash: wait for it.
|
|
4682
|
+
*
|
|
4683
|
+
* @example
|
|
4684
|
+
* ```typescript
|
|
4685
|
+
* // Bramble approves an agent session on the user's Chipi wallet.
|
|
4686
|
+
* const bramble = window.starknet_bramble;
|
|
4687
|
+
* const txHash = await sdk.executeWithExternalSigner({
|
|
4688
|
+
* params: {
|
|
4689
|
+
* walletAddress: wallet.publicKey,
|
|
4690
|
+
* ownerIndex: 1, // Bramble's index in the wallet's owner set
|
|
4691
|
+
* calls: buildSessionSetupCalls(wallet.publicKey, sessionConfig, policies),
|
|
4692
|
+
* signTypedData: (typedData) =>
|
|
4693
|
+
* bramble.request({ type: "wallet_signTypedData", params: typedData }),
|
|
4694
|
+
* },
|
|
4695
|
+
* bearerToken,
|
|
4696
|
+
* });
|
|
4697
|
+
* ```
|
|
4698
|
+
*/
|
|
4699
|
+
async executeWithExternalSigner({
|
|
4700
|
+
params,
|
|
4701
|
+
bearerToken
|
|
4702
|
+
}) {
|
|
4703
|
+
return executeShhhWithExternalSigner({
|
|
4704
|
+
...params,
|
|
4705
|
+
client: this.client,
|
|
4706
|
+
bearerToken: this.resolveBearerToken(bearerToken)
|
|
4707
|
+
});
|
|
4708
|
+
}
|
|
4010
4709
|
/**
|
|
4011
4710
|
* Transfer tokens
|
|
4012
4711
|
*/
|
|
@@ -4123,8 +4822,8 @@ var ChipiSDK = class {
|
|
|
4123
4822
|
/**
|
|
4124
4823
|
* Get on-chain transaction status (supports polling for confirmation)
|
|
4125
4824
|
*/
|
|
4126
|
-
async getTransactionStatus(
|
|
4127
|
-
return this.transactions.getTransactionStatus(
|
|
4825
|
+
async getTransactionStatus(hash13, bearerToken) {
|
|
4826
|
+
return this.transactions.getTransactionStatus(hash13, this.resolveBearerToken(bearerToken));
|
|
4128
4827
|
}
|
|
4129
4828
|
/**
|
|
4130
4829
|
* Prepare a wallet upgrade (e.g., READY → CHIPI or CHIPI v29 → v33).
|
|
@@ -4496,12 +5195,135 @@ function x402Middleware(config) {
|
|
|
4496
5195
|
next();
|
|
4497
5196
|
};
|
|
4498
5197
|
}
|
|
5198
|
+
var SIWS_DOMAIN_NAME = "Sign in with Starknet";
|
|
5199
|
+
var SIWS_DOMAIN_VERSION = "1";
|
|
5200
|
+
var SIWS_CHAIN_ID = "SN_MAIN";
|
|
5201
|
+
var DEFAULT_STATEMENT = "Sign in. This request costs nothing and moves no funds.";
|
|
5202
|
+
function assertPrintableAscii(field, value) {
|
|
5203
|
+
if (!/^[\x20-\x7e]*$/.test(value)) {
|
|
5204
|
+
throw new Error(`SIWS ${field} must be single-line printable ASCII`);
|
|
5205
|
+
}
|
|
5206
|
+
}
|
|
5207
|
+
function createStarknetSignInTypedData(params) {
|
|
5208
|
+
const message = {
|
|
5209
|
+
domain: params.domain,
|
|
5210
|
+
address: normalizeStarknetAddress(params.address),
|
|
5211
|
+
statement: params.statement ?? DEFAULT_STATEMENT,
|
|
5212
|
+
uri: params.uri,
|
|
5213
|
+
nonce: params.nonce,
|
|
5214
|
+
issuedAt: params.issuedAt ?? Math.floor(Date.now() / 1e3),
|
|
5215
|
+
expirationTime: params.expirationTime
|
|
5216
|
+
};
|
|
5217
|
+
for (const field of ["domain", "statement", "uri", "nonce"]) {
|
|
5218
|
+
assertPrintableAscii(field, message[field]);
|
|
5219
|
+
}
|
|
5220
|
+
if (!/^[A-Za-z0-9]{8,}$/.test(message.nonce)) {
|
|
5221
|
+
throw new Error("SIWS nonce must be at least 8 letters or digits");
|
|
5222
|
+
}
|
|
5223
|
+
if (!Number.isInteger(message.issuedAt) || !Number.isInteger(message.expirationTime)) {
|
|
5224
|
+
throw new Error("SIWS times must be whole unix seconds");
|
|
5225
|
+
}
|
|
5226
|
+
if (message.expirationTime <= message.issuedAt) {
|
|
5227
|
+
throw new Error("SIWS expirationTime must be after issuedAt");
|
|
5228
|
+
}
|
|
5229
|
+
return {
|
|
5230
|
+
types: {
|
|
5231
|
+
StarknetDomain: [
|
|
5232
|
+
{ name: "name", type: "shortstring" },
|
|
5233
|
+
{ name: "version", type: "shortstring" },
|
|
5234
|
+
{ name: "chainId", type: "shortstring" },
|
|
5235
|
+
{ name: "revision", type: "shortstring" }
|
|
5236
|
+
],
|
|
5237
|
+
SignIn: [
|
|
5238
|
+
{ name: "domain", type: "string" },
|
|
5239
|
+
{ name: "address", type: "ContractAddress" },
|
|
5240
|
+
{ name: "statement", type: "string" },
|
|
5241
|
+
{ name: "uri", type: "string" },
|
|
5242
|
+
{ name: "nonce", type: "string" },
|
|
5243
|
+
{ name: "issuedAt", type: "timestamp" },
|
|
5244
|
+
{ name: "expirationTime", type: "timestamp" }
|
|
5245
|
+
]
|
|
5246
|
+
},
|
|
5247
|
+
primaryType: "SignIn",
|
|
5248
|
+
domain: {
|
|
5249
|
+
name: SIWS_DOMAIN_NAME,
|
|
5250
|
+
version: SIWS_DOMAIN_VERSION,
|
|
5251
|
+
chainId: SIWS_CHAIN_ID,
|
|
5252
|
+
revision: "1"
|
|
5253
|
+
},
|
|
5254
|
+
message: { ...message }
|
|
5255
|
+
};
|
|
5256
|
+
}
|
|
5257
|
+
var MAX_SKEW_SECONDS = 60;
|
|
5258
|
+
var SIWS_CHAIN_ID_FELT = BigInt(shortString.encodeShortString(SIWS_CHAIN_ID));
|
|
5259
|
+
function isMainnetChainId(chainId) {
|
|
5260
|
+
if (chainId === SIWS_CHAIN_ID) return true;
|
|
5261
|
+
if (typeof chainId === "bigint") return chainId === SIWS_CHAIN_ID_FELT;
|
|
5262
|
+
if (typeof chainId !== "string" || !/^(0x[0-9a-f]+|[0-9]+)$/i.test(chainId)) return false;
|
|
5263
|
+
return BigInt(chainId) === SIWS_CHAIN_ID_FELT;
|
|
5264
|
+
}
|
|
5265
|
+
async function verifyStarknetSignIn(params) {
|
|
5266
|
+
const { typedData: typedData2, signature, provider, expected, deploymentData } = params;
|
|
5267
|
+
const raw = typedData2?.message;
|
|
5268
|
+
if (!raw || !Array.isArray(signature) || signature.length === 0) {
|
|
5269
|
+
return { ok: false, reason: "MALFORMED" };
|
|
5270
|
+
}
|
|
5271
|
+
if (!isMainnetChainId(typedData2.domain?.chainId)) return { ok: false, reason: "WRONG_CHAIN" };
|
|
5272
|
+
let canonical;
|
|
5273
|
+
let message;
|
|
5274
|
+
try {
|
|
5275
|
+
canonical = createStarknetSignInTypedData({
|
|
5276
|
+
domain: String(raw.domain),
|
|
5277
|
+
uri: String(raw.uri),
|
|
5278
|
+
address: String(raw.address),
|
|
5279
|
+
nonce: String(raw.nonce),
|
|
5280
|
+
statement: String(raw.statement),
|
|
5281
|
+
issuedAt: Number(raw.issuedAt),
|
|
5282
|
+
expirationTime: Number(raw.expirationTime)
|
|
5283
|
+
});
|
|
5284
|
+
message = canonical.message;
|
|
5285
|
+
} catch {
|
|
5286
|
+
return { ok: false, reason: "MALFORMED" };
|
|
5287
|
+
}
|
|
5288
|
+
if (message.domain !== expected.domain) return { ok: false, reason: "WRONG_DOMAIN" };
|
|
5289
|
+
if (message.uri !== expected.uri) return { ok: false, reason: "WRONG_URI" };
|
|
5290
|
+
if (message.nonce !== expected.nonce) return { ok: false, reason: "WRONG_NONCE" };
|
|
5291
|
+
const now = expected.now ?? Math.floor(Date.now() / 1e3);
|
|
5292
|
+
if (now >= message.expirationTime) return { ok: false, reason: "EXPIRED" };
|
|
5293
|
+
if (message.issuedAt > now + MAX_SKEW_SECONDS) return { ok: false, reason: "NOT_YET_VALID" };
|
|
5294
|
+
const messageHash = typedData.getMessageHash(canonical, message.address);
|
|
5295
|
+
const onChain = await isValidStarknetSignature(provider, message.address, messageHash, signature);
|
|
5296
|
+
if (onChain.valid) return { ok: true, address: message.address, message };
|
|
5297
|
+
if (onChain.reason !== "ACCOUNT_NOT_DEPLOYED") return { ok: false, reason: "INVALID_SIGNATURE" };
|
|
5298
|
+
if (!deploymentData) return { ok: false, reason: "ACCOUNT_NOT_DEPLOYED" };
|
|
5299
|
+
if (normalizeStarknetAddress(deploymentData.address) !== message.address) {
|
|
5300
|
+
return { ok: false, reason: "ADDRESS_MISMATCH" };
|
|
5301
|
+
}
|
|
5302
|
+
const offChain = verifyUndeployedStarknetSignature(deploymentData, messageHash, signature);
|
|
5303
|
+
return offChain.valid ? { ok: true, address: message.address, message } : { ok: false, reason: offChain.reason };
|
|
5304
|
+
}
|
|
4499
5305
|
|
|
4500
5306
|
// src/shhh/index.ts
|
|
4501
5307
|
init_snip12_hash();
|
|
4502
5308
|
init_compute_wallet_address();
|
|
4503
5309
|
init_oe();
|
|
4504
5310
|
init_stark();
|
|
5311
|
+
function isClassHashNotFound(err) {
|
|
5312
|
+
const e = err;
|
|
5313
|
+
if (e?.baseError?.code === 28 || e?.code === 28) return true;
|
|
5314
|
+
return /class hash not found/i.test(e?.message ?? String(err));
|
|
5315
|
+
}
|
|
5316
|
+
async function isShhhVerifierDeclared(provider, kind, classHash = SHHH_VERIFIER_CLASS_HASHES[kind]) {
|
|
5317
|
+
try {
|
|
5318
|
+
await provider.getClassByHash(classHash);
|
|
5319
|
+
return true;
|
|
5320
|
+
} catch (err) {
|
|
5321
|
+
if (isClassHashNotFound(err)) return false;
|
|
5322
|
+
throw err;
|
|
5323
|
+
}
|
|
5324
|
+
}
|
|
5325
|
+
|
|
5326
|
+
// src/shhh/index.ts
|
|
4505
5327
|
init_ed25519();
|
|
4506
5328
|
|
|
4507
5329
|
// src/shhh/signers/eip191.ts
|
|
@@ -5169,150 +5991,6 @@ async function buildJwtAppleSubEnvelopeFromTestKey(params) {
|
|
|
5169
5991
|
});
|
|
5170
5992
|
return { envelope, pubkey, idToken };
|
|
5171
5993
|
}
|
|
5172
|
-
var ROLE_OWNER = BigInt(shortString.encodeShortString("OWNER"));
|
|
5173
|
-
var ROLE_GUARDIAN = BigInt(shortString.encodeShortString("GUARDIAN"));
|
|
5174
|
-
var OP_ADD_OWNER = BigInt(shortString.encodeShortString("ADD_OWNER"));
|
|
5175
|
-
var OP_REMOVE_OWNER = BigInt(shortString.encodeShortString("REMOVE_OWNER"));
|
|
5176
|
-
var OP_ROTATE_OWNER = BigInt(shortString.encodeShortString("ROTATE_OWNER"));
|
|
5177
|
-
var OP_SET_THRESHOLD = BigInt(shortString.encodeShortString("SET_THRESHOLD"));
|
|
5178
|
-
var TIMELOCK_SECONDS = {
|
|
5179
|
-
ADD_OWNER: 172800,
|
|
5180
|
-
// 48h
|
|
5181
|
-
REMOVE_OWNER: 86400,
|
|
5182
|
-
// 24h
|
|
5183
|
-
ROTATE_OWNER: 86400,
|
|
5184
|
-
// 24h
|
|
5185
|
-
SET_THRESHOLD: 172800,
|
|
5186
|
-
// 48h
|
|
5187
|
-
ADD_VERIFIER: 172800,
|
|
5188
|
-
// 48h
|
|
5189
|
-
REMOVE_VERIFIER: 86400,
|
|
5190
|
-
// 24h
|
|
5191
|
-
ADD_GUARDIAN: 86400,
|
|
5192
|
-
// 24h
|
|
5193
|
-
REMOVE_GUARDIAN: 86400,
|
|
5194
|
-
// 24h
|
|
5195
|
-
RECOVERY: 604800
|
|
5196
|
-
// 7d — `TIMELOCK_RECOVERY`, the headline UX gate
|
|
5197
|
-
};
|
|
5198
|
-
var DEFAULT_OP_EXPIRY_SECONDS = 1209600;
|
|
5199
|
-
function _felt2(x, field = "felt") {
|
|
5200
|
-
const v = typeof x === "bigint" ? x : BigInt(x);
|
|
5201
|
-
if (v < 0n) {
|
|
5202
|
-
throw new RangeError(`${field} must be a non-negative felt; got ${v.toString()}`);
|
|
5203
|
-
}
|
|
5204
|
-
return v;
|
|
5205
|
-
}
|
|
5206
|
-
function _encodeOwnerInput(input) {
|
|
5207
|
-
if (input.weight < 0) {
|
|
5208
|
-
throw new RangeError(`NewOwnerInput.weight must be non-negative; got ${input.weight}`);
|
|
5209
|
-
}
|
|
5210
|
-
const kindFelt = _felt2(BigInt(shortString.encodeShortString(input.kind)), "kind");
|
|
5211
|
-
const roleFelt = input.role === "OWNER" ? ROLE_OWNER : ROLE_GUARDIAN;
|
|
5212
|
-
const pubkey = input.pubkeyBytes.map((p, i) => _felt2(p, `pubkeyBytes[${i}]`));
|
|
5213
|
-
return [
|
|
5214
|
-
kindFelt,
|
|
5215
|
-
BigInt(pubkey.length),
|
|
5216
|
-
...pubkey,
|
|
5217
|
-
roleFelt,
|
|
5218
|
-
BigInt(input.weight),
|
|
5219
|
-
_felt2(BigInt(shortString.encodeShortString(input.label)), "label")
|
|
5220
|
-
];
|
|
5221
|
-
}
|
|
5222
|
-
function _call(walletAddress, entrypoint, calldata) {
|
|
5223
|
-
for (let i = 0; i < calldata.length; i++) {
|
|
5224
|
-
if (calldata[i] < 0n) {
|
|
5225
|
-
throw new RangeError(
|
|
5226
|
-
`calldata[${i}] must be a non-negative felt; got ${calldata[i].toString()}`
|
|
5227
|
-
);
|
|
5228
|
-
}
|
|
5229
|
-
}
|
|
5230
|
-
return {
|
|
5231
|
-
contractAddress: typeof walletAddress === "bigint" ? "0x" + walletAddress.toString(16) : walletAddress,
|
|
5232
|
-
entrypoint,
|
|
5233
|
-
calldata: calldata.map((v) => "0x" + v.toString(16))
|
|
5234
|
-
};
|
|
5235
|
-
}
|
|
5236
|
-
function buildProposeAddOwnerCall(args) {
|
|
5237
|
-
const calldata = [BigInt(args.proposer), ..._encodeOwnerInput(args.newOwner)];
|
|
5238
|
-
return _call(args.walletAddress, "propose_add_owner", calldata);
|
|
5239
|
-
}
|
|
5240
|
-
function buildExecuteAddOwnerCall(args) {
|
|
5241
|
-
const calldata = [_felt2(args.opId), ..._encodeOwnerInput(args.newOwner)];
|
|
5242
|
-
return _call(args.walletAddress, "execute_add_owner", calldata);
|
|
5243
|
-
}
|
|
5244
|
-
function buildProposeRemoveOwnerCall(args) {
|
|
5245
|
-
return _call(args.walletAddress, "propose_remove_owner", [
|
|
5246
|
-
BigInt(args.proposer),
|
|
5247
|
-
BigInt(args.ownerId)
|
|
5248
|
-
]);
|
|
5249
|
-
}
|
|
5250
|
-
function buildExecuteRemoveOwnerCall(args) {
|
|
5251
|
-
return _call(args.walletAddress, "execute_remove_owner", [
|
|
5252
|
-
_felt2(args.opId),
|
|
5253
|
-
BigInt(args.ownerId)
|
|
5254
|
-
]);
|
|
5255
|
-
}
|
|
5256
|
-
function buildProposeRotateOwnerCall(args) {
|
|
5257
|
-
return _call(args.walletAddress, "propose_rotate_owner", [
|
|
5258
|
-
BigInt(args.proposer),
|
|
5259
|
-
BigInt(args.ownerId),
|
|
5260
|
-
BigInt(args.newPubkeyBytes.length),
|
|
5261
|
-
...args.newPubkeyBytes
|
|
5262
|
-
]);
|
|
5263
|
-
}
|
|
5264
|
-
function buildExecuteRotateOwnerCall(args) {
|
|
5265
|
-
return _call(args.walletAddress, "execute_rotate_owner", [
|
|
5266
|
-
_felt2(args.opId),
|
|
5267
|
-
BigInt(args.ownerId),
|
|
5268
|
-
BigInt(args.newPubkeyBytes.length),
|
|
5269
|
-
...args.newPubkeyBytes
|
|
5270
|
-
]);
|
|
5271
|
-
}
|
|
5272
|
-
function buildProposeSetThresholdCall(args) {
|
|
5273
|
-
return _call(args.walletAddress, "propose_set_threshold", [
|
|
5274
|
-
BigInt(args.proposer),
|
|
5275
|
-
BigInt(args.newThreshold)
|
|
5276
|
-
]);
|
|
5277
|
-
}
|
|
5278
|
-
function buildExecuteSetThresholdCall(args) {
|
|
5279
|
-
return _call(args.walletAddress, "execute_set_threshold", [
|
|
5280
|
-
_felt2(args.opId),
|
|
5281
|
-
BigInt(args.newThreshold)
|
|
5282
|
-
]);
|
|
5283
|
-
}
|
|
5284
|
-
function buildCancelPendingOpCall(args) {
|
|
5285
|
-
return _call(args.walletAddress, "cancel_pending_op", [_felt2(args.opId)]);
|
|
5286
|
-
}
|
|
5287
|
-
function buildInitiateRecoveryCall(args) {
|
|
5288
|
-
const calldata = [BigInt(args.proposer), ..._encodeOwnerInput(args.newOwner)];
|
|
5289
|
-
return _call(args.walletAddress, "initiate_recovery", calldata);
|
|
5290
|
-
}
|
|
5291
|
-
function buildCancelRecoveryCall(args) {
|
|
5292
|
-
return _call(args.walletAddress, "cancel_recovery", [BigInt(args.ownerId)]);
|
|
5293
|
-
}
|
|
5294
|
-
function buildFinalizeRecoveryCall(args) {
|
|
5295
|
-
return _call(args.walletAddress, "finalize_recovery", _encodeOwnerInput(args.newOwner));
|
|
5296
|
-
}
|
|
5297
|
-
var VIEW_SELECTORS = {
|
|
5298
|
-
get_pending_op: hash.getSelectorFromName("get_pending_op"),
|
|
5299
|
-
get_pending_recovery: hash.getSelectorFromName("get_pending_recovery"),
|
|
5300
|
-
get_owner: hash.getSelectorFromName("get_owner")
|
|
5301
|
-
};
|
|
5302
|
-
function _toSecondsBigInt(value, field) {
|
|
5303
|
-
if (typeof value === "bigint") return value;
|
|
5304
|
-
if (!Number.isFinite(value)) {
|
|
5305
|
-
throw new TypeError(`${field} must be a finite timestamp; got ${value}`);
|
|
5306
|
-
}
|
|
5307
|
-
return BigInt(Math.floor(value));
|
|
5308
|
-
}
|
|
5309
|
-
function isReadyToExecute(validAfterSecs, nowSecs) {
|
|
5310
|
-
return _toSecondsBigInt(nowSecs, "nowSecs") >= _toSecondsBigInt(validAfterSecs, "validAfterSecs");
|
|
5311
|
-
}
|
|
5312
|
-
function secondsUntilExecutable(validAfterSecs, nowSecs) {
|
|
5313
|
-
const remaining = _toSecondsBigInt(validAfterSecs, "validAfterSecs") - _toSecondsBigInt(nowSecs, "nowSecs");
|
|
5314
|
-
return remaining <= 0n ? 0 : Number(remaining);
|
|
5315
|
-
}
|
|
5316
5994
|
|
|
5317
5995
|
// src/shhh/index.ts
|
|
5318
5996
|
init_threshold();
|
|
@@ -5394,6 +6072,6 @@ function submitViaAccount(funded) {
|
|
|
5394
6072
|
};
|
|
5395
6073
|
}
|
|
5396
6074
|
|
|
5397
|
-
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 };
|
|
6075
|
+
export { ANY_CALLER_FELT, APPLE_ISSUER, BOOTSTRAP_DOMAIN_SEPARATOR, COUNTERFACTUAL_ACCOUNT_CLASSES, 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_ADD_VERIFIER_CLASS, 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, SIWS_CHAIN_ID, SIWS_DOMAIN_NAME, SIWS_DOMAIN_VERSION, STARKNET_MESSAGE_PREFIX, STARKNET_SIGNATURE_VALID, STARK_SNIP12_KIND_TAG, SessionTxVerifier, ShhhAccount, TIMELOCK_SECONDS, VIEW_SELECTORS, X402Facilitator, X402ShhhClient, assertValidV2Snip12Envelope, buildAddSessionKeyCall, buildBootstrapSignedCall, buildCancelPendingOpCall, buildCancelRecoveryCall, buildEd25519Envelope, buildEd25519EnvelopeFromSignature, buildEip191EnvelopeFromPrivateKey, buildEip191EnvelopeFromSignature, buildExecuteAddOwnerCall, buildExecuteAddVerifierClassCall, buildExecuteRemoveOwnerCall, buildExecuteRotateOwnerCall, buildExecuteSetThresholdCall, buildFinalizeRecoveryCall, buildInitiateRecoveryCall, buildJwtAppleSubEnvelopeFromTestKey, buildJwtAppleSubEnvelopeFromTokenResponse, buildMigrationCalls, buildOutsideExecution, buildProposeAddOwnerCall, buildProposeAddVerifierClassCall, buildProposeRemoveOwnerCall, buildProposeRotateOwnerCall, buildProposeSetThresholdCall, buildRemoveSpendingPolicyCall, buildRevokeSessionKeyCall, buildSessionSetupCalls, buildSetSpendingPolicyCall, buildStarkEnvelope, buildStarkSnip12Envelope, buildThresholdEnvelope, buildWebAuthnEnvelopeFromAssertion, buildWebAuthnEnvelopeFromPrivateKey, byteArrayToFelts, computeAddressSalt, computeBootstrapMessage, computeISignerId, computeOeHash, computeShhhAddress, computeSnip12Hash, createStarknetSignInTypedData, decryptPrivateKey, ed25519OwnerId, ed25519OwnerPubkeyParam, ed25519PubkeyFelts, ed25519SignedBytes, eip191OwnerId, eip191OwnerPubkeyParam, eip191PubkeyFelts, encryptPrivateKey, estimateThresholdGasOverhead, executeShhhSponsoredRaw, executeShhhWithExternalSigner, executeShhhWithStarkKey, hashCall, hashCalls, hashOutsideExecutionStruct, hashStarknetDomain, isReadyToExecute, isShhhVerifierDeclared, isThinkDecision, isValidStarknetSignature, jwtAppleSubHash, jwtAppleSubOwnerId, jwtAppleSubPubkeyFelts, labelToFelt, locateSubClaim, messageHashToNonceB64url, migrateChipiWalletToShhh, normalizeEntrypoints, normalizeStarknetAddress, ownerCommitment, parseAppleIdToken, parseDerEcdsaSignature, parseEip191Signature, parseOpProposedEvents, parseStarknetWalletSignature, parseThresholdEnvelope, prepareExternalOwnerExecution, readPendingRecovery, readShhhOwners, readVerifierClass, resolveShhhChainId, resolveStarkSnip12Signer, secondsUntilExecutable, serializeExecuteFromOutsideV2Calldata, signBootstrapMessage, signTypedData, signTypedDataArray, snip12HashToHexAsciiBytes, starkOwnerId, starkPubkeyFelts, starkSnip12ApprovalHash, starkSnip12ApprovalTypedData, starkSnip12OwnerCommitment, starkSnip12PubkeyFelts, submitExternalOwnerExecution, submitViaAccount, validateSpendingPolicyConfig, verifyStarkSnip12Approval, verifyStarknetSignIn, verifyUndeployedStarknetSignature, waitForTransaction, webauthnOwnerId, webauthnOwnerPubkeyParam, webauthnPubkeyFelts, wrapV2Snip12Envelope, wrapV2ThresholdEnvelope, x402Middleware };
|
|
5398
6076
|
//# sourceMappingURL=index.mjs.map
|
|
5399
6077
|
//# sourceMappingURL=index.mjs.map
|