@chipi-stack/backend 14.6.0 → 14.8.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.js CHANGED
@@ -405,21 +405,52 @@ async function buildEd25519Envelope(params) {
405
405
  );
406
406
  }
407
407
  const ed = await import('@noble/ed25519');
408
- const garaga = await ensureGaragaInit();
409
408
  const publicKey = await ed.getPublicKeyAsync(params.privateKey);
410
409
  const signedBytes = ed25519SignedBytes(params.messageHash);
411
410
  const signature = await ed.signAsync(signedBytes, params.privateKey);
412
- const R = signature.slice(0, 32);
413
- const s = signature.slice(32, 64);
414
- const payload = garaga.eddsaCalldataBuilder(
415
- bytesToLeBigInt(R),
416
- bytesToLeBigInt(s),
417
- bytesToLeBigInt(publicKey),
411
+ return assembleEd25519Envelope({
412
+ R: signature.slice(0, 32),
413
+ s: signature.slice(32, 64),
414
+ publicKey,
418
415
  signedBytes,
416
+ ownerIndex
417
+ });
418
+ }
419
+ async function buildEd25519EnvelopeFromSignature(params) {
420
+ const ownerIndex = params.ownerIndex ?? 0n;
421
+ if (ownerIndex < 0n || ownerIndex >= 0x100000000n) {
422
+ throw new Error(
423
+ `buildEd25519EnvelopeFromSignature: ownerIndex ${ownerIndex} is out of u32 range [0, 2^32). owner_id is the u32 INDEX into the wallet's owner_set (0 for primary); do NOT pass an owner_commitment or pubkey here.`
424
+ );
425
+ }
426
+ if (params.signature.length !== 64) {
427
+ throw new Error(
428
+ `Ed25519 signature must be exactly 64 bytes (R\u2016s); got ${params.signature.length}.`
429
+ );
430
+ }
431
+ if (params.publicKey.length !== 32) {
432
+ throw new Error(`Ed25519 public key must be exactly 32 bytes; got ${params.publicKey.length}.`);
433
+ }
434
+ const signedBytes = ed25519SignedBytes(params.messageHash);
435
+ return assembleEd25519Envelope({
436
+ R: params.signature.slice(0, 32),
437
+ s: params.signature.slice(32, 64),
438
+ publicKey: params.publicKey,
439
+ signedBytes,
440
+ ownerIndex
441
+ });
442
+ }
443
+ async function assembleEd25519Envelope(parts) {
444
+ const garaga = await ensureGaragaInit();
445
+ const payload = garaga.eddsaCalldataBuilder(
446
+ bytesToLeBigInt(parts.R),
447
+ bytesToLeBigInt(parts.s),
448
+ bytesToLeBigInt(parts.publicKey),
449
+ parts.signedBytes,
419
450
  false
420
451
  );
421
452
  return wrapV2Snip12Envelope({
422
- ownerId: ownerIndex,
453
+ ownerId: parts.ownerIndex,
423
454
  kindTag: ED25519_KIND_TAG,
424
455
  payload
425
456
  });
@@ -1434,12 +1465,17 @@ var ChipiWallets = class {
1434
1465
  }
1435
1466
  const isShhh = walletType === "SHHH";
1436
1467
  const effectiveSignerKind = isShhh ? params.signerKind ?? "STARK" : void 0;
1437
- const SDK_SHIPPED_SHHH_KINDS = ["STARK", "ED25519"];
1468
+ const SDK_SHIPPED_SHHH_KINDS = [
1469
+ "STARK",
1470
+ "ED25519",
1471
+ "WEBAUTHN_P256",
1472
+ "EIP191_SECP256K1"
1473
+ ];
1438
1474
  if (isShhh && !SDK_SHIPPED_SHHH_KINDS.includes(
1439
1475
  effectiveSignerKind
1440
1476
  )) {
1441
1477
  throw new Error(
1442
- `SHHH signerKind=${effectiveSignerKind} is not yet shipped from the SDK (Wave B ships STARK + ED25519). Use signerKind="STARK" or "ED25519", or wait for the follow-up PRs that add external-rooted (MetaMask, Phantom, passkey, Apple) deploy support.`
1478
+ `SHHH signerKind=${effectiveSignerKind} is not yet shipped from the SDK (supports STARK, ED25519, WEBAUTHN_P256, EIP191_SECP256K1). JWT_ES256_APPLE_SUB and others remain deferred to their follow-up PRs (OAuth / Apple-Developer context).`
1443
1479
  );
1444
1480
  }
1445
1481
  const rpcUrl = walletType === "READY" ? shared.WALLET_RPC_ENDPOINTS.READY : shared.WALLET_RPC_ENDPOINTS.CHIPI;
@@ -1474,6 +1510,14 @@ var ChipiWallets = class {
1474
1510
  pubkeyFelts = ed25519PubkeyFelts(edPubKey);
1475
1511
  shhhPrivateKeyHex = Buffer.from(edPrivKey).toString("hex");
1476
1512
  }
1513
+ } else if (effectiveSignerKind === "WEBAUTHN_P256" || effectiveSignerKind === "EIP191_SECP256K1") {
1514
+ if (!params.ownerPubkeyFelts || params.ownerPubkeyFelts.length !== 4) {
1515
+ throw new Error(
1516
+ `SHHH ${effectiveSignerKind} ownerPubkeyFelts must be [x_low, x_high, y_low, y_high] (4 felts); got ${params.ownerPubkeyFelts?.length ?? 0}.`
1517
+ );
1518
+ }
1519
+ pubkeyFelts = params.ownerPubkeyFelts.map((s) => BigInt(s));
1520
+ shhhPrivateKeyHex = "";
1477
1521
  } else {
1478
1522
  throw new Error(
1479
1523
  `SHHH signerKind=${effectiveSignerKind} reached the address-derivation block without an implementation.`
@@ -1584,12 +1628,18 @@ var ChipiWallets = class {
1584
1628
  userSignature: userSignaturePayload,
1585
1629
  typedData: typedData2,
1586
1630
  ...encryptedPrivateKey !== void 0 && { encryptedPrivateKey },
1587
- // SHHH: write the signer kind to the new wallet row. P0.3's
1588
- // STARK-only path uses a Chipi-held STARK key, so
1589
- // ownerPublicKey stays unset (encryptedPrivateKey carries
1590
- // the same key the verifier checks against). External-rooted
1591
- // wallets will pass ownerPublicKey instead in a follow-up PR.
1631
+ // SHHH: write the signer kind to the new wallet row.
1592
1632
  ...isShhh && { signerKind: effectiveSignerKind },
1633
+ // External-rooted SHHH (passkey / MetaMask / Phantom): no
1634
+ // Chipi-held key, so chipi-back needs the pubkey felts (address
1635
+ // derivation) + `ownerPublicKey` as the credential source it
1636
+ // stores (encryptedPrivateKey stays null). Canonical
1637
+ // ownerPublicKey = comma-joined felts. STARK / Chipi-held kinds
1638
+ // are untouched — encryptedPrivateKey is their credential source.
1639
+ ...isShhh && encryptedPrivateKey === void 0 && shhhOwnerPubkeyFelts && {
1640
+ ownerPubkeyFelts: shhhOwnerPubkeyFelts,
1641
+ ownerPublicKey: shhhOwnerPubkeyFelts.join(",")
1642
+ },
1593
1643
  ...encryptedPrivateKeyBackup && { encryptedPrivateKeyBackup },
1594
1644
  ...params.authMethod && { authMethod: params.authMethod },
1595
1645
  ...params.credentialId && { credentialId: params.credentialId },
@@ -2776,6 +2826,79 @@ var ChipiSessions = class {
2776
2826
  }
2777
2827
  }
2778
2828
  };
2829
+ var ChipiTreasury = class {
2830
+ constructor(client, apiSecretKey) {
2831
+ this.client = client;
2832
+ this.apiSecretKey = apiSecretKey;
2833
+ }
2834
+ base(treasuryId) {
2835
+ return `${shared.API_ENDPOINTS.TREASURIES}/${treasuryId}/transactions`;
2836
+ }
2837
+ /** Resolve a `sk_` for the secret-gated reads/execute, or fail loudly. */
2838
+ secret(bearerToken) {
2839
+ const token = bearerToken ?? this.apiSecretKey;
2840
+ if (!token) {
2841
+ throw new Error(
2842
+ "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."
2843
+ );
2844
+ }
2845
+ return token;
2846
+ }
2847
+ /**
2848
+ * Build a {@link TreasuryTransport} for one treasury + owner. Wire the
2849
+ * returned object directly into chipi-react's `useProposeAction` /
2850
+ * `useTreasuryProposals` `transport` prop, or call its methods yourself.
2851
+ */
2852
+ forTreasury(config) {
2853
+ const { treasuryId, ownerPubkey } = config;
2854
+ const base = this.base(treasuryId);
2855
+ return {
2856
+ // sk_ — read the proposal list. chipi-back returns
2857
+ // { items, total, page, limit, hasMore }; the hook only reads `items`.
2858
+ list: async () => {
2859
+ const res = await this.client.get({
2860
+ endpoint: base,
2861
+ bearerToken: this.secret(config.bearerToken)
2862
+ });
2863
+ return { ...res, items: res.items ?? [] };
2864
+ },
2865
+ // pk_ + owner sig — no secret. `ownerPubkey` lets the backend verify the
2866
+ // proposer envelope. `meta` (if present) is stripped server-side.
2867
+ propose: async (body) => {
2868
+ return this.client.post({
2869
+ endpoint: base,
2870
+ // Empty string → no Authorization header; the pk_ travels in
2871
+ // x-api-key, which ApiKeyGuard accepts for propose.
2872
+ bearerToken: "",
2873
+ body: { ...body, ownerPubkey }
2874
+ });
2875
+ },
2876
+ // pk_ + owner sig — approve an existing proposal.
2877
+ sign: async (proposalId, body) => {
2878
+ return this.client.post({
2879
+ endpoint: `${base}/${proposalId}/sign`,
2880
+ bearerToken: "",
2881
+ body: { ...body, ownerPubkey }
2882
+ });
2883
+ },
2884
+ // sk_ — relay the assembled threshold calldata through the paymaster.
2885
+ execute: async (proposalId, calldata) => {
2886
+ return this.client.post({
2887
+ endpoint: `${base}/${proposalId}/execute`,
2888
+ bearerToken: this.secret(config.bearerToken),
2889
+ body: { calldata }
2890
+ });
2891
+ },
2892
+ // sk_ — the free-execute meter (org-scoped).
2893
+ getMultisigAllowance: async () => {
2894
+ return this.client.get({
2895
+ endpoint: `${shared.API_ENDPOINTS.TREASURIES}/${treasuryId}/multisig-allowance`,
2896
+ bearerToken: this.secret(config.bearerToken)
2897
+ });
2898
+ }
2899
+ };
2900
+ }
2901
+ };
2779
2902
  var InMemoryNonceStore = class {
2780
2903
  constructor() {
2781
2904
  this.used = /* @__PURE__ */ new Set();
@@ -3055,6 +3178,7 @@ var ChipiSDK = class {
3055
3178
  this.skus = new ChipiSkus(this.client);
3056
3179
  this.sessions = new ChipiSessions(this.client);
3057
3180
  this.exchanges = new ChipiExchanges(this.client);
3181
+ this.treasury = new ChipiTreasury(this.client, config.apiSecretKey);
3058
3182
  this.executeTransaction = this.executeTransaction.bind(this);
3059
3183
  this.executeTransactionWithSession = this.executeTransactionWithSession.bind(this);
3060
3184
  this.transfer = this.transfer.bind(this);
@@ -3190,9 +3314,7 @@ var ChipiSDK = class {
3190
3314
  * });
3191
3315
  * ```
3192
3316
  */
3193
- async signTypedData({
3194
- params
3195
- }) {
3317
+ async signTypedData({ params }) {
3196
3318
  return signTypedData({ params });
3197
3319
  }
3198
3320
  /**
@@ -4517,6 +4639,7 @@ exports.ChipiSessions = ChipiSessions;
4517
4639
  exports.ChipiSkuPurchases = ChipiSkuPurchases;
4518
4640
  exports.ChipiSkus = ChipiSkus;
4519
4641
  exports.ChipiTransactions = ChipiTransactions;
4642
+ exports.ChipiTreasury = ChipiTreasury;
4520
4643
  exports.ChipiWallets = ChipiWallets;
4521
4644
  exports.DEFAULT_OP_EXPIRY_SECONDS = DEFAULT_OP_EXPIRY_SECONDS;
4522
4645
  exports.OP_ADD_OWNER = OP_ADD_OWNER;
@@ -4534,6 +4657,7 @@ exports.buildBootstrapSignedCall = buildBootstrapSignedCall;
4534
4657
  exports.buildCancelPendingOpCall = buildCancelPendingOpCall;
4535
4658
  exports.buildCancelRecoveryCall = buildCancelRecoveryCall;
4536
4659
  exports.buildEd25519Envelope = buildEd25519Envelope;
4660
+ exports.buildEd25519EnvelopeFromSignature = buildEd25519EnvelopeFromSignature;
4537
4661
  exports.buildEip191EnvelopeFromPrivateKey = buildEip191EnvelopeFromPrivateKey;
4538
4662
  exports.buildEip191EnvelopeFromSignature = buildEip191EnvelopeFromSignature;
4539
4663
  exports.buildExecuteAddOwnerCall = buildExecuteAddOwnerCall;