@chipi-stack/backend 14.15.0 → 14.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +163 -10
- package/dist/index.d.ts +163 -10
- package/dist/index.js +292 -29
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +283 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1953,9 +1953,9 @@ var ChipiTransactions = class {
|
|
|
1953
1953
|
/**
|
|
1954
1954
|
* Get on-chain transaction status
|
|
1955
1955
|
*/
|
|
1956
|
-
async getTransactionStatus(
|
|
1956
|
+
async getTransactionStatus(hash13, bearerToken) {
|
|
1957
1957
|
return this.client.get({
|
|
1958
|
-
endpoint: `${API_ENDPOINTS.TRANSACTIONS}/${
|
|
1958
|
+
endpoint: `${API_ENDPOINTS.TRANSACTIONS}/${hash13}/status`,
|
|
1959
1959
|
bearerToken
|
|
1960
1960
|
});
|
|
1961
1961
|
}
|
|
@@ -3310,9 +3310,13 @@ var ChipiAi = class {
|
|
|
3310
3310
|
* session key: a USDC `transfer` to the offer's `payTo`, then the same call
|
|
3311
3311
|
* again with `X-PAYMENT`. The price must be at most `maxAmount`, `model`
|
|
3312
3312
|
* must be payable and the input within `maxPromptBytes`, all checked before
|
|
3313
|
-
* paying. The
|
|
3314
|
-
*
|
|
3315
|
-
*
|
|
3313
|
+
* paying. The wallet must be a wallet of the organization that owns the
|
|
3314
|
+
* `sk_`: the first request names it in `X-PAYER`, and when the API answers
|
|
3315
|
+
* that a payment from it would be refused, nothing is paid
|
|
3316
|
+
* (`X402_PAYER_NOT_IN_ORG`). The session must whitelist `transfer` and cap
|
|
3317
|
+
* USDC. A payment that was made but not served is reported in
|
|
3318
|
+
* `error.details.xPayment`; pass it back as `options.xPayment` to retry
|
|
3319
|
+
* without paying again.
|
|
3316
3320
|
*
|
|
3317
3321
|
* @example
|
|
3318
3322
|
* ```typescript
|
|
@@ -3324,20 +3328,32 @@ var ChipiAi = class {
|
|
|
3324
3328
|
* ```
|
|
3325
3329
|
*/
|
|
3326
3330
|
async think(params, options = {}) {
|
|
3331
|
+
let payer;
|
|
3332
|
+
if (options.payWithSession && !options.xPayment) {
|
|
3333
|
+
try {
|
|
3334
|
+
payer = padFelt(options.payWithSession.wallet.publicKey);
|
|
3335
|
+
} catch {
|
|
3336
|
+
payer = void 0;
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3327
3339
|
try {
|
|
3328
|
-
return await this.postThink(params, options.xPayment);
|
|
3340
|
+
return await this.postThink(params, options.xPayment, payer);
|
|
3329
3341
|
} catch (err) {
|
|
3330
3342
|
const offer = options.payWithSession ? sessionTransferOffer(err) : void 0;
|
|
3331
3343
|
if (!offer || !options.payWithSession) throw err;
|
|
3332
3344
|
return this.payAndThink(params, offer, options.payWithSession);
|
|
3333
3345
|
}
|
|
3334
3346
|
}
|
|
3335
|
-
postThink(params, xPayment) {
|
|
3347
|
+
postThink(params, xPayment, payer) {
|
|
3348
|
+
const headers = {
|
|
3349
|
+
...xPayment ? { "X-PAYMENT": xPayment } : {},
|
|
3350
|
+
...payer ? { "X-PAYER": payer } : {}
|
|
3351
|
+
};
|
|
3336
3352
|
return this.client.post({
|
|
3337
3353
|
endpoint: `${AI_BASE}/think`,
|
|
3338
3354
|
bearerToken: this.secret(),
|
|
3339
3355
|
body: params,
|
|
3340
|
-
...
|
|
3356
|
+
...Object.keys(headers).length > 0 ? { headers } : {}
|
|
3341
3357
|
});
|
|
3342
3358
|
}
|
|
3343
3359
|
/**
|
|
@@ -3390,6 +3406,15 @@ var ChipiAi = class {
|
|
|
3390
3406
|
{ x402: { accepts: [offer] } }
|
|
3391
3407
|
);
|
|
3392
3408
|
}
|
|
3409
|
+
const payerCheck = offer.extra?.payer;
|
|
3410
|
+
if (payerCheck?.accepted === false && typeof payerCheck.address === "string" && sameFelt(payerCheck.address, pay.wallet.publicKey)) {
|
|
3411
|
+
throw new ChipiApiError(
|
|
3412
|
+
`Wallet ${pay.wallet.publicKey} is not a wallet of the organization that owns this API key, so the API would refuse its payment; nothing was paid. Pay from a wallet of this organization.`,
|
|
3413
|
+
"X402_PAYER_NOT_IN_ORG",
|
|
3414
|
+
402,
|
|
3415
|
+
{ x402: { accepts: [offer] } }
|
|
3416
|
+
);
|
|
3417
|
+
}
|
|
3393
3418
|
const payer = pay.wallet.publicKey;
|
|
3394
3419
|
const mask = (1n << 128n) - 1n;
|
|
3395
3420
|
const transactionHash = await this.sessions.executeTransactionWithSession(
|
|
@@ -3517,6 +3542,122 @@ var ChipiAi = class {
|
|
|
3517
3542
|
});
|
|
3518
3543
|
}
|
|
3519
3544
|
};
|
|
3545
|
+
var STARKNET_SIGNATURE_VALID = "0x56414c4944";
|
|
3546
|
+
function toFeltHex(value) {
|
|
3547
|
+
return num.toHex(BigInt(value));
|
|
3548
|
+
}
|
|
3549
|
+
function normalizeStarknetAddress(address) {
|
|
3550
|
+
return `0x${BigInt(address).toString(16).padStart(64, "0")}`;
|
|
3551
|
+
}
|
|
3552
|
+
function isContractNotFound(err) {
|
|
3553
|
+
const e = err;
|
|
3554
|
+
if (e?.baseError?.code === 20 || e?.code === 20) return true;
|
|
3555
|
+
return /contract not found/i.test(e?.message ?? String(err));
|
|
3556
|
+
}
|
|
3557
|
+
async function isValidStarknetSignature(provider, accountAddress, messageHash, signature) {
|
|
3558
|
+
try {
|
|
3559
|
+
const sig = signature.map(toFeltHex);
|
|
3560
|
+
const result = await provider.callContract({
|
|
3561
|
+
contractAddress: normalizeStarknetAddress(accountAddress),
|
|
3562
|
+
entrypoint: "is_valid_signature",
|
|
3563
|
+
calldata: [toFeltHex(messageHash), toFeltHex(sig.length), ...sig]
|
|
3564
|
+
});
|
|
3565
|
+
const first = result?.[0];
|
|
3566
|
+
if (first !== void 0 && BigInt(first) === BigInt(STARKNET_SIGNATURE_VALID)) {
|
|
3567
|
+
return { valid: true };
|
|
3568
|
+
}
|
|
3569
|
+
return { valid: false, reason: "INVALID_SIGNATURE" };
|
|
3570
|
+
} catch (err) {
|
|
3571
|
+
if (isContractNotFound(err)) return { valid: false, reason: "ACCOUNT_NOT_DEPLOYED" };
|
|
3572
|
+
return {
|
|
3573
|
+
valid: false,
|
|
3574
|
+
reason: "INVALID_SIGNATURE",
|
|
3575
|
+
detail: err instanceof Error ? err.message : String(err)
|
|
3576
|
+
};
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
var COUNTERFACTUAL_ACCOUNT_CLASSES = {
|
|
3580
|
+
/** OpenZeppelin AccountUpgradeable 3.0 (Bramble's default account). */
|
|
3581
|
+
OPENZEPPELIN_V3: "0x01d1777db36cdd06dd62cfde77b1b6ae06412af95d57a13dc40ac77b8a702381",
|
|
3582
|
+
/** Argent X / Ready 0.4 (`WALLET_CLASS_HASHES.READY`). */
|
|
3583
|
+
ARGENT_V0_4: "0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f"
|
|
3584
|
+
};
|
|
3585
|
+
function starkVerify(r, s, messageHash, publicKey) {
|
|
3586
|
+
const x = BigInt(publicKey).toString(16).padStart(64, "0");
|
|
3587
|
+
const sig = new ec.starkCurve.Signature(BigInt(r), BigInt(s));
|
|
3588
|
+
for (const prefix of ["02", "03"]) {
|
|
3589
|
+
try {
|
|
3590
|
+
if (ec.starkCurve.verify(sig, toFeltHex(messageHash), prefix + x)) return true;
|
|
3591
|
+
} catch {
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
return false;
|
|
3595
|
+
}
|
|
3596
|
+
function verifyUndeployedStarknetSignature(deployment, messageHash, signature) {
|
|
3597
|
+
const classHash = normalizeStarknetAddress(deployment.class_hash);
|
|
3598
|
+
const calldata = deployment.calldata.map(toFeltHex);
|
|
3599
|
+
const sig = signature.map(toFeltHex);
|
|
3600
|
+
let publicKey;
|
|
3601
|
+
let r;
|
|
3602
|
+
let s;
|
|
3603
|
+
if (classHash === COUNTERFACTUAL_ACCOUNT_CLASSES.OPENZEPPELIN_V3) {
|
|
3604
|
+
if (calldata.length !== 1 || sig.length !== 2) {
|
|
3605
|
+
return { valid: false, reason: "INVALID_SIGNATURE" };
|
|
3606
|
+
}
|
|
3607
|
+
[publicKey] = calldata;
|
|
3608
|
+
[r, s] = sig;
|
|
3609
|
+
} else if (classHash === COUNTERFACTUAL_ACCOUNT_CLASSES.ARGENT_V0_4) {
|
|
3610
|
+
if (calldata.length !== 3 || BigInt(calldata[0]) !== 0n || BigInt(calldata[2]) !== 1n) {
|
|
3611
|
+
return { valid: false, reason: "UNSUPPORTED_ACCOUNT_CLASS" };
|
|
3612
|
+
}
|
|
3613
|
+
if (sig.length !== 5 || BigInt(sig[0]) !== 1n || BigInt(sig[1]) !== 0n) {
|
|
3614
|
+
return { valid: false, reason: "INVALID_SIGNATURE" };
|
|
3615
|
+
}
|
|
3616
|
+
if (BigInt(sig[2]) !== BigInt(calldata[1])) {
|
|
3617
|
+
return { valid: false, reason: "INVALID_SIGNATURE" };
|
|
3618
|
+
}
|
|
3619
|
+
publicKey = calldata[1];
|
|
3620
|
+
[, , , r, s] = sig;
|
|
3621
|
+
} else {
|
|
3622
|
+
return { valid: false, reason: "UNSUPPORTED_ACCOUNT_CLASS" };
|
|
3623
|
+
}
|
|
3624
|
+
const expected = hash.calculateContractAddressFromHash(
|
|
3625
|
+
toFeltHex(deployment.salt),
|
|
3626
|
+
classHash,
|
|
3627
|
+
calldata,
|
|
3628
|
+
0
|
|
3629
|
+
);
|
|
3630
|
+
if (normalizeStarknetAddress(expected) !== normalizeStarknetAddress(deployment.address)) {
|
|
3631
|
+
return { valid: false, reason: "ADDRESS_MISMATCH" };
|
|
3632
|
+
}
|
|
3633
|
+
return starkVerify(r, s, messageHash, publicKey) ? { valid: true } : { valid: false, reason: "INVALID_SIGNATURE" };
|
|
3634
|
+
}
|
|
3635
|
+
|
|
3636
|
+
// src/x402/facilitator.ts
|
|
3637
|
+
var TRANSFER_SELECTOR2 = BigInt(hash.getSelectorFromName("transfer"));
|
|
3638
|
+
function shhhTransferMatches(oeCalldata, payload) {
|
|
3639
|
+
try {
|
|
3640
|
+
const felts = oeCalldata.map((v) => BigInt(v));
|
|
3641
|
+
const [, , , executeBefore, callsLen] = felts;
|
|
3642
|
+
if (callsLen !== 1n) return { ok: false, reason: "SHHH payment must be exactly one transfer" };
|
|
3643
|
+
const [to, selector, len, recipient, low, high] = felts.slice(5, 11);
|
|
3644
|
+
if (to !== BigInt(payload.asset) || selector !== TRANSFER_SELECTOR2 || len !== 3n) {
|
|
3645
|
+
return { ok: false, reason: "SHHH payment call is not a transfer of the payment asset" };
|
|
3646
|
+
}
|
|
3647
|
+
if (recipient !== BigInt(payload.toAddress)) {
|
|
3648
|
+
return { ok: false, reason: "SHHH payment pays a different recipient" };
|
|
3649
|
+
}
|
|
3650
|
+
if (low + (high << 128n) !== BigInt(payload.amount)) {
|
|
3651
|
+
return { ok: false, reason: "SHHH payment amount differs from the declared amount" };
|
|
3652
|
+
}
|
|
3653
|
+
if (executeBefore <= BigInt(Math.floor(Date.now() / 1e3))) {
|
|
3654
|
+
return { ok: false, reason: "SHHH payment has expired (execute_before in the past)" };
|
|
3655
|
+
}
|
|
3656
|
+
return { ok: true };
|
|
3657
|
+
} catch {
|
|
3658
|
+
return { ok: false, reason: "Malformed SHHH oeCalldata" };
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3520
3661
|
var InMemoryNonceStore = class {
|
|
3521
3662
|
constructor() {
|
|
3522
3663
|
this.used = /* @__PURE__ */ new Set();
|
|
@@ -3559,11 +3700,18 @@ var X402Facilitator = class _X402Facilitator {
|
|
|
3559
3700
|
* Verify a payment signature is valid (doesn't execute the transfer).
|
|
3560
3701
|
*
|
|
3561
3702
|
* Checks:
|
|
3562
|
-
* 1.
|
|
3563
|
-
* 2.
|
|
3564
|
-
* 3.
|
|
3565
|
-
* 4.
|
|
3566
|
-
* 5.
|
|
3703
|
+
* 1. x402 version is 1
|
|
3704
|
+
* 2. Network is starknet-mainnet
|
|
3705
|
+
* 3. Nonce has not been used (replay protection)
|
|
3706
|
+
* 4. Payment has not expired (validUntil > now)
|
|
3707
|
+
* 5. Asset is USDC mainnet
|
|
3708
|
+
* 6. Amount is positive
|
|
3709
|
+
* 7. Addresses are non-empty
|
|
3710
|
+
* 8. Signature: with a `provider`, the payer account's `is_valid_signature`
|
|
3711
|
+
* must return 'VALID'. Without one, only its presence is checked (not a
|
|
3712
|
+
* cryptographic check). SHHH payloads must sign exactly one transfer
|
|
3713
|
+
* of `amount` of `asset` to `toAddress`; their signature is checked
|
|
3714
|
+
* on-chain at settle.
|
|
3567
3715
|
*/
|
|
3568
3716
|
async verify(payment) {
|
|
3569
3717
|
const { payload } = payment;
|
|
@@ -3619,6 +3767,8 @@ var X402Facilitator = class _X402Facilitator {
|
|
|
3619
3767
|
if (!Array.isArray(oeCalldata) || oeCalldata.length === 0) {
|
|
3620
3768
|
return { valid: false, reason: "Missing SHHH oeCalldata" };
|
|
3621
3769
|
}
|
|
3770
|
+
const bound = shhhTransferMatches(oeCalldata, payment.payload);
|
|
3771
|
+
if (!bound.ok) return { valid: false, reason: bound.reason };
|
|
3622
3772
|
return { valid: true };
|
|
3623
3773
|
}
|
|
3624
3774
|
if (!this.provider) {
|
|
@@ -3639,22 +3789,25 @@ var X402Facilitator = class _X402Facilitator {
|
|
|
3639
3789
|
valid_until: String(payload.validUntil),
|
|
3640
3790
|
nonce: payload.nonce
|
|
3641
3791
|
});
|
|
3642
|
-
|
|
3792
|
+
let msgHash;
|
|
3643
3793
|
try {
|
|
3644
|
-
|
|
3645
|
-
contractAddress: payload.fromAddress,
|
|
3646
|
-
entrypoint: "is_valid_signature",
|
|
3647
|
-
calldata: [msgHash, "2", payload.signature.r, payload.signature.s]
|
|
3648
|
-
});
|
|
3649
|
-
const VALID = "0x56414c4944";
|
|
3650
|
-
if (result[0] === VALID || result[0] === BigInt(VALID).toString()) {
|
|
3651
|
-
return { valid: true };
|
|
3652
|
-
}
|
|
3653
|
-
return { valid: false, reason: "Invalid SNIP-12 signature" };
|
|
3794
|
+
msgHash = typedData.getMessageHash(paymentTypedData, payload.fromAddress);
|
|
3654
3795
|
} catch (err) {
|
|
3655
3796
|
const message = err instanceof Error ? err.message : String(err);
|
|
3656
|
-
return { valid: false, reason: `
|
|
3797
|
+
return { valid: false, reason: `Malformed payment: ${message}` };
|
|
3657
3798
|
}
|
|
3799
|
+
const check = await isValidStarknetSignature(this.provider, payload.fromAddress, msgHash, [
|
|
3800
|
+
payload.signature.r,
|
|
3801
|
+
payload.signature.s
|
|
3802
|
+
]);
|
|
3803
|
+
if (check.valid) return { valid: true };
|
|
3804
|
+
if (check.reason === "ACCOUNT_NOT_DEPLOYED") {
|
|
3805
|
+
return { valid: false, reason: "Payer account is not deployed" };
|
|
3806
|
+
}
|
|
3807
|
+
return {
|
|
3808
|
+
valid: false,
|
|
3809
|
+
reason: check.detail ? `Signature verification failed: ${check.detail}` : "Invalid SNIP-12 signature"
|
|
3810
|
+
};
|
|
3658
3811
|
}
|
|
3659
3812
|
/**
|
|
3660
3813
|
* Settle a verified payment by executing the USDC transfer via paymaster.
|
|
@@ -3783,7 +3936,7 @@ var signTypedData = async ({
|
|
|
3783
3936
|
throw error;
|
|
3784
3937
|
}
|
|
3785
3938
|
};
|
|
3786
|
-
function
|
|
3939
|
+
function toFeltHex2(x) {
|
|
3787
3940
|
return "0x" + x.toString(16).padStart(64, "0");
|
|
3788
3941
|
}
|
|
3789
3942
|
var signTypedDataArray = async ({
|
|
@@ -3813,7 +3966,7 @@ var signTypedDataArray = async ({
|
|
|
3813
3966
|
messageHash,
|
|
3814
3967
|
ownerIndex: 0n
|
|
3815
3968
|
});
|
|
3816
|
-
return envelope.map(
|
|
3969
|
+
return envelope.map(toFeltHex2);
|
|
3817
3970
|
}
|
|
3818
3971
|
const provider = new RpcProvider({ nodeUrl: WALLET_RPC_ENDPOINTS[walletType] });
|
|
3819
3972
|
const account = new Account({ provider, address: wallet.publicKey, signer: privateKeyDecrypted });
|
|
@@ -4098,8 +4251,8 @@ var ChipiSDK = class {
|
|
|
4098
4251
|
/**
|
|
4099
4252
|
* Get on-chain transaction status (supports polling for confirmation)
|
|
4100
4253
|
*/
|
|
4101
|
-
async getTransactionStatus(
|
|
4102
|
-
return this.transactions.getTransactionStatus(
|
|
4254
|
+
async getTransactionStatus(hash13, bearerToken) {
|
|
4255
|
+
return this.transactions.getTransactionStatus(hash13, this.resolveBearerToken(bearerToken));
|
|
4103
4256
|
}
|
|
4104
4257
|
/**
|
|
4105
4258
|
* Prepare a wallet upgrade (e.g., READY → CHIPI or CHIPI v29 → v33).
|
|
@@ -4471,6 +4624,106 @@ function x402Middleware(config) {
|
|
|
4471
4624
|
next();
|
|
4472
4625
|
};
|
|
4473
4626
|
}
|
|
4627
|
+
var SIWS_DOMAIN_NAME = "Sign in with Starknet";
|
|
4628
|
+
var SIWS_DOMAIN_VERSION = "1";
|
|
4629
|
+
var SIWS_CHAIN_ID = "SN_MAIN";
|
|
4630
|
+
var DEFAULT_STATEMENT = "Sign in. This request costs nothing and moves no funds.";
|
|
4631
|
+
function assertPrintableAscii(field, value) {
|
|
4632
|
+
if (!/^[\x20-\x7e]*$/.test(value)) {
|
|
4633
|
+
throw new Error(`SIWS ${field} must be single-line printable ASCII`);
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
function createStarknetSignInTypedData(params) {
|
|
4637
|
+
const message = {
|
|
4638
|
+
domain: params.domain,
|
|
4639
|
+
address: normalizeStarknetAddress(params.address),
|
|
4640
|
+
statement: params.statement ?? DEFAULT_STATEMENT,
|
|
4641
|
+
uri: params.uri,
|
|
4642
|
+
nonce: params.nonce,
|
|
4643
|
+
issuedAt: params.issuedAt ?? Math.floor(Date.now() / 1e3),
|
|
4644
|
+
expirationTime: params.expirationTime
|
|
4645
|
+
};
|
|
4646
|
+
for (const field of ["domain", "statement", "uri", "nonce"]) {
|
|
4647
|
+
assertPrintableAscii(field, message[field]);
|
|
4648
|
+
}
|
|
4649
|
+
if (!/^[A-Za-z0-9]{8,}$/.test(message.nonce)) {
|
|
4650
|
+
throw new Error("SIWS nonce must be at least 8 letters or digits");
|
|
4651
|
+
}
|
|
4652
|
+
if (!Number.isInteger(message.issuedAt) || !Number.isInteger(message.expirationTime)) {
|
|
4653
|
+
throw new Error("SIWS times must be whole unix seconds");
|
|
4654
|
+
}
|
|
4655
|
+
if (message.expirationTime <= message.issuedAt) {
|
|
4656
|
+
throw new Error("SIWS expirationTime must be after issuedAt");
|
|
4657
|
+
}
|
|
4658
|
+
return {
|
|
4659
|
+
types: {
|
|
4660
|
+
StarknetDomain: [
|
|
4661
|
+
{ name: "name", type: "shortstring" },
|
|
4662
|
+
{ name: "version", type: "shortstring" },
|
|
4663
|
+
{ name: "chainId", type: "shortstring" },
|
|
4664
|
+
{ name: "revision", type: "shortstring" }
|
|
4665
|
+
],
|
|
4666
|
+
SignIn: [
|
|
4667
|
+
{ name: "domain", type: "string" },
|
|
4668
|
+
{ name: "address", type: "ContractAddress" },
|
|
4669
|
+
{ name: "statement", type: "string" },
|
|
4670
|
+
{ name: "uri", type: "string" },
|
|
4671
|
+
{ name: "nonce", type: "string" },
|
|
4672
|
+
{ name: "issuedAt", type: "timestamp" },
|
|
4673
|
+
{ name: "expirationTime", type: "timestamp" }
|
|
4674
|
+
]
|
|
4675
|
+
},
|
|
4676
|
+
primaryType: "SignIn",
|
|
4677
|
+
domain: {
|
|
4678
|
+
name: SIWS_DOMAIN_NAME,
|
|
4679
|
+
version: SIWS_DOMAIN_VERSION,
|
|
4680
|
+
chainId: SIWS_CHAIN_ID,
|
|
4681
|
+
revision: "1"
|
|
4682
|
+
},
|
|
4683
|
+
message: { ...message }
|
|
4684
|
+
};
|
|
4685
|
+
}
|
|
4686
|
+
var MAX_SKEW_SECONDS = 60;
|
|
4687
|
+
async function verifyStarknetSignIn(params) {
|
|
4688
|
+
const { typedData: typedData2, signature, provider, expected, deploymentData } = params;
|
|
4689
|
+
const raw = typedData2?.message;
|
|
4690
|
+
if (!raw || !Array.isArray(signature) || signature.length === 0) {
|
|
4691
|
+
return { ok: false, reason: "MALFORMED" };
|
|
4692
|
+
}
|
|
4693
|
+
if (typedData2.domain?.chainId !== SIWS_CHAIN_ID) return { ok: false, reason: "WRONG_CHAIN" };
|
|
4694
|
+
let canonical;
|
|
4695
|
+
let message;
|
|
4696
|
+
try {
|
|
4697
|
+
canonical = createStarknetSignInTypedData({
|
|
4698
|
+
domain: String(raw.domain),
|
|
4699
|
+
uri: String(raw.uri),
|
|
4700
|
+
address: String(raw.address),
|
|
4701
|
+
nonce: String(raw.nonce),
|
|
4702
|
+
statement: String(raw.statement),
|
|
4703
|
+
issuedAt: Number(raw.issuedAt),
|
|
4704
|
+
expirationTime: Number(raw.expirationTime)
|
|
4705
|
+
});
|
|
4706
|
+
message = canonical.message;
|
|
4707
|
+
} catch {
|
|
4708
|
+
return { ok: false, reason: "MALFORMED" };
|
|
4709
|
+
}
|
|
4710
|
+
if (message.domain !== expected.domain) return { ok: false, reason: "WRONG_DOMAIN" };
|
|
4711
|
+
if (message.uri !== expected.uri) return { ok: false, reason: "WRONG_URI" };
|
|
4712
|
+
if (message.nonce !== expected.nonce) return { ok: false, reason: "WRONG_NONCE" };
|
|
4713
|
+
const now = expected.now ?? Math.floor(Date.now() / 1e3);
|
|
4714
|
+
if (now >= message.expirationTime) return { ok: false, reason: "EXPIRED" };
|
|
4715
|
+
if (message.issuedAt > now + MAX_SKEW_SECONDS) return { ok: false, reason: "NOT_YET_VALID" };
|
|
4716
|
+
const messageHash = typedData.getMessageHash(canonical, message.address);
|
|
4717
|
+
const onChain = await isValidStarknetSignature(provider, message.address, messageHash, signature);
|
|
4718
|
+
if (onChain.valid) return { ok: true, address: message.address, message };
|
|
4719
|
+
if (onChain.reason !== "ACCOUNT_NOT_DEPLOYED") return { ok: false, reason: "INVALID_SIGNATURE" };
|
|
4720
|
+
if (!deploymentData) return { ok: false, reason: "ACCOUNT_NOT_DEPLOYED" };
|
|
4721
|
+
if (normalizeStarknetAddress(deploymentData.address) !== message.address) {
|
|
4722
|
+
return { ok: false, reason: "ADDRESS_MISMATCH" };
|
|
4723
|
+
}
|
|
4724
|
+
const offChain = verifyUndeployedStarknetSignature(deploymentData, messageHash, signature);
|
|
4725
|
+
return offChain.valid ? { ok: true, address: message.address, message } : { ok: false, reason: offChain.reason };
|
|
4726
|
+
}
|
|
4474
4727
|
|
|
4475
4728
|
// src/shhh/index.ts
|
|
4476
4729
|
init_snip12_hash();
|
|
@@ -5369,6 +5622,6 @@ function submitViaAccount(funded) {
|
|
|
5369
5622
|
};
|
|
5370
5623
|
}
|
|
5371
5624
|
|
|
5372
|
-
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 };
|
|
5625
|
+
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_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, 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, createStarknetSignInTypedData, decryptPrivateKey, ed25519OwnerId, ed25519OwnerPubkeyParam, ed25519PubkeyFelts, ed25519SignedBytes, eip191OwnerId, eip191OwnerPubkeyParam, eip191PubkeyFelts, encryptPrivateKey, estimateThresholdGasOverhead, executeShhhSponsoredRaw, hashCall, hashCalls, hashOutsideExecutionStruct, hashStarknetDomain, isReadyToExecute, isThinkDecision, isValidStarknetSignature, jwtAppleSubHash, jwtAppleSubOwnerId, jwtAppleSubPubkeyFelts, labelToFelt, locateSubClaim, messageHashToNonceB64url, migrateChipiWalletToShhh, normalizeEntrypoints, normalizeStarknetAddress, ownerCommitment, parseAppleIdToken, parseDerEcdsaSignature, parseEip191Signature, parseThresholdEnvelope, resolveShhhChainId, secondsUntilExecutable, serializeExecuteFromOutsideV2Calldata, signBootstrapMessage, signTypedData, signTypedDataArray, snip12HashToHexAsciiBytes, starkOwnerId, starkPubkeyFelts, submitViaAccount, validateSpendingPolicyConfig, verifyStarknetSignIn, verifyUndeployedStarknetSignature, waitForTransaction, webauthnOwnerId, webauthnOwnerPubkeyParam, webauthnPubkeyFelts, wrapV2Snip12Envelope, wrapV2ThresholdEnvelope, x402Middleware };
|
|
5373
5626
|
//# sourceMappingURL=index.mjs.map
|
|
5374
5627
|
//# sourceMappingURL=index.mjs.map
|