@chipi-stack/backend 14.7.0 → 14.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -387,6 +387,9 @@ function ed25519PubkeyFelts(publicKey) {
387
387
  const { low, high } = bytesToLeU256(publicKey);
388
388
  return [low, high];
389
389
  }
390
+ function ed25519OwnerPubkeyParam(publicKey) {
391
+ return ed25519PubkeyFelts(publicKey).map((f) => "0x" + f.toString(16)).join(",");
392
+ }
390
393
  async function buildEd25519Envelope(params) {
391
394
  const ownerIndex = params.ownerIndex ?? 0n;
392
395
  if (ownerIndex < 0n || ownerIndex >= 0x100000000n) {
@@ -497,6 +500,14 @@ var init_encryption2 = __esm({
497
500
  init_encryption();
498
501
  }
499
502
  });
503
+
504
+ // src/shhh/signers/stark.ts
505
+ var stark_exports = {};
506
+ __export(stark_exports, {
507
+ buildStarkEnvelope: () => buildStarkEnvelope,
508
+ starkOwnerId: () => starkOwnerId,
509
+ starkPubkeyFelts: () => starkPubkeyFelts
510
+ });
500
511
  function buildStarkEnvelope(params) {
501
512
  const pkHex = "0x" + (typeof params.privateKey === "bigint" ? params.privateKey : BigInt(params.privateKey)).toString(16).padStart(64, "0");
502
513
  const sig = ec.starkCurve.sign("0x" + params.messageHash.toString(16), pkHex);
@@ -947,7 +958,15 @@ var executePaymasterTransaction = async ({
947
958
  usePasskey ? "encryptKey is required when using passkey. The passkey authentication should have provided the encryptKey." : "encryptKey is required for transaction execution"
948
959
  );
949
960
  }
950
- const walletType = wallet.walletType ?? "READY";
961
+ let walletType = wallet.walletType ?? "READY";
962
+ if (!wallet.walletType) {
963
+ try {
964
+ const resolveProvider = new RpcProvider({ nodeUrl: WALLET_RPC_ENDPOINTS.CHIPI });
965
+ const onChainClassHash = await resolveProvider.getClassHashAt(wallet.publicKey, "latest");
966
+ walletType = getWalletTypeFromClassHash(onChainClassHash) ?? "READY";
967
+ } catch {
968
+ }
969
+ }
951
970
  if (walletType === "SHHH") {
952
971
  const { executeShhhSponsoredRaw: executeShhhSponsoredRaw2 } = await Promise.resolve().then(() => (init_execute_paymaster_raw(), execute_paymaster_raw_exports));
953
972
  const shhhSignerKind = (wallet.signerKind ?? "STARK") || "STARK";
@@ -2821,6 +2840,79 @@ var ChipiSessions = class {
2821
2840
  }
2822
2841
  }
2823
2842
  };
2843
+ var ChipiTreasury = class {
2844
+ constructor(client, apiSecretKey) {
2845
+ this.client = client;
2846
+ this.apiSecretKey = apiSecretKey;
2847
+ }
2848
+ base(treasuryId) {
2849
+ return `${API_ENDPOINTS.TREASURIES}/${treasuryId}/transactions`;
2850
+ }
2851
+ /** Resolve a `sk_` for the secret-gated reads/execute, or fail loudly. */
2852
+ secret(bearerToken) {
2853
+ const token = bearerToken ?? this.apiSecretKey;
2854
+ if (!token) {
2855
+ throw new Error(
2856
+ "A secret key (sk_) is required for treasury execute / list / allowance. Pass `bearerToken` to forTreasury(...) or configure the SDK with apiSecretKey. Call these from a server, never the browser."
2857
+ );
2858
+ }
2859
+ return token;
2860
+ }
2861
+ /**
2862
+ * Build a {@link TreasuryTransport} for one treasury + owner. Wire the
2863
+ * returned object directly into chipi-react's `useProposeAction` /
2864
+ * `useTreasuryProposals` `transport` prop, or call its methods yourself.
2865
+ */
2866
+ forTreasury(config) {
2867
+ const { treasuryId, ownerPubkey } = config;
2868
+ const base = this.base(treasuryId);
2869
+ return {
2870
+ // sk_ — read the proposal list. chipi-back returns
2871
+ // { items, total, page, limit, hasMore }; the hook only reads `items`.
2872
+ list: async () => {
2873
+ const res = await this.client.get({
2874
+ endpoint: base,
2875
+ bearerToken: this.secret(config.bearerToken)
2876
+ });
2877
+ return { ...res, items: res.items ?? [] };
2878
+ },
2879
+ // pk_ + owner sig — no secret. `ownerPubkey` lets the backend verify the
2880
+ // proposer envelope. `meta` (if present) is stripped server-side.
2881
+ propose: async (body) => {
2882
+ return this.client.post({
2883
+ endpoint: base,
2884
+ // Empty string → no Authorization header; the pk_ travels in
2885
+ // x-api-key, which ApiKeyGuard accepts for propose.
2886
+ bearerToken: "",
2887
+ body: { ...body, ownerPubkey }
2888
+ });
2889
+ },
2890
+ // pk_ + owner sig — approve an existing proposal.
2891
+ sign: async (proposalId, body) => {
2892
+ return this.client.post({
2893
+ endpoint: `${base}/${proposalId}/sign`,
2894
+ bearerToken: "",
2895
+ body: { ...body, ownerPubkey }
2896
+ });
2897
+ },
2898
+ // sk_ — relay the assembled threshold calldata through the paymaster.
2899
+ execute: async (proposalId, calldata) => {
2900
+ return this.client.post({
2901
+ endpoint: `${base}/${proposalId}/execute`,
2902
+ bearerToken: this.secret(config.bearerToken),
2903
+ body: { calldata }
2904
+ });
2905
+ },
2906
+ // sk_ — the free-execute meter (org-scoped).
2907
+ getMultisigAllowance: async () => {
2908
+ return this.client.get({
2909
+ endpoint: `${API_ENDPOINTS.TREASURIES}/${treasuryId}/multisig-allowance`,
2910
+ bearerToken: this.secret(config.bearerToken)
2911
+ });
2912
+ }
2913
+ };
2914
+ }
2915
+ };
2824
2916
  var InMemoryNonceStore = class {
2825
2917
  constructor() {
2826
2918
  this.used = /* @__PURE__ */ new Set();
@@ -3087,6 +3179,43 @@ var signTypedData = async ({
3087
3179
  throw error;
3088
3180
  }
3089
3181
  };
3182
+ function toFeltHex(x) {
3183
+ return "0x" + x.toString(16).padStart(64, "0");
3184
+ }
3185
+ var signTypedDataArray = async ({
3186
+ params
3187
+ }) => {
3188
+ const { encryptKey, wallet, typedData: typedData2 } = params;
3189
+ if (!encryptKey) throw new Error("encryptKey is required for signing typed data");
3190
+ if (!wallet || !wallet.encryptedPrivateKey || !wallet.publicKey) {
3191
+ throw new Error("wallet with publicKey and encryptedPrivateKey is required");
3192
+ }
3193
+ if (!typedData2) throw new Error("typedData is required for signing");
3194
+ const walletType = wallet.walletType ?? "READY";
3195
+ if (!Object.prototype.hasOwnProperty.call(WALLET_RPC_ENDPOINTS, walletType)) {
3196
+ throw new Error(`Unsupported wallet type: "${String(walletType)}"`);
3197
+ }
3198
+ let privateKeyDecrypted;
3199
+ try {
3200
+ privateKeyDecrypted = decryptPrivateKey(wallet.encryptedPrivateKey, encryptKey);
3201
+ } catch {
3202
+ throw new Error("Failed to decrypt private key. Verify the encryptKey is correct.");
3203
+ }
3204
+ const messageHash = BigInt(typedData.getMessageHash(typedData2, wallet.publicKey));
3205
+ if (walletType === "SHHH") {
3206
+ const { buildStarkEnvelope: buildStarkEnvelope2 } = await Promise.resolve().then(() => (init_stark(), stark_exports));
3207
+ const envelope = buildStarkEnvelope2({
3208
+ privateKey: privateKeyDecrypted,
3209
+ messageHash,
3210
+ ownerIndex: 0n
3211
+ });
3212
+ return envelope.map(toFeltHex);
3213
+ }
3214
+ const provider = new RpcProvider({ nodeUrl: WALLET_RPC_ENDPOINTS[walletType] });
3215
+ const account = new Account({ provider, address: wallet.publicKey, signer: privateKeyDecrypted });
3216
+ const { r, s } = normalizeSignature(await account.signMessage(typedData2));
3217
+ return [r, s];
3218
+ };
3090
3219
 
3091
3220
  // src/chipi-sdk.ts
3092
3221
  var ChipiSDK = class {
@@ -3100,6 +3229,7 @@ var ChipiSDK = class {
3100
3229
  this.skus = new ChipiSkus(this.client);
3101
3230
  this.sessions = new ChipiSessions(this.client);
3102
3231
  this.exchanges = new ChipiExchanges(this.client);
3232
+ this.treasury = new ChipiTreasury(this.client, config.apiSecretKey);
3103
3233
  this.executeTransaction = this.executeTransaction.bind(this);
3104
3234
  this.executeTransactionWithSession = this.executeTransactionWithSession.bind(this);
3105
3235
  this.transfer = this.transfer.bind(this);
@@ -3110,6 +3240,7 @@ var ChipiSDK = class {
3110
3240
  this.purchaseSku = this.purchaseSku.bind(this);
3111
3241
  this.getUsdAmount = this.getUsdAmount.bind(this);
3112
3242
  this.signTypedData = this.signTypedData.bind(this);
3243
+ this.signTypedDataArray = this.signTypedDataArray.bind(this);
3113
3244
  this.createPaymasterAdapter = this.createPaymasterAdapter.bind(this);
3114
3245
  this.createX402Facilitator = this.createX402Facilitator.bind(this);
3115
3246
  }
@@ -3238,6 +3369,14 @@ var ChipiSDK = class {
3238
3369
  async signTypedData({ params }) {
3239
3370
  return signTypedData({ params });
3240
3371
  }
3372
+ /**
3373
+ * Sign SNIP-12 typed data and return the full signature span (felt strings) —
3374
+ * the shape a dApp's `wallet_signTypedData` expects. Wallet-type aware:
3375
+ * SHHH returns the V2_SNIP12 owner envelope; standard accounts return [r, s].
3376
+ */
3377
+ async signTypedDataArray({ params }) {
3378
+ return signTypedDataArray({ params });
3379
+ }
3241
3380
  /**
3242
3381
  * Transfer tokens
3243
3382
  */
@@ -3760,6 +3899,12 @@ function eip191PubkeyFelts(pubkey) {
3760
3899
  function eip191OwnerId(pubkey) {
3761
3900
  return ownerCommitment(EIP191_KIND_TAG_FELT, eip191PubkeyFelts(pubkey));
3762
3901
  }
3902
+ function eip191OwnerPubkeyParam(pubkey) {
3903
+ assertBytes("secp256k1 x coordinate", pubkey.x, 32);
3904
+ assertBytes("secp256k1 y coordinate", pubkey.y, 32);
3905
+ const toHex = (b) => "0x" + Array.from(b, (v) => v.toString(16).padStart(2, "0")).join("");
3906
+ return `${toHex(pubkey.x)},${toHex(pubkey.y)}`;
3907
+ }
3763
3908
  function parseEip191Signature(signatureHex) {
3764
3909
  const hex = signatureHex.startsWith("0x") ? signatureHex.slice(2) : signatureHex;
3765
3910
  if (hex.length !== 130) {
@@ -3982,6 +4127,12 @@ function webauthnPubkeyFelts(pub) {
3982
4127
  function webauthnOwnerId(pub) {
3983
4128
  return ownerCommitment(WEBAUTHN_KIND_TAG_FELT, webauthnPubkeyFelts(pub));
3984
4129
  }
4130
+ function webauthnOwnerPubkeyParam(pub) {
4131
+ assertBytes2("P-256 x coordinate", pub.x, 32);
4132
+ assertBytes2("P-256 y coordinate", pub.y, 32);
4133
+ const toHex = (b) => "0x" + Array.from(b, (v) => v.toString(16).padStart(2, "0")).join("");
4134
+ return `${toHex(pub.x)},${toHex(pub.y)}`;
4135
+ }
3985
4136
  function buildWebAuthnEnvelopeFromAssertion(params) {
3986
4137
  const ownerIndex = params.ownerIndex ?? 0n;
3987
4138
  if (ownerIndex < 0n || ownerIndex >= 0x100000000n) {
@@ -4537,6 +4688,82 @@ function secondsUntilExecutable(validAfterSecs, nowSecs) {
4537
4688
  init_threshold();
4538
4689
  init_execute_paymaster_raw();
4539
4690
 
4540
- export { ANY_CALLER_FELT, APPLE_ISSUER, BOOTSTRAP_DOMAIN_SEPARATOR, ChipiBrowserSDK, ChipiClient, ChipiPaymasterAdapter, ChipiSDK, ChipiServerSDK, ChipiSessions, ChipiSkuPurchases, ChipiSkus, ChipiTransactions, 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, TIMELOCK_SECONDS, VIEW_SELECTORS, X402Facilitator, X402ShhhClient, assertValidV2Snip12Envelope, buildBootstrapSignedCall, buildCancelPendingOpCall, buildCancelRecoveryCall, buildEd25519Envelope, buildEd25519EnvelopeFromSignature, buildEip191EnvelopeFromPrivateKey, buildEip191EnvelopeFromSignature, buildExecuteAddOwnerCall, buildExecuteRemoveOwnerCall, buildExecuteRotateOwnerCall, buildExecuteSetThresholdCall, buildFinalizeRecoveryCall, buildInitiateRecoveryCall, buildJwtAppleSubEnvelopeFromTestKey, buildJwtAppleSubEnvelopeFromTokenResponse, buildMigrationCalls, buildOutsideExecution, buildProposeAddOwnerCall, buildProposeRemoveOwnerCall, buildProposeRotateOwnerCall, buildProposeSetThresholdCall, buildStarkEnvelope, buildThresholdEnvelope, buildWebAuthnEnvelopeFromAssertion, buildWebAuthnEnvelopeFromPrivateKey, byteArrayToFelts, computeAddressSalt, computeBootstrapMessage, computeISignerId, computeOeHash, computeShhhAddress, computeSnip12Hash, decryptPrivateKey, ed25519OwnerId, ed25519PubkeyFelts, ed25519SignedBytes, eip191OwnerId, eip191PubkeyFelts, encryptPrivateKey, estimateThresholdGasOverhead, executeShhhSponsoredRaw, hashCall, hashCalls, hashOutsideExecutionStruct, hashStarknetDomain, isReadyToExecute, jwtAppleSubHash, jwtAppleSubOwnerId, jwtAppleSubPubkeyFelts, labelToFelt, locateSubClaim, messageHashToNonceB64url, migrateChipiWalletToShhh, ownerCommitment, parseAppleIdToken, parseDerEcdsaSignature, parseEip191Signature, parseThresholdEnvelope, resolveShhhChainId, secondsUntilExecutable, serializeExecuteFromOutsideV2Calldata, signBootstrapMessage, signTypedData, snip12HashToHexAsciiBytes, starkOwnerId, starkPubkeyFelts, webauthnOwnerId, webauthnPubkeyFelts, wrapV2Snip12Envelope, wrapV2ThresholdEnvelope, x402Middleware };
4691
+ // src/shhh/account.ts
4692
+ init_oe();
4693
+ init_stark();
4694
+ init_execute_paymaster_raw();
4695
+ function generateNonce2() {
4696
+ return BigInt(Date.now()) << 24n | BigInt(Math.floor(Math.random() * 16777216));
4697
+ }
4698
+ var ShhhAccount = class {
4699
+ constructor(provider, address, privateKey, options = {}) {
4700
+ this.provider = provider;
4701
+ this.address = address;
4702
+ this.privateKey = privateKey;
4703
+ this.ownerIndex = options.ownerIndex ?? 0n;
4704
+ this.chainId = options.chainId ?? resolveShhhChainId({});
4705
+ this.submitFn = options.submit;
4706
+ }
4707
+ /**
4708
+ * Build + sign an OutsideExecution for `calls` and return the
4709
+ * serialized `execute_from_outside_v2` calldata (plus the underlying
4710
+ * pieces). Use this when you want to broadcast the calldata yourself.
4711
+ */
4712
+ async signExecution(calls, options = {}) {
4713
+ if (options.validForSeconds !== void 0) {
4714
+ const maxValid = MAX_OE_VALIDITY_WINDOW_SECONDS - OE_EXECUTE_AFTER_CLOCK_SKEW_BUFFER;
4715
+ if (!Number.isFinite(options.validForSeconds) || options.validForSeconds <= 0) {
4716
+ throw new Error(
4717
+ "ShhhAccount: validForSeconds must be a positive finite number of seconds."
4718
+ );
4719
+ }
4720
+ if (options.validForSeconds > maxValid) {
4721
+ throw new Error(
4722
+ `ShhhAccount: validForSeconds (${options.validForSeconds}) exceeds the max ${maxValid}s (the account caps the OE window at ${MAX_OE_VALIDITY_WINDOW_SECONDS}s and ${OE_EXECUTE_AFTER_CLOCK_SKEW_BUFFER}s is reserved for clock skew).`
4723
+ );
4724
+ }
4725
+ }
4726
+ const outsideExecution = buildOutsideExecution({
4727
+ nonce: options.nonce ?? generateNonce2(),
4728
+ calls,
4729
+ ...options.validForSeconds !== void 0 ? { executeBefore: BigInt(Math.floor(Date.now() / 1e3) + options.validForSeconds) } : {}
4730
+ });
4731
+ const messageHash = computeOeHash(outsideExecution, this.address, this.chainId);
4732
+ const signature = buildStarkEnvelope({
4733
+ privateKey: this.privateKey,
4734
+ messageHash,
4735
+ ownerIndex: this.ownerIndex
4736
+ });
4737
+ const calldata = serializeExecuteFromOutsideV2Calldata({ outsideExecution, signature });
4738
+ return { outsideExecution, signature, messageHash, calldata };
4739
+ }
4740
+ /**
4741
+ * Sign `calls` and broadcast them via the configured `submit` strategy.
4742
+ * Mirrors starknet.js `Account.execute` ergonomically. Returns the
4743
+ * transaction hash without waiting for inclusion — use
4744
+ * `provider.waitForTransaction(transactionHash)` if you need to block.
4745
+ */
4746
+ async execute(calls, options = {}) {
4747
+ if (!this.submitFn) {
4748
+ throw new Error(
4749
+ "ShhhAccount.execute: no submit strategy configured. Pass `submit` in the ShhhAccount constructor options (e.g. submitViaAccount(fundedAccount) for self-sovereign, or a paymaster relay for gasless), or call signExecution() and broadcast the calldata yourself."
4750
+ );
4751
+ }
4752
+ const { calldata } = await this.signExecution(calls, options);
4753
+ return this.submitFn({ accountAddress: this.address, calldata });
4754
+ }
4755
+ };
4756
+ function submitViaAccount(funded) {
4757
+ return async ({ accountAddress, calldata }) => {
4758
+ const { transaction_hash } = await funded.execute({
4759
+ contractAddress: accountAddress,
4760
+ entrypoint: "execute_from_outside_v2",
4761
+ calldata
4762
+ });
4763
+ return { transactionHash: transaction_hash };
4764
+ };
4765
+ }
4766
+
4767
+ export { ANY_CALLER_FELT, APPLE_ISSUER, BOOTSTRAP_DOMAIN_SEPARATOR, ChipiBrowserSDK, ChipiClient, ChipiPaymasterAdapter, ChipiSDK, ChipiServerSDK, ChipiSessions, ChipiSkuPurchases, ChipiSkus, ChipiTransactions, ChipiTreasury, ChipiWallets, DEFAULT_OP_EXPIRY_SECONDS, ISIGNER_CANONICAL_LABEL, ISIGNER_ID, ISRC9_V2_ID, MAX_OE_VALIDITY_WINDOW_SECONDS, MIN_THRESHOLD_OWNERS, OE_DOMAIN_NAME, OE_DOMAIN_REVISION, OE_DOMAIN_VERSION, OP_ADD_OWNER, OP_REMOVE_OWNER, OP_ROTATE_OWNER, OP_SET_THRESHOLD, ROLE_GUARDIAN, ROLE_OWNER, SIG_VERSION_V1_HEX_ASCII, SIG_VERSION_V2_SNIP12, SIG_VERSION_V2_THRESHOLD, STARKNET_MESSAGE_PREFIX, ShhhAccount, TIMELOCK_SECONDS, VIEW_SELECTORS, X402Facilitator, X402ShhhClient, assertValidV2Snip12Envelope, buildBootstrapSignedCall, buildCancelPendingOpCall, buildCancelRecoveryCall, buildEd25519Envelope, buildEd25519EnvelopeFromSignature, buildEip191EnvelopeFromPrivateKey, buildEip191EnvelopeFromSignature, buildExecuteAddOwnerCall, buildExecuteRemoveOwnerCall, buildExecuteRotateOwnerCall, buildExecuteSetThresholdCall, buildFinalizeRecoveryCall, buildInitiateRecoveryCall, buildJwtAppleSubEnvelopeFromTestKey, buildJwtAppleSubEnvelopeFromTokenResponse, buildMigrationCalls, buildOutsideExecution, buildProposeAddOwnerCall, buildProposeRemoveOwnerCall, buildProposeRotateOwnerCall, buildProposeSetThresholdCall, buildStarkEnvelope, buildThresholdEnvelope, buildWebAuthnEnvelopeFromAssertion, buildWebAuthnEnvelopeFromPrivateKey, byteArrayToFelts, computeAddressSalt, computeBootstrapMessage, computeISignerId, computeOeHash, computeShhhAddress, computeSnip12Hash, decryptPrivateKey, ed25519OwnerId, ed25519OwnerPubkeyParam, ed25519PubkeyFelts, ed25519SignedBytes, eip191OwnerId, eip191OwnerPubkeyParam, eip191PubkeyFelts, encryptPrivateKey, estimateThresholdGasOverhead, executeShhhSponsoredRaw, hashCall, hashCalls, hashOutsideExecutionStruct, hashStarknetDomain, isReadyToExecute, jwtAppleSubHash, jwtAppleSubOwnerId, jwtAppleSubPubkeyFelts, labelToFelt, locateSubClaim, messageHashToNonceB64url, migrateChipiWalletToShhh, ownerCommitment, parseAppleIdToken, parseDerEcdsaSignature, parseEip191Signature, parseThresholdEnvelope, resolveShhhChainId, secondsUntilExecutable, serializeExecuteFromOutsideV2Calldata, signBootstrapMessage, signTypedData, signTypedDataArray, snip12HashToHexAsciiBytes, starkOwnerId, starkPubkeyFelts, submitViaAccount, webauthnOwnerId, webauthnOwnerPubkeyParam, webauthnPubkeyFelts, wrapV2Snip12Envelope, wrapV2ThresholdEnvelope, x402Middleware };
4541
4768
  //# sourceMappingURL=index.mjs.map
4542
4769
  //# sourceMappingURL=index.mjs.map