@soropass/core 0.1.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 (83) hide show
  1. package/dist/checkAuth-C2AcXqFe.d.cts +110 -0
  2. package/dist/checkAuth-C2AcXqFe.d.ts +110 -0
  3. package/dist/chunk-AHFGTIBY.js +36 -0
  4. package/dist/chunk-AHFGTIBY.js.map +1 -0
  5. package/dist/chunk-AMYFJQAC.js +29 -0
  6. package/dist/chunk-AMYFJQAC.js.map +1 -0
  7. package/dist/chunk-BIRF5I6I.js +265 -0
  8. package/dist/chunk-BIRF5I6I.js.map +1 -0
  9. package/dist/chunk-JNJ2FY45.js +209 -0
  10. package/dist/chunk-JNJ2FY45.js.map +1 -0
  11. package/dist/chunk-LB4HOTLV.js +135 -0
  12. package/dist/chunk-LB4HOTLV.js.map +1 -0
  13. package/dist/chunk-LM2AZXKZ.js +108 -0
  14. package/dist/chunk-LM2AZXKZ.js.map +1 -0
  15. package/dist/chunk-LUDXP56M.js +3 -0
  16. package/dist/chunk-LUDXP56M.js.map +1 -0
  17. package/dist/chunk-MMB4ZIW3.js +48 -0
  18. package/dist/chunk-MMB4ZIW3.js.map +1 -0
  19. package/dist/chunk-MOLZIRIH.js +22 -0
  20. package/dist/chunk-MOLZIRIH.js.map +1 -0
  21. package/dist/chunk-OGSUGATA.js +3 -0
  22. package/dist/chunk-OGSUGATA.js.map +1 -0
  23. package/dist/chunk-TPBBZNPP.js +30 -0
  24. package/dist/chunk-TPBBZNPP.js.map +1 -0
  25. package/dist/chunk-UQKNPO44.js +32 -0
  26. package/dist/chunk-UQKNPO44.js.map +1 -0
  27. package/dist/chunk-UV5HORMF.js +175 -0
  28. package/dist/chunk-UV5HORMF.js.map +1 -0
  29. package/dist/chunk-W75OQKHR.js +133 -0
  30. package/dist/chunk-W75OQKHR.js.map +1 -0
  31. package/dist/connect.cjs +166 -0
  32. package/dist/connect.cjs.map +1 -0
  33. package/dist/connect.d.cts +24 -0
  34. package/dist/connect.d.ts +24 -0
  35. package/dist/connect.js +6 -0
  36. package/dist/connect.js.map +1 -0
  37. package/dist/create.cjs +483 -0
  38. package/dist/create.cjs.map +1 -0
  39. package/dist/create.d.cts +106 -0
  40. package/dist/create.d.ts +106 -0
  41. package/dist/create.js +8 -0
  42. package/dist/create.js.map +1 -0
  43. package/dist/index.cjs +1542 -0
  44. package/dist/index.cjs.map +1 -0
  45. package/dist/index.d.cts +197 -0
  46. package/dist/index.d.ts +197 -0
  47. package/dist/index.js +354 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/recover-0wbOXDjR.d.cts +23 -0
  50. package/dist/recover-COnsxhYk.d.ts +23 -0
  51. package/dist/recover.cjs +802 -0
  52. package/dist/recover.cjs.map +1 -0
  53. package/dist/recover.d.cts +49 -0
  54. package/dist/recover.d.ts +49 -0
  55. package/dist/recover.js +10 -0
  56. package/dist/recover.js.map +1 -0
  57. package/dist/sign-Cfg0NM0T.d.cts +73 -0
  58. package/dist/sign-Cfg0NM0T.d.ts +73 -0
  59. package/dist/sign.cjs +883 -0
  60. package/dist/sign.cjs.map +1 -0
  61. package/dist/sign.d.cts +143 -0
  62. package/dist/sign.d.ts +143 -0
  63. package/dist/sign.js +8 -0
  64. package/dist/sign.js.map +1 -0
  65. package/dist/submit-BDKADQq0.d.cts +112 -0
  66. package/dist/submit-BO0Nh49I.d.ts +112 -0
  67. package/dist/testing.cjs +955 -0
  68. package/dist/testing.cjs.map +1 -0
  69. package/dist/testing.d.cts +86 -0
  70. package/dist/testing.d.ts +86 -0
  71. package/dist/testing.js +235 -0
  72. package/dist/testing.js.map +1 -0
  73. package/dist/types--WNl-Sda.d.cts +125 -0
  74. package/dist/types--WNl-Sda.d.ts +125 -0
  75. package/dist/types-dMRWEEo0.d.cts +73 -0
  76. package/dist/types-lW2h8Uxn.d.ts +73 -0
  77. package/dist/types.cjs +44 -0
  78. package/dist/types.cjs.map +1 -0
  79. package/dist/types.d.cts +5 -0
  80. package/dist/types.d.ts +5 -0
  81. package/dist/types.js +5 -0
  82. package/dist/types.js.map +1 -0
  83. package/package.json +117 -0
@@ -0,0 +1,197 @@
1
+ export { B as BATTLE_TESTED_ANCHORS, a as BattleTestedAnchor, K as KIT_ERROR_CODES, b as KitError, c as KitErrorCode, P as PasskeyCredential, d as assertES256, e as assertUserActivation, i as isKitError } from './types-lW2h8Uxn.js';
2
+ export { CreatePasskeyOptions, DeriveAccountAddressOptions, DeriveSmartWalletAddressOptions, RegisterPasskeyOptions, RegisteredPasskey, browserWebAuthnClient, coseKeyToSec1, createPasskey, defaultCredentialStorage, deriveAccountAddress, deriveSmartWalletAddress, extractPublicKeyFromAttestationObject, extractPublicKeyFromAuthData, registerPasskey } from './create.js';
3
+ import { S as SubmissionAdapter, b as ResolvedAccount, I as IndexerAdapter, A as AccountDeployer } from './types--WNl-Sda.js';
4
+ export { B as BuildCreateOptionsInput, C as CredentialStorage, P as PubKeyCredParam, a as PublicKeyCredentialCreationOptionsJSON, R as ResidentKeyRequirement, c as SubmitResult, U as UserVerificationRequirement, W as WebAuthnClient, d as WebAuthnCreateResult, e as WebAuthnGetOptions, f as WebAuthnGetResult, g as buildCreateOptions } from './types--WNl-Sda.js';
5
+ export { BrowserPasskeySignerOptions, applyAssertionToEntry, applyAssertionToSmartWalletEntry, authEntryChallenge, authEntryChallengeBytes, browserPasskeySigner, buildSignerKeyScVal, buildSmartWalletSignatureVariant, compareSignerKeyScVal, derToCompact, derToCompactLowS, isLowS, normalizeLowS, reconstructSignedPayload } from './sign.js';
6
+ export { A as AuthenticatorDataFlags, C as CheckAuthResult, a as ClientData, P as ParsedAuthenticatorData, S as SmartWalletCheckAuthResult, V as VerifyAssertionInput, d as decodeChallenge, e as encodeChallenge, p as parseAuthenticatorData, b as parseClientDataJSON, r as referenceCheckAuth, c as referenceSmartWalletCheckAuth, v as verifyAssertionSignature, f as verifyClientDataJSON, g as verifyRpIdHash } from './checkAuth-C2AcXqFe.js';
7
+ export { A as AssertionResult, S as SignVerifyOptions, a as SorobanSignOptions, W as WalletTarget, b as WebAuthnSigner, s as signAuthEntry, c as signTransaction } from './sign-Cfg0NM0T.js';
8
+ export { B as BuildAddSignerOptions, a as BuildRemoveSignerOptions, S as Secp256r1SignerSpec, b as SendSmartWalletTxOptions, c as SignerStorage, d as buildAddSignerOperation, e as buildRemoveSignerOperation, f as buildSecp256r1Signer, s as sendSmartWalletTx } from './submit-BO0Nh49I.js';
9
+ export { ConnectOptions, ConnectResult, connect } from './connect.js';
10
+ export { R as RecoverOptions, a as RecoverResult, r as recover } from './recover-COnsxhYk.js';
11
+ export { AddSignerOptions, NewDeviceSigner, RemoveSignerOptions, WalletCallOptions, addSigner, removeSigner } from './recover.js';
12
+ import { rpc } from '@stellar/stellar-sdk';
13
+
14
+ interface DirectSubmissionOptions {
15
+ rpcUrl: string;
16
+ networkPassphrase: string;
17
+ allowHttp?: boolean;
18
+ /** Max confirmation-poll attempts before failing with NETWORK_ERROR (default 30). */
19
+ pollAttempts?: number;
20
+ /** Delay between confirmation polls, in ms (default 1000). */
21
+ pollIntervalMs?: number;
22
+ }
23
+ /**
24
+ * Default, zero-infra submission: send straight to soroban-rpc and poll. No
25
+ * relayer, no API key. Swappable with `launchtube`/`openzeppelinRelayer` with
26
+ * zero ceremony changes (same `SubmissionAdapter` shape).
27
+ */
28
+ declare function directSubmission(options: DirectSubmissionOptions): SubmissionAdapter;
29
+
30
+ /**
31
+ * Bounded retry/backoff for the optional HTTP adapters (Launchtube / OZ Relayer /
32
+ * Mercury). Opt-in: `retries` defaults to 1 (no retry), preserving the plain
33
+ * single-shot behavior unless a caller asks for resilience.
34
+ */
35
+ interface RetryOptions {
36
+ /** Total attempts including the first (default 1 = no retry). */
37
+ retries?: number;
38
+ /** Linear backoff base in ms; attempt N waits `backoffMs * N` (default 300). */
39
+ backoffMs?: number;
40
+ }
41
+
42
+ interface LaunchtubeSubmissionOptions {
43
+ url: string;
44
+ /** Bearer token (Launchtube is invite/credit-gated). */
45
+ token?: string;
46
+ /** Optional bounded retry on transient (429 / 5xx / network) failures. */
47
+ retry?: RetryOptions;
48
+ }
49
+ /**
50
+ * Legacy Launchtube relay (optional). Modelled as ONE submission adapter — the
51
+ * SDK does not depend on it; `direct` is the default and `openzeppelinRelayer`
52
+ * is the post-Launchtube direction. A network failure surfaces as a typed
53
+ * `KitError('NETWORK_ERROR')`; an HTTP error becomes a `FAILED` result carrying
54
+ * the relay's error body.
55
+ */
56
+ declare function launchtubeSubmission(options: LaunchtubeSubmissionOptions): SubmissionAdapter;
57
+
58
+ interface OpenZeppelinRelayerOptions {
59
+ url: string;
60
+ apiKey?: string;
61
+ /** Optional bounded retry on transient (429 / 5xx / network) failures. */
62
+ retry?: RetryOptions;
63
+ }
64
+ /**
65
+ * OpenZeppelin Relayer / Channels submission (the post-Launchtube direction).
66
+ * Same `SubmissionAdapter` shape, so swapping it in is a one-line config change.
67
+ * A network failure surfaces as `KitError('NETWORK_ERROR')`; an HTTP error (or a
68
+ * `status: "failed"` body) becomes a `FAILED` result.
69
+ */
70
+ declare function openzeppelinRelayerSubmission(options: OpenZeppelinRelayerOptions): SubmissionAdapter;
71
+
72
+ interface EventsIndexerOptions {
73
+ rpcUrl: string;
74
+ /** The passkey factory contract that emits an `add`/deploy event per account. */
75
+ factoryContractId: string;
76
+ /** Ledger to scan from; defaults to ~1 day back from the latest ledger. */
77
+ startLedger?: number;
78
+ allowHttp?: boolean;
79
+ /**
80
+ * Map a factory event → resolved account when it concerns `credentialId`.
81
+ * Defaults to the deployed `AccountFactory` schema (see contracts/account-factory):
82
+ * topics `[symbol "deployed", bytes credentialId]`, value = the deployed C-address.
83
+ * Override only for a different factory event shape.
84
+ */
85
+ matchEvent?: (event: rpc.Api.EventResponse, credentialId: string) => ResolvedAccount | null;
86
+ }
87
+ /**
88
+ * Default, zero-infra indexer: soroban-rpc `getEvents` filtered on the factory
89
+ * contract — no external indexing service. `mercury` is an optional alternative;
90
+ * the SDK works with `events` alone.
91
+ */
92
+ declare function eventsIndexer(options: EventsIndexerOptions): IndexerAdapter;
93
+
94
+ interface MercuryIndexerOptions {
95
+ url: string;
96
+ token?: string;
97
+ /** Map the Mercury/Zephyr JSON response → resolved accounts. */
98
+ parse?: (json: unknown) => ResolvedAccount[];
99
+ /** Optional bounded retry on transient (429 / 5xx / network) failures. */
100
+ retry?: RetryOptions;
101
+ }
102
+ /**
103
+ * Optional Mercury (Zephyr) indexer. Entirely optional — `events` is the
104
+ * zero-infra default and the SDK never requires Mercury. A network failure
105
+ * surfaces as `KitError('NETWORK_ERROR')`; an HTTP error throws
106
+ * `NETWORK_ERROR` too, so a server error is never silently read as "no accounts".
107
+ */
108
+ declare function mercuryIndexer(options: MercuryIndexerOptions): IndexerAdapter;
109
+
110
+ interface DefaultAdapterOptions {
111
+ rpcUrl: string;
112
+ networkPassphrase: string;
113
+ factoryContractId: string;
114
+ allowHttp?: boolean;
115
+ }
116
+ /** The zero-infra default stack: `direct` submission + `events` indexer. */
117
+ declare function defaultAdapters(options: DefaultAdapterOptions): {
118
+ submission: SubmissionAdapter;
119
+ indexer: IndexerAdapter;
120
+ };
121
+
122
+ interface FactoryDeployerOptions {
123
+ rpcUrl: string;
124
+ networkPassphrase: string;
125
+ /** The deployed `AccountFactory` contract id (`C…`) — see contracts/account-factory. */
126
+ factoryContractId: string;
127
+ /**
128
+ * Secret of the testnet account that pays the fee + signs the deploy tx. The
129
+ * factory's `deploy` is not auth-gated, so this just sources/sponsors the
130
+ * transaction. In a public demo this is an ephemeral, friendbot-funded key —
131
+ * never a key with value.
132
+ */
133
+ sourceSecret: string;
134
+ allowHttp?: boolean;
135
+ fee?: string;
136
+ }
137
+ /**
138
+ * `AccountDeployer` backed by the on-chain `AccountFactory`: invokes
139
+ * `factory.deploy(public_key, credential_id)`, which deploys a fresh
140
+ * `webauthn-account` for the passkey and emits the `(deployed, credentialId)`
141
+ * event the `eventsIndexer` resolves. Returns the new smart-account C-address.
142
+ * This is the real "create a passkey wallet on-chain" path.
143
+ */
144
+ declare function factoryDeployer(options: FactoryDeployerOptions): AccountDeployer;
145
+
146
+ /** The canonical audited v1 smart-wallet wasm hash on testnet (kalepail #32). */
147
+ declare const SMART_WALLET_V1_WASM_HASH = "84924c53a413318df2ce753e30de53ec651404c916d30e861718ad155c94b319";
148
+ interface SmartWalletV1DeployerOptions {
149
+ rpcUrl: string;
150
+ networkPassphrase: string;
151
+ /**
152
+ * Secret of the funded classic account that deploys + pays. It must be STABLE so
153
+ * the deployed address stays offline-derivable via {@link deriveSmartWalletAddress}
154
+ * (the deployer is part of the contract-id preimage). In a demo this is a fixed
155
+ * friendbot-funded key; in production a wallet team's deployer/relayer.
156
+ */
157
+ deployerSecret: string;
158
+ /** v1 smart-wallet wasm hash (hex). Defaults to the canonical testnet hash. */
159
+ wasmHash?: string;
160
+ allowHttp?: boolean;
161
+ fee?: string;
162
+ }
163
+ /**
164
+ * `AccountDeployer` for the passkey-kit **v1 smart-wallet**: deploys a fresh wallet
165
+ * from the audited wasm via `createCustomContract`, salted by
166
+ * `sha256(rawCredentialId)` from a fixed deployer — so the address is deterministic
167
+ * and offline-derivable. The contract's first `add_signer` (from `__constructor`)
168
+ * is unauthenticated, so the deploy is a plain source-signed transaction. Pair with
169
+ * {@link deriveSmartWalletAddress} for `getAddress` and {@link smartWalletV1Indexer}
170
+ * for recovery.
171
+ */
172
+ declare function smartWalletV1Deployer(options: SmartWalletV1DeployerOptions): AccountDeployer;
173
+ interface SmartWalletV1IndexerOptions {
174
+ rpcUrl: string;
175
+ /** Ledger to scan from; defaults to ~1 day back. The events RPC retains a limited window. */
176
+ startLedger?: number;
177
+ allowHttp?: boolean;
178
+ }
179
+ /**
180
+ * `IndexerAdapter` for the v1 smart-wallet: resolves a credential id → wallet
181
+ * address from the on-chain `signer_added` events. Schema confirmed empirically
182
+ * against the deployed v0.13.0 wasm (`scripts/v1-events-probe.ts`):
183
+ * `topic[0]=Symbol("signer_added")`, `topic[1]=SignerKey::Secp256r1(rawCredId)`,
184
+ * and the wallet is the EMITTING contract. Works for BOTH the founding credential
185
+ * (deploy emits `signer_added`) and signers added later via `add_signer`.
186
+ *
187
+ * A single `getEvents` call only scans a bounded ledger slice from `startLedger`
188
+ * (not the whole window) and returns a cursor, so a naive one-shot query misses
189
+ * events near the tip — the exact reason recovery of a just-created wallet found
190
+ * nothing. We therefore PAGINATE by cursor from `startLedger` to the tip,
191
+ * accumulating every wallet the credential signs for. soroban-rpc retains only a
192
+ * limited window, so this is the zero-infra default for recent wallets; use a
193
+ * persistent indexer (Mercury) for older ones.
194
+ */
195
+ declare function smartWalletV1Indexer(options: SmartWalletV1IndexerOptions): IndexerAdapter;
196
+
197
+ export { AccountDeployer, type DefaultAdapterOptions, type DirectSubmissionOptions, type EventsIndexerOptions, type FactoryDeployerOptions, IndexerAdapter, type LaunchtubeSubmissionOptions, type MercuryIndexerOptions, type OpenZeppelinRelayerOptions, ResolvedAccount, SMART_WALLET_V1_WASM_HASH, type SmartWalletV1DeployerOptions, type SmartWalletV1IndexerOptions, SubmissionAdapter, defaultAdapters, directSubmission, eventsIndexer, factoryDeployer, launchtubeSubmission, mercuryIndexer, openzeppelinRelayerSubmission, smartWalletV1Deployer, smartWalletV1Indexer };
package/dist/index.js ADDED
@@ -0,0 +1,354 @@
1
+ import { deriveSmartWalletAddress } from './chunk-MMB4ZIW3.js';
2
+ export { deriveAccountAddress, deriveSmartWalletAddress } from './chunk-MMB4ZIW3.js';
3
+ import './chunk-OGSUGATA.js';
4
+ export { browserPasskeySigner, referenceCheckAuth, referenceSmartWalletCheckAuth } from './chunk-LM2AZXKZ.js';
5
+ export { addSigner, removeSigner } from './chunk-UQKNPO44.js';
6
+ import { directSubmission, buildSecp256r1Signer } from './chunk-UV5HORMF.js';
7
+ export { buildAddSignerOperation, buildRemoveSignerOperation, buildSecp256r1Signer, directSubmission, sendSmartWalletTx } from './chunk-UV5HORMF.js';
8
+ import './chunk-LUDXP56M.js';
9
+ export { buildCreateOptions, coseKeyToSec1, createPasskey, extractPublicKeyFromAttestationObject, extractPublicKeyFromAuthData, registerPasskey } from './chunk-W75OQKHR.js';
10
+ export { connect } from './chunk-AHFGTIBY.js';
11
+ export { recover } from './chunk-MOLZIRIH.js';
12
+ import { buildSignerKeyScVal } from './chunk-BIRF5I6I.js';
13
+ export { applyAssertionToEntry, applyAssertionToSmartWalletEntry, authEntryChallenge, authEntryChallengeBytes, buildSignerKeyScVal, buildSmartWalletSignatureVariant, compareSignerKeyScVal, derToCompact, derToCompactLowS, isLowS, normalizeLowS, reconstructSignedPayload, signAuthEntry, signTransaction, verifyAssertionSignature } from './chunk-BIRF5I6I.js';
14
+ import { decodeChallenge } from './chunk-JNJ2FY45.js';
15
+ export { decodeChallenge, encodeChallenge, parseAuthenticatorData, parseClientDataJSON, verifyClientDataJSON, verifyRpIdHash } from './chunk-JNJ2FY45.js';
16
+ export { browserWebAuthnClient, defaultCredentialStorage } from './chunk-LB4HOTLV.js';
17
+ export { BATTLE_TESTED_ANCHORS, assertES256, assertUserActivation } from './chunk-TPBBZNPP.js';
18
+ import { KitError } from './chunk-AMYFJQAC.js';
19
+ export { KIT_ERROR_CODES, KitError, isKitError } from './chunk-AMYFJQAC.js';
20
+ import { rpc, Keypair, nativeToScVal, TransactionBuilder, Contract, scValToNative, Operation, Address, xdr } from '@stellar/stellar-sdk';
21
+ import { sha256 } from '@noble/hashes/sha256';
22
+
23
+ // src/adapters/http.ts
24
+ var sleep = (ms) => ms > 0 ? new Promise((resolve) => setTimeout(resolve, ms)) : Promise.resolve();
25
+ function isTransientStatus(status) {
26
+ return status === 429 || status >= 500;
27
+ }
28
+ async function httpPost(url, init, retry) {
29
+ const attempts = Math.max(1, retry?.retries ?? 1);
30
+ const backoffMs = retry?.backoffMs ?? 300;
31
+ for (let i = 1; i <= attempts; i++) {
32
+ try {
33
+ const response = await fetch(url, {
34
+ method: "POST",
35
+ headers: init.headers,
36
+ body: init.body
37
+ });
38
+ if (isTransientStatus(response.status) && i < attempts) {
39
+ await sleep(backoffMs * i);
40
+ continue;
41
+ }
42
+ return response;
43
+ } catch (cause) {
44
+ if (i < attempts) {
45
+ await sleep(backoffMs * i);
46
+ continue;
47
+ }
48
+ throw new KitError("NETWORK_ERROR", `POST to ${url} failed`, { cause });
49
+ }
50
+ }
51
+ throw new KitError("NETWORK_ERROR", `POST to ${url} failed`);
52
+ }
53
+
54
+ // src/adapters/launchtube.ts
55
+ function launchtubeSubmission(options) {
56
+ return {
57
+ async send(signedTxXdr) {
58
+ const headers = {
59
+ "content-type": "application/x-www-form-urlencoded"
60
+ };
61
+ if (options.token) headers["authorization"] = `Bearer ${options.token}`;
62
+ const response = await httpPost(
63
+ options.url,
64
+ { headers, body: new URLSearchParams({ xdr: signedTxXdr }).toString() },
65
+ options.retry
66
+ );
67
+ const body = await response.json().catch(() => ({}));
68
+ if (!response.ok || body.status === "FAILED" || body.error) {
69
+ return { status: "FAILED", hash: body.hash ?? "", errorResultXdr: body.errorResultXdr };
70
+ }
71
+ return { status: "SUCCESS", hash: body.hash ?? "", returnValue: body };
72
+ }
73
+ };
74
+ }
75
+
76
+ // src/adapters/ozRelayer.ts
77
+ function openzeppelinRelayerSubmission(options) {
78
+ return {
79
+ async send(signedTxXdr) {
80
+ const headers = { "content-type": "application/json" };
81
+ if (options.apiKey) headers["authorization"] = `Bearer ${options.apiKey}`;
82
+ const response = await httpPost(
83
+ options.url,
84
+ { headers, body: JSON.stringify({ transaction_xdr: signedTxXdr }) },
85
+ options.retry
86
+ );
87
+ const body = await response.json().catch(() => ({}));
88
+ if (!response.ok || body.status === "failed") {
89
+ return { status: "FAILED", hash: body.hash ?? "", errorResultXdr: body.errorResultXdr };
90
+ }
91
+ return { status: "SUCCESS", hash: body.hash ?? "", returnValue: body };
92
+ }
93
+ };
94
+ }
95
+
96
+ // src/adapters/eventsPaging.ts
97
+ var EVENTS_PAGE_LIMIT = 1e4;
98
+ var MAX_EVENT_PAGES = 40;
99
+ function cursorLedger(cursor) {
100
+ try {
101
+ const toid = cursor.split("-")[0];
102
+ if (!toid) return null;
103
+ return Number(BigInt(toid) >> 32n);
104
+ } catch {
105
+ return null;
106
+ }
107
+ }
108
+ function parseOldestLedger(error) {
109
+ const raw = typeof error === "object" && error !== null && "message" in error ? error.message : error;
110
+ const message = typeof raw === "string" ? raw : String(raw);
111
+ const match = /ledger range:\s*(\d+)\s*-\s*\d+/.exec(message);
112
+ return match ? Number(match[1]) : null;
113
+ }
114
+ async function collectEventsToTip(server, filters, startLedger) {
115
+ const events = [];
116
+ let start = startLedger;
117
+ let cursor;
118
+ let previousCursor;
119
+ for (let page = 0; page < MAX_EVENT_PAGES; page++) {
120
+ let response;
121
+ try {
122
+ response = await server.getEvents(
123
+ cursor ? { filters, cursor, limit: EVENTS_PAGE_LIMIT } : { filters, startLedger: start, limit: EVENTS_PAGE_LIMIT }
124
+ );
125
+ } catch (error) {
126
+ const oldest = parseOldestLedger(error);
127
+ if (!cursor && oldest != null && start <= oldest) {
128
+ start = oldest + 2;
129
+ continue;
130
+ }
131
+ throw error;
132
+ }
133
+ events.push(...response.events);
134
+ previousCursor = cursor;
135
+ cursor = response.cursor;
136
+ if (!cursor || cursor === previousCursor) break;
137
+ const scanned = cursorLedger(cursor);
138
+ if (scanned != null && scanned >= response.latestLedger) break;
139
+ }
140
+ return events;
141
+ }
142
+
143
+ // src/adapters/events.ts
144
+ function decodeNative(scv) {
145
+ try {
146
+ return scValToNative(scv);
147
+ } catch {
148
+ return void 0;
149
+ }
150
+ }
151
+ var LEDGERS_PER_DAY = 17280;
152
+ function defaultMatch(event, credentialId) {
153
+ try {
154
+ const topics = event.topic ?? [];
155
+ if (topics.length >= 2) {
156
+ const tag = decodeNative(topics[0]);
157
+ const credRaw = decodeNative(topics[1]);
158
+ const cred = credRaw instanceof Uint8Array ? new TextDecoder().decode(credRaw) : String(credRaw ?? "");
159
+ if (tag === "deployed" && cred === credentialId) {
160
+ const addr2 = decodeNative(event.value);
161
+ if (typeof addr2 === "string" && addr2.startsWith("C")) return { contractId: addr2 };
162
+ }
163
+ }
164
+ const haystack = [event.value, ...topics].map((v) => v.toXDR("base64")).join("|");
165
+ if (!haystack.includes(credentialId)) return null;
166
+ const addr = decodeNative(event.value);
167
+ if (typeof addr === "string" && addr.startsWith("C")) return { contractId: addr };
168
+ return event.contractId ? { contractId: event.contractId.toString() } : null;
169
+ } catch {
170
+ return null;
171
+ }
172
+ }
173
+ function eventsIndexer(options) {
174
+ const server = new rpc.Server(options.rpcUrl, {
175
+ allowHttp: options.allowHttp ?? options.rpcUrl.startsWith("http://")
176
+ });
177
+ const match = options.matchEvent ?? defaultMatch;
178
+ return {
179
+ async resolveByCredential(credentialId) {
180
+ const startLedger = options.startLedger ?? Math.max(1, (await server.getLatestLedger()).sequence - LEDGERS_PER_DAY);
181
+ const events = await collectEventsToTip(
182
+ server,
183
+ [{ type: "contract", contractIds: [options.factoryContractId] }],
184
+ startLedger
185
+ );
186
+ const accounts = [];
187
+ for (const event of events) {
188
+ const resolved = match(event, credentialId);
189
+ if (resolved) accounts.push(resolved);
190
+ }
191
+ return accounts;
192
+ }
193
+ };
194
+ }
195
+
196
+ // src/adapters/mercury.ts
197
+ function mercuryIndexer(options) {
198
+ const parse = options.parse ?? ((json) => {
199
+ const rows = json.accounts ?? [];
200
+ return rows.flatMap((r) => r.contractId ? [{ contractId: r.contractId }] : []);
201
+ });
202
+ return {
203
+ async resolveByCredential(credentialId) {
204
+ const headers = { "content-type": "application/json" };
205
+ if (options.token) headers["authorization"] = `Bearer ${options.token}`;
206
+ const response = await httpPost(
207
+ options.url,
208
+ { headers, body: JSON.stringify({ credentialId }) },
209
+ options.retry
210
+ );
211
+ if (!response.ok) {
212
+ throw new KitError(
213
+ "NETWORK_ERROR",
214
+ `mercury indexer returned HTTP ${String(response.status)}`
215
+ );
216
+ }
217
+ return parse(await response.json().catch(() => ({})));
218
+ }
219
+ };
220
+ }
221
+
222
+ // src/adapters/defaults.ts
223
+ function defaultAdapters(options) {
224
+ return {
225
+ submission: directSubmission({
226
+ rpcUrl: options.rpcUrl,
227
+ networkPassphrase: options.networkPassphrase,
228
+ allowHttp: options.allowHttp
229
+ }),
230
+ indexer: eventsIndexer({
231
+ rpcUrl: options.rpcUrl,
232
+ factoryContractId: options.factoryContractId,
233
+ allowHttp: options.allowHttp
234
+ })
235
+ };
236
+ }
237
+ function factoryDeployer(options) {
238
+ const server = new rpc.Server(options.rpcUrl, {
239
+ allowHttp: options.allowHttp ?? options.rpcUrl.startsWith("http://")
240
+ });
241
+ const source = Keypair.fromSecret(options.sourceSecret);
242
+ return {
243
+ async deploy(input) {
244
+ const pk = nativeToScVal(Buffer.from(input.publicKey), { type: "bytes" });
245
+ const cred = nativeToScVal(Buffer.from(new TextEncoder().encode(input.credentialId)), {
246
+ type: "bytes"
247
+ });
248
+ const account = await server.getAccount(source.publicKey());
249
+ const tx = new TransactionBuilder(account, {
250
+ fee: options.fee ?? "2000000",
251
+ networkPassphrase: options.networkPassphrase
252
+ }).addOperation(new Contract(options.factoryContractId).call("deploy", pk, cred)).setTimeout(120).build();
253
+ const sim = await server.simulateTransaction(tx);
254
+ if (!rpc.Api.isSimulationSuccess(sim)) {
255
+ throw new KitError("CONTRACT_AUTH_FAILED", "factory deploy simulation failed");
256
+ }
257
+ const prepared = rpc.assembleTransaction(tx, sim).build();
258
+ prepared.sign(source);
259
+ const sent = await server.sendTransaction(prepared);
260
+ if (sent.status === "ERROR") {
261
+ throw new KitError("NETWORK_ERROR", "factory deploy submit error");
262
+ }
263
+ const final = await server.pollTransaction(sent.hash);
264
+ if (final.status !== rpc.Api.GetTransactionStatus.SUCCESS) {
265
+ throw new KitError("CONTRACT_AUTH_FAILED", `factory deploy ${final.status}`);
266
+ }
267
+ const ret = final.returnValue;
268
+ const contractId = ret ? String(scValToNative(ret)) : "";
269
+ return { contractId, txHash: sent.hash };
270
+ }
271
+ };
272
+ }
273
+ var SMART_WALLET_V1_WASM_HASH = "84924c53a413318df2ce753e30de53ec651404c916d30e861718ad155c94b319";
274
+ function smartWalletV1Deployer(options) {
275
+ const server = new rpc.Server(options.rpcUrl, {
276
+ allowHttp: options.allowHttp ?? options.rpcUrl.startsWith("http://")
277
+ });
278
+ const source = Keypair.fromSecret(options.deployerSecret);
279
+ const wasmHash = options.wasmHash ?? SMART_WALLET_V1_WASM_HASH;
280
+ return {
281
+ async deploy(input) {
282
+ const raw = decodeChallenge(input.credentialId);
283
+ const contractId = deriveSmartWalletAddress({
284
+ deployer: source.publicKey(),
285
+ credentialId: input.credentialId,
286
+ networkPassphrase: options.networkPassphrase
287
+ });
288
+ const op = Operation.createCustomContract({
289
+ address: Address.fromString(source.publicKey()),
290
+ wasmHash: Buffer.from(wasmHash, "hex"),
291
+ salt: Buffer.from(sha256(raw)),
292
+ constructorArgs: [buildSecp256r1Signer({ credentialId: raw, publicKey: input.publicKey })]
293
+ });
294
+ const account = await server.getAccount(source.publicKey());
295
+ const tx = new TransactionBuilder(account, {
296
+ fee: options.fee ?? "10000000",
297
+ networkPassphrase: options.networkPassphrase
298
+ }).addOperation(op).setTimeout(120).build();
299
+ const sim = await server.simulateTransaction(tx);
300
+ if (!rpc.Api.isSimulationSuccess(sim)) {
301
+ throw new KitError("CONTRACT_AUTH_FAILED", "smart-wallet v1 deploy simulation failed");
302
+ }
303
+ const prepared = rpc.assembleTransaction(tx, sim).build();
304
+ prepared.sign(source);
305
+ const sent = await server.sendTransaction(prepared);
306
+ if (sent.status === "ERROR") {
307
+ throw new KitError("NETWORK_ERROR", "smart-wallet v1 deploy submit error");
308
+ }
309
+ const final = await server.pollTransaction(sent.hash);
310
+ if (final.status !== rpc.Api.GetTransactionStatus.SUCCESS) {
311
+ throw new KitError("CONTRACT_AUTH_FAILED", `smart-wallet v1 deploy ${final.status}`);
312
+ }
313
+ return { contractId, txHash: sent.hash };
314
+ }
315
+ };
316
+ }
317
+ var LEDGERS_PER_DAY2 = 17280;
318
+ function smartWalletV1Indexer(options) {
319
+ const server = new rpc.Server(options.rpcUrl, {
320
+ allowHttp: options.allowHttp ?? options.rpcUrl.startsWith("http://")
321
+ });
322
+ return {
323
+ async resolveByCredential(credentialId) {
324
+ const raw = decodeChallenge(credentialId);
325
+ const filters = [
326
+ {
327
+ type: "contract",
328
+ topics: [
329
+ [
330
+ xdr.ScVal.scvSymbol("signer_added").toXDR("base64"),
331
+ buildSignerKeyScVal(raw).toXDR("base64")
332
+ ]
333
+ ]
334
+ }
335
+ ];
336
+ const startLedger = options.startLedger ?? Math.max(1, (await server.getLatestLedger()).sequence - LEDGERS_PER_DAY2);
337
+ const events = await collectEventsToTip(server, filters, startLedger);
338
+ const seen = /* @__PURE__ */ new Set();
339
+ const accounts = [];
340
+ for (const event of events) {
341
+ const contractId = event.contractId?.toString();
342
+ if (contractId && !seen.has(contractId)) {
343
+ seen.add(contractId);
344
+ accounts.push({ contractId });
345
+ }
346
+ }
347
+ return accounts;
348
+ }
349
+ };
350
+ }
351
+
352
+ export { SMART_WALLET_V1_WASM_HASH, defaultAdapters, eventsIndexer, factoryDeployer, launchtubeSubmission, mercuryIndexer, openzeppelinRelayerSubmission, smartWalletV1Deployer, smartWalletV1Indexer };
353
+ //# sourceMappingURL=index.js.map
354
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/http.ts","../src/adapters/launchtube.ts","../src/adapters/ozRelayer.ts","../src/adapters/eventsPaging.ts","../src/adapters/events.ts","../src/adapters/mercury.ts","../src/adapters/defaults.ts","../src/adapters/factory.ts","../src/adapters/smartWalletV1.ts"],"names":["addr","rpc","scValToNative","Keypair","TransactionBuilder","LEDGERS_PER_DAY"],"mappings":"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","file":"index.js","sourcesContent":["import { KitError } from '../errors';\n\n/**\n * Bounded retry/backoff for the optional HTTP adapters (Launchtube / OZ Relayer /\n * Mercury). Opt-in: `retries` defaults to 1 (no retry), preserving the plain\n * single-shot behavior unless a caller asks for resilience.\n */\nexport interface RetryOptions {\n /** Total attempts including the first (default 1 = no retry). */\n retries?: number;\n /** Linear backoff base in ms; attempt N waits `backoffMs * N` (default 300). */\n backoffMs?: number;\n}\n\nconst sleep = (ms: number): Promise<void> =>\n ms > 0 ? new Promise<void>((resolve) => setTimeout(resolve, ms)) : Promise.resolve();\n\n/** A transient status worth retrying: rate-limit or any server error. */\nfunction isTransientStatus(status: number): boolean {\n return status === 429 || status >= 500;\n}\n\n/**\n * POST with typed failure semantics: a thrown fetch (DNS/connection/abort) after\n * the last attempt becomes `KitError('NETWORK_ERROR')`; a transient HTTP status\n * (429 / 5xx) is retried up to `retries`, then the response is returned for the\n * caller to interpret (so the failure body is preserved). Non-transient responses\n * return immediately.\n */\nexport async function httpPost(\n url: string,\n init: { headers?: Record<string, string>; body?: string },\n retry?: RetryOptions,\n): Promise<Response> {\n const attempts = Math.max(1, retry?.retries ?? 1);\n const backoffMs = retry?.backoffMs ?? 300;\n for (let i = 1; i <= attempts; i++) {\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: init.headers,\n body: init.body,\n });\n if (isTransientStatus(response.status) && i < attempts) {\n await sleep(backoffMs * i);\n continue;\n }\n return response;\n } catch (cause) {\n if (i < attempts) {\n await sleep(backoffMs * i);\n continue;\n }\n throw new KitError('NETWORK_ERROR', `POST to ${url} failed`, { cause });\n }\n }\n // Unreachable (the loop always returns or throws), but keeps the type total.\n throw new KitError('NETWORK_ERROR', `POST to ${url} failed`);\n}\n","import { httpPost, type RetryOptions } from './http';\nimport type { SubmissionAdapter, SubmitResult } from './types';\n\nexport interface LaunchtubeSubmissionOptions {\n url: string;\n /** Bearer token (Launchtube is invite/credit-gated). */\n token?: string;\n /** Optional bounded retry on transient (429 / 5xx / network) failures. */\n retry?: RetryOptions;\n}\n\ninterface LaunchtubeResponse {\n hash?: string;\n status?: string;\n error?: string;\n errorResultXdr?: string;\n}\n\n/**\n * Legacy Launchtube relay (optional). Modelled as ONE submission adapter — the\n * SDK does not depend on it; `direct` is the default and `openzeppelinRelayer`\n * is the post-Launchtube direction. A network failure surfaces as a typed\n * `KitError('NETWORK_ERROR')`; an HTTP error becomes a `FAILED` result carrying\n * the relay's error body.\n */\nexport function launchtubeSubmission(options: LaunchtubeSubmissionOptions): SubmissionAdapter {\n return {\n async send(signedTxXdr: string): Promise<SubmitResult> {\n const headers: Record<string, string> = {\n 'content-type': 'application/x-www-form-urlencoded',\n };\n if (options.token) headers['authorization'] = `Bearer ${options.token}`;\n const response = await httpPost(\n options.url,\n { headers, body: new URLSearchParams({ xdr: signedTxXdr }).toString() },\n options.retry,\n );\n const body = (await response.json().catch(() => ({}))) as LaunchtubeResponse;\n if (!response.ok || body.status === 'FAILED' || body.error) {\n return { status: 'FAILED', hash: body.hash ?? '', errorResultXdr: body.errorResultXdr };\n }\n return { status: 'SUCCESS', hash: body.hash ?? '', returnValue: body };\n },\n };\n}\n","import { httpPost, type RetryOptions } from './http';\nimport type { SubmissionAdapter, SubmitResult } from './types';\n\nexport interface OpenZeppelinRelayerOptions {\n url: string;\n apiKey?: string;\n /** Optional bounded retry on transient (429 / 5xx / network) failures. */\n retry?: RetryOptions;\n}\n\ninterface RelayerResponse {\n hash?: string;\n status?: string;\n errorResultXdr?: string;\n}\n\n/**\n * OpenZeppelin Relayer / Channels submission (the post-Launchtube direction).\n * Same `SubmissionAdapter` shape, so swapping it in is a one-line config change.\n * A network failure surfaces as `KitError('NETWORK_ERROR')`; an HTTP error (or a\n * `status: \"failed\"` body) becomes a `FAILED` result.\n */\nexport function openzeppelinRelayerSubmission(\n options: OpenZeppelinRelayerOptions,\n): SubmissionAdapter {\n return {\n async send(signedTxXdr: string): Promise<SubmitResult> {\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n if (options.apiKey) headers['authorization'] = `Bearer ${options.apiKey}`;\n const response = await httpPost(\n options.url,\n { headers, body: JSON.stringify({ transaction_xdr: signedTxXdr }) },\n options.retry,\n );\n const body = (await response.json().catch(() => ({}))) as RelayerResponse;\n if (!response.ok || body.status === 'failed') {\n return { status: 'FAILED', hash: body.hash ?? '', errorResultXdr: body.errorResultXdr };\n }\n return { status: 'SUCCESS', hash: body.hash ?? '', returnValue: body };\n },\n };\n}\n","import type { rpc } from '@stellar/stellar-sdk';\n\n/**\n * Shared soroban-rpc `getEvents` pagination.\n *\n * A single `getEvents` call scans only a BOUNDED ledger slice from `startLedger`\n * (not the whole retained window) and returns a `cursor`; a naive one-shot query\n * therefore misses events near the tip. That is precisely why recovering a\n * just-created wallet found nothing: the founding `signer_added` sat ~17k ledgers\n * ahead of `latest - 1 day`, past the first page. `collectEventsToTip` follows the\n * cursor from `startLedger` to the chain tip and returns every matched event.\n */\n\nexport const EVENTS_PAGE_LIMIT = 10_000; // soroban-rpc max page size\nexport const MAX_EVENT_PAGES = 40; // safety backstop; ~1 day is 2-3 pages\n\n/** Decode the ledger sequence out of a getEvents paging cursor (`<toid>-<index>`);\n * the TOID's top 32 bits are the ledger. Returns `null` if the shape is unexpected. */\nexport function cursorLedger(cursor: string): number | null {\n try {\n const toid = cursor.split('-')[0];\n if (!toid) return null;\n return Number(BigInt(toid) >> 32n);\n } catch {\n return null;\n }\n}\n\n/** Parse the retained window floor out of the RPC's out-of-range error, e.g.\n * \"startLedger must be within the ledger range: 3933976 - 4054935\". */\nexport function parseOldestLedger(error: unknown): number | null {\n const raw =\n typeof error === 'object' && error !== null && 'message' in error\n ? (error as { message?: unknown }).message\n : error;\n const message = typeof raw === 'string' ? raw : String(raw);\n const match = /ledger range:\\s*(\\d+)\\s*-\\s*\\d+/.exec(message);\n return match ? Number(match[1]) : null;\n}\n\ntype EventsServer = Pick<rpc.Server, 'getEvents'>;\n\n/**\n * Page through `getEvents` from `startLedger` to the tip, returning all events.\n * If `startLedger` predates the retained window, clamps just inside the reported\n * floor (+2 absorbs the window advancing mid-round-trip and an exclusive bound)\n * and retries. Bounded by {@link MAX_EVENT_PAGES}.\n */\nexport async function collectEventsToTip(\n server: EventsServer,\n filters: rpc.Api.EventFilter[],\n startLedger: number,\n): Promise<rpc.Api.EventResponse[]> {\n const events: rpc.Api.EventResponse[] = [];\n let start = startLedger;\n let cursor: string | undefined;\n let previousCursor: string | undefined;\n\n for (let page = 0; page < MAX_EVENT_PAGES; page++) {\n let response: rpc.Api.GetEventsResponse;\n try {\n response = await server.getEvents(\n cursor\n ? { filters, cursor, limit: EVENTS_PAGE_LIMIT }\n : { filters, startLedger: start, limit: EVENTS_PAGE_LIMIT },\n );\n } catch (error) {\n const oldest = parseOldestLedger(error);\n if (!cursor && oldest != null && start <= oldest) {\n start = oldest + 2;\n continue;\n }\n throw error;\n }\n events.push(...response.events);\n previousCursor = cursor;\n cursor = response.cursor;\n // Stop once the scan reaches the tip, the cursor stops advancing, or it is gone.\n if (!cursor || cursor === previousCursor) break;\n const scanned = cursorLedger(cursor);\n if (scanned != null && scanned >= response.latestLedger) break;\n }\n return events;\n}\n","import { rpc, scValToNative } from '@stellar/stellar-sdk';\nimport { collectEventsToTip } from './eventsPaging';\nimport type { IndexerAdapter, ResolvedAccount } from './types';\n\nfunction decodeNative(scv: unknown): unknown {\n try {\n return scValToNative(scv as never);\n } catch {\n return undefined;\n }\n}\n\nexport interface EventsIndexerOptions {\n rpcUrl: string;\n /** The passkey factory contract that emits an `add`/deploy event per account. */\n factoryContractId: string;\n /** Ledger to scan from; defaults to ~1 day back from the latest ledger. */\n startLedger?: number;\n allowHttp?: boolean;\n /**\n * Map a factory event → resolved account when it concerns `credentialId`.\n * Defaults to the deployed `AccountFactory` schema (see contracts/account-factory):\n * topics `[symbol \"deployed\", bytes credentialId]`, value = the deployed C-address.\n * Override only for a different factory event shape.\n */\n matchEvent?: (event: rpc.Api.EventResponse, credentialId: string) => ResolvedAccount | null;\n}\n\nconst LEDGERS_PER_DAY = 17_280; // ~5s ledgers\n\n/**\n * Parse the `AccountFactory.deploy` event `('deployed', credentialId) -> address`:\n * confirm the second topic (credential-id bytes, utf-8) equals `credentialId` and\n * resolve to the deployed account address carried in the event value. Falls back\n * to a raw-XDR scan if the topics aren't in the expected shape.\n */\nfunction defaultMatch(event: rpc.Api.EventResponse, credentialId: string): ResolvedAccount | null {\n try {\n const topics = event.topic ?? [];\n if (topics.length >= 2) {\n const tag = decodeNative(topics[0]);\n const credRaw = decodeNative(topics[1]);\n const cred =\n credRaw instanceof Uint8Array ? new TextDecoder().decode(credRaw) : String(credRaw ?? '');\n if (tag === 'deployed' && cred === credentialId) {\n const addr = decodeNative(event.value);\n if (typeof addr === 'string' && addr.startsWith('C')) return { contractId: addr };\n }\n }\n // Fallback: scan the raw XDR for the credential id; prefer the deployed\n // address in the value, else the emitting contract.\n const haystack = [event.value, ...topics].map((v) => v.toXDR('base64')).join('|');\n if (!haystack.includes(credentialId)) return null;\n const addr = decodeNative(event.value);\n if (typeof addr === 'string' && addr.startsWith('C')) return { contractId: addr };\n return event.contractId ? { contractId: event.contractId.toString() } : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Default, zero-infra indexer: soroban-rpc `getEvents` filtered on the factory\n * contract — no external indexing service. `mercury` is an optional alternative;\n * the SDK works with `events` alone.\n */\nexport function eventsIndexer(options: EventsIndexerOptions): IndexerAdapter {\n const server = new rpc.Server(options.rpcUrl, {\n allowHttp: options.allowHttp ?? options.rpcUrl.startsWith('http://'),\n });\n const match = options.matchEvent ?? defaultMatch;\n return {\n async resolveByCredential(credentialId: string): Promise<ResolvedAccount[]> {\n const startLedger =\n options.startLedger ??\n Math.max(1, (await server.getLatestLedger()).sequence - LEDGERS_PER_DAY);\n // Paginate to the tip: a single getEvents scans only a bounded slice, so a\n // one-shot query misses factory deploys near the latest ledger.\n const events = await collectEventsToTip(\n server,\n [{ type: 'contract', contractIds: [options.factoryContractId] }],\n startLedger,\n );\n const accounts: ResolvedAccount[] = [];\n for (const event of events) {\n const resolved = match(event, credentialId);\n if (resolved) accounts.push(resolved);\n }\n return accounts;\n },\n };\n}\n","import { KitError } from '../errors';\nimport { httpPost, type RetryOptions } from './http';\nimport type { IndexerAdapter, ResolvedAccount } from './types';\n\nexport interface MercuryIndexerOptions {\n url: string;\n token?: string;\n /** Map the Mercury/Zephyr JSON response → resolved accounts. */\n parse?: (json: unknown) => ResolvedAccount[];\n /** Optional bounded retry on transient (429 / 5xx / network) failures. */\n retry?: RetryOptions;\n}\n\n/**\n * Optional Mercury (Zephyr) indexer. Entirely optional — `events` is the\n * zero-infra default and the SDK never requires Mercury. A network failure\n * surfaces as `KitError('NETWORK_ERROR')`; an HTTP error throws\n * `NETWORK_ERROR` too, so a server error is never silently read as \"no accounts\".\n */\nexport function mercuryIndexer(options: MercuryIndexerOptions): IndexerAdapter {\n const parse =\n options.parse ??\n ((json: unknown): ResolvedAccount[] => {\n const rows = (json as { accounts?: { contractId?: string }[] }).accounts ?? [];\n return rows.flatMap((r) => (r.contractId ? [{ contractId: r.contractId }] : []));\n });\n return {\n async resolveByCredential(credentialId: string): Promise<ResolvedAccount[]> {\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n if (options.token) headers['authorization'] = `Bearer ${options.token}`;\n const response = await httpPost(\n options.url,\n { headers, body: JSON.stringify({ credentialId }) },\n options.retry,\n );\n if (!response.ok) {\n throw new KitError(\n 'NETWORK_ERROR',\n `mercury indexer returned HTTP ${String(response.status)}`,\n );\n }\n return parse(await response.json().catch(() => ({})));\n },\n };\n}\n","import type { IndexerAdapter, SubmissionAdapter } from './types';\nimport { directSubmission } from './direct';\nimport { eventsIndexer } from './events';\n\nexport interface DefaultAdapterOptions {\n rpcUrl: string;\n networkPassphrase: string;\n factoryContractId: string;\n allowHttp?: boolean;\n}\n\n/** The zero-infra default stack: `direct` submission + `events` indexer. */\nexport function defaultAdapters(options: DefaultAdapterOptions): {\n submission: SubmissionAdapter;\n indexer: IndexerAdapter;\n} {\n return {\n submission: directSubmission({\n rpcUrl: options.rpcUrl,\n networkPassphrase: options.networkPassphrase,\n allowHttp: options.allowHttp,\n }),\n indexer: eventsIndexer({\n rpcUrl: options.rpcUrl,\n factoryContractId: options.factoryContractId,\n allowHttp: options.allowHttp,\n }),\n };\n}\n","import {\n rpc,\n Contract,\n Keypair,\n TransactionBuilder,\n nativeToScVal,\n scValToNative,\n} from '@stellar/stellar-sdk';\nimport { KitError } from '../errors';\nimport type { AccountDeployer } from '../ceremonies/types';\n\nexport interface FactoryDeployerOptions {\n rpcUrl: string;\n networkPassphrase: string;\n /** The deployed `AccountFactory` contract id (`C…`) — see contracts/account-factory. */\n factoryContractId: string;\n /**\n * Secret of the testnet account that pays the fee + signs the deploy tx. The\n * factory's `deploy` is not auth-gated, so this just sources/sponsors the\n * transaction. In a public demo this is an ephemeral, friendbot-funded key —\n * never a key with value.\n */\n sourceSecret: string;\n allowHttp?: boolean;\n fee?: string;\n}\n\n/**\n * `AccountDeployer` backed by the on-chain `AccountFactory`: invokes\n * `factory.deploy(public_key, credential_id)`, which deploys a fresh\n * `webauthn-account` for the passkey and emits the `(deployed, credentialId)`\n * event the `eventsIndexer` resolves. Returns the new smart-account C-address.\n * This is the real \"create a passkey wallet on-chain\" path.\n */\nexport function factoryDeployer(options: FactoryDeployerOptions): AccountDeployer {\n const server = new rpc.Server(options.rpcUrl, {\n allowHttp: options.allowHttp ?? options.rpcUrl.startsWith('http://'),\n });\n const source = Keypair.fromSecret(options.sourceSecret);\n return {\n async deploy(input) {\n const pk = nativeToScVal(Buffer.from(input.publicKey), { type: 'bytes' });\n const cred = nativeToScVal(Buffer.from(new TextEncoder().encode(input.credentialId)), {\n type: 'bytes',\n });\n const account = await server.getAccount(source.publicKey());\n const tx = new TransactionBuilder(account, {\n fee: options.fee ?? '2000000',\n networkPassphrase: options.networkPassphrase,\n })\n .addOperation(new Contract(options.factoryContractId).call('deploy', pk, cred))\n .setTimeout(120)\n .build();\n\n const sim = await server.simulateTransaction(tx);\n if (!rpc.Api.isSimulationSuccess(sim)) {\n throw new KitError('CONTRACT_AUTH_FAILED', 'factory deploy simulation failed');\n }\n const prepared = rpc.assembleTransaction(tx, sim).build();\n prepared.sign(source);\n\n const sent = await server.sendTransaction(prepared);\n if (sent.status === 'ERROR') {\n throw new KitError('NETWORK_ERROR', 'factory deploy submit error');\n }\n const final = await server.pollTransaction(sent.hash);\n if (final.status !== rpc.Api.GetTransactionStatus.SUCCESS) {\n throw new KitError('CONTRACT_AUTH_FAILED', `factory deploy ${final.status}`);\n }\n const ret = (final as { returnValue?: unknown }).returnValue;\n const contractId = ret ? String(scValToNative(ret as never)) : '';\n return { contractId, txHash: sent.hash };\n },\n };\n}\n","import { Address, Keypair, Operation, TransactionBuilder, rpc, xdr } from '@stellar/stellar-sdk';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { KitError } from '../errors';\nimport { decodeChallenge } from '../webauthn/clientData';\nimport { buildSecp256r1Signer } from '../soroban/signer';\nimport { buildSignerKeyScVal } from '../soroban/smartWallet';\nimport { deriveSmartWalletAddress } from '../soroban/address';\nimport { collectEventsToTip } from './eventsPaging';\nimport type { AccountDeployer } from '../ceremonies/types';\nimport type { IndexerAdapter, ResolvedAccount } from './types';\n\n/** The canonical audited v1 smart-wallet wasm hash on testnet (kalepail #32). */\nexport const SMART_WALLET_V1_WASM_HASH =\n '84924c53a413318df2ce753e30de53ec651404c916d30e861718ad155c94b319';\n\nexport interface SmartWalletV1DeployerOptions {\n rpcUrl: string;\n networkPassphrase: string;\n /**\n * Secret of the funded classic account that deploys + pays. It must be STABLE so\n * the deployed address stays offline-derivable via {@link deriveSmartWalletAddress}\n * (the deployer is part of the contract-id preimage). In a demo this is a fixed\n * friendbot-funded key; in production a wallet team's deployer/relayer.\n */\n deployerSecret: string;\n /** v1 smart-wallet wasm hash (hex). Defaults to the canonical testnet hash. */\n wasmHash?: string;\n allowHttp?: boolean;\n fee?: string;\n}\n\n/**\n * `AccountDeployer` for the passkey-kit **v1 smart-wallet**: deploys a fresh wallet\n * from the audited wasm via `createCustomContract`, salted by\n * `sha256(rawCredentialId)` from a fixed deployer — so the address is deterministic\n * and offline-derivable. The contract's first `add_signer` (from `__constructor`)\n * is unauthenticated, so the deploy is a plain source-signed transaction. Pair with\n * {@link deriveSmartWalletAddress} for `getAddress` and {@link smartWalletV1Indexer}\n * for recovery.\n */\nexport function smartWalletV1Deployer(options: SmartWalletV1DeployerOptions): AccountDeployer {\n const server = new rpc.Server(options.rpcUrl, {\n allowHttp: options.allowHttp ?? options.rpcUrl.startsWith('http://'),\n });\n const source = Keypair.fromSecret(options.deployerSecret);\n const wasmHash = options.wasmHash ?? SMART_WALLET_V1_WASM_HASH;\n return {\n async deploy(input) {\n const raw = decodeChallenge(input.credentialId);\n const contractId = deriveSmartWalletAddress({\n deployer: source.publicKey(),\n credentialId: input.credentialId,\n networkPassphrase: options.networkPassphrase,\n });\n const op = Operation.createCustomContract({\n address: Address.fromString(source.publicKey()),\n wasmHash: Buffer.from(wasmHash, 'hex'),\n salt: Buffer.from(sha256(raw)),\n constructorArgs: [buildSecp256r1Signer({ credentialId: raw, publicKey: input.publicKey })],\n });\n const account = await server.getAccount(source.publicKey());\n const tx = new TransactionBuilder(account, {\n fee: options.fee ?? '10000000',\n networkPassphrase: options.networkPassphrase,\n })\n .addOperation(op)\n .setTimeout(120)\n .build();\n const sim = await server.simulateTransaction(tx);\n if (!rpc.Api.isSimulationSuccess(sim)) {\n throw new KitError('CONTRACT_AUTH_FAILED', 'smart-wallet v1 deploy simulation failed');\n }\n const prepared = rpc.assembleTransaction(tx, sim).build();\n prepared.sign(source);\n const sent = await server.sendTransaction(prepared);\n if (sent.status === 'ERROR') {\n throw new KitError('NETWORK_ERROR', 'smart-wallet v1 deploy submit error');\n }\n const final = await server.pollTransaction(sent.hash);\n if (final.status !== rpc.Api.GetTransactionStatus.SUCCESS) {\n throw new KitError('CONTRACT_AUTH_FAILED', `smart-wallet v1 deploy ${final.status}`);\n }\n return { contractId, txHash: sent.hash };\n },\n };\n}\n\nconst LEDGERS_PER_DAY = 17_280; // ~5s ledgers\n\nexport interface SmartWalletV1IndexerOptions {\n rpcUrl: string;\n /** Ledger to scan from; defaults to ~1 day back. The events RPC retains a limited window. */\n startLedger?: number;\n allowHttp?: boolean;\n}\n\n/**\n * `IndexerAdapter` for the v1 smart-wallet: resolves a credential id → wallet\n * address from the on-chain `signer_added` events. Schema confirmed empirically\n * against the deployed v0.13.0 wasm (`scripts/v1-events-probe.ts`):\n * `topic[0]=Symbol(\"signer_added\")`, `topic[1]=SignerKey::Secp256r1(rawCredId)`,\n * and the wallet is the EMITTING contract. Works for BOTH the founding credential\n * (deploy emits `signer_added`) and signers added later via `add_signer`.\n *\n * A single `getEvents` call only scans a bounded ledger slice from `startLedger`\n * (not the whole window) and returns a cursor, so a naive one-shot query misses\n * events near the tip — the exact reason recovery of a just-created wallet found\n * nothing. We therefore PAGINATE by cursor from `startLedger` to the tip,\n * accumulating every wallet the credential signs for. soroban-rpc retains only a\n * limited window, so this is the zero-infra default for recent wallets; use a\n * persistent indexer (Mercury) for older ones.\n */\nexport function smartWalletV1Indexer(options: SmartWalletV1IndexerOptions): IndexerAdapter {\n const server = new rpc.Server(options.rpcUrl, {\n allowHttp: options.allowHttp ?? options.rpcUrl.startsWith('http://'),\n });\n return {\n async resolveByCredential(credentialId: string): Promise<ResolvedAccount[]> {\n const raw = decodeChallenge(credentialId);\n // Filter directly on the two topics: the event name + this credential's SignerKey.\n const filters = [\n {\n type: 'contract' as const,\n topics: [\n [\n xdr.ScVal.scvSymbol('signer_added').toXDR('base64'),\n buildSignerKeyScVal(raw).toXDR('base64'),\n ],\n ],\n },\n ];\n const startLedger =\n options.startLedger ??\n Math.max(1, (await server.getLatestLedger()).sequence - LEDGERS_PER_DAY);\n\n const events = await collectEventsToTip(server, filters, startLedger);\n const seen = new Set<string>();\n const accounts: ResolvedAccount[] = [];\n for (const event of events) {\n const contractId = event.contractId?.toString();\n if (contractId && !seen.has(contractId)) {\n seen.add(contractId);\n accounts.push({ contractId });\n }\n }\n return accounts;\n },\n };\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import { I as IndexerAdapter, W as WebAuthnClient } from './types--WNl-Sda.cjs';
2
+
3
+ interface RecoverOptions {
4
+ rpId: string;
5
+ indexer: IndexerAdapter;
6
+ webauthn?: WebAuthnClient;
7
+ challenge?: Uint8Array;
8
+ userActivation?: {
9
+ isActive: boolean;
10
+ };
11
+ }
12
+ interface RecoverResult {
13
+ contractId: string;
14
+ credentialId: string;
15
+ }
16
+ /**
17
+ * `recover` — the lost-localStorage / new-device path. Performs a
18
+ * discoverable-credential `get()` (no allowCredentials), then resolves every
19
+ * smart account controlled by that credential via the IndexerAdapter.
20
+ */
21
+ declare function recover(options: RecoverOptions): Promise<RecoverResult[]>;
22
+
23
+ export { type RecoverOptions as R, type RecoverResult as a, recover as r };