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