passkey-kit 0.12.1 → 0.14.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.
Files changed (172) hide show
  1. package/README.md +408 -227
  2. package/{types → dist}/base.d.ts +1 -0
  3. package/dist/base.d.ts.map +1 -0
  4. package/{src/base.ts → dist/base.js} +8 -10
  5. package/dist/base.js.map +1 -0
  6. package/dist/base64url.d.ts +18 -0
  7. package/dist/base64url.d.ts.map +1 -0
  8. package/dist/base64url.js +18 -0
  9. package/dist/base64url.js.map +1 -0
  10. package/dist/constants.d.ts +91 -0
  11. package/dist/constants.d.ts.map +1 -0
  12. package/dist/constants.js +115 -0
  13. package/dist/constants.js.map +1 -0
  14. package/dist/contract-errors.d.ts +69 -0
  15. package/dist/contract-errors.d.ts.map +1 -0
  16. package/dist/contract-errors.js +132 -0
  17. package/dist/contract-errors.js.map +1 -0
  18. package/dist/errors.d.ts +163 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +244 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/events.d.ts +94 -0
  23. package/dist/events.d.ts.map +1 -0
  24. package/dist/events.js +92 -0
  25. package/dist/events.js.map +1 -0
  26. package/dist/index.d.ts +22 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +36 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/indexer/codec.d.ts +18 -0
  31. package/dist/indexer/codec.d.ts.map +1 -0
  32. package/dist/indexer/codec.js +32 -0
  33. package/dist/indexer/codec.js.map +1 -0
  34. package/dist/indexer/index.d.ts +25 -0
  35. package/dist/indexer/index.d.ts.map +1 -0
  36. package/dist/indexer/index.js +34 -0
  37. package/dist/indexer/index.js.map +1 -0
  38. package/dist/indexer/mercury.d.ts +94 -0
  39. package/dist/indexer/mercury.d.ts.map +1 -0
  40. package/dist/indexer/mercury.js +245 -0
  41. package/dist/indexer/mercury.js.map +1 -0
  42. package/dist/indexer/stellar-indexer.d.ts +115 -0
  43. package/dist/indexer/stellar-indexer.d.ts.map +1 -0
  44. package/dist/indexer/stellar-indexer.js +279 -0
  45. package/dist/indexer/stellar-indexer.js.map +1 -0
  46. package/dist/indexer/types.d.ts +73 -0
  47. package/dist/indexer/types.d.ts.map +1 -0
  48. package/dist/indexer/types.js +9 -0
  49. package/dist/indexer/types.js.map +1 -0
  50. package/dist/kit/auth-payload.d.ts +106 -0
  51. package/dist/kit/auth-payload.d.ts.map +1 -0
  52. package/dist/kit/auth-payload.js +227 -0
  53. package/dist/kit/auth-payload.js.map +1 -0
  54. package/dist/kit/deploy-ops.d.ts +45 -0
  55. package/dist/kit/deploy-ops.d.ts.map +1 -0
  56. package/dist/kit/deploy-ops.js +69 -0
  57. package/dist/kit/deploy-ops.js.map +1 -0
  58. package/dist/kit/tx-ops.d.ts +95 -0
  59. package/dist/kit/tx-ops.d.ts.map +1 -0
  60. package/dist/kit/tx-ops.js +125 -0
  61. package/dist/kit/tx-ops.js.map +1 -0
  62. package/dist/kit/wallet-ops.d.ts +59 -0
  63. package/dist/kit/wallet-ops.d.ts.map +1 -0
  64. package/dist/kit/wallet-ops.js +122 -0
  65. package/dist/kit/wallet-ops.js.map +1 -0
  66. package/dist/kit/webauthn-ops.d.ts +55 -0
  67. package/dist/kit/webauthn-ops.d.ts.map +1 -0
  68. package/dist/kit/webauthn-ops.js +79 -0
  69. package/dist/kit/webauthn-ops.js.map +1 -0
  70. package/dist/kit.d.ts +132 -0
  71. package/dist/kit.d.ts.map +1 -0
  72. package/dist/kit.js +290 -0
  73. package/dist/kit.js.map +1 -0
  74. package/dist/managers/credential-manager.d.ts +39 -0
  75. package/dist/managers/credential-manager.d.ts.map +1 -0
  76. package/dist/managers/credential-manager.js +47 -0
  77. package/dist/managers/credential-manager.js.map +1 -0
  78. package/dist/managers/index.d.ts +7 -0
  79. package/dist/managers/index.d.ts.map +1 -0
  80. package/dist/managers/index.js +7 -0
  81. package/dist/managers/index.js.map +1 -0
  82. package/dist/managers/signer-manager.d.ts +62 -0
  83. package/dist/managers/signer-manager.d.ts.map +1 -0
  84. package/dist/managers/signer-manager.js +111 -0
  85. package/dist/managers/signer-manager.js.map +1 -0
  86. package/dist/managers/submission-manager.d.ts +52 -0
  87. package/dist/managers/submission-manager.d.ts.map +1 -0
  88. package/dist/managers/submission-manager.js +77 -0
  89. package/dist/managers/submission-manager.js.map +1 -0
  90. package/dist/relayer.d.ts +61 -0
  91. package/dist/relayer.d.ts.map +1 -0
  92. package/dist/relayer.js +122 -0
  93. package/dist/relayer.js.map +1 -0
  94. package/dist/rpc-data.d.ts +45 -0
  95. package/dist/rpc-data.d.ts.map +1 -0
  96. package/dist/rpc-data.js +61 -0
  97. package/dist/rpc-data.js.map +1 -0
  98. package/dist/sac.d.ts +31 -0
  99. package/dist/sac.d.ts.map +1 -0
  100. package/dist/sac.js +47 -0
  101. package/dist/sac.js.map +1 -0
  102. package/dist/server.d.ts +79 -0
  103. package/dist/server.d.ts.map +1 -0
  104. package/dist/server.js +152 -0
  105. package/dist/server.js.map +1 -0
  106. package/dist/signers.d.ts +83 -0
  107. package/dist/signers.d.ts.map +1 -0
  108. package/dist/signers.js +124 -0
  109. package/dist/signers.js.map +1 -0
  110. package/dist/storage/index.d.ts +13 -0
  111. package/dist/storage/index.d.ts.map +1 -0
  112. package/dist/storage/index.js +12 -0
  113. package/dist/storage/index.js.map +1 -0
  114. package/dist/storage/indexeddb.d.ts +26 -0
  115. package/dist/storage/indexeddb.d.ts.map +1 -0
  116. package/dist/storage/indexeddb.js +100 -0
  117. package/dist/storage/indexeddb.js.map +1 -0
  118. package/dist/storage/localStorage.d.ts +22 -0
  119. package/dist/storage/localStorage.d.ts.map +1 -0
  120. package/dist/storage/localStorage.js +86 -0
  121. package/dist/storage/localStorage.js.map +1 -0
  122. package/dist/storage/memory.d.ts +18 -0
  123. package/dist/storage/memory.d.ts.map +1 -0
  124. package/dist/storage/memory.js +41 -0
  125. package/dist/storage/memory.js.map +1 -0
  126. package/dist/types.d.ts +136 -0
  127. package/dist/types.d.ts.map +1 -0
  128. package/dist/types.js +39 -0
  129. package/dist/types.js.map +1 -0
  130. package/dist/utils.d.ts +72 -0
  131. package/dist/utils.d.ts.map +1 -0
  132. package/dist/utils.js +253 -0
  133. package/dist/utils.js.map +1 -0
  134. package/dist/validation.d.ts +42 -0
  135. package/dist/validation.d.ts.map +1 -0
  136. package/dist/validation.js +75 -0
  137. package/dist/validation.js.map +1 -0
  138. package/dist/version.d.ts +7 -0
  139. package/dist/version.d.ts.map +1 -0
  140. package/dist/version.js +9 -0
  141. package/dist/version.js.map +1 -0
  142. package/package.json +47 -20
  143. package/.claude/settings.local.json +0 -20
  144. package/.cursorrules +0 -170
  145. package/.gitattributes +0 -2
  146. package/.github/workflows/release.yml +0 -21
  147. package/.vscode/settings.json +0 -6
  148. package/PROPOSAL.md +0 -397
  149. package/cheatsheet.txt +0 -18
  150. package/clone-js-sdk.sh +0 -21
  151. package/packages/passkey-kit-sdk/README.md +0 -54
  152. package/packages/passkey-kit-sdk/package.json +0 -21
  153. package/packages/passkey-kit-sdk/src/index.ts +0 -171
  154. package/packages/passkey-kit-sdk/tsconfig.json +0 -98
  155. package/packages/passkey-kit-sdk/types/index.d.ts +0 -190
  156. package/packages/sac-sdk/README.md +0 -54
  157. package/packages/sac-sdk/package.json +0 -21
  158. package/packages/sac-sdk/src/index.ts +0 -586
  159. package/packages/sac-sdk/tsconfig.json +0 -98
  160. package/packages/sac-sdk/types/index.d.ts +0 -532
  161. package/pnpm-workspace.yaml +0 -2
  162. package/src/index.ts +0 -5
  163. package/src/kit.ts +0 -823
  164. package/src/sac.ts +0 -29
  165. package/src/server.ts +0 -179
  166. package/src/types.ts +0 -32
  167. package/tsconfig.json +0 -28
  168. package/types/index.d.ts +0 -5
  169. package/types/kit.d.ts +0 -95
  170. package/types/sac.d.ts +0 -13
  171. package/types/server.d.ts +0 -29
  172. package/types/types.d.ts +0 -22
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Submission manager: builds and signs the deploy transaction with the fee-
3
+ * paying deployer keypair, derives deterministic wallet addresses, and drives
4
+ * the footprint-restore flow.
5
+ *
6
+ * Network submission itself is the server's job (`PasskeyServer` / relayer); this
7
+ * manager owns the deployer keypair and the fee-payer signature that make a
8
+ * deploy transaction submittable.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ import type { Keypair } from "@stellar/stellar-sdk";
13
+ import type { AssembledTransaction } from "@stellar/stellar-sdk/contract";
14
+ import type { Server } from "@stellar/stellar-sdk/rpc";
15
+ import type { Client as PasskeyClient } from "passkey-kit-sdk";
16
+ import { type RestorePreamble } from "../kit/tx-ops.js";
17
+ export interface SubmissionManagerDeps {
18
+ rpc: Server;
19
+ rpcUrl: string;
20
+ networkPassphrase: string;
21
+ walletWasmHash: string;
22
+ deployerKeypair: Keypair;
23
+ timeoutInSeconds: number;
24
+ }
25
+ export declare class SubmissionManager {
26
+ private readonly deps;
27
+ constructor(deps: SubmissionManagerDeps);
28
+ /** The deployer's `G…` public key (fee source + derivation deployer). */
29
+ get deployerPublicKey(): string;
30
+ /** Deterministically derive the wallet address for a passkey credential. */
31
+ deriveWalletAddress(keyId: Buffer): string;
32
+ /** Build the wallet deploy transaction (initial Secp256r1 signer). */
33
+ buildDeployTransaction(keyId: Buffer, publicKey: Uint8Array): Promise<AssembledTransaction<PasskeyClient>>;
34
+ /**
35
+ * Sign a deploy transaction with the deployer keypair (the fee source) and
36
+ * return the signed transaction XDR.
37
+ *
38
+ * The deploy carries source-account auth, so it is submitted through the
39
+ * relayer's fee-bump (`{ xdr }`) path. A fee-bumped Soroban inner transaction
40
+ * must have `fee == resourceFee` — the fee-bump supplies the inclusion fee —
41
+ * or the relayer rejects it with a fee mismatch ("Transaction fee must be
42
+ * equal to the resource fee"). The assembled fee is `inclusion + resource`,
43
+ * so pin it to the resource fee BEFORE the deployer signs (the signature
44
+ * commits to the fee). `TransactionBuilder.cloneFrom` drops
45
+ * `SorobanTransactionData` (→ txMalformed), so set the fee field surgically on
46
+ * the envelope and rebuild.
47
+ */
48
+ signDeploy(tx: AssembledTransaction<PasskeyClient>): Promise<string>;
49
+ /** Restore an archived footprint reported by simulation. */
50
+ restoreFootprint(restorePreamble: RestorePreamble): Promise<string>;
51
+ }
52
+ //# sourceMappingURL=submission-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submission-manager.d.ts","sourceRoot":"","sources":["../../src/managers/submission-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,sBAAsB,CAAC;AACjE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAK/D,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,qBAAqB;IAExD,yEAAyE;IACzE,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED,4EAA4E;IAC5E,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAU1C,sEAAsE;IACtE,sBAAsB,CACpB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAC;IAc/C;;;;;;;;;;;;;OAaG;IACG,UAAU,CAAC,EAAE,EAAE,oBAAoB,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAiB1E,4DAA4D;IAC5D,gBAAgB,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;CAWpE"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Submission manager: builds and signs the deploy transaction with the fee-
3
+ * paying deployer keypair, derives deterministic wallet addresses, and drives
4
+ * the footprint-restore flow.
5
+ *
6
+ * Network submission itself is the server's job (`PasskeyServer` / relayer); this
7
+ * manager owns the deployer keypair and the fee-payer signature that make a
8
+ * deploy transaction submittable.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ import { TransactionBuilder } from "@stellar/stellar-sdk";
13
+ import { buildDeployTransaction as buildDeployTransactionOp, deriveWalletAddress as deriveWalletAddressOp, } from "../kit/deploy-ops.js";
14
+ import { restoreFootprint as restoreFootprintOp, } from "../kit/tx-ops.js";
15
+ export class SubmissionManager {
16
+ deps;
17
+ constructor(deps) {
18
+ this.deps = deps;
19
+ }
20
+ /** The deployer's `G…` public key (fee source + derivation deployer). */
21
+ get deployerPublicKey() {
22
+ return this.deps.deployerKeypair.publicKey();
23
+ }
24
+ /** Deterministically derive the wallet address for a passkey credential. */
25
+ deriveWalletAddress(keyId) {
26
+ return deriveWalletAddressOp({
27
+ networkPassphrase: this.deps.networkPassphrase,
28
+ deployerPublicKey: this.deployerPublicKey,
29
+ }, keyId);
30
+ }
31
+ /** Build the wallet deploy transaction (initial Secp256r1 signer). */
32
+ buildDeployTransaction(keyId, publicKey) {
33
+ return buildDeployTransactionOp({
34
+ rpcUrl: this.deps.rpcUrl,
35
+ networkPassphrase: this.deps.networkPassphrase,
36
+ walletWasmHash: this.deps.walletWasmHash,
37
+ deployerPublicKey: this.deployerPublicKey,
38
+ timeoutInSeconds: this.deps.timeoutInSeconds,
39
+ }, keyId, publicKey);
40
+ }
41
+ /**
42
+ * Sign a deploy transaction with the deployer keypair (the fee source) and
43
+ * return the signed transaction XDR.
44
+ *
45
+ * The deploy carries source-account auth, so it is submitted through the
46
+ * relayer's fee-bump (`{ xdr }`) path. A fee-bumped Soroban inner transaction
47
+ * must have `fee == resourceFee` — the fee-bump supplies the inclusion fee —
48
+ * or the relayer rejects it with a fee mismatch ("Transaction fee must be
49
+ * equal to the resource fee"). The assembled fee is `inclusion + resource`,
50
+ * so pin it to the resource fee BEFORE the deployer signs (the signature
51
+ * commits to the fee). `TransactionBuilder.cloneFrom` drops
52
+ * `SorobanTransactionData` (→ txMalformed), so set the fee field surgically on
53
+ * the envelope and rebuild.
54
+ */
55
+ async signDeploy(tx) {
56
+ if (!tx.built) {
57
+ throw new Error("deploy transaction has not been built/simulated");
58
+ }
59
+ const envelope = tx.built.toEnvelope();
60
+ const inner = envelope.v1().tx();
61
+ const resourceFee = inner.ext().sorobanData().resourceFee().toString();
62
+ inner.fee(Number(resourceFee));
63
+ const feeAdjusted = TransactionBuilder.fromXDR(envelope.toXDR("base64"), this.deps.networkPassphrase);
64
+ feeAdjusted.sign(this.deps.deployerKeypair);
65
+ return feeAdjusted.toXDR();
66
+ }
67
+ /** Restore an archived footprint reported by simulation. */
68
+ restoreFootprint(restorePreamble) {
69
+ return restoreFootprintOp({
70
+ rpc: this.deps.rpc,
71
+ networkPassphrase: this.deps.networkPassphrase,
72
+ deployerKeypair: this.deps.deployerKeypair,
73
+ timeoutInSeconds: this.deps.timeoutInSeconds,
74
+ }, restorePreamble);
75
+ }
76
+ }
77
+ //# sourceMappingURL=submission-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submission-manager.js","sourceRoot":"","sources":["../../src/managers/submission-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAK1D,OAAO,EACL,sBAAsB,IAAI,wBAAwB,EAClD,mBAAmB,IAAI,qBAAqB,GAC7C,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,gBAAgB,IAAI,kBAAkB,GAEvC,MAAM,kBAAkB,CAAC;AAW1B,MAAM,OAAO,iBAAiB;IACC;IAA7B,YAA6B,IAA2B;QAA3B,SAAI,GAAJ,IAAI,CAAuB;IAAG,CAAC;IAE5D,yEAAyE;IACzE,IAAI,iBAAiB;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC;IAC/C,CAAC;IAED,4EAA4E;IAC5E,mBAAmB,CAAC,KAAa;QAC/B,OAAO,qBAAqB,CAC1B;YACE,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB;YAC9C,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;SAC1C,EACD,KAAK,CACN,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,sBAAsB,CACpB,KAAa,EACb,SAAqB;QAErB,OAAO,wBAAwB,CAC7B;YACE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM;YACxB,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB;YAC9C,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc;YACxC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB;SAC7C,EACD,KAAK,EACL,SAAS,CACV,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,UAAU,CAAC,EAAuC;QACtD,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,QAAQ,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,CAAC;QACvE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAE/B,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAC5C,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EACxB,IAAI,CAAC,IAAI,CAAC,iBAAiB,CACb,CAAC;QACjB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC5C,OAAO,WAAW,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,4DAA4D;IAC5D,gBAAgB,CAAC,eAAgC;QAC/C,OAAO,kBAAkB,CACvB;YACE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG;YAClB,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB;YAC9C,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,eAAe;YAC1C,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB;SAC7C,EACD,eAAe,CAChB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Server-side relayer client.
3
+ *
4
+ * A thin, typed wrapper over the OpenZeppelin Channels client
5
+ * (`@openzeppelin/relayer-plugin-channels` ^0.20) for fee-sponsored submission.
6
+ * It holds the relayer API key, so it MUST run server-side only (it is reached
7
+ * through `PasskeyServer`, exported from the `passkey-kit/server` subpath).
8
+ *
9
+ * Two submission modes:
10
+ * - {@link RelayerClient.send} — `{ func, auth }` for invokeHostFunction flows
11
+ * (the preferred Soroban path; the relayer builds the envelope + pays fees).
12
+ * - {@link RelayerClient.sendTransaction} — `{ xdr }` for a signed envelope
13
+ * (e.g. a deploy transaction that needs source-account auth + a fee bump).
14
+ *
15
+ * Every method returns a discriminated {@link TransactionResult} and NEVER
16
+ * throws for expected relayer/on-chain failures — a `PluginClientError` is
17
+ * mapped to a typed {@link RelayerError} (or a {@link ContractError} when a
18
+ * contract code can be decoded from its details).
19
+ *
20
+ * @packageDocumentation
21
+ */
22
+ import type { TransactionResult } from "./types.js";
23
+ /** Configuration for a {@link RelayerClient}. */
24
+ export interface RelayerClientConfig {
25
+ /** Base URL of the Channels relayer service. */
26
+ baseUrl: string;
27
+ /** API key for the relayer service (server-side secret). */
28
+ apiKey: string;
29
+ /** Optional admin secret for management operations. */
30
+ adminSecret?: string;
31
+ /** Request timeout in ms (default {@link DEFAULT_RELAYER_TIMEOUT_MS}). */
32
+ timeout?: number;
33
+ }
34
+ /** Per-submission relayer options. */
35
+ export interface RelayerSubmitOptions {
36
+ /** Return immediately after submission; poll {@link RelayerClient.getTransaction}. */
37
+ skipWait?: boolean;
38
+ /** Alternative fund-relayer id for the fee bump (must be allow-listed). */
39
+ fundRelayerId?: string;
40
+ }
41
+ export declare class RelayerClient {
42
+ private readonly channels;
43
+ constructor(config: RelayerClientConfig);
44
+ /**
45
+ * Submit an invokeHostFunction via `{ func, auth }` (the preferred Soroban
46
+ * path). The relayer builds the transaction envelope with a channel account
47
+ * and pays the fees.
48
+ */
49
+ send(func: string, auth: string[], options?: RelayerSubmitOptions): Promise<TransactionResult>;
50
+ /**
51
+ * Submit a signed transaction envelope via `{ xdr }` for a fee bump (preserves
52
+ * the inner signature; use for deploys / source-account-auth transactions).
53
+ */
54
+ sendTransaction(xdr: string, options?: RelayerSubmitOptions): Promise<TransactionResult>;
55
+ /** Poll a previously-submitted (`skipWait`) transaction by its relayer id. */
56
+ getTransaction(transactionId: string): Promise<TransactionResult>;
57
+ private run;
58
+ private toResult;
59
+ private mapError;
60
+ }
61
+ //# sourceMappingURL=relayer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relayer.d.ts","sourceRoot":"","sources":["../src/relayer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,YAAY,CAAC;AAQxE,iDAAiD;AACjD,MAAM,WAAW,mBAAmB;IAClC,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,sCAAsC;AACtC,MAAM,WAAW,oBAAoB;IACnC,sFAAsF;IACtF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAgBD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;gBAE9B,MAAM,EAAE,mBAAmB;IAevC;;;;OAIG;IACG,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,iBAAiB,CAAC;IAW7B;;;OAGG;IACG,eAAe,CACnB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,iBAAiB,CAAC;IAU7B,8EAA8E;IACxE,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAIzD,GAAG;IAUjB,OAAO,CAAC,QAAQ;IAqChB,OAAO,CAAC,QAAQ;CAiCjB"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Server-side relayer client.
3
+ *
4
+ * A thin, typed wrapper over the OpenZeppelin Channels client
5
+ * (`@openzeppelin/relayer-plugin-channels` ^0.20) for fee-sponsored submission.
6
+ * It holds the relayer API key, so it MUST run server-side only (it is reached
7
+ * through `PasskeyServer`, exported from the `passkey-kit/server` subpath).
8
+ *
9
+ * Two submission modes:
10
+ * - {@link RelayerClient.send} — `{ func, auth }` for invokeHostFunction flows
11
+ * (the preferred Soroban path; the relayer builds the envelope + pays fees).
12
+ * - {@link RelayerClient.sendTransaction} — `{ xdr }` for a signed envelope
13
+ * (e.g. a deploy transaction that needs source-account auth + a fee bump).
14
+ *
15
+ * Every method returns a discriminated {@link TransactionResult} and NEVER
16
+ * throws for expected relayer/on-chain failures — a `PluginClientError` is
17
+ * mapped to a typed {@link RelayerError} (or a {@link ContractError} when a
18
+ * contract code can be decoded from its details).
19
+ *
20
+ * @packageDocumentation
21
+ */
22
+ import { ChannelsClient, PluginClientError, } from "@openzeppelin/relayer-plugin-channels";
23
+ import { RelayerError, PasskeyKitErrorCode } from "./errors.js";
24
+ import { decodeContractError, failedTransaction, } from "./contract-errors.js";
25
+ import { DEFAULT_RELAYER_TIMEOUT_MS } from "./constants.js";
26
+ /**
27
+ * Terminal-success statuses (ALLOWLIST). Only a status that positively confirms
28
+ * on-chain inclusion counts as success — anything else is failure or still
29
+ * pending. An allowlist (not a failure denylist) is deliberate: an unrecognized
30
+ * or non-terminal status must never be mistaken for a confirmed transaction.
31
+ * Word-bounded so negated forms ("unsuccessful", "unconfirmed") and
32
+ * non-terminal forms ("confirming") never match. Keep identical to
33
+ * relayer-proxy/src/constants.ts.
34
+ */
35
+ const SUCCESS_STATUS = /\b(?:confirm(?:ed)?|success(?:ful)?)\b/i;
36
+ /** Terminal-failure statuses. */
37
+ const FAILURE_STATUS = /fail|error|revert|reject/i;
38
+ export class RelayerClient {
39
+ channels;
40
+ constructor(config) {
41
+ if (!config.baseUrl || !config.apiKey) {
42
+ throw new RelayerError("RelayerClient requires both baseUrl and apiKey", PasskeyKitErrorCode.RELAYER_NOT_CONFIGURED);
43
+ }
44
+ this.channels = new ChannelsClient({
45
+ baseUrl: config.baseUrl,
46
+ apiKey: config.apiKey,
47
+ adminSecret: config.adminSecret,
48
+ timeout: config.timeout ?? DEFAULT_RELAYER_TIMEOUT_MS,
49
+ });
50
+ }
51
+ /**
52
+ * Submit an invokeHostFunction via `{ func, auth }` (the preferred Soroban
53
+ * path). The relayer builds the transaction envelope with a channel account
54
+ * and pays the fees.
55
+ */
56
+ async send(func, auth, options) {
57
+ return this.run(() => this.channels.submitSorobanTransaction({
58
+ func,
59
+ auth,
60
+ skipWait: options?.skipWait,
61
+ fundRelayerId: options?.fundRelayerId,
62
+ }));
63
+ }
64
+ /**
65
+ * Submit a signed transaction envelope via `{ xdr }` for a fee bump (preserves
66
+ * the inner signature; use for deploys / source-account-auth transactions).
67
+ */
68
+ async sendTransaction(xdr, options) {
69
+ return this.run(() => this.channels.submitTransaction({
70
+ xdr,
71
+ skipWait: options?.skipWait,
72
+ fundRelayerId: options?.fundRelayerId,
73
+ }));
74
+ }
75
+ /** Poll a previously-submitted (`skipWait`) transaction by its relayer id. */
76
+ async getTransaction(transactionId) {
77
+ return this.run(() => this.channels.getTransaction({ transactionId }));
78
+ }
79
+ async run(fn) {
80
+ try {
81
+ return this.toResult(await fn());
82
+ }
83
+ catch (err) {
84
+ return this.mapError(err);
85
+ }
86
+ }
87
+ toResult(res) {
88
+ const status = res.status ?? "";
89
+ if (SUCCESS_STATUS.test(status)) {
90
+ return {
91
+ success: true,
92
+ hash: res.hash ?? "",
93
+ ...(res.transactionId ? { transactionId: res.transactionId } : {}),
94
+ };
95
+ }
96
+ if (FAILURE_STATUS.test(status)) {
97
+ return failedTransaction(new RelayerError(`Relayer reported status "${res.status}"`, PasskeyKitErrorCode.RELAYER_REQUEST_FAILED, { status: res.status, transactionId: res.transactionId }), res.hash ?? undefined);
98
+ }
99
+ // Neither terminal-success nor terminal-failure: the transaction is still
100
+ // pending (e.g. a `skipWait` submit not yet polled to confirmation). Surface
101
+ // it as a distinct, NON-success result carrying RELAYER_PENDING — never as
102
+ // `success: true` — so a poll loop keeps polling instead of treating an
103
+ // unconfirmed (or later-reverted) transaction as done.
104
+ return failedTransaction(new RelayerError(`Relayer status "${res.status ?? "unknown"}" is not terminal (pending)`, PasskeyKitErrorCode.RELAYER_PENDING, { status: res.status, transactionId: res.transactionId, pending: true }), res.hash ?? undefined);
105
+ }
106
+ mapError(err) {
107
+ // Prefer a decoded contract error when the relayer surfaced one.
108
+ const details = err instanceof PluginClientError
109
+ ? err.errorDetails
110
+ : undefined;
111
+ const contractError = (err instanceof Error && decodeContractError(err.message)) ||
112
+ decodeContractError(details);
113
+ if (contractError) {
114
+ return failedTransaction(contractError);
115
+ }
116
+ if (err instanceof PluginClientError) {
117
+ return failedTransaction(new RelayerError(err.message, PasskeyKitErrorCode.RELAYER_REQUEST_FAILED, { category: err.category, details }, err));
118
+ }
119
+ return failedTransaction(new RelayerError(err instanceof Error ? err.message : String(err), PasskeyKitErrorCode.RELAYER_REQUEST_FAILED, undefined, err instanceof Error ? err : undefined));
120
+ }
121
+ }
122
+ //# sourceMappingURL=relayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relayer.js","sourceRoot":"","sources":["../src/relayer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Direct contract-data ledger reads that distinguish a genuine not-found from a
3
+ * transport failure.
4
+ *
5
+ * `Server.getContractData` collapses BOTH a real not-found AND any transport
6
+ * error (429/5xx/timeout, aborted fetch) into an identical `{ code: 404 }`
7
+ * throw, so a caller can't tell "the entry is gone" from "the RPC hiccuped".
8
+ * These helpers go one level lower: `getLedgerEntries` resolves with an empty
9
+ * `entries` array for a genuine not-found and only throws on an actual transport
10
+ * failure. That lets eviction detection and `getSigner`'s ownership check treat
11
+ * the two cases correctly instead of false-evicting live signers (audit H2) or
12
+ * reporting a valid passkey as "not a signer" on a flaky RPC.
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ import { xdr } from "@stellar/stellar-sdk";
17
+ import { Durability, type Server } from "@stellar/stellar-sdk/rpc";
18
+ /** Build the contract-data `LedgerKey` for a (contract, key, durability) triple. */
19
+ export declare function contractDataLedgerKey(contractId: string, key: xdr.ScVal, durability: Durability): xdr.LedgerKey;
20
+ /**
21
+ * Read a contract-data entry's stored ScVal, or `null` when the entry genuinely
22
+ * does not exist in that durability.
23
+ *
24
+ * Transport errors are NOT swallowed — they propagate so a caller never mistakes
25
+ * a flaky RPC for an absent entry.
26
+ */
27
+ export declare function readContractData(rpc: Server, contractId: string, key: xdr.ScVal, durability: Durability): Promise<xdr.ScVal | null>;
28
+ /**
29
+ * Whether a contract's instance entry exists on-chain.
30
+ *
31
+ * Returns `false` only on a genuine not-found; a transport error (429/5xx/
32
+ * timeout) throws. `connectWallet` uses this to confirm the deterministically
33
+ * derived wallet address: only an authoritative not-found may abandon the
34
+ * canonical derivation for the storage/indexer fallbacks — a flaky RPC must
35
+ * never reroute resolution away from the canonical derivation.
36
+ */
37
+ export declare function contractInstanceExists(rpc: Server, contractId: string): Promise<boolean>;
38
+ /**
39
+ * Whether a contract-data entry exists in the given durability.
40
+ *
41
+ * Returns `false` only on a genuine not-found; a transport error throws (so
42
+ * callers conclude eviction exclusively from an authoritative not-found).
43
+ */
44
+ export declare function contractDataExists(rpc: Server, contractId: string, key: xdr.ScVal, durability: Durability): Promise<boolean>;
45
+ //# sourceMappingURL=rpc-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-data.d.ts","sourceRoot":"","sources":["../src/rpc-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAW,GAAG,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEnE,oFAAoF;AACpF,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,GAAG,CAAC,KAAK,EACd,UAAU,EAAE,UAAU,GACrB,GAAG,CAAC,SAAS,CAWf;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,GAAG,CAAC,KAAK,EACd,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAM3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,GAAG,CAAC,KAAK,EACd,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,OAAO,CAAC,CAElB"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Direct contract-data ledger reads that distinguish a genuine not-found from a
3
+ * transport failure.
4
+ *
5
+ * `Server.getContractData` collapses BOTH a real not-found AND any transport
6
+ * error (429/5xx/timeout, aborted fetch) into an identical `{ code: 404 }`
7
+ * throw, so a caller can't tell "the entry is gone" from "the RPC hiccuped".
8
+ * These helpers go one level lower: `getLedgerEntries` resolves with an empty
9
+ * `entries` array for a genuine not-found and only throws on an actual transport
10
+ * failure. That lets eviction detection and `getSigner`'s ownership check treat
11
+ * the two cases correctly instead of false-evicting live signers (audit H2) or
12
+ * reporting a valid passkey as "not a signer" on a flaky RPC.
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ import { Address, xdr } from "@stellar/stellar-sdk";
17
+ import { Durability } from "@stellar/stellar-sdk/rpc";
18
+ /** Build the contract-data `LedgerKey` for a (contract, key, durability) triple. */
19
+ export function contractDataLedgerKey(contractId, key, durability) {
20
+ return xdr.LedgerKey.contractData(new xdr.LedgerKeyContractData({
21
+ contract: Address.fromString(contractId).toScAddress(),
22
+ key,
23
+ durability: durability === Durability.Temporary
24
+ ? xdr.ContractDataDurability.temporary()
25
+ : xdr.ContractDataDurability.persistent(),
26
+ }));
27
+ }
28
+ /**
29
+ * Read a contract-data entry's stored ScVal, or `null` when the entry genuinely
30
+ * does not exist in that durability.
31
+ *
32
+ * Transport errors are NOT swallowed — they propagate so a caller never mistakes
33
+ * a flaky RPC for an absent entry.
34
+ */
35
+ export async function readContractData(rpc, contractId, key, durability) {
36
+ const { entries } = await rpc.getLedgerEntries(contractDataLedgerKey(contractId, key, durability));
37
+ const entry = entries[0];
38
+ return entry ? entry.val.contractData().val() : null;
39
+ }
40
+ /**
41
+ * Whether a contract's instance entry exists on-chain.
42
+ *
43
+ * Returns `false` only on a genuine not-found; a transport error (429/5xx/
44
+ * timeout) throws. `connectWallet` uses this to confirm the deterministically
45
+ * derived wallet address: only an authoritative not-found may abandon the
46
+ * canonical derivation for the storage/indexer fallbacks — a flaky RPC must
47
+ * never reroute resolution away from the canonical derivation.
48
+ */
49
+ export async function contractInstanceExists(rpc, contractId) {
50
+ return contractDataExists(rpc, contractId, xdr.ScVal.scvLedgerKeyContractInstance(), Durability.Persistent);
51
+ }
52
+ /**
53
+ * Whether a contract-data entry exists in the given durability.
54
+ *
55
+ * Returns `false` only on a genuine not-found; a transport error throws (so
56
+ * callers conclude eviction exclusively from an authoritative not-found).
57
+ */
58
+ export async function contractDataExists(rpc, contractId, key, durability) {
59
+ return (await readContractData(rpc, contractId, key, durability)) !== null;
60
+ }
61
+ //# sourceMappingURL=rpc-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-data.js","sourceRoot":"","sources":["../src/rpc-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAe,MAAM,0BAA0B,CAAC;AAEnE,oFAAoF;AACpF,MAAM,UAAU,qBAAqB,CACnC,UAAkB,EAClB,GAAc,EACd,UAAsB;IAEtB,OAAO,GAAG,CAAC,SAAS,CAAC,YAAY,CAC/B,IAAI,GAAG,CAAC,qBAAqB,CAAC;QAC5B,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE;QACtD,GAAG;QACH,UAAU,EACR,UAAU,KAAK,UAAU,CAAC,SAAS;YACjC,CAAC,CAAC,GAAG,CAAC,sBAAsB,CAAC,SAAS,EAAE;YACxC,CAAC,CAAC,GAAG,CAAC,sBAAsB,CAAC,UAAU,EAAE;KAC9C,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAW,EACX,UAAkB,EAClB,GAAc,EACd,UAAsB;IAEtB,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAC5C,qBAAqB,CAAC,UAAU,EAAE,GAAG,EAAE,UAAU,CAAC,CACnD,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,GAAW,EACX,UAAkB;IAElB,OAAO,kBAAkB,CACvB,GAAG,EACH,UAAU,EACV,GAAG,CAAC,KAAK,CAAC,4BAA4B,EAAE,EACxC,UAAU,CAAC,UAAU,CACtB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAW,EACX,UAAkB,EAClB,GAAc,EACd,UAAsB;IAEtB,OAAO,CAAC,MAAM,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,KAAK,IAAI,CAAC;AAC7E,CAAC"}
package/dist/sac.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Stellar Asset Contract (SEP-41) helpers.
3
+ *
4
+ * DECISION (todo 950): keep the generated `sac-sdk` client rather than collapsing
5
+ * it to a bare `buildTokenTransferHostFunction` helper. The demo needs the full
6
+ * SEP-41 surface (balance, name/symbol/decimals reads, transfer) for token UX,
7
+ * which a transfer-only host-function builder cannot provide. We ALSO expose
8
+ * {@link buildTokenTransferHostFunction} for the low-level relayer `{func,auth}`
9
+ * path. (`sac-sdk` regeneration from a canonical source is handled in B4.)
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ import { xdr } from "@stellar/stellar-sdk";
14
+ import { Client as SacClient } from "sac-sdk";
15
+ /** A thin factory around the generated SEP-41 `sac-sdk` client. */
16
+ export declare class SACClient {
17
+ readonly networkPassphrase: string;
18
+ readonly rpcUrl: string;
19
+ constructor(options: {
20
+ networkPassphrase: string;
21
+ rpcUrl: string;
22
+ });
23
+ /** Build a SEP-41 client for a specific SAC/token contract. */
24
+ getSACClient(sacContractId: string): SacClient;
25
+ }
26
+ /**
27
+ * Build a raw SEP-41 `transfer(from, to, amount)` host function, for the
28
+ * low-level relayer `{ func, auth }` submission path (no client instance needed).
29
+ */
30
+ export declare function buildTokenTransferHostFunction(tokenContract: string, from: string, to: string, amountInStroops: bigint): xdr.HostFunction;
31
+ //# sourceMappingURL=sac.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sac.d.ts","sourceRoot":"","sources":["../src/sac.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAW,GAAG,EAAiB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,SAAS,CAAC;AAE9C,mEAAmE;AACnE,qBAAa,SAAS;IACpB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,OAAO,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;IAKlE,+DAA+D;IAC/D,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS;CAO/C;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,MAAM,GACtB,GAAG,CAAC,YAAY,CAYlB"}
package/dist/sac.js ADDED
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Stellar Asset Contract (SEP-41) helpers.
3
+ *
4
+ * DECISION (todo 950): keep the generated `sac-sdk` client rather than collapsing
5
+ * it to a bare `buildTokenTransferHostFunction` helper. The demo needs the full
6
+ * SEP-41 surface (balance, name/symbol/decimals reads, transfer) for token UX,
7
+ * which a transfer-only host-function builder cannot provide. We ALSO expose
8
+ * {@link buildTokenTransferHostFunction} for the low-level relayer `{func,auth}`
9
+ * path. (`sac-sdk` regeneration from a canonical source is handled in B4.)
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ import { Address, xdr, nativeToScVal } from "@stellar/stellar-sdk";
14
+ import { Client as SacClient } from "sac-sdk";
15
+ /** A thin factory around the generated SEP-41 `sac-sdk` client. */
16
+ export class SACClient {
17
+ networkPassphrase;
18
+ rpcUrl;
19
+ constructor(options) {
20
+ this.networkPassphrase = options.networkPassphrase;
21
+ this.rpcUrl = options.rpcUrl;
22
+ }
23
+ /** Build a SEP-41 client for a specific SAC/token contract. */
24
+ getSACClient(sacContractId) {
25
+ return new SacClient({
26
+ contractId: sacContractId,
27
+ networkPassphrase: this.networkPassphrase,
28
+ rpcUrl: this.rpcUrl,
29
+ });
30
+ }
31
+ }
32
+ /**
33
+ * Build a raw SEP-41 `transfer(from, to, amount)` host function, for the
34
+ * low-level relayer `{ func, auth }` submission path (no client instance needed).
35
+ */
36
+ export function buildTokenTransferHostFunction(tokenContract, from, to, amountInStroops) {
37
+ return xdr.HostFunction.hostFunctionTypeInvokeContract(new xdr.InvokeContractArgs({
38
+ contractAddress: Address.fromString(tokenContract).toScAddress(),
39
+ functionName: "transfer",
40
+ args: [
41
+ xdr.ScVal.scvAddress(Address.fromString(from).toScAddress()),
42
+ xdr.ScVal.scvAddress(Address.fromString(to).toScAddress()),
43
+ nativeToScVal(amountInStroops, { type: "i128" }),
44
+ ],
45
+ }));
46
+ }
47
+ //# sourceMappingURL=sac.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sac.js","sourceRoot":"","sources":["../src/sac.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,SAAS,CAAC;AAE9C,mEAAmE;AACnE,MAAM,OAAO,SAAS;IACX,iBAAiB,CAAS;IAC1B,MAAM,CAAS;IAExB,YAAY,OAAsD;QAChE,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;QACnD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,+DAA+D;IAC/D,YAAY,CAAC,aAAqB;QAChC,OAAO,IAAI,SAAS,CAAC;YACnB,UAAU,EAAE,aAAa;YACzB,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAC5C,aAAqB,EACrB,IAAY,EACZ,EAAU,EACV,eAAuB;IAEvB,OAAO,GAAG,CAAC,YAAY,CAAC,8BAA8B,CACpD,IAAI,GAAG,CAAC,kBAAkB,CAAC;QACzB,eAAe,EAAE,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE;QAChE,YAAY,EAAE,UAAU;QACxB,IAAI,EAAE;YACJ,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAC5D,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;YAC1D,aAAa,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SACjD;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * `PasskeyServer` — the SERVER-ONLY counterpart to {@link PasskeyKit}.
3
+ *
4
+ * It holds the relayer API key and therefore must never run in a browser
5
+ * bundle: it is exported exclusively from the `passkey-kit/server` subpath so a
6
+ * bundler can't pull it into client code, and its config must come from
7
+ * server-side environment variables (never `VITE_`-prefixed).
8
+ *
9
+ * Responsibilities: fee-sponsored submission via {@link RelayerClient} and
10
+ * convenience signer-discovery helpers that delegate to a {@link MercuryIndexer}
11
+ * over Mercury's keyless hosted passkey-indexer. (`MercuryIndexer` itself is
12
+ * keyless and browser-safe — exported from the main `passkey-kit` entry; these
13
+ * server methods are a thin convenience over it.)
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+ import { type Transaction } from "@stellar/stellar-sdk";
18
+ import { Server } from "@stellar/stellar-sdk/rpc";
19
+ import { AssembledTransaction } from "@stellar/stellar-sdk/contract";
20
+ import { type RelayerClientConfig, type RelayerSubmitOptions } from "./relayer.js";
21
+ import type { WalletSigner } from "./indexer/index.js";
22
+ import type { TransactionResult } from "./types.js";
23
+ export { RelayerClient, type RelayerClientConfig, type RelayerSubmitOptions, } from "./relayer.js";
24
+ /** Mercury hosted passkey-indexer configuration (keyless). */
25
+ export interface MercuryConfig {
26
+ /**
27
+ * Passkey-indexer base URL. Defaults to the network's hosted endpoint
28
+ * (`https://{testnet,mainnet}.mercurydata.app/rest/passkey-indexer`); set it
29
+ * only to point at a self-hosted instance.
30
+ */
31
+ url?: string;
32
+ }
33
+ /** Configuration for a {@link PasskeyServer}. */
34
+ export interface PasskeyServerConfig {
35
+ /** Network passphrase (required). */
36
+ networkPassphrase: string;
37
+ /** Stellar RPC URL (needed for temporary-signer eviction probes). */
38
+ rpcUrl?: string;
39
+ /** Relayer configuration for fee-sponsored submission. */
40
+ relayer?: RelayerClientConfig;
41
+ /** Mercury indexer configuration. */
42
+ mercury?: MercuryConfig;
43
+ }
44
+ export declare class PasskeyServer {
45
+ readonly networkPassphrase: string;
46
+ readonly rpc?: Server;
47
+ private readonly relayer?;
48
+ private readonly mercury?;
49
+ constructor(config: PasskeyServerConfig);
50
+ /**
51
+ * Submit a transaction via the relayer for fee sponsorship.
52
+ *
53
+ * invokeHostFunction transactions without source-account auth use the preferred
54
+ * `{ func, auth }` Soroban path; everything else (deploys, source-account auth)
55
+ * is fee-bumped via the `{ xdr }` envelope path. Never throws — returns a typed
56
+ * {@link TransactionResult}.
57
+ */
58
+ send(input: AssembledTransaction<unknown> | Transaction | string, options?: RelayerSubmitOptions): Promise<TransactionResult>;
59
+ /** Poll a `skipWait` submission by its relayer transaction id. */
60
+ getTransaction(transactionId: string): Promise<TransactionResult>;
61
+ private requireMercury;
62
+ /**
63
+ * Enumerate a wallet's signers via Mercury. Temporary signers whose ledger
64
+ * entry has been evicted are flagged `status: "evicted"` when this server was
65
+ * given an `rpcUrl` (the indexer can't observe TTL eviction directly).
66
+ */
67
+ getSigners(contractId: string): Promise<WalletSigner[]>;
68
+ /**
69
+ * Reverse lookup: find the wallet(s) a signer belongs to via Mercury.
70
+ *
71
+ * @returns the confirmed address at `index`, or `undefined` if there are none.
72
+ */
73
+ getContractId(options: {
74
+ keyId?: string;
75
+ publicKey?: string;
76
+ policy?: string;
77
+ }, index?: number): Promise<string | undefined>;
78
+ }
79
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAiB,KAAK,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AASlG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAIpD,OAAO,EACL,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,cAAc,CAAC;AAEtB,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,iDAAiD;AACjD,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,qCAAqC;IACrC,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAmCD,qBAAa,aAAa;IACxB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAiB;gBAE9B,MAAM,EAAE,mBAAmB;IAgCvC;;;;;;;OAOG;IACG,IAAI,CACR,KAAK,EAAE,oBAAoB,CAAC,OAAO,CAAC,GAAG,WAAW,GAAG,MAAM,EAC3D,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,iBAAiB,CAAC;IAmC7B,kEAAkE;IAClE,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAgBjE,OAAO,CAAC,cAAc;IAUtB;;;;OAIG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAIvD;;;;OAIG;IACG,aAAa,CACjB,OAAO,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAChE,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CAmB/B"}