@lightninglabs/wavelength-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 (93) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +31 -0
  3. package/dist/activity-options.d.ts +15 -0
  4. package/dist/activity-options.d.ts.map +1 -0
  5. package/dist/activity-options.js +7 -0
  6. package/dist/base-client.d.ts +59 -0
  7. package/dist/base-client.d.ts.map +1 -0
  8. package/dist/base-client.js +144 -0
  9. package/dist/casing.d.ts +4 -0
  10. package/dist/casing.d.ts.map +1 -0
  11. package/dist/casing.js +42 -0
  12. package/dist/client.d.ts +90 -0
  13. package/dist/client.d.ts.map +1 -0
  14. package/dist/client.js +1 -0
  15. package/dist/config.d.ts +128 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +142 -0
  18. package/dist/destination.d.ts +56 -0
  19. package/dist/destination.d.ts.map +1 -0
  20. package/dist/destination.js +90 -0
  21. package/dist/engine/activity.d.ts +25 -0
  22. package/dist/engine/activity.d.ts.map +1 -0
  23. package/dist/engine/activity.js +119 -0
  24. package/dist/engine/constants.d.ts +29 -0
  25. package/dist/engine/constants.d.ts.map +1 -0
  26. package/dist/engine/constants.js +29 -0
  27. package/dist/engine/engine.d.ts +115 -0
  28. package/dist/engine/engine.d.ts.map +1 -0
  29. package/dist/engine/engine.js +548 -0
  30. package/dist/engine/machine.d.ts +50 -0
  31. package/dist/engine/machine.d.ts.map +1 -0
  32. package/dist/engine/machine.js +55 -0
  33. package/dist/engine/optionsAssertions.d.ts +2 -0
  34. package/dist/engine/optionsAssertions.d.ts.map +1 -0
  35. package/dist/engine/optionsAssertions.js +20 -0
  36. package/dist/engine/poller.d.ts +20 -0
  37. package/dist/engine/poller.d.ts.map +1 -0
  38. package/dist/engine/poller.js +51 -0
  39. package/dist/engine/reconcile.d.ts +36 -0
  40. package/dist/engine/reconcile.d.ts.map +1 -0
  41. package/dist/engine/reconcile.js +81 -0
  42. package/dist/engine/snapshot.d.ts +58 -0
  43. package/dist/engine/snapshot.d.ts.map +1 -0
  44. package/dist/engine/snapshot.js +10 -0
  45. package/dist/engine/stabilize.d.ts +8 -0
  46. package/dist/engine/stabilize.d.ts.map +1 -0
  47. package/dist/engine/stabilize.js +17 -0
  48. package/dist/engine/store.d.ts +21 -0
  49. package/dist/engine/store.d.ts.map +1 -0
  50. package/dist/engine/store.js +46 -0
  51. package/dist/errors.d.ts +55 -0
  52. package/dist/errors.d.ts.map +1 -0
  53. package/dist/errors.js +80 -0
  54. package/dist/events.d.ts +62 -0
  55. package/dist/events.d.ts.map +1 -0
  56. package/dist/events.js +1 -0
  57. package/dist/exit.d.ts +93 -0
  58. package/dist/exit.d.ts.map +1 -0
  59. package/dist/exit.js +86 -0
  60. package/dist/facade.d.ts +88 -0
  61. package/dist/facade.d.ts.map +1 -0
  62. package/dist/facade.js +150 -0
  63. package/dist/generated.d.ts +1197 -0
  64. package/dist/generated.d.ts.map +1 -0
  65. package/dist/generated.js +206 -0
  66. package/dist/index.d.ts +28 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +36 -0
  69. package/dist/passkey.d.ts +46 -0
  70. package/dist/passkey.d.ts.map +1 -0
  71. package/dist/passkey.js +16 -0
  72. package/dist/public-api-assertions.d.ts +2 -0
  73. package/dist/public-api-assertions.d.ts.map +1 -0
  74. package/dist/public-api-assertions.js +42 -0
  75. package/dist/request-assertions.d.ts +2 -0
  76. package/dist/request-assertions.d.ts.map +1 -0
  77. package/dist/request-assertions.js +12 -0
  78. package/dist/requests.d.ts +186 -0
  79. package/dist/requests.d.ts.map +1 -0
  80. package/dist/requests.js +5 -0
  81. package/dist/response-normalization.d.ts +5 -0
  82. package/dist/response-normalization.d.ts.map +1 -0
  83. package/dist/response-normalization.js +101 -0
  84. package/dist/results.d.ts +49 -0
  85. package/dist/results.d.ts.map +1 -0
  86. package/dist/results.js +4 -0
  87. package/dist/state.d.ts +87 -0
  88. package/dist/state.d.ts.map +1 -0
  89. package/dist/state.js +87 -0
  90. package/dist/version.d.ts +18 -0
  91. package/dist/version.d.ts.map +1 -0
  92. package/dist/version.js +17 -0
  93. package/package.json +42 -0
package/dist/exit.d.ts ADDED
@@ -0,0 +1,93 @@
1
+ import type { WavelengthClient } from './client.ts';
2
+ import type { ExitInfeasibilityReason, ExitResult, GetExitPlanResult } from './results.ts';
3
+ /**
4
+ * Options for {@link exitBatch}, a discriminated union on `mode`. A cooperative
5
+ * batch queues each outpoint into the next round to an optional on-chain
6
+ * `destination`. A unilateral batch forces each outpoint on-chain, funding the
7
+ * recovery from the backing wallet, and previews funding with `getExitPlan`
8
+ * before each start.
9
+ */
10
+ export type ExitBatchOptions = {
11
+ mode: 'cooperative';
12
+ outpoints: string[];
13
+ destination?: string;
14
+ } | {
15
+ mode: 'unilateral';
16
+ outpoints: string[];
17
+ confTarget?: number;
18
+ };
19
+ /**
20
+ * A progress event emitted by {@link exitBatch} as it works through a batch.
21
+ * `planned` carries the latest unilateral funding plan; `starting` fires before
22
+ * each exit call; `started` fires after one succeeds; `stopped` fires once when
23
+ * the batch halts early.
24
+ */
25
+ export type ExitBatchEvent = {
26
+ type: 'planned';
27
+ plan: GetExitPlanResult;
28
+ } | {
29
+ type: 'starting';
30
+ outpoint: string;
31
+ } | {
32
+ type: 'started';
33
+ outpoint: string;
34
+ result: ExitResult;
35
+ } | {
36
+ type: 'stopped';
37
+ stoppedBy: ExitBatchStop;
38
+ remaining: string[];
39
+ };
40
+ /**
41
+ * Why an {@link exitBatch} stopped before finishing. `infeasible` means a
42
+ * re-plan reported the backing wallet can no longer fund the remaining exits;
43
+ * `rejected` means an individual `exit` call was rejected by the daemon.
44
+ */
45
+ export type ExitBatchStop = {
46
+ reason: 'infeasible';
47
+ plan: GetExitPlanResult;
48
+ } | {
49
+ reason: 'rejected';
50
+ outpoint: string;
51
+ error: Error;
52
+ };
53
+ /**
54
+ * The outcome of {@link exitBatch}. `started` lists the exits that were
55
+ * successfully started (each still runs for hours or days afterward on the
56
+ * unilateral path); `skipped` lists outpoints already running an exit;
57
+ * `remaining` lists outpoints never started; `stoppedBy` is present when the
58
+ * batch halted early.
59
+ */
60
+ export type ExitBatchResult = {
61
+ started: {
62
+ outpoint: string;
63
+ result: ExitResult;
64
+ }[];
65
+ skipped: string[];
66
+ remaining: string[];
67
+ stoppedBy?: ExitBatchStop;
68
+ };
69
+ /**
70
+ * Distinguishes a fixable exit-infeasibility (the backing wallet needs more
71
+ * confirmed funds or inputs) from a structural one (the VTXO cannot be exited
72
+ * economically at all). Use it to decide whether to show a "fund your wallet"
73
+ * affordance or a terminal "cannot exit this VTXO" message. Mirrors the
74
+ * daemon's own `ExitInfeasibility.Impossible()` split.
75
+ */
76
+ export declare function isExitInfeasibilityFundable(reason: ExitInfeasibilityReason): boolean;
77
+ /**
78
+ * Starts a batch of exits, one outpoint per daemon call, and reports which
79
+ * started, which were skipped, and which never started. It resolves once every
80
+ * exit has been STARTED, not completed: a unilateral exit continues to run for
81
+ * hours or days after this resolves. On the unilateral path it previews funding
82
+ * with `getExitPlan`, skips outpoints already running an exit, refuses to start
83
+ * anything if the wallet cannot fund the batch, and re-plans between starts;
84
+ * because fee inputs are leased only at broadcast time, it also treats a
85
+ * mid-batch `exit` rejection as a clean stop. On the cooperative path it queues
86
+ * each outpoint into the next round.
87
+ */
88
+ export declare function exitBatch(opts: ExitBatchOptions & {
89
+ client: WavelengthClient;
90
+ signal?: AbortSignal;
91
+ onEvent?: (event: ExitBatchEvent) => void;
92
+ }): Promise<ExitBatchResult>;
93
+ //# sourceMappingURL=exit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit.d.ts","sourceRoot":"","sources":["../src/exit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,KAAK,EACV,uBAAuB,EACvB,UAAU,EACV,iBAAiB,EAClB,MAAM,cAAc,CAAC;AAEtB;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,aAAa,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEvE;;;;GAIG;AACH,MAAM,MAAM,aAAa,GACrB;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,GACjD;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAE3D;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IACpD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAIT;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,gBAAgB,GAAG;IACvB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CAC3C,GACA,OAAO,CAAC,eAAe,CAAC,CAwE1B"}
package/dist/exit.js ADDED
@@ -0,0 +1,86 @@
1
+ import { FORCE_UNROLL_ACK } from "./requests.js";
2
+ /**
3
+ * Distinguishes a fixable exit-infeasibility (the backing wallet needs more
4
+ * confirmed funds or inputs) from a structural one (the VTXO cannot be exited
5
+ * economically at all). Use it to decide whether to show a "fund your wallet"
6
+ * affordance or a terminal "cannot exit this VTXO" message. Mirrors the
7
+ * daemon's own `ExitInfeasibility.Impossible()` split.
8
+ */
9
+ export function isExitInfeasibilityFundable(reason) {
10
+ return (reason === 'wallet_underfunded' || reason === 'wallet_too_few_inputs');
11
+ }
12
+ /**
13
+ * Starts a batch of exits, one outpoint per daemon call, and reports which
14
+ * started, which were skipped, and which never started. It resolves once every
15
+ * exit has been STARTED, not completed: a unilateral exit continues to run for
16
+ * hours or days after this resolves. On the unilateral path it previews funding
17
+ * with `getExitPlan`, skips outpoints already running an exit, refuses to start
18
+ * anything if the wallet cannot fund the batch, and re-plans between starts;
19
+ * because fee inputs are leased only at broadcast time, it also treats a
20
+ * mid-batch `exit` rejection as a clean stop. On the cooperative path it queues
21
+ * each outpoint into the next round.
22
+ */
23
+ export async function exitBatch(opts) {
24
+ const { client, signal, onEvent } = opts;
25
+ const started = [];
26
+ const skipped = [];
27
+ let remaining = [...opts.outpoints];
28
+ while (remaining.length > 0) {
29
+ signal?.throwIfAborted();
30
+ if (opts.mode === 'unilateral') {
31
+ const currentPlan = await client.getExitPlan({
32
+ outpoints: remaining,
33
+ confTarget: opts.confTarget,
34
+ });
35
+ onEvent?.({ type: 'planned', plan: currentPlan });
36
+ // Drop outpoints the daemon already runs an exit for: it rejects a
37
+ // second exit for one outpoint, and the plan already flags them.
38
+ const running = new Set(currentPlan.plans.filter((p) => p.exitJobFound).map((p) => p.outpoint));
39
+ if (running.size > 0) {
40
+ const newlySkipped = remaining.filter((o) => running.has(o) && !skipped.includes(o));
41
+ for (const o of newlySkipped)
42
+ skipped.push(o);
43
+ remaining = remaining.filter((o) => !running.has(o));
44
+ if (remaining.length === 0)
45
+ break;
46
+ if (newlySkipped.length > 0) {
47
+ // Re-plan against the reduced set before gating on canStart: the
48
+ // plan we just read still counted the now-skipped (already-running)
49
+ // outpoints, whose leased fee inputs can make the aggregate
50
+ // canStart false.
51
+ continue;
52
+ }
53
+ }
54
+ // Funding is never reserved, so re-planning each round is the only way
55
+ // to notice an earlier start consumed the inputs a later one needs.
56
+ if (!currentPlan.canStart) {
57
+ const stoppedBy = {
58
+ reason: 'infeasible',
59
+ plan: currentPlan,
60
+ };
61
+ onEvent?.({ type: 'stopped', stoppedBy, remaining });
62
+ return { started, skipped, remaining, stoppedBy };
63
+ }
64
+ }
65
+ const outpoint = remaining[0];
66
+ onEvent?.({ type: 'starting', outpoint });
67
+ try {
68
+ const result = await client.exit(opts.mode === 'unilateral'
69
+ ? { outpoint, forceUnrollAck: FORCE_UNROLL_ACK }
70
+ : { outpoint, destination: opts.destination });
71
+ started.push({ outpoint, result });
72
+ remaining = remaining.slice(1);
73
+ onEvent?.({ type: 'started', outpoint, result });
74
+ }
75
+ catch (error) {
76
+ const stoppedBy = {
77
+ reason: 'rejected',
78
+ outpoint,
79
+ error: error,
80
+ };
81
+ onEvent?.({ type: 'stopped', stoppedBy, remaining });
82
+ return { started, skipped, remaining, stoppedBy };
83
+ }
84
+ }
85
+ return { started, skipped, remaining: [] };
86
+ }
@@ -0,0 +1,88 @@
1
+ import type { RuntimeConfig } from './config.ts';
2
+ import type { CreateWalletRequest, UnlockWalletRequest } from './requests.ts';
3
+ /** Portable mobile and WASM facade methods available through `callFacade()`. */
4
+ export declare const FACADE_METHODS: readonly ["start", "stop", "getInfo", "status", "balance", "createWallet", "unlockWallet", "openWalletFromPasskey", "deposit", "receive", "prepareSend", "sendPrepared", "list", "exit", "exitStatus", "exitSummary", "getExitPlan", "sweepWallet", "confirmedBalanceSat", "pendingInboundSat", "walletReady", "isRunning"];
5
+ /** One portable daemon facade method accepted by `callFacade()`. */
6
+ export type FacadeMethod = (typeof FACADE_METHODS)[number];
7
+ export declare function assertFacadeMethod(method: unknown): asserts method is FacadeMethod;
8
+ /**
9
+ * Selects how the embedded daemon dials the Ark operator and swap server. The
10
+ * browser transport must use 'rest' (a browser cannot speak native gRPC over
11
+ * the wire), while native transports use 'grpc'. The choice also changes what
12
+ * the address fields mean: with 'rest', the Ark and swap server addresses are
13
+ * gateway URLs; with 'grpc', they are host:port gRPC addresses.
14
+ */
15
+ export type ServerTransport = 'rest' | 'grpc';
16
+ /**
17
+ * The flat, snake_case config the wavewalletdk mobile facade's `start` verb
18
+ * decodes (sdk/wavewalletdk/mobile.mobileConfig). Every transport forwards it
19
+ * verbatim to the facade's Start.
20
+ */
21
+ export type MobileConfig = {
22
+ data_dir?: string;
23
+ network?: string;
24
+ debug_level?: string;
25
+ allow_mainnet?: boolean;
26
+ server_address?: string;
27
+ server_tls_cert_path?: string;
28
+ server_transport?: ServerTransport;
29
+ server_insecure?: boolean;
30
+ wallet_type?: 'lwwallet' | 'btcwallet';
31
+ wallet_esplora_url?: string;
32
+ wallet_password_file?: string;
33
+ wallet_poll_interval_seconds?: number;
34
+ wallet_recovery_window?: number;
35
+ wallet_fee_url?: string;
36
+ wallet_block_headers_source?: string;
37
+ wallet_filter_headers_source?: string;
38
+ swap_server_address?: string;
39
+ swap_server_tls_cert_path?: string;
40
+ swap_server_transport?: ServerTransport;
41
+ swap_server_insecure?: boolean;
42
+ swap_database_file_name?: string;
43
+ max_operator_fee_sat?: number;
44
+ signing_workers?: number;
45
+ buffer_size?: number;
46
+ };
47
+ /**
48
+ * Maps the public RuntimeConfig onto the flat config the mobile facade
49
+ * expects.
50
+ *
51
+ * Mailbox addressing: the facade's MobileConfig has a single server_address
52
+ * (and swap_server_address) per service. Mailbox traffic shares that edge, so
53
+ * RuntimeConfig deliberately does not expose separate mailbox gateway fields.
54
+ * If a future facade version splits the mailbox onto its own address, add the
55
+ * field to RuntimeConfig and thread it through here.
56
+ *
57
+ * @param config - The public runtime configuration.
58
+ * @param serverTransport - How this transport's daemon dials the servers; see
59
+ * {@link ServerTransport}.
60
+ */
61
+ export declare function toMobileConfig(config: RuntimeConfig, serverTransport: ServerTransport): MobileConfig;
62
+ /**
63
+ * Encodes a string as base64 of its UTF-8 bytes, matching how Go's
64
+ * encoding/json represents a []byte field. Implemented without btoa or
65
+ * TextEncoder so it behaves identically in the browser, a worker, and Hermes.
66
+ */
67
+ export declare function base64FromUtf8(value: string): string;
68
+ /**
69
+ * Maps the TS-convention {@link CreateWalletRequest} (with a string password
70
+ * field) to the Go JSON shape the facade expects. Go's encoding/json uses
71
+ * struct field names verbatim and represents []byte as base64, so
72
+ * WalletPassword and SeedPassphrase must arrive as base64.
73
+ */
74
+ export declare function toGoCreateWalletReq(req: CreateWalletRequest): {
75
+ WalletPassword: string | undefined;
76
+ Mnemonic: string[] | undefined;
77
+ SeedPassphrase: string | undefined;
78
+ RecoverState: boolean | undefined;
79
+ RecoveryWindow: number | undefined;
80
+ };
81
+ /**
82
+ * Maps the TS-convention {@link UnlockWalletRequest} to the Go JSON shape,
83
+ * base64-encoding the password string for the []byte field.
84
+ */
85
+ export declare function toGoUnlockWalletReq(req: UnlockWalletRequest): {
86
+ WalletPassword: string | undefined;
87
+ };
88
+ //# sourceMappingURL=facade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"facade.d.ts","sourceRoot":"","sources":["../src/facade.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAG9E,gFAAgF;AAChF,eAAO,MAAM,cAAc,6TAuBjB,CAAC;AAEX,oEAAoE;AACpE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAI3D,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,MAAM,IAAI,YAAY,CAOhC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9C;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,eAAe,CAAC;IACnC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,qBAAqB,CAAC,EAAE,eAAe,CAAC;IACxC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,eAAe,EAAE,eAAe,GAC/B,YAAY,CAwCd;AAMD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAoCpD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,mBAAmB;;;;;;EAc3D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,mBAAmB;;EAI3D"}
package/dist/facade.js ADDED
@@ -0,0 +1,150 @@
1
+ import { WavelengthError } from "./errors.js";
2
+ /** Portable mobile and WASM facade methods available through `callFacade()`. */
3
+ export const FACADE_METHODS = [
4
+ 'start',
5
+ 'stop',
6
+ 'getInfo',
7
+ 'status',
8
+ 'balance',
9
+ 'createWallet',
10
+ 'unlockWallet',
11
+ 'openWalletFromPasskey',
12
+ 'deposit',
13
+ 'receive',
14
+ 'prepareSend',
15
+ 'sendPrepared',
16
+ 'list',
17
+ 'exit',
18
+ 'exitStatus',
19
+ 'exitSummary',
20
+ 'getExitPlan',
21
+ 'sweepWallet',
22
+ 'confirmedBalanceSat',
23
+ 'pendingInboundSat',
24
+ 'walletReady',
25
+ 'isRunning',
26
+ ];
27
+ const FACADE_METHOD_SET = new Set(FACADE_METHODS);
28
+ export function assertFacadeMethod(method) {
29
+ if (typeof method !== 'string' || !FACADE_METHOD_SET.has(method)) {
30
+ throw new WavelengthError(`unsupported facade method: ${String(method)}`, 'unsupported_facade_method');
31
+ }
32
+ }
33
+ /**
34
+ * Maps the public RuntimeConfig onto the flat config the mobile facade
35
+ * expects.
36
+ *
37
+ * Mailbox addressing: the facade's MobileConfig has a single server_address
38
+ * (and swap_server_address) per service. Mailbox traffic shares that edge, so
39
+ * RuntimeConfig deliberately does not expose separate mailbox gateway fields.
40
+ * If a future facade version splits the mailbox onto its own address, add the
41
+ * field to RuntimeConfig and thread it through here.
42
+ *
43
+ * @param config - The public runtime configuration.
44
+ * @param serverTransport - How this transport's daemon dials the servers; see
45
+ * {@link ServerTransport}.
46
+ */
47
+ export function toMobileConfig(config, serverTransport) {
48
+ const out = {
49
+ data_dir: config.dataDir,
50
+ network: config.network,
51
+ debug_level: config.debugLevel,
52
+ allow_mainnet: config.allowMainnet,
53
+ server_address: config.arkServerAddress,
54
+ server_tls_cert_path: config.arkServerTlsCertPath,
55
+ server_transport: serverTransport,
56
+ server_insecure: config.arkServerInsecure,
57
+ wallet_type: config.walletType ?? 'lwwallet',
58
+ wallet_esplora_url: config.walletEsploraUrl,
59
+ wallet_password_file: config.walletPasswordFile,
60
+ wallet_poll_interval_seconds: config.walletPollIntervalSeconds,
61
+ wallet_recovery_window: config.walletRecoveryWindow,
62
+ wallet_fee_url: config.walletFeeUrl,
63
+ wallet_block_headers_source: config.walletBlockHeadersSource,
64
+ wallet_filter_headers_source: config.walletFilterHeadersSource,
65
+ max_operator_fee_sat: config.maxOperatorFeeSat,
66
+ signing_workers: config.signingWorkers,
67
+ buffer_size: config.bufferSize,
68
+ };
69
+ // Leaving the swap server address unset disables the swap subsystem, so omit
70
+ // every swap field when the host asked to run without swaps.
71
+ if (!config.disableSwaps) {
72
+ out.swap_server_address = config.swapServerAddress;
73
+ out.swap_server_tls_cert_path = config.swapServerTlsCertPath;
74
+ out.swap_server_transport = serverTransport;
75
+ out.swap_server_insecure = config.swapServerInsecure;
76
+ out.swap_database_file_name = config.swapDatabaseFileName;
77
+ }
78
+ for (const key of Object.keys(out)) {
79
+ if (out[key] === undefined) {
80
+ delete out[key];
81
+ }
82
+ }
83
+ return out;
84
+ }
85
+ // The base64 alphabet, indexed by 6-bit value.
86
+ const BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
87
+ /**
88
+ * Encodes a string as base64 of its UTF-8 bytes, matching how Go's
89
+ * encoding/json represents a []byte field. Implemented without btoa or
90
+ * TextEncoder so it behaves identically in the browser, a worker, and Hermes.
91
+ */
92
+ export function base64FromUtf8(value) {
93
+ const bytes = [];
94
+ for (const ch of value) {
95
+ const cp = ch.codePointAt(0);
96
+ if (cp < 0x80) {
97
+ bytes.push(cp);
98
+ }
99
+ else if (cp < 0x800) {
100
+ bytes.push(0xc0 | (cp >> 6), 0x80 | (cp & 0x3f));
101
+ }
102
+ else if (cp < 0x10000) {
103
+ bytes.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
104
+ }
105
+ else {
106
+ bytes.push(0xf0 | (cp >> 18), 0x80 | ((cp >> 12) & 0x3f), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
107
+ }
108
+ }
109
+ let out = '';
110
+ for (let i = 0; i < bytes.length; i += 3) {
111
+ const b0 = bytes[i];
112
+ const b1 = bytes[i + 1];
113
+ const b2 = bytes[i + 2];
114
+ out += BASE64_ALPHABET[b0 >> 2];
115
+ out += BASE64_ALPHABET[((b0 & 0x03) << 4) | ((b1 ?? 0) >> 4)];
116
+ out += b1 === undefined ? '=' : BASE64_ALPHABET[((b1 & 0x0f) << 2) | ((b2 ?? 0) >> 6)];
117
+ out += b2 === undefined ? '=' : BASE64_ALPHABET[b2 & 0x3f];
118
+ }
119
+ return out;
120
+ }
121
+ /**
122
+ * Maps the TS-convention {@link CreateWalletRequest} (with a string password
123
+ * field) to the Go JSON shape the facade expects. Go's encoding/json uses
124
+ * struct field names verbatim and represents []byte as base64, so
125
+ * WalletPassword and SeedPassphrase must arrive as base64.
126
+ */
127
+ export function toGoCreateWalletReq(req) {
128
+ return {
129
+ WalletPassword: req.password ? base64FromUtf8(req.password) : undefined,
130
+ Mnemonic: req.mnemonic,
131
+ SeedPassphrase: req.seedPassphrase
132
+ ? base64FromUtf8(req.seedPassphrase)
133
+ : undefined,
134
+ // The Go facade struct has no json tags, so field names stay PascalCase on
135
+ // the wire (unlike the camelCase TS mirror in generated.ts). Pass both
136
+ // recovery fields straight through; JSON drops the undefined ones, letting
137
+ // the daemon apply its own defaults.
138
+ RecoverState: req.recoverState,
139
+ RecoveryWindow: req.recoveryWindow,
140
+ };
141
+ }
142
+ /**
143
+ * Maps the TS-convention {@link UnlockWalletRequest} to the Go JSON shape,
144
+ * base64-encoding the password string for the []byte field.
145
+ */
146
+ export function toGoUnlockWalletReq(req) {
147
+ return {
148
+ WalletPassword: req.password ? base64FromUtf8(req.password) : undefined,
149
+ };
150
+ }