stellar-shade 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +54 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -5
- package/dist/index.d.ts +51 -5
- package/dist/index.js +54 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -597,15 +597,20 @@ var StealthClient = class {
|
|
|
597
597
|
* Derives a one-time stealth address from the recipient's meta-address,
|
|
598
598
|
* deposits tokens into the pool contract, and records the announcement.
|
|
599
599
|
*
|
|
600
|
+
* Signing: by default the transaction is signed with `senderSecret` (a
|
|
601
|
+
* Stellar secret key). If `opts.signTransaction` is provided, signing is
|
|
602
|
+
* delegated to that external signer (e.g. a browser wallet) and the
|
|
603
|
+
* `senderSecret` argument is treated as the sender's public key instead.
|
|
604
|
+
*
|
|
600
605
|
* @param metaAddress - Recipient's meta-address (st:stellar:... format)
|
|
601
606
|
* @param amount - Amount in whole units (e.g. 100 = 100 XLM)
|
|
602
|
-
* @param senderSecret - Sender's
|
|
603
|
-
* @param opts - Optional: asset to send
|
|
607
|
+
* @param senderSecret - Sender's secret key, or public key when using `opts.signTransaction`
|
|
608
|
+
* @param opts - Optional: asset to send, external signer
|
|
604
609
|
*/
|
|
605
610
|
async send(metaAddress, amount, senderSecret, opts) {
|
|
606
611
|
if (amount <= 0) throw new Error("Amount must be positive");
|
|
607
612
|
const { spendPubKey, viewPubKey } = decodeMetaAddress(metaAddress);
|
|
608
|
-
const
|
|
613
|
+
const senderPublicKey = opts?.signTransaction ? senderSecret : StellarSdk.Keypair.fromSecret(senderSecret).publicKey();
|
|
609
614
|
const tokenAddress = resolveTokenAddress(opts?.asset, this.networkPassphrase);
|
|
610
615
|
const stroops = BigInt(Math.round(amount * 1e7));
|
|
611
616
|
const ephemeralPrivKey = new Uint8Array(utils.randomBytes(32));
|
|
@@ -615,14 +620,14 @@ var StealthClient = class {
|
|
|
615
620
|
ephemeralPrivKey
|
|
616
621
|
);
|
|
617
622
|
const contract = new StellarSdk.Contract(this.contractId);
|
|
618
|
-
const account = await this.server.getAccount(
|
|
623
|
+
const account = await this.server.getAccount(senderPublicKey);
|
|
619
624
|
const depositTx = new StellarSdk.TransactionBuilder(account, {
|
|
620
625
|
fee: "100",
|
|
621
626
|
networkPassphrase: this.networkPassphrase
|
|
622
627
|
}).addOperation(
|
|
623
628
|
contract.call(
|
|
624
629
|
"deposit",
|
|
625
|
-
new StellarSdk__namespace.Address(
|
|
630
|
+
new StellarSdk__namespace.Address(senderPublicKey).toScVal(),
|
|
626
631
|
new StellarSdk__namespace.Address(tokenAddress).toScVal(),
|
|
627
632
|
StellarSdk.nativeToScVal(stroops, { type: "i128" }),
|
|
628
633
|
StellarSdk.nativeToScVal(Buffer.from(stealth.stealthPubKey)),
|
|
@@ -631,8 +636,13 @@ var StealthClient = class {
|
|
|
631
636
|
)
|
|
632
637
|
).setTimeout(30).build();
|
|
633
638
|
const prepared = await this.server.prepareTransaction(depositTx);
|
|
634
|
-
|
|
635
|
-
|
|
639
|
+
const signed = await this.signTx(
|
|
640
|
+
prepared,
|
|
641
|
+
senderSecret,
|
|
642
|
+
senderPublicKey,
|
|
643
|
+
opts?.signTransaction
|
|
644
|
+
);
|
|
645
|
+
const result = await this.server.sendTransaction(signed);
|
|
636
646
|
if (result.status === "ERROR") {
|
|
637
647
|
throw new Error("Transaction submission failed");
|
|
638
648
|
}
|
|
@@ -644,6 +654,27 @@ var StealthClient = class {
|
|
|
644
654
|
txHash: result.hash
|
|
645
655
|
};
|
|
646
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Sign a prepared transaction either with a local secret key (legacy path)
|
|
659
|
+
* or by delegating to an external signer that returns signed XDR.
|
|
660
|
+
*
|
|
661
|
+
* @param prepared - The prepared transaction to sign
|
|
662
|
+
* @param secretOrPublic - Secret key (local signing) or public key (external)
|
|
663
|
+
* @param publicKey - Signer's public key (G...)
|
|
664
|
+
* @param signer - Optional external signer; when present, no secret is used
|
|
665
|
+
*/
|
|
666
|
+
async signTx(prepared, secretOrPublic, publicKey, signer) {
|
|
667
|
+
if (signer) {
|
|
668
|
+
const signedXdr = await signer(prepared.toXDR(), {
|
|
669
|
+
networkPassphrase: this.networkPassphrase,
|
|
670
|
+
address: publicKey
|
|
671
|
+
});
|
|
672
|
+
const tx = StellarSdk.TransactionBuilder.fromXDR(signedXdr, this.networkPassphrase);
|
|
673
|
+
return tx;
|
|
674
|
+
}
|
|
675
|
+
prepared.sign(StellarSdk.Keypair.fromSecret(secretOrPublic));
|
|
676
|
+
return prepared;
|
|
677
|
+
}
|
|
647
678
|
/**
|
|
648
679
|
* Scan for stealth payments you received.
|
|
649
680
|
*
|
|
@@ -785,9 +816,15 @@ var StealthClient = class {
|
|
|
785
816
|
nonce
|
|
786
817
|
);
|
|
787
818
|
const signature = signWithStealthKey(messageHash, stealthPrivKey);
|
|
788
|
-
|
|
819
|
+
if (!opts.signTransaction && !opts.feePayer) {
|
|
820
|
+
throw new Error("Provide either opts.feePayer or opts.signTransaction + opts.feePayerAddress");
|
|
821
|
+
}
|
|
822
|
+
if (opts.signTransaction && !opts.feePayerAddress) {
|
|
823
|
+
throw new Error("opts.feePayerAddress is required when using opts.signTransaction");
|
|
824
|
+
}
|
|
825
|
+
const feePayerPublicKey = opts.signTransaction ? opts.feePayerAddress : StellarSdk.Keypair.fromSecret(opts.feePayer).publicKey();
|
|
789
826
|
const contract = new StellarSdk.Contract(this.contractId);
|
|
790
|
-
const feePayerAccount = await this.server.getAccount(
|
|
827
|
+
const feePayerAccount = await this.server.getAccount(feePayerPublicKey);
|
|
791
828
|
const withdrawTx = new StellarSdk.TransactionBuilder(feePayerAccount, {
|
|
792
829
|
fee: "100",
|
|
793
830
|
networkPassphrase: this.networkPassphrase
|
|
@@ -803,14 +840,19 @@ var StealthClient = class {
|
|
|
803
840
|
)
|
|
804
841
|
).setTimeout(30).build();
|
|
805
842
|
const prepared = await this.server.prepareTransaction(withdrawTx);
|
|
806
|
-
|
|
843
|
+
const signedTx = await this.signTx(
|
|
844
|
+
prepared,
|
|
845
|
+
opts.feePayer ?? "",
|
|
846
|
+
feePayerPublicKey,
|
|
847
|
+
opts.signTransaction
|
|
848
|
+
);
|
|
807
849
|
let txHash;
|
|
808
850
|
if (opts.relay) {
|
|
809
851
|
const url = opts.relay.endsWith("/relay") ? opts.relay : `${opts.relay}/relay`;
|
|
810
852
|
const res = await fetch(url, {
|
|
811
853
|
method: "POST",
|
|
812
854
|
headers: { "Content-Type": "application/json" },
|
|
813
|
-
body: JSON.stringify({ xdr:
|
|
855
|
+
body: JSON.stringify({ xdr: signedTx.toEnvelope().toXDR("base64") })
|
|
814
856
|
});
|
|
815
857
|
if (!res.ok) {
|
|
816
858
|
const err = await res.json();
|
|
@@ -819,7 +861,7 @@ var StealthClient = class {
|
|
|
819
861
|
const data = await res.json();
|
|
820
862
|
txHash = data.txHash;
|
|
821
863
|
} else {
|
|
822
|
-
const result = await this.server.sendTransaction(
|
|
864
|
+
const result = await this.server.sendTransaction(signedTx);
|
|
823
865
|
if (result.status === "ERROR") throw new Error("Transaction submission failed");
|
|
824
866
|
if (result.status === "PENDING") {
|
|
825
867
|
await waitForTransaction(this.server, result.hash);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../crypto/src/errors.ts","../../crypto/src/ed25519.ts","../../crypto/src/keys.ts","../../crypto/src/hash.ts","../../crypto/src/stellar-keys.ts","../../crypto/src/scan.ts","../../crypto/src/recover.ts","../../crypto/src/prove.ts","../../crypto/src/advanced.ts","../../crypto/src/hd.ts","../src/soroban.ts","../src/client.ts"],"names":["ed25519","bytesToNumberLE","numberToBytesLE","randomBytes","sha256","sha512","_generateMnemonic","wordlist","_validateMnemonic","mnemonicToSeedSync","viewTag","Networks","StellarSdk","TransactionBuilder","Contract","Asset","nativeToScVal","StrKey","Keypair","StellarSdk2"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Custom error types for crypto operations\r\n */\r\n\r\n/**\r\n * Error thrown when a point operation results in the point at infinity\r\n */\r\nexport class PointAtInfinity extends Error {\r\n constructor(operation: string) {\r\n super(`Point at infinity encountered in ${operation}`);\r\n this.name = 'PointAtInfinity';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a public key is not on the ed25519 curve\r\n */\r\nexport class InvalidPublicKey extends Error {\r\n constructor(message = 'Invalid public key: not on curve') {\r\n super(message);\r\n this.name = 'InvalidPublicKey';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a scalar value is invalid (e.g., zero where not allowed)\r\n */\r\nexport class InvalidScalar extends Error {\r\n constructor(message = 'Invalid scalar value') {\r\n super(message);\r\n this.name = 'InvalidScalar';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when meta-address encoding/decoding fails\r\n */\r\nexport class InvalidMetaAddress extends Error {\r\n constructor(message = 'Invalid meta-address format') {\r\n super(message);\r\n this.name = 'InvalidMetaAddress';\r\n }\r\n}","import { ed25519 } from '@noble/curves/ed25519';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { PointAtInfinity, InvalidPublicKey, InvalidScalar } from './errors.js';\r\n\r\n/**\r\n * Curve order L for ed25519\r\n */\r\nexport const L = 2n ** 252n + 27742317777372353535851937790883648493n;\r\n\r\n/**\r\n * Validate that a point is on the ed25519 curve.\r\n * @param point 32-byte compressed point\r\n * @returns true if valid\r\n * @throws InvalidPublicKey if not on curve\r\n */\r\nexport function validatePoint(point: Uint8Array): boolean {\r\n if (point.length !== 32) {\r\n throw new InvalidPublicKey('Invalid point length');\r\n }\r\n\r\n try {\r\n // This will throw if point is not on curve\r\n ed25519.ExtendedPoint.fromHex(point);\r\n return true;\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) throw e;\r\n throw new InvalidPublicKey('Point not on curve');\r\n }\r\n}\r\n\r\n/**\r\n * Add two ed25519 points.\r\n * @param p1 First point (32-byte compressed)\r\n * @param p2 Second point (32-byte compressed)\r\n * @returns Result point (32-byte compressed)\r\n * @throws PointAtInfinity if result is point at infinity\r\n * @throws InvalidPublicKey if points are not on curve\r\n */\r\nexport function pointAdd(p1: Uint8Array, p2: Uint8Array): Uint8Array {\r\n if (p1.length !== 32) throw new InvalidPublicKey('Invalid p1 length');\r\n if (p2.length !== 32) throw new InvalidPublicKey('Invalid p2 length');\r\n\r\n // Validate both points are on curve\r\n validatePoint(p1);\r\n validatePoint(p2);\r\n\r\n const point1 = ed25519.ExtendedPoint.fromHex(p1);\r\n const point2 = ed25519.ExtendedPoint.fromHex(p2);\r\n const result = point1.add(point2);\r\n\r\n // Check for point at infinity\r\n if (result.equals(ed25519.ExtendedPoint.ZERO)) {\r\n throw new PointAtInfinity('pointAdd');\r\n }\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Scalar multiplication with generator point.\r\n * @param scalar 32-byte scalar (little-endian)\r\n * @param allowZero Allow zero scalar (returns point at infinity)\r\n * @returns Result point (32-byte compressed)\r\n * @throws InvalidScalar if scalar is zero and not allowed\r\n */\r\nexport function scalarMultBase(scalar: Uint8Array, allowZero = false): Uint8Array {\r\n if (scalar.length !== 32) throw new InvalidScalar('Invalid scalar length');\r\n\r\n // Reduce scalar modulo L\r\n const s = bytesToNumberLE(scalar) % L;\r\n\r\n // Handle zero scalar case\r\n if (s === 0n) {\r\n if (!allowZero) {\r\n throw new InvalidScalar('Zero scalar not allowed');\r\n }\r\n return ed25519.ExtendedPoint.ZERO.toRawBytes();\r\n }\r\n\r\n const result = ed25519.ExtendedPoint.BASE.multiply(s);\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Scalar multiplication with arbitrary point.\r\n * @param scalar 32-byte scalar (little-endian)\r\n * @param point 32-byte compressed point\r\n * @param allowZero Allow zero scalar (returns point at infinity)\r\n * @returns Result point (32-byte compressed)\r\n * @throws InvalidScalar if scalar is zero and not allowed\r\n * @throws InvalidPublicKey if point is not on curve\r\n * @throws PointAtInfinity if result is point at infinity\r\n */\r\nexport function scalarMult(scalar: Uint8Array, point: Uint8Array, allowZero = false): Uint8Array {\r\n if (scalar.length !== 32) throw new InvalidScalar('Invalid scalar length');\r\n if (point.length !== 32) throw new InvalidPublicKey('Invalid point length');\r\n\r\n // Validate point is on curve\r\n validatePoint(point);\r\n\r\n // Reduce scalar modulo L\r\n const s = bytesToNumberLE(scalar) % L;\r\n\r\n // Handle zero scalar case\r\n if (s === 0n) {\r\n if (!allowZero) {\r\n throw new InvalidScalar('Zero scalar not allowed');\r\n }\r\n return ed25519.ExtendedPoint.ZERO.toRawBytes();\r\n }\r\n\r\n const p = ed25519.ExtendedPoint.fromHex(point);\r\n const result = p.multiply(s);\r\n\r\n // Check for point at infinity (should not happen with valid inputs)\r\n if (result.equals(ed25519.ExtendedPoint.ZERO)) {\r\n throw new PointAtInfinity('scalarMult');\r\n }\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Add two scalars modulo curve order L.\r\n * @param s1 First scalar (32-byte, little-endian)\r\n * @param s2 Second scalar (32-byte, little-endian)\r\n * @returns Result scalar (32-byte, little-endian)\r\n * @throws InvalidScalar if inputs have wrong length\r\n */\r\nexport function scalarAdd(s1: Uint8Array, s2: Uint8Array): Uint8Array {\r\n if (s1.length !== 32) throw new InvalidScalar('Invalid s1 length');\r\n if (s2.length !== 32) throw new InvalidScalar('Invalid s2 length');\r\n\r\n const a = bytesToNumberLE(s1) % L;\r\n const b = bytesToNumberLE(s2) % L;\r\n const result = (a + b) % L;\r\n\r\n return numberToBytesLE(result, 32);\r\n}","import { randomBytes } from '@noble/hashes/utils';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\nimport type { StealthKeys, StealthMetaAddress } from './types.js';\r\nimport { L, scalarMultBase, validatePoint } from './ed25519.js';\r\nimport { InvalidMetaAddress, InvalidPublicKey } from './errors.js';\r\n\r\n/**\r\n * Generate a new stealth meta-address with random keys.\r\n *\r\n * Creates a complete stealth key pair using cryptographically secure\r\n * random number generation. The resulting keys can be used for:\r\n * - Receiving stealth payments (using the meta-address)\r\n * - Scanning for incoming payments (using view private key)\r\n * - Spending from stealth addresses (using spend private key)\r\n *\r\n * @returns Complete stealth keys including private keys and meta-address\r\n *\r\n * @example\r\n * ```typescript\r\n * const keys = generateMetaAddress();\r\n *\r\n * // Share the meta-address publicly\r\n * const encoded = encodeMetaAddress(keys.metaAddress);\r\n * console.log('Share this:', encoded);\r\n *\r\n * // Keep private keys secure\r\n * saveSecurely(keys.spendPrivKey, keys.viewPrivKey);\r\n * ```\r\n */\r\nexport function generateMetaAddress(): StealthKeys {\r\n // Generate two random 32-byte scalars (reduced mod L)\r\n const spendPrivKey = generateRandomScalar();\r\n const viewPrivKey = generateRandomScalar();\r\n\r\n // Derive public keys\r\n const spendPubKey = scalarMultBase(spendPrivKey);\r\n const viewPubKey = scalarMultBase(viewPrivKey);\r\n\r\n return {\r\n spendPrivKey,\r\n viewPrivKey,\r\n metaAddress: {\r\n spendPubKey,\r\n viewPubKey,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Generate a random scalar reduced modulo L.\r\n * @returns 32-byte scalar (little-endian, reduced mod L)\r\n */\r\nfunction generateRandomScalar(): Uint8Array {\r\n const bytes = randomBytes(32);\r\n const scalar = bytesToNumberLE(bytes) % L;\r\n return numberToBytesLE(scalar, 32);\r\n}\r\n\r\n/**\r\n * Encode a stealth meta-address to a string format with checksum.\r\n *\r\n * Encodes the meta-address into a shareable string format that includes:\r\n * - Protocol identifier (\"st:stellar:\")\r\n * - Concatenated public keys (spend || view)\r\n * - CRC32 checksum for error detection\r\n *\r\n * @param meta - Stealth meta-address containing spend and view public keys\r\n * @returns Encoded string in format \"st:stellar:<hex(spend_pk || view_pk)><checksum>\"\r\n * @throws {InvalidMetaAddress} If public keys are invalid length or not on curve\r\n *\r\n * @example\r\n * ```typescript\r\n * const keys = generateMetaAddress();\r\n * const encoded = encodeMetaAddress(keys.metaAddress);\r\n * console.log(encoded); // \"st:stellar:abc123...def456\"\r\n *\r\n * // Share this encoded string with senders\r\n * publishMetaAddress(encoded);\r\n * ```\r\n */\r\nexport function encodeMetaAddress(meta: StealthMetaAddress): string {\r\n if (meta.spendPubKey.length !== 32) {\r\n throw new InvalidMetaAddress('Invalid spend public key length');\r\n }\r\n if (meta.viewPubKey.length !== 32) {\r\n throw new InvalidMetaAddress('Invalid view public key length');\r\n }\r\n\r\n // Validate both keys are on curve\r\n try {\r\n validatePoint(meta.spendPubKey);\r\n validatePoint(meta.viewPubKey);\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) {\r\n throw new InvalidMetaAddress(`Invalid public key: ${e.message}`);\r\n }\r\n throw e;\r\n }\r\n\r\n // Concatenate both public keys\r\n const payload = new Uint8Array(64);\r\n payload.set(meta.spendPubKey, 0);\r\n payload.set(meta.viewPubKey, 32);\r\n\r\n // Calculate checksum (last 4 bytes of SHA-256)\r\n const hash = sha256(payload);\r\n const checksum = hash.slice(28, 32);\r\n\r\n // Combine payload and checksum\r\n const combined = new Uint8Array(68);\r\n combined.set(payload, 0);\r\n combined.set(checksum, 64);\r\n\r\n // Convert to hex\r\n const hex = Array.from(combined)\r\n .map((b) => b.toString(16).padStart(2, '0'))\r\n .join('');\r\n\r\n return `st:stellar:${hex}`;\r\n}\r\n\r\n/**\r\n * Decode a string-encoded stealth meta-address with checksum validation.\r\n *\r\n * Parses an encoded meta-address string and validates:\r\n * - Correct format and prefix\r\n * - Valid hex encoding\r\n * - Checksum integrity\r\n * - Public keys are on curve\r\n *\r\n * @param encoded - Encoded meta-address string (\"st:stellar:...\")\r\n * @returns Decoded stealth meta-address with public keys\r\n * @throws {InvalidMetaAddress} If format, checksum, or keys are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * const encoded = \"st:stellar:abc123...def456\";\r\n * const meta = decodeMetaAddress(encoded);\r\n *\r\n * // Use for deriving stealth addresses\r\n * const stealth = deriveStealthAddress(meta);\r\n * ```\r\n */\r\nexport function decodeMetaAddress(encoded: string): StealthMetaAddress {\r\n if (!encoded.startsWith('st:stellar:')) {\r\n throw new InvalidMetaAddress('Invalid meta-address prefix');\r\n }\r\n\r\n const hex = encoded.slice(11); // Remove \"st:stellar:\" prefix\r\n if (hex.length !== 136) {\r\n // 64 bytes payload + 4 bytes checksum = 68 bytes = 136 hex chars\r\n throw new InvalidMetaAddress('Invalid meta-address length');\r\n }\r\n\r\n // Parse hex to bytes\r\n const combined = new Uint8Array(68);\r\n for (let i = 0; i < 68; i++) {\r\n const byte = parseInt(hex.substr(i * 2, 2), 16);\r\n if (isNaN(byte)) {\r\n throw new InvalidMetaAddress('Invalid hex encoding');\r\n }\r\n combined[i] = byte;\r\n }\r\n\r\n // Split payload and checksum\r\n const payload = combined.slice(0, 64);\r\n const checksum = combined.slice(64, 68);\r\n\r\n // Verify checksum\r\n const hash = sha256(payload);\r\n const expectedChecksum = hash.slice(28, 32);\r\n\r\n let checksumValid = true;\r\n for (let i = 0; i < 4; i++) {\r\n if (checksum[i] !== expectedChecksum[i]) {\r\n checksumValid = false;\r\n break;\r\n }\r\n }\r\n\r\n if (!checksumValid) {\r\n throw new InvalidMetaAddress('Invalid checksum');\r\n }\r\n\r\n const spendPubKey = payload.slice(0, 32);\r\n const viewPubKey = payload.slice(32, 64);\r\n\r\n // Validate both keys are on curve\r\n try {\r\n validatePoint(spendPubKey);\r\n validatePoint(viewPubKey);\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) {\r\n throw new InvalidMetaAddress(`Invalid public key in meta-address: ${e.message}`);\r\n }\r\n throw e;\r\n }\r\n\r\n return {\r\n spendPubKey,\r\n viewPubKey,\r\n };\r\n}","import { sha256 } from '@noble/hashes/sha256';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { L } from './ed25519.js';\r\nimport { InvalidScalar } from './errors.js';\r\n\r\n/**\r\n * Hash data to a scalar value modulo curve order L.\r\n *\r\n * Implements the hash-to-scalar function used in DKSAP for deriving\r\n * the blinding factor from the shared secret.\r\n *\r\n * @param data - Input data to hash (typically a 32-byte shared secret)\r\n * @returns 32-byte scalar (little-endian, reduced mod L)\r\n * @throws {InvalidScalar} If hash produces zero scalar (extremely unlikely)\r\n *\r\n * @example\r\n * ```typescript\r\n * const sharedSecret = scalarMult(ephemeralPrivKey, viewPubKey);\r\n * const s = hashToScalar(sharedSecret);\r\n * // Use s as blinding factor for stealth key derivation\r\n * ```\r\n */\r\nexport function hashToScalar(data: Uint8Array): Uint8Array {\r\n const hash = sha256(data);\r\n const scalar = bytesToNumberLE(hash) % L;\r\n\r\n // In the extremely unlikely event the hash produces zero mod L\r\n if (scalar === 0n) {\r\n throw new InvalidScalar('Hash produced zero scalar');\r\n }\r\n\r\n return numberToBytesLE(scalar, 32);\r\n}\r\n\r\n/**\r\n * Extract view tag from shared secret.\r\n *\r\n * The view tag is the first byte of SHA256(shared_secret) and enables\r\n * ~25x faster scanning by filtering announcements before expensive EC operations.\r\n *\r\n * @param sharedSecret - 32-byte shared secret from ECDH\r\n * @returns Single byte view tag (0-255)\r\n * @throws {Error} If shared secret is not 32 bytes\r\n *\r\n * @example\r\n * ```typescript\r\n * const sharedSecret = scalarMult(viewPrivKey, ephemeralPubKey);\r\n * const tag = viewTag(sharedSecret);\r\n * // Use tag for fast announcement filtering\r\n * ```\r\n */\r\nexport function viewTag(sharedSecret: Uint8Array): number {\r\n if (sharedSecret.length !== 32) {\r\n throw new Error('Invalid shared secret length');\r\n }\r\n const hash = sha256(sharedSecret);\r\n return hash[0]!;\r\n}","/**\r\n * Stellar StrKey encoding (base32check) for ed25519 public keys.\r\n * This module provides pure TypeScript implementation without @stellar/stellar-sdk dependency.\r\n */\r\n\r\nconst ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';\r\nconst VERSION_BYTE_PUBLIC_KEY = 6 << 3; // G addresses\r\n\r\n/**\r\n * CRC16-XModem checksum implementation.\r\n */\r\nfunction crc16XModem(data: Uint8Array): number {\r\n let crc = 0x0000;\r\n for (let i = 0; i < data.length; i++) {\r\n crc ^= data[i]! << 8;\r\n for (let j = 0; j < 8; j++) {\r\n if (crc & 0x8000) {\r\n crc = (crc << 1) ^ 0x1021;\r\n } else {\r\n crc = crc << 1;\r\n }\r\n }\r\n }\r\n return crc & 0xffff;\r\n}\r\n\r\n/**\r\n * Base32 encode (RFC 4648) without padding.\r\n */\r\nfunction base32Encode(data: Uint8Array): string {\r\n let bits = 0;\r\n let value = 0;\r\n let output = '';\r\n\r\n for (let i = 0; i < data.length; i++) {\r\n value = (value << 8) | data[i]!;\r\n bits += 8;\r\n\r\n while (bits >= 5) {\r\n output += ALPHABET[(value >>> (bits - 5)) & 31];\r\n bits -= 5;\r\n }\r\n }\r\n\r\n if (bits > 0) {\r\n output += ALPHABET[(value << (5 - bits)) & 31];\r\n }\r\n\r\n return output;\r\n}\r\n\r\n/**\r\n * Base32 decode (RFC 4648).\r\n */\r\nfunction base32Decode(str: string): Uint8Array {\r\n const output: number[] = [];\r\n let bits = 0;\r\n let value = 0;\r\n\r\n for (let i = 0; i < str.length; i++) {\r\n const idx = ALPHABET.indexOf(str[i]!);\r\n if (idx === -1) {\r\n throw new Error(`Invalid base32 character: ${str[i]}`);\r\n }\r\n\r\n value = (value << 5) | idx;\r\n bits += 5;\r\n\r\n while (bits >= 8) {\r\n output.push((value >>> (bits - 8)) & 255);\r\n bits -= 8;\r\n }\r\n }\r\n\r\n return new Uint8Array(output);\r\n}\r\n\r\n/**\r\n * Encode ed25519 public key to Stellar address format (G...).\r\n *\r\n * Implements Stellar's StrKey encoding (SEP-23) using base32check format.\r\n *\r\n * @param pubKey - 32-byte ed25519 public key\r\n * @returns Stellar address in StrKey format (G...)\r\n * @throws {Error} If public key is not exactly 32 bytes\r\n *\r\n * @example\r\n * ```typescript\r\n * const pubKey = new Uint8Array(32); // Your public key\r\n * const address = encodePublicKey(pubKey);\r\n * console.log(address); // \"GABC...XYZ\"\r\n * ```\r\n */\r\nexport function encodePublicKey(pubKey: Uint8Array): string {\r\n if (pubKey.length !== 32) {\r\n throw new Error('Public key must be 32 bytes');\r\n }\r\n\r\n const versionedPayload = new Uint8Array(33);\r\n versionedPayload[0] = VERSION_BYTE_PUBLIC_KEY;\r\n versionedPayload.set(pubKey, 1);\r\n\r\n const checksum = crc16XModem(versionedPayload);\r\n const checksumBytes = new Uint8Array(2);\r\n checksumBytes[0] = checksum & 0xff;\r\n checksumBytes[1] = (checksum >>> 8) & 0xff;\r\n\r\n const fullPayload = new Uint8Array(35);\r\n fullPayload.set(versionedPayload, 0);\r\n fullPayload.set(checksumBytes, 33);\r\n\r\n return base32Encode(fullPayload);\r\n}\r\n\r\n/**\r\n * Decode Stellar address to ed25519 public key.\r\n *\r\n * Implements Stellar's StrKey decoding (SEP-23) with checksum validation.\r\n *\r\n * @param address - Stellar address in StrKey format (G...)\r\n * @returns 32-byte ed25519 public key\r\n * @throws {Error} If address format is invalid or checksum fails\r\n *\r\n * @example\r\n * ```typescript\r\n * const address = \"GABC...XYZ\";\r\n * const pubKey = decodePublicKey(address);\r\n * console.log(pubKey.length); // 32\r\n * ```\r\n */\r\nexport function decodePublicKey(address: string): Uint8Array {\r\n if (!address.startsWith('G')) {\r\n throw new Error('Invalid Stellar address: must start with G');\r\n }\r\n\r\n const decoded = base32Decode(address);\r\n if (decoded.length !== 35) {\r\n throw new Error('Invalid Stellar address: incorrect length');\r\n }\r\n\r\n const versionByte = decoded[0]!;\r\n if (versionByte !== VERSION_BYTE_PUBLIC_KEY) {\r\n throw new Error('Invalid Stellar address: wrong version byte');\r\n }\r\n\r\n const versionedPayload = decoded.slice(0, 33);\r\n const providedChecksum = (decoded[34]! << 8) | decoded[33]!;\r\n const calculatedChecksum = crc16XModem(versionedPayload);\r\n\r\n if (providedChecksum !== calculatedChecksum) {\r\n throw new Error('Invalid Stellar address: checksum mismatch');\r\n }\r\n\r\n return decoded.slice(1, 33);\r\n}","import type { Announcement, StealthAddress } from './types.js';\r\nimport { scalarMult, pointAdd, scalarMultBase } from './ed25519.js';\r\nimport { hashToScalar, viewTag } from './hash.js';\r\nimport { encodePublicKey } from './stellar-keys.js';\r\n\r\n/**\r\n * Check if a view tag matches for a given ephemeral public key.\r\n *\r\n * This is a fast pre-filter before doing the expensive EC operations.\r\n * Only computes the shared secret and extracts the first byte for comparison.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @param expectedTag - Expected view tag from announcement (0-255)\r\n * @returns Object with match result and shared secret if matched\r\n * @throws {Error} If key lengths are invalid or tag is out of range\r\n *\r\n * @example\r\n * ```typescript\r\n * // Fast filtering before full verification\r\n * const result = checkViewTag(viewPrivKey, announcement.ephemeralPubKey, announcement.viewTag);\r\n * if (result.matches) {\r\n * // Use the shared secret for further verification\r\n * const s = hashToScalar(result.sharedSecret);\r\n * }\r\n * ```\r\n */\r\nexport function checkViewTag(\r\n viewPrivKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array,\r\n expectedTag: number\r\n): { matches: boolean; sharedSecret?: Uint8Array } {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n if (expectedTag < 0 || expectedTag > 255) {\r\n throw new Error('Invalid view tag');\r\n }\r\n\r\n // Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Extract and compare view tag (first byte of SHA256(S))\r\n const computedTag = viewTag(S);\r\n\r\n if (computedTag === expectedTag) {\r\n return { matches: true, sharedSecret: S };\r\n }\r\n return { matches: false };\r\n}\r\n\r\n/**\r\n * Scan announcements to find stealth addresses belonging to the receiver.\r\n *\r\n * This implements an optimized two-pass scanning algorithm:\r\n * - Pass 1: Filter by view tag (cheap byte comparison)\r\n * - Pass 2: Full EC math (scalarMult + pointAdd) only on tag matches\r\n *\r\n * This optimization provides ~25x speedup for large announcement sets\r\n * by avoiding expensive EC operations on non-matching announcements.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param announcements - List of announcements to scan\r\n * @returns Array of stealth addresses belonging to the receiver\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Scan blockchain announcements\r\n * const announcements = await fetchAnnouncements();\r\n * const myAddresses = scanAnnouncements(\r\n * keys.viewPrivKey,\r\n * keys.metaAddress.spendPubKey,\r\n * announcements\r\n * );\r\n *\r\n * // Check balances of discovered addresses\r\n * for (const addr of myAddresses) {\r\n * const balance = await getBalance(addr.address);\r\n * console.log(`${addr.address}: ${balance} XLM`);\r\n * }\r\n * ```\r\n */\r\nexport function scanAnnouncements(\r\n viewPrivKey: Uint8Array,\r\n spendPubKey: Uint8Array,\r\n announcements: Announcement[]\r\n): StealthAddress[] {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (spendPubKey.length !== 32) {\r\n throw new Error('Invalid spend public key length');\r\n }\r\n\r\n const results: StealthAddress[] = [];\r\n\r\n // Two-pass scanning for optimization\r\n // Pass 1: Quick view tag filtering with shared secret caching\r\n const tagMatches: Array<{ announcement: Announcement; sharedSecret: Uint8Array }> = [];\r\n for (const announcement of announcements) {\r\n const tagResult = checkViewTag(viewPrivKey, announcement.ephemeralPubKey, announcement.viewTag);\r\n if (tagResult.matches && tagResult.sharedSecret) {\r\n tagMatches.push({ announcement, sharedSecret: tagResult.sharedSecret });\r\n }\r\n }\r\n\r\n // Pass 2: Full verification only on tag matches (reusing shared secrets)\r\n for (const { announcement, sharedSecret } of tagMatches) {\r\n // Hash to scalar s = SHA256(S) mod L (using cached shared secret)\r\n const s = hashToScalar(sharedSecret);\r\n\r\n // Compute expected stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Convert to Stellar address and compare\r\n const computedAddress = encodePublicKey(P);\r\n\r\n if (computedAddress === announcement.stealthAddress) {\r\n results.push({\r\n publicKey: P,\r\n address: computedAddress,\r\n });\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Check if a specific stealth address belongs to the receiver.\r\n *\r\n * Performs full DKSAP verification to determine ownership of a stealth address.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @param stealthAddress - Stellar address to check (G... format)\r\n * @returns True if the stealth address belongs to the receiver\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Check if a payment is for you\r\n * const isMine = isMyStealthAddress(\r\n * keys.viewPrivKey,\r\n * keys.metaAddress.spendPubKey,\r\n * announcement.ephemeralPubKey,\r\n * announcement.stealthAddress\r\n * );\r\n *\r\n * if (isMine) {\r\n * console.log('Found payment to:', announcement.stealthAddress);\r\n * }\r\n * ```\r\n */\r\nexport function isMyStealthAddress(\r\n viewPrivKey: Uint8Array,\r\n spendPubKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array,\r\n stealthAddress: string\r\n): boolean {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (spendPubKey.length !== 32) {\r\n throw new Error('Invalid spend public key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n\r\n // Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Hash to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Compute expected stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Convert to Stellar address and compare\r\n const computedAddress = encodePublicKey(P);\r\n\r\n return computedAddress === stealthAddress;\r\n}","import { scalarMult, scalarAdd } from './ed25519.js';\r\nimport { hashToScalar } from './hash.js';\r\n\r\n/**\r\n * Recover the stealth private key for a stealth address.\r\n *\r\n * This implements the receiver's private key recovery:\r\n * 1. Compute shared secret S = k_view * R\r\n * 2. Hash to scalar s = SHA256(S) mod L\r\n * 3. Compute stealth private key p = k_spend + s mod L\r\n *\r\n * The recovered private key can be used to:\r\n * - Sign transactions from the stealth address\r\n * - Derive the corresponding public key for verification\r\n *\r\n * @param spendPrivKey - Receiver's 32-byte spend private key\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @returns 32-byte stealth private key for signing transactions\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Recover private key to withdraw funds\r\n * const stealthPrivKey = recoverStealthPrivateKey(\r\n * keys.spendPrivKey,\r\n * keys.viewPrivKey,\r\n * announcement.ephemeralPubKey\r\n * );\r\n *\r\n * // Use with Stellar SDK to sign transaction\r\n * const keypair = Keypair.fromRawEd25519Seed(stealthPrivKey);\r\n * transaction.sign(keypair);\r\n *\r\n * // IMPORTANT: Clear private key from memory after use\r\n * stealthPrivKey.fill(0);\r\n * ```\r\n */\r\nexport function recoverStealthPrivateKey(\r\n spendPrivKey: Uint8Array,\r\n viewPrivKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array\r\n): Uint8Array {\r\n if (spendPrivKey.length !== 32) {\r\n throw new Error('Invalid spend private key length');\r\n }\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n\r\n // Step 1: Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Step 2: Hash shared secret to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Step 3: Compute stealth private key p = k_spend + s mod L\r\n const stealthPrivKey = scalarAdd(spendPrivKey, s);\r\n\r\n return stealthPrivKey;\r\n}","import { ed25519 } from '@noble/curves/ed25519';\r\nimport { sha512 } from '@noble/hashes/sha512';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { L, scalarMultBase } from './ed25519.js';\r\n\r\n/**\r\n * Sign a message using a raw ed25519 scalar (stealth private key).\r\n *\r\n * Standard ed25519.sign() hashes the seed to derive the signing scalar,\r\n * but stealth private keys are already raw scalars from modular addition\r\n * (k_spend + s mod L). This function constructs a valid ed25519 signature\r\n * directly from the raw scalar, producing signatures that verify with\r\n * standard ed25519.verify() against the corresponding public key (scalar * G).\r\n *\r\n * @param message - The message to sign\r\n * @param privateScalar - 32-byte raw scalar (stealth private key)\r\n * @returns 64-byte ed25519 signature (R || S)\r\n */\r\nexport function signWithStealthKey(message: Uint8Array, privateScalar: Uint8Array): Uint8Array {\r\n if (privateScalar.length !== 32) {\r\n throw new Error('Invalid stealth private key length');\r\n }\r\n if (message.length === 0) {\r\n throw new Error('Message cannot be empty');\r\n }\r\n\r\n const a = bytesToNumberLE(privateScalar) % L;\r\n const pubKeyBytes = scalarMultBase(privateScalar);\r\n\r\n // Deterministic nonce: r = SHA-512(privateScalar || message) mod L\r\n const nonceInput = new Uint8Array(32 + message.length);\r\n nonceInput.set(privateScalar, 0);\r\n nonceInput.set(message, 32);\r\n const r = bytesToNumberLE(sha512(nonceInput)) % L;\r\n\r\n const R = ed25519.ExtendedPoint.BASE.multiply(r);\r\n const Rbytes = R.toRawBytes();\r\n\r\n // Challenge: k = SHA-512(R || pubKey || message) mod L\r\n const challengeInput = new Uint8Array(32 + 32 + message.length);\r\n challengeInput.set(Rbytes, 0);\r\n challengeInput.set(pubKeyBytes, 32);\r\n challengeInput.set(message, 64);\r\n const k = bytesToNumberLE(sha512(challengeInput)) % L;\r\n\r\n // Response: S = (r + k * a) mod L\r\n const S = (r + k * a) % L;\r\n\r\n const sig = new Uint8Array(64);\r\n sig.set(Rbytes, 0);\r\n sig.set(numberToBytesLE(S, 32), 32);\r\n return sig;\r\n}\r\n\r\n/**\r\n * Prove ownership of a stealth address by signing a challenge.\r\n *\r\n * Uses raw-scalar ed25519 signing so the signature verifies against\r\n * the stealth public key (privateScalar * G), not the hashed-seed public key.\r\n *\r\n * @param stealthPrivKey - The 32-byte stealth private key (raw scalar)\r\n * @param challenge - The challenge to sign (typically a nonce or timestamp)\r\n * @returns The 64-byte ed25519 signature\r\n * @throws {Error} If private key is not 32 bytes or challenge is empty\r\n */\r\nexport function proveOwnership(\r\n stealthPrivKey: Uint8Array,\r\n challenge: Uint8Array\r\n): Uint8Array {\r\n return signWithStealthKey(challenge, stealthPrivKey);\r\n}\r\n\r\n/**\r\n * Verify ownership proof of a stealth address.\r\n *\r\n * Verifies a standard ed25519 signature against the stealth public key.\r\n * Works with signatures produced by signWithStealthKey/proveOwnership.\r\n *\r\n * @param stealthPubKey - The 32-byte stealth public key (scalar * G)\r\n * @param challenge - The challenge that was signed\r\n * @param signature - The 64-byte signature to verify\r\n * @returns True if the signature is valid, false otherwise\r\n */\r\nexport function verifyOwnership(\r\n stealthPubKey: Uint8Array,\r\n challenge: Uint8Array,\r\n signature: Uint8Array,\r\n): boolean {\r\n if (stealthPubKey.length !== 32) {\r\n throw new Error('Invalid stealth public key length');\r\n }\r\n if (challenge.length === 0) {\r\n throw new Error('Challenge cannot be empty');\r\n }\r\n if (signature.length !== 64) {\r\n throw new Error('Invalid signature length');\r\n }\r\n\r\n try {\r\n return ed25519.verify(signature, challenge, stealthPubKey);\r\n } catch {\r\n return false;\r\n }\r\n}","// Advanced stealth address functions\r\nimport type { StealthDerivation } from './stealth.js';\r\nimport { scalarMult, scalarMultBase, pointAdd } from './ed25519.js';\r\nimport { hashToScalar, viewTag } from './hash.js';\r\nimport { encodePublicKey } from './stellar-keys.js';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\n\r\n/**\r\n * Encrypt an amount using the shared secret.\r\n *\r\n * Uses XOR encryption with SHA256(sharedSecret || \"amount\") as the key.\r\n * This provides confidential amounts in stealth transactions.\r\n *\r\n * @param amount - The amount to encrypt\r\n * @param sharedSecret - The 32-byte shared secret from ECDH\r\n * @returns 8-byte encrypted amount\r\n */\r\nexport function encryptAmount(amount: number, sharedSecret: Uint8Array): Uint8Array {\r\n if (sharedSecret.length !== 32) {\r\n throw new Error(`Invalid shared secret: expected 32 bytes, got ${sharedSecret.length}`);\r\n }\r\n\r\n // Create key material\r\n const keyInput = new Uint8Array(32 + 6);\r\n keyInput.set(sharedSecret, 0);\r\n keyInput.set(new TextEncoder().encode('amount'), 32);\r\n const key = sha256(keyInput);\r\n\r\n // Convert amount to 8-byte little-endian\r\n const amountBytes = new Uint8Array(8);\r\n const view = new DataView(amountBytes.buffer);\r\n view.setFloat64(0, amount, true); // little-endian\r\n\r\n // XOR encrypt\r\n const encrypted = new Uint8Array(8);\r\n for (let i = 0; i < 8; i++) {\r\n encrypted[i] = amountBytes[i]! ^ key[i]!;\r\n }\r\n\r\n return encrypted;\r\n}\r\n\r\n/**\r\n * Decrypt an amount using the shared secret.\r\n *\r\n * @param encrypted - The 8-byte encrypted amount\r\n * @param sharedSecret - The 32-byte shared secret from ECDH\r\n * @returns The decrypted amount\r\n * @throws {Error} If encrypted is not exactly 8 bytes\r\n * @throws {Error} If sharedSecret is not exactly 32 bytes\r\n */\r\nexport function decryptAmount(encrypted: Uint8Array, sharedSecret: Uint8Array): number {\r\n // Validate inputs\r\n if (encrypted.length !== 8) {\r\n throw new Error(`Invalid encrypted amount: expected 8 bytes, got ${encrypted.length}`);\r\n }\r\n if (sharedSecret.length !== 32) {\r\n throw new Error(`Invalid shared secret: expected 32 bytes, got ${sharedSecret.length}`);\r\n }\r\n\r\n // Create key material\r\n const keyInput = new Uint8Array(32 + 6);\r\n keyInput.set(sharedSecret, 0);\r\n keyInput.set(new TextEncoder().encode('amount'), 32);\r\n const key = sha256(keyInput);\r\n\r\n // XOR decrypt\r\n const decrypted = new Uint8Array(8);\r\n for (let i = 0; i < 8; i++) {\r\n decrypted[i] = encrypted[i]! ^ key[i]!;\r\n }\r\n\r\n // Convert from little-endian to number\r\n const view = new DataView(decrypted.buffer);\r\n return view.getFloat64(0, true); // little-endian\r\n}\r\n\r\nexport interface StealthDerivationWithSecret extends StealthDerivation {\r\n sharedSecret: Uint8Array;\r\n}\r\n\r\n/**\r\n * Derive a stealth address with the shared secret exposed.\r\n *\r\n * Similar to deriveStealthAddress but also returns the shared secret,\r\n * useful for applications that need amount encryption or other\r\n * shared secret-based features.\r\n *\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param viewPubKey - Receiver's 32-byte view public key\r\n * @param ephemeralPrivKey - Sender's 32-byte ephemeral private key\r\n * @returns Stealth derivation including the shared secret\r\n */\r\nexport function deriveStealthAddressWithSecret(\r\n spendPubKey: Uint8Array,\r\n viewPubKey: Uint8Array,\r\n ephemeralPrivKey: Uint8Array\r\n): StealthDerivationWithSecret {\r\n // Compute ephemeral public key R = r*G\r\n const R = scalarMultBase(ephemeralPrivKey);\r\n\r\n // Compute shared secret S = r*K_view\r\n const S = scalarMult(ephemeralPrivKey, viewPubKey);\r\n\r\n // Hash shared secret to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Compute stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Get view tag\r\n const tag = viewTag(S);\r\n\r\n return {\r\n stealthPubKey: P,\r\n stealthAddress: encodePublicKey(P),\r\n ephemeralPubKey: R,\r\n viewTag: tag,\r\n ephemeralPrivKey: ephemeralPrivKey,\r\n sharedSecret: S\r\n };\r\n}","import { generateMnemonic as _generateMnemonic, validateMnemonic as _validateMnemonic, mnemonicToSeedSync } from '@scure/bip39';\r\nimport { wordlist } from '@scure/bip39/wordlists/english';\r\nimport type { StealthKeys } from './types.js';\r\nimport { scalarMultBase } from './ed25519.js';\r\nimport { hashToScalar } from './hash.js';\r\n\r\nconst textEncoder = new TextEncoder();\r\n\r\n/**\r\n * Generate a 12-word BIP-39 mnemonic phrase.\r\n */\r\nexport function generateMnemonic(): string {\r\n return _generateMnemonic(wordlist);\r\n}\r\n\r\n/**\r\n * Validate a mnemonic phrase against the BIP-39 english wordlist.\r\n */\r\nexport function validateMnemonic(mnemonic: string): boolean {\r\n return _validateMnemonic(mnemonic, wordlist);\r\n}\r\n\r\n/**\r\n * Derive stealth spend and view keys from a BIP-39 mnemonic.\r\n *\r\n * Uses domain-separated SHA-256 hashing of the BIP-39 seed to derive\r\n * two independent ed25519 scalars for the spend and view key pairs.\r\n */\r\nexport function mnemonicToStealthKeys(mnemonic: string, passphrase?: string): StealthKeys {\r\n if (!_validateMnemonic(mnemonic, wordlist)) {\r\n throw new Error('Invalid mnemonic phrase');\r\n }\r\n\r\n const seed = mnemonicToSeedSync(mnemonic, passphrase || '');\r\n\r\n const spendTag = textEncoder.encode('stealth-spend');\r\n const viewTag = textEncoder.encode('stealth-view');\r\n\r\n const spendInput = new Uint8Array(spendTag.length + seed.length);\r\n spendInput.set(spendTag, 0);\r\n spendInput.set(seed, spendTag.length);\r\n\r\n const viewInput = new Uint8Array(viewTag.length + seed.length);\r\n viewInput.set(viewTag, 0);\r\n viewInput.set(seed, viewTag.length);\r\n\r\n const spendPrivKey = hashToScalar(spendInput);\r\n const viewPrivKey = hashToScalar(viewInput);\r\n\r\n // Zero sensitive intermediates\r\n seed.fill(0);\r\n spendInput.fill(0);\r\n viewInput.fill(0);\r\n\r\n const spendPubKey = scalarMultBase(spendPrivKey);\r\n const viewPubKey = scalarMultBase(viewPrivKey);\r\n\r\n return {\r\n spendPrivKey,\r\n viewPrivKey,\r\n metaAddress: { spendPubKey, viewPubKey },\r\n };\r\n}\r\n","import {\r\n Networks,\r\n Contract,\r\n nativeToScVal,\r\n Asset,\r\n TransactionBuilder,\r\n StrKey,\r\n} from '@stellar/stellar-sdk';\r\nimport * as StellarSdk from '@stellar/stellar-sdk';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\n\r\n/** Network configuration resolved from a network name. */\r\nexport interface NetworkConfig {\r\n networkPassphrase: string;\r\n rpcUrl: string;\r\n server: StellarSdk.rpc.Server;\r\n}\r\n\r\n/** Build network config from a network name. */\r\nexport function getNetworkConfig(network: 'local' | 'testnet'): NetworkConfig {\r\n const networkPassphrase = network === 'local'\r\n ? Networks.STANDALONE\r\n : Networks.TESTNET;\r\n\r\n const rpcUrl = network === 'local'\r\n ? 'http://localhost:8000/soroban/rpc'\r\n : 'https://soroban-testnet.stellar.org';\r\n\r\n const server = new StellarSdk.rpc.Server(rpcUrl, {\r\n allowHttp: network === 'local',\r\n });\r\n\r\n return { networkPassphrase, rpcUrl, server };\r\n}\r\n\r\n/** Create a dummy transaction for read-only contract simulation. */\r\nexport function createSimulationTx(\r\n operation: StellarSdk.xdr.Operation,\r\n networkPassphrase: string,\r\n): StellarSdk.Transaction {\r\n return new TransactionBuilder(\r\n new StellarSdk.Account('GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF', '0'),\r\n { fee: '100', networkPassphrase },\r\n )\r\n .addOperation(operation)\r\n .setTimeout(30)\r\n .build();\r\n}\r\n\r\n/** Execute a read-only contract call via simulation. Returns the decoded native result. */\r\nexport async function simulateReadOnly(\r\n contractId: string,\r\n method: string,\r\n args: StellarSdk.xdr.ScVal[],\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<unknown | null> {\r\n const contract = new Contract(contractId);\r\n const op = contract.call(method, ...args);\r\n const sim = await server.simulateTransaction(\r\n createSimulationTx(op, networkPassphrase),\r\n );\r\n\r\n if (StellarSdk.rpc.Api.isSimulationSuccess(sim) && sim.result?.retval) {\r\n return StellarSdk.scValToNative(sim.result.retval);\r\n }\r\n return null;\r\n}\r\n\r\n/** Resolve an asset string (\"native\", \"XLM\", or \"CODE:ISSUER\") to a SAC contract address. */\r\nexport function resolveTokenAddress(\r\n assetArg: string | undefined,\r\n networkPassphrase: string,\r\n): string {\r\n if (!assetArg || assetArg === 'native' || assetArg === 'XLM') {\r\n return Asset.native().contractId(networkPassphrase);\r\n }\r\n const parts = assetArg.split(':');\r\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\r\n throw new Error('Invalid asset format. Use CODE:ISSUER or \"native\"');\r\n }\r\n return new Asset(parts[0], parts[1]).contractId(networkPassphrase);\r\n}\r\n\r\n/** Poll for transaction confirmation. Throws on failure or timeout. */\r\nexport async function waitForTransaction(\r\n server: StellarSdk.rpc.Server,\r\n hash: string,\r\n): Promise<void> {\r\n let attempts = 0;\r\n while (attempts < 30) {\r\n await new Promise(resolve => setTimeout(resolve, 1000));\r\n try {\r\n const result = await server.getTransaction(hash);\r\n if (result.status === 'SUCCESS') return;\r\n if (result.status === 'FAILED') throw new Error('Transaction failed on-chain');\r\n } catch (e: unknown) {\r\n const msg = e instanceof Error ? e.message : String(e);\r\n if (msg === 'Transaction failed on-chain') throw e;\r\n }\r\n attempts++;\r\n }\r\n throw new Error('Transaction confirmation timed out');\r\n}\r\n\r\n/** Fetch announcements from the stealth pool contract. */\r\nexport async function fetchAnnouncements(\r\n contractId: string,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<RawAnnouncement[]> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_announcements',\r\n [nativeToScVal(0, { type: 'u64' }), nativeToScVal(1000, { type: 'u64' })],\r\n server,\r\n networkPassphrase,\r\n );\r\n\r\n if (!result || !Array.isArray(result)) return [];\r\n\r\n return (result as unknown[]).map((ann: unknown) => {\r\n const a = ann as Record<string, unknown>;\r\n const stealthPk = new Uint8Array(a.stealth_pk as ArrayLike<number>);\r\n return {\r\n ephemeralPubKey: new Uint8Array(a.ephemeral_pk as ArrayLike<number>),\r\n viewTag: a.view_tag as number,\r\n stealthPubKey: stealthPk,\r\n stealthAddress: StrKey.encodeEd25519PublicKey(Buffer.from(stealthPk)),\r\n token: (a.token as { toString(): string })?.toString?.() || 'unknown',\r\n amount: BigInt((a.amount as string | number) || 0),\r\n };\r\n });\r\n}\r\n\r\nexport interface RawAnnouncement {\r\n ephemeralPubKey: Uint8Array;\r\n viewTag: number;\r\n stealthPubKey: Uint8Array;\r\n stealthAddress: string;\r\n token: string;\r\n amount: bigint;\r\n}\r\n\r\n/** Query the contract balance for a stealth key + token pair. */\r\nexport async function queryBalance(\r\n contractId: string,\r\n stealthPk: Uint8Array,\r\n tokenAddress: string,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<bigint> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_balance',\r\n [nativeToScVal(Buffer.from(stealthPk)), new StellarSdk.Address(tokenAddress).toScVal()],\r\n server,\r\n networkPassphrase,\r\n );\r\n if (result !== null) return BigInt(result as string | number);\r\n return 0n;\r\n}\r\n\r\n/** Query the nonce for a stealth key. */\r\nexport async function queryNonce(\r\n contractId: string,\r\n stealthPk: Uint8Array,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<bigint> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_nonce',\r\n [nativeToScVal(Buffer.from(stealthPk))],\r\n server,\r\n networkPassphrase,\r\n );\r\n if (result !== null) return BigInt(result as string | number);\r\n return 0n;\r\n}\r\n\r\nfunction i128ToBigEndian(value: bigint): Uint8Array {\r\n const buf = new Uint8Array(16);\r\n const dv = new DataView(buf.buffer);\r\n dv.setBigInt64(0, value >> 64n);\r\n dv.setBigUint64(8, value & 0xFFFFFFFFFFFFFFFFn);\r\n return buf;\r\n}\r\n\r\nfunction u64ToBigEndian(value: bigint): Uint8Array {\r\n const buf = new Uint8Array(8);\r\n const dv = new DataView(buf.buffer);\r\n dv.setBigUint64(0, value);\r\n return buf;\r\n}\r\n\r\n/** Build the withdraw message hash. Must be byte-identical to the contract's build_withdraw_message. */\r\nexport function buildWithdrawMessage(\r\n stealthPk: Uint8Array,\r\n tokenAddress: string,\r\n amount: bigint,\r\n destination: string,\r\n nonce: bigint,\r\n): Uint8Array {\r\n const tokenBytes = Buffer.from(tokenAddress, 'utf-8');\r\n const destBytes = Buffer.from(destination, 'utf-8');\r\n if (tokenBytes.length !== 56) throw new Error(`Token address must be 56 bytes StrKey, got ${tokenBytes.length}`);\r\n if (destBytes.length !== 56) throw new Error(`Destination must be 56 bytes StrKey, got ${destBytes.length}`);\r\n\r\n const amountBytes = i128ToBigEndian(amount);\r\n const nonceBytes = u64ToBigEndian(nonce);\r\n\r\n const msg = new Uint8Array(32 + 56 + 16 + 56 + 8);\r\n let offset = 0;\r\n msg.set(stealthPk, offset); offset += 32;\r\n msg.set(tokenBytes, offset); offset += 56;\r\n msg.set(amountBytes, offset); offset += 16;\r\n msg.set(destBytes, offset); offset += 56;\r\n msg.set(nonceBytes, offset);\r\n\r\n return sha256(msg);\r\n}\r\n","import {\r\n generateMetaAddress,\r\n encodeMetaAddress,\r\n decodeMetaAddress,\r\n deriveStealthAddressWithSecret,\r\n scanAnnouncements,\r\n recoverStealthPrivateKey,\r\n signWithStealthKey,\r\n generateMnemonic,\r\n mnemonicToStealthKeys,\r\n} from '@stealth/crypto';\r\nimport {\r\n Keypair,\r\n TransactionBuilder,\r\n Contract,\r\n nativeToScVal,\r\n StrKey,\r\n} from '@stellar/stellar-sdk';\r\nimport * as StellarSdk from '@stellar/stellar-sdk';\r\nimport { randomBytes } from '@noble/hashes/utils';\r\nimport {\r\n getNetworkConfig,\r\n resolveTokenAddress,\r\n fetchAnnouncements,\r\n queryBalance,\r\n queryNonce,\r\n buildWithdrawMessage,\r\n waitForTransaction,\r\n} from './soroban.js';\r\nimport type {\r\n ClientConfig,\r\n StealthKeys,\r\n SendReceipt,\r\n SendOpts,\r\n Payment,\r\n Balance,\r\n WithdrawReceipt,\r\n WithdrawOpts,\r\n} from './types.js';\r\n\r\n/** Default contract addresses per network. */\r\nconst DEFAULT_CONTRACTS: Record<string, string> = {\r\n local: 'CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGABAX',\r\n};\r\n\r\n/**\r\n * High-level client for stealth payments on Stellar.\r\n *\r\n * Wraps DKSAP cryptography and Soroban contract interaction into a simple API.\r\n * Developers don't need to understand the underlying protocol to use this.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new StealthClient({ network: 'local', contractId: 'CXXX...' });\r\n *\r\n * // Generate keys\r\n * const keys = StealthClient.keygen();\r\n *\r\n * // Send 100 XLM to a stealth address\r\n * const receipt = await client.send(keys.metaAddress, 100, 'SXXX...');\r\n *\r\n * // Scan for received payments\r\n * const payments = await client.scan(keys);\r\n *\r\n * // Withdraw\r\n * await client.withdraw(payments[0].stealthAddress, 'GDEST...', {\r\n * keys,\r\n * feePayer: 'SXXX...',\r\n * });\r\n * ```\r\n */\r\nexport class StealthClient {\r\n private readonly contractId: string;\r\n private readonly networkPassphrase: string;\r\n private readonly server: StellarSdk.rpc.Server;\r\n\r\n constructor(config: ClientConfig) {\r\n this.contractId = config.contractId || DEFAULT_CONTRACTS[config.network] || '';\r\n const netConfig = getNetworkConfig(config.network);\r\n this.networkPassphrase = netConfig.networkPassphrase;\r\n this.server = netConfig.server;\r\n }\r\n\r\n /**\r\n * Generate a new random stealth key pair.\r\n * No network connection needed.\r\n */\r\n static keygen(): StealthKeys {\r\n const keys = generateMetaAddress();\r\n const metaAddress = encodeMetaAddress(keys.metaAddress);\r\n\r\n return {\r\n metaAddress,\r\n spendPubKey: Buffer.from(keys.metaAddress.spendPubKey).toString('hex'),\r\n spendPrivKey: Buffer.from(keys.spendPrivKey).toString('hex'),\r\n viewPubKey: Buffer.from(keys.metaAddress.viewPubKey).toString('hex'),\r\n viewPrivKey: Buffer.from(keys.viewPrivKey).toString('hex'),\r\n };\r\n }\r\n\r\n /**\r\n * Generate stealth keys from a BIP-39 mnemonic.\r\n * Returns the mnemonic alongside the keys for backup.\r\n * No network connection needed.\r\n */\r\n static fromMnemonic(mnemonic?: string): StealthKeys & { mnemonic: string } {\r\n const phrase = mnemonic || generateMnemonic();\r\n const keys = mnemonicToStealthKeys(phrase);\r\n const metaAddress = encodeMetaAddress(keys.metaAddress);\r\n\r\n return {\r\n mnemonic: phrase,\r\n metaAddress,\r\n spendPubKey: Buffer.from(keys.metaAddress.spendPubKey).toString('hex'),\r\n spendPrivKey: Buffer.from(keys.spendPrivKey).toString('hex'),\r\n viewPubKey: Buffer.from(keys.metaAddress.viewPubKey).toString('hex'),\r\n viewPrivKey: Buffer.from(keys.viewPrivKey).toString('hex'),\r\n };\r\n }\r\n\r\n /**\r\n * Send tokens to a stealth address.\r\n *\r\n * Derives a one-time stealth address from the recipient's meta-address,\r\n * deposits tokens into the pool contract, and records the announcement.\r\n *\r\n * @param metaAddress - Recipient's meta-address (st:stellar:... format)\r\n * @param amount - Amount in whole units (e.g. 100 = 100 XLM)\r\n * @param senderSecret - Sender's Stellar secret key\r\n * @param opts - Optional: asset to send\r\n */\r\n async send(\r\n metaAddress: string,\r\n amount: number,\r\n senderSecret: string,\r\n opts?: SendOpts,\r\n ): Promise<SendReceipt> {\r\n if (amount <= 0) throw new Error('Amount must be positive');\r\n\r\n const { spendPubKey, viewPubKey } = decodeMetaAddress(metaAddress);\r\n const senderKeypair = Keypair.fromSecret(senderSecret);\r\n const tokenAddress = resolveTokenAddress(opts?.asset, this.networkPassphrase);\r\n const stroops = BigInt(Math.round(amount * 1e7));\r\n\r\n // Derive stealth address\r\n const ephemeralPrivKey = new Uint8Array(randomBytes(32));\r\n const stealth = deriveStealthAddressWithSecret(\r\n spendPubKey,\r\n viewPubKey,\r\n ephemeralPrivKey,\r\n );\r\n\r\n // Build and submit deposit transaction\r\n const contract = new Contract(this.contractId);\r\n const account = await this.server.getAccount(senderKeypair.publicKey());\r\n\r\n const depositTx = new TransactionBuilder(account, {\r\n fee: '100',\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(\r\n contract.call(\r\n 'deposit',\r\n new StellarSdk.Address(senderKeypair.publicKey()).toScVal(),\r\n new StellarSdk.Address(tokenAddress).toScVal(),\r\n nativeToScVal(stroops, { type: 'i128' }),\r\n nativeToScVal(Buffer.from(stealth.stealthPubKey)),\r\n nativeToScVal(Buffer.from(stealth.ephemeralPubKey)),\r\n nativeToScVal(stealth.viewTag, { type: 'u32' }),\r\n ),\r\n )\r\n .setTimeout(30)\r\n .build();\r\n\r\n const prepared = await this.server.prepareTransaction(depositTx);\r\n prepared.sign(senderKeypair);\r\n const result = await this.server.sendTransaction(prepared);\r\n\r\n if (result.status === 'ERROR') {\r\n throw new Error('Transaction submission failed');\r\n }\r\n if (result.status === 'PENDING') {\r\n await waitForTransaction(this.server, result.hash);\r\n }\r\n\r\n return {\r\n stealthAddress: stealth.stealthAddress,\r\n txHash: result.hash,\r\n };\r\n }\r\n\r\n /**\r\n * Scan for stealth payments you received.\r\n *\r\n * Uses the view key to detect which announcements are yours,\r\n * then queries the contract for current balances.\r\n *\r\n * @param keys - Your stealth keys (needs viewPrivKey + spendPubKey)\r\n */\r\n async scan(keys: StealthKeys): Promise<Payment[]> {\r\n const viewPrivKey = Buffer.from(keys.viewPrivKey, 'hex');\r\n const spendPubKey = Buffer.from(keys.spendPubKey, 'hex');\r\n\r\n const announcements = await fetchAnnouncements(\r\n this.contractId,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n if (announcements.length === 0) return [];\r\n\r\n const matches = scanAnnouncements(\r\n viewPrivKey,\r\n spendPubKey,\r\n announcements.map(a => ({\r\n ephemeralPubKey: a.ephemeralPubKey,\r\n viewTag: a.viewTag,\r\n stealthAddress: a.stealthAddress,\r\n })),\r\n );\r\n\r\n const payments: Payment[] = [];\r\n\r\n for (const match of matches) {\r\n if (!match) continue;\r\n const ann = announcements.find(a => a.stealthAddress === match.address);\r\n if (!ann) continue;\r\n\r\n const balance = await queryBalance(\r\n this.contractId,\r\n ann.stealthPubKey,\r\n ann.token,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n if (balance <= 0n) continue;\r\n\r\n payments.push({\r\n stealthAddress: ann.stealthAddress,\r\n ephemeralPubKey: Buffer.from(ann.ephemeralPubKey).toString('hex'),\r\n token: ann.token,\r\n amount: Number(balance) / 1e7,\r\n });\r\n }\r\n\r\n return payments;\r\n }\r\n\r\n /**\r\n * Get balances for all your stealth addresses in the pool.\r\n *\r\n * @param keys - Your stealth keys (needs viewPrivKey + spendPubKey)\r\n */\r\n async balance(keys: StealthKeys): Promise<Balance[]> {\r\n const payments = await this.scan(keys);\r\n return payments.map(p => ({\r\n stealthAddress: p.stealthAddress,\r\n token: p.token,\r\n amount: p.amount,\r\n }));\r\n }\r\n\r\n /**\r\n * Withdraw tokens from the stealth pool.\r\n *\r\n * Recovers the stealth private key, signs a withdraw message,\r\n * and submits the transaction. Use `opts.relay` for privacy-preserving\r\n * withdrawal via a relayer.\r\n *\r\n * @param stealthAddress - The stealth address to withdraw from\r\n * @param destination - Destination Stellar address (G...)\r\n * @param opts - Withdraw options (keys, feePayer, optional relay/asset/amount)\r\n */\r\n async withdraw(\r\n stealthAddress: string,\r\n destination: string,\r\n opts: WithdrawOpts,\r\n ): Promise<WithdrawReceipt> {\r\n if (!StrKey.isValidEd25519PublicKey(stealthAddress)) {\r\n throw new Error('Invalid stealth address');\r\n }\r\n if (!StrKey.isValidEd25519PublicKey(destination)) {\r\n throw new Error('Invalid destination address');\r\n }\r\n\r\n const viewPrivKey = Buffer.from(opts.keys.viewPrivKey, 'hex');\r\n const spendPrivKey = Buffer.from(opts.keys.spendPrivKey, 'hex');\r\n const spendPubKey = Buffer.from(opts.keys.spendPubKey, 'hex');\r\n const tokenAddress = resolveTokenAddress(opts.asset, this.networkPassphrase);\r\n\r\n // Find matching announcement\r\n const announcements = await fetchAnnouncements(\r\n this.contractId,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n const allMatches = scanAnnouncements(\r\n viewPrivKey,\r\n spendPubKey,\r\n announcements.map(a => ({\r\n ephemeralPubKey: a.ephemeralPubKey,\r\n viewTag: a.viewTag,\r\n stealthAddress: a.stealthAddress,\r\n })),\r\n );\r\n\r\n const matchedAnn = announcements.find(a => {\r\n if (a.stealthAddress !== stealthAddress) return false;\r\n return allMatches.some(m => m?.address === stealthAddress);\r\n });\r\n\r\n if (!matchedAnn) {\r\n throw new Error('Could not find announcement for this stealth address');\r\n }\r\n\r\n // Recover stealth private key\r\n const stealthPrivKey = recoverStealthPrivateKey(\r\n spendPrivKey,\r\n viewPrivKey,\r\n matchedAnn.ephemeralPubKey,\r\n );\r\n\r\n // Get balance\r\n const balance = await queryBalance(\r\n this.contractId,\r\n matchedAnn.stealthPubKey,\r\n tokenAddress,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n if (balance <= 0n) throw new Error('Stealth address has no balance in the pool');\r\n\r\n // Determine amount\r\n let withdrawAmount: bigint;\r\n if (opts.amount !== undefined) {\r\n withdrawAmount = BigInt(Math.round(opts.amount * 1e7));\r\n if (withdrawAmount > balance) {\r\n throw new Error(`Requested ${opts.amount} but balance is ${Number(balance) / 1e7}`);\r\n }\r\n } else {\r\n withdrawAmount = balance;\r\n }\r\n\r\n // Get nonce and build signed message\r\n const currentNonce = await queryNonce(\r\n this.contractId,\r\n matchedAnn.stealthPubKey,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n const nonce = currentNonce + 1n;\r\n\r\n const messageHash = buildWithdrawMessage(\r\n matchedAnn.stealthPubKey,\r\n tokenAddress,\r\n withdrawAmount,\r\n destination,\r\n nonce,\r\n );\r\n\r\n const signature = signWithStealthKey(messageHash, stealthPrivKey);\r\n\r\n // Build transaction\r\n const feePayerKeypair = Keypair.fromSecret(opts.feePayer);\r\n const contract = new Contract(this.contractId);\r\n const feePayerAccount = await this.server.getAccount(feePayerKeypair.publicKey());\r\n\r\n const withdrawTx = new TransactionBuilder(feePayerAccount, {\r\n fee: '100',\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(\r\n contract.call(\r\n 'withdraw',\r\n nativeToScVal(Buffer.from(matchedAnn.stealthPubKey)),\r\n new StellarSdk.Address(tokenAddress).toScVal(),\r\n nativeToScVal(withdrawAmount, { type: 'i128' }),\r\n new StellarSdk.Address(destination).toScVal(),\r\n nativeToScVal(nonce, { type: 'u64' }),\r\n nativeToScVal(Buffer.from(signature)),\r\n ),\r\n )\r\n .setTimeout(30)\r\n .build();\r\n\r\n const prepared = await this.server.prepareTransaction(withdrawTx);\r\n prepared.sign(feePayerKeypair);\r\n\r\n // Submit (direct or via relay)\r\n let txHash: string;\r\n\r\n if (opts.relay) {\r\n const url = opts.relay.endsWith('/relay') ? opts.relay : `${opts.relay}/relay`;\r\n const res = await fetch(url, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ xdr: prepared.toEnvelope().toXDR('base64') }),\r\n });\r\n if (!res.ok) {\r\n const err = await res.json() as { error?: string };\r\n throw new Error(`Relay error: ${err.error || 'unknown'}`);\r\n }\r\n const data = await res.json() as { txHash: string };\r\n txHash = data.txHash;\r\n } else {\r\n const result = await this.server.sendTransaction(prepared);\r\n if (result.status === 'ERROR') throw new Error('Transaction submission failed');\r\n if (result.status === 'PENDING') {\r\n await waitForTransaction(this.server, result.hash);\r\n }\r\n txHash = result.hash;\r\n }\r\n\r\n return {\r\n txHash,\r\n amount: Number(withdrawAmount) / 1e7,\r\n };\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../crypto/src/errors.ts","../../crypto/src/ed25519.ts","../../crypto/src/keys.ts","../../crypto/src/hash.ts","../../crypto/src/stellar-keys.ts","../../crypto/src/scan.ts","../../crypto/src/recover.ts","../../crypto/src/prove.ts","../../crypto/src/advanced.ts","../../crypto/src/hd.ts","../src/soroban.ts","../src/client.ts"],"names":["ed25519","bytesToNumberLE","numberToBytesLE","randomBytes","sha256","sha512","_generateMnemonic","wordlist","_validateMnemonic","mnemonicToSeedSync","viewTag","Networks","StellarSdk","TransactionBuilder","Contract","Asset","nativeToScVal","StrKey","Keypair","StellarSdk2"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * Custom error types for crypto operations\r\n */\r\n\r\n/**\r\n * Error thrown when a point operation results in the point at infinity\r\n */\r\nexport class PointAtInfinity extends Error {\r\n constructor(operation: string) {\r\n super(`Point at infinity encountered in ${operation}`);\r\n this.name = 'PointAtInfinity';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a public key is not on the ed25519 curve\r\n */\r\nexport class InvalidPublicKey extends Error {\r\n constructor(message = 'Invalid public key: not on curve') {\r\n super(message);\r\n this.name = 'InvalidPublicKey';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when a scalar value is invalid (e.g., zero where not allowed)\r\n */\r\nexport class InvalidScalar extends Error {\r\n constructor(message = 'Invalid scalar value') {\r\n super(message);\r\n this.name = 'InvalidScalar';\r\n }\r\n}\r\n\r\n/**\r\n * Error thrown when meta-address encoding/decoding fails\r\n */\r\nexport class InvalidMetaAddress extends Error {\r\n constructor(message = 'Invalid meta-address format') {\r\n super(message);\r\n this.name = 'InvalidMetaAddress';\r\n }\r\n}","import { ed25519 } from '@noble/curves/ed25519';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { PointAtInfinity, InvalidPublicKey, InvalidScalar } from './errors.js';\r\n\r\n/**\r\n * Curve order L for ed25519\r\n */\r\nexport const L = 2n ** 252n + 27742317777372353535851937790883648493n;\r\n\r\n/**\r\n * Validate that a point is on the ed25519 curve.\r\n * @param point 32-byte compressed point\r\n * @returns true if valid\r\n * @throws InvalidPublicKey if not on curve\r\n */\r\nexport function validatePoint(point: Uint8Array): boolean {\r\n if (point.length !== 32) {\r\n throw new InvalidPublicKey('Invalid point length');\r\n }\r\n\r\n try {\r\n // This will throw if point is not on curve\r\n ed25519.ExtendedPoint.fromHex(point);\r\n return true;\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) throw e;\r\n throw new InvalidPublicKey('Point not on curve');\r\n }\r\n}\r\n\r\n/**\r\n * Add two ed25519 points.\r\n * @param p1 First point (32-byte compressed)\r\n * @param p2 Second point (32-byte compressed)\r\n * @returns Result point (32-byte compressed)\r\n * @throws PointAtInfinity if result is point at infinity\r\n * @throws InvalidPublicKey if points are not on curve\r\n */\r\nexport function pointAdd(p1: Uint8Array, p2: Uint8Array): Uint8Array {\r\n if (p1.length !== 32) throw new InvalidPublicKey('Invalid p1 length');\r\n if (p2.length !== 32) throw new InvalidPublicKey('Invalid p2 length');\r\n\r\n // Validate both points are on curve\r\n validatePoint(p1);\r\n validatePoint(p2);\r\n\r\n const point1 = ed25519.ExtendedPoint.fromHex(p1);\r\n const point2 = ed25519.ExtendedPoint.fromHex(p2);\r\n const result = point1.add(point2);\r\n\r\n // Check for point at infinity\r\n if (result.equals(ed25519.ExtendedPoint.ZERO)) {\r\n throw new PointAtInfinity('pointAdd');\r\n }\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Scalar multiplication with generator point.\r\n * @param scalar 32-byte scalar (little-endian)\r\n * @param allowZero Allow zero scalar (returns point at infinity)\r\n * @returns Result point (32-byte compressed)\r\n * @throws InvalidScalar if scalar is zero and not allowed\r\n */\r\nexport function scalarMultBase(scalar: Uint8Array, allowZero = false): Uint8Array {\r\n if (scalar.length !== 32) throw new InvalidScalar('Invalid scalar length');\r\n\r\n // Reduce scalar modulo L\r\n const s = bytesToNumberLE(scalar) % L;\r\n\r\n // Handle zero scalar case\r\n if (s === 0n) {\r\n if (!allowZero) {\r\n throw new InvalidScalar('Zero scalar not allowed');\r\n }\r\n return ed25519.ExtendedPoint.ZERO.toRawBytes();\r\n }\r\n\r\n const result = ed25519.ExtendedPoint.BASE.multiply(s);\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Scalar multiplication with arbitrary point.\r\n * @param scalar 32-byte scalar (little-endian)\r\n * @param point 32-byte compressed point\r\n * @param allowZero Allow zero scalar (returns point at infinity)\r\n * @returns Result point (32-byte compressed)\r\n * @throws InvalidScalar if scalar is zero and not allowed\r\n * @throws InvalidPublicKey if point is not on curve\r\n * @throws PointAtInfinity if result is point at infinity\r\n */\r\nexport function scalarMult(scalar: Uint8Array, point: Uint8Array, allowZero = false): Uint8Array {\r\n if (scalar.length !== 32) throw new InvalidScalar('Invalid scalar length');\r\n if (point.length !== 32) throw new InvalidPublicKey('Invalid point length');\r\n\r\n // Validate point is on curve\r\n validatePoint(point);\r\n\r\n // Reduce scalar modulo L\r\n const s = bytesToNumberLE(scalar) % L;\r\n\r\n // Handle zero scalar case\r\n if (s === 0n) {\r\n if (!allowZero) {\r\n throw new InvalidScalar('Zero scalar not allowed');\r\n }\r\n return ed25519.ExtendedPoint.ZERO.toRawBytes();\r\n }\r\n\r\n const p = ed25519.ExtendedPoint.fromHex(point);\r\n const result = p.multiply(s);\r\n\r\n // Check for point at infinity (should not happen with valid inputs)\r\n if (result.equals(ed25519.ExtendedPoint.ZERO)) {\r\n throw new PointAtInfinity('scalarMult');\r\n }\r\n\r\n return result.toRawBytes();\r\n}\r\n\r\n/**\r\n * Add two scalars modulo curve order L.\r\n * @param s1 First scalar (32-byte, little-endian)\r\n * @param s2 Second scalar (32-byte, little-endian)\r\n * @returns Result scalar (32-byte, little-endian)\r\n * @throws InvalidScalar if inputs have wrong length\r\n */\r\nexport function scalarAdd(s1: Uint8Array, s2: Uint8Array): Uint8Array {\r\n if (s1.length !== 32) throw new InvalidScalar('Invalid s1 length');\r\n if (s2.length !== 32) throw new InvalidScalar('Invalid s2 length');\r\n\r\n const a = bytesToNumberLE(s1) % L;\r\n const b = bytesToNumberLE(s2) % L;\r\n const result = (a + b) % L;\r\n\r\n return numberToBytesLE(result, 32);\r\n}","import { randomBytes } from '@noble/hashes/utils';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\nimport type { StealthKeys, StealthMetaAddress } from './types.js';\r\nimport { L, scalarMultBase, validatePoint } from './ed25519.js';\r\nimport { InvalidMetaAddress, InvalidPublicKey } from './errors.js';\r\n\r\n/**\r\n * Generate a new stealth meta-address with random keys.\r\n *\r\n * Creates a complete stealth key pair using cryptographically secure\r\n * random number generation. The resulting keys can be used for:\r\n * - Receiving stealth payments (using the meta-address)\r\n * - Scanning for incoming payments (using view private key)\r\n * - Spending from stealth addresses (using spend private key)\r\n *\r\n * @returns Complete stealth keys including private keys and meta-address\r\n *\r\n * @example\r\n * ```typescript\r\n * const keys = generateMetaAddress();\r\n *\r\n * // Share the meta-address publicly\r\n * const encoded = encodeMetaAddress(keys.metaAddress);\r\n * console.log('Share this:', encoded);\r\n *\r\n * // Keep private keys secure\r\n * saveSecurely(keys.spendPrivKey, keys.viewPrivKey);\r\n * ```\r\n */\r\nexport function generateMetaAddress(): StealthKeys {\r\n // Generate two random 32-byte scalars (reduced mod L)\r\n const spendPrivKey = generateRandomScalar();\r\n const viewPrivKey = generateRandomScalar();\r\n\r\n // Derive public keys\r\n const spendPubKey = scalarMultBase(spendPrivKey);\r\n const viewPubKey = scalarMultBase(viewPrivKey);\r\n\r\n return {\r\n spendPrivKey,\r\n viewPrivKey,\r\n metaAddress: {\r\n spendPubKey,\r\n viewPubKey,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Generate a random scalar reduced modulo L.\r\n * @returns 32-byte scalar (little-endian, reduced mod L)\r\n */\r\nfunction generateRandomScalar(): Uint8Array {\r\n const bytes = randomBytes(32);\r\n const scalar = bytesToNumberLE(bytes) % L;\r\n return numberToBytesLE(scalar, 32);\r\n}\r\n\r\n/**\r\n * Encode a stealth meta-address to a string format with checksum.\r\n *\r\n * Encodes the meta-address into a shareable string format that includes:\r\n * - Protocol identifier (\"st:stellar:\")\r\n * - Concatenated public keys (spend || view)\r\n * - CRC32 checksum for error detection\r\n *\r\n * @param meta - Stealth meta-address containing spend and view public keys\r\n * @returns Encoded string in format \"st:stellar:<hex(spend_pk || view_pk)><checksum>\"\r\n * @throws {InvalidMetaAddress} If public keys are invalid length or not on curve\r\n *\r\n * @example\r\n * ```typescript\r\n * const keys = generateMetaAddress();\r\n * const encoded = encodeMetaAddress(keys.metaAddress);\r\n * console.log(encoded); // \"st:stellar:abc123...def456\"\r\n *\r\n * // Share this encoded string with senders\r\n * publishMetaAddress(encoded);\r\n * ```\r\n */\r\nexport function encodeMetaAddress(meta: StealthMetaAddress): string {\r\n if (meta.spendPubKey.length !== 32) {\r\n throw new InvalidMetaAddress('Invalid spend public key length');\r\n }\r\n if (meta.viewPubKey.length !== 32) {\r\n throw new InvalidMetaAddress('Invalid view public key length');\r\n }\r\n\r\n // Validate both keys are on curve\r\n try {\r\n validatePoint(meta.spendPubKey);\r\n validatePoint(meta.viewPubKey);\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) {\r\n throw new InvalidMetaAddress(`Invalid public key: ${e.message}`);\r\n }\r\n throw e;\r\n }\r\n\r\n // Concatenate both public keys\r\n const payload = new Uint8Array(64);\r\n payload.set(meta.spendPubKey, 0);\r\n payload.set(meta.viewPubKey, 32);\r\n\r\n // Calculate checksum (last 4 bytes of SHA-256)\r\n const hash = sha256(payload);\r\n const checksum = hash.slice(28, 32);\r\n\r\n // Combine payload and checksum\r\n const combined = new Uint8Array(68);\r\n combined.set(payload, 0);\r\n combined.set(checksum, 64);\r\n\r\n // Convert to hex\r\n const hex = Array.from(combined)\r\n .map((b) => b.toString(16).padStart(2, '0'))\r\n .join('');\r\n\r\n return `st:stellar:${hex}`;\r\n}\r\n\r\n/**\r\n * Decode a string-encoded stealth meta-address with checksum validation.\r\n *\r\n * Parses an encoded meta-address string and validates:\r\n * - Correct format and prefix\r\n * - Valid hex encoding\r\n * - Checksum integrity\r\n * - Public keys are on curve\r\n *\r\n * @param encoded - Encoded meta-address string (\"st:stellar:...\")\r\n * @returns Decoded stealth meta-address with public keys\r\n * @throws {InvalidMetaAddress} If format, checksum, or keys are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * const encoded = \"st:stellar:abc123...def456\";\r\n * const meta = decodeMetaAddress(encoded);\r\n *\r\n * // Use for deriving stealth addresses\r\n * const stealth = deriveStealthAddress(meta);\r\n * ```\r\n */\r\nexport function decodeMetaAddress(encoded: string): StealthMetaAddress {\r\n if (!encoded.startsWith('st:stellar:')) {\r\n throw new InvalidMetaAddress('Invalid meta-address prefix');\r\n }\r\n\r\n const hex = encoded.slice(11); // Remove \"st:stellar:\" prefix\r\n if (hex.length !== 136) {\r\n // 64 bytes payload + 4 bytes checksum = 68 bytes = 136 hex chars\r\n throw new InvalidMetaAddress('Invalid meta-address length');\r\n }\r\n\r\n // Parse hex to bytes\r\n const combined = new Uint8Array(68);\r\n for (let i = 0; i < 68; i++) {\r\n const byte = parseInt(hex.substr(i * 2, 2), 16);\r\n if (isNaN(byte)) {\r\n throw new InvalidMetaAddress('Invalid hex encoding');\r\n }\r\n combined[i] = byte;\r\n }\r\n\r\n // Split payload and checksum\r\n const payload = combined.slice(0, 64);\r\n const checksum = combined.slice(64, 68);\r\n\r\n // Verify checksum\r\n const hash = sha256(payload);\r\n const expectedChecksum = hash.slice(28, 32);\r\n\r\n let checksumValid = true;\r\n for (let i = 0; i < 4; i++) {\r\n if (checksum[i] !== expectedChecksum[i]) {\r\n checksumValid = false;\r\n break;\r\n }\r\n }\r\n\r\n if (!checksumValid) {\r\n throw new InvalidMetaAddress('Invalid checksum');\r\n }\r\n\r\n const spendPubKey = payload.slice(0, 32);\r\n const viewPubKey = payload.slice(32, 64);\r\n\r\n // Validate both keys are on curve\r\n try {\r\n validatePoint(spendPubKey);\r\n validatePoint(viewPubKey);\r\n } catch (e) {\r\n if (e instanceof InvalidPublicKey) {\r\n throw new InvalidMetaAddress(`Invalid public key in meta-address: ${e.message}`);\r\n }\r\n throw e;\r\n }\r\n\r\n return {\r\n spendPubKey,\r\n viewPubKey,\r\n };\r\n}","import { sha256 } from '@noble/hashes/sha256';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { L } from './ed25519.js';\r\nimport { InvalidScalar } from './errors.js';\r\n\r\n/**\r\n * Hash data to a scalar value modulo curve order L.\r\n *\r\n * Implements the hash-to-scalar function used in DKSAP for deriving\r\n * the blinding factor from the shared secret.\r\n *\r\n * @param data - Input data to hash (typically a 32-byte shared secret)\r\n * @returns 32-byte scalar (little-endian, reduced mod L)\r\n * @throws {InvalidScalar} If hash produces zero scalar (extremely unlikely)\r\n *\r\n * @example\r\n * ```typescript\r\n * const sharedSecret = scalarMult(ephemeralPrivKey, viewPubKey);\r\n * const s = hashToScalar(sharedSecret);\r\n * // Use s as blinding factor for stealth key derivation\r\n * ```\r\n */\r\nexport function hashToScalar(data: Uint8Array): Uint8Array {\r\n const hash = sha256(data);\r\n const scalar = bytesToNumberLE(hash) % L;\r\n\r\n // In the extremely unlikely event the hash produces zero mod L\r\n if (scalar === 0n) {\r\n throw new InvalidScalar('Hash produced zero scalar');\r\n }\r\n\r\n return numberToBytesLE(scalar, 32);\r\n}\r\n\r\n/**\r\n * Extract view tag from shared secret.\r\n *\r\n * The view tag is the first byte of SHA256(shared_secret) and enables\r\n * ~25x faster scanning by filtering announcements before expensive EC operations.\r\n *\r\n * @param sharedSecret - 32-byte shared secret from ECDH\r\n * @returns Single byte view tag (0-255)\r\n * @throws {Error} If shared secret is not 32 bytes\r\n *\r\n * @example\r\n * ```typescript\r\n * const sharedSecret = scalarMult(viewPrivKey, ephemeralPubKey);\r\n * const tag = viewTag(sharedSecret);\r\n * // Use tag for fast announcement filtering\r\n * ```\r\n */\r\nexport function viewTag(sharedSecret: Uint8Array): number {\r\n if (sharedSecret.length !== 32) {\r\n throw new Error('Invalid shared secret length');\r\n }\r\n const hash = sha256(sharedSecret);\r\n return hash[0]!;\r\n}","/**\r\n * Stellar StrKey encoding (base32check) for ed25519 public keys.\r\n * This module provides pure TypeScript implementation without @stellar/stellar-sdk dependency.\r\n */\r\n\r\nconst ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';\r\nconst VERSION_BYTE_PUBLIC_KEY = 6 << 3; // G addresses\r\n\r\n/**\r\n * CRC16-XModem checksum implementation.\r\n */\r\nfunction crc16XModem(data: Uint8Array): number {\r\n let crc = 0x0000;\r\n for (let i = 0; i < data.length; i++) {\r\n crc ^= data[i]! << 8;\r\n for (let j = 0; j < 8; j++) {\r\n if (crc & 0x8000) {\r\n crc = (crc << 1) ^ 0x1021;\r\n } else {\r\n crc = crc << 1;\r\n }\r\n }\r\n }\r\n return crc & 0xffff;\r\n}\r\n\r\n/**\r\n * Base32 encode (RFC 4648) without padding.\r\n */\r\nfunction base32Encode(data: Uint8Array): string {\r\n let bits = 0;\r\n let value = 0;\r\n let output = '';\r\n\r\n for (let i = 0; i < data.length; i++) {\r\n value = (value << 8) | data[i]!;\r\n bits += 8;\r\n\r\n while (bits >= 5) {\r\n output += ALPHABET[(value >>> (bits - 5)) & 31];\r\n bits -= 5;\r\n }\r\n }\r\n\r\n if (bits > 0) {\r\n output += ALPHABET[(value << (5 - bits)) & 31];\r\n }\r\n\r\n return output;\r\n}\r\n\r\n/**\r\n * Base32 decode (RFC 4648).\r\n */\r\nfunction base32Decode(str: string): Uint8Array {\r\n const output: number[] = [];\r\n let bits = 0;\r\n let value = 0;\r\n\r\n for (let i = 0; i < str.length; i++) {\r\n const idx = ALPHABET.indexOf(str[i]!);\r\n if (idx === -1) {\r\n throw new Error(`Invalid base32 character: ${str[i]}`);\r\n }\r\n\r\n value = (value << 5) | idx;\r\n bits += 5;\r\n\r\n while (bits >= 8) {\r\n output.push((value >>> (bits - 8)) & 255);\r\n bits -= 8;\r\n }\r\n }\r\n\r\n return new Uint8Array(output);\r\n}\r\n\r\n/**\r\n * Encode ed25519 public key to Stellar address format (G...).\r\n *\r\n * Implements Stellar's StrKey encoding (SEP-23) using base32check format.\r\n *\r\n * @param pubKey - 32-byte ed25519 public key\r\n * @returns Stellar address in StrKey format (G...)\r\n * @throws {Error} If public key is not exactly 32 bytes\r\n *\r\n * @example\r\n * ```typescript\r\n * const pubKey = new Uint8Array(32); // Your public key\r\n * const address = encodePublicKey(pubKey);\r\n * console.log(address); // \"GABC...XYZ\"\r\n * ```\r\n */\r\nexport function encodePublicKey(pubKey: Uint8Array): string {\r\n if (pubKey.length !== 32) {\r\n throw new Error('Public key must be 32 bytes');\r\n }\r\n\r\n const versionedPayload = new Uint8Array(33);\r\n versionedPayload[0] = VERSION_BYTE_PUBLIC_KEY;\r\n versionedPayload.set(pubKey, 1);\r\n\r\n const checksum = crc16XModem(versionedPayload);\r\n const checksumBytes = new Uint8Array(2);\r\n checksumBytes[0] = checksum & 0xff;\r\n checksumBytes[1] = (checksum >>> 8) & 0xff;\r\n\r\n const fullPayload = new Uint8Array(35);\r\n fullPayload.set(versionedPayload, 0);\r\n fullPayload.set(checksumBytes, 33);\r\n\r\n return base32Encode(fullPayload);\r\n}\r\n\r\n/**\r\n * Decode Stellar address to ed25519 public key.\r\n *\r\n * Implements Stellar's StrKey decoding (SEP-23) with checksum validation.\r\n *\r\n * @param address - Stellar address in StrKey format (G...)\r\n * @returns 32-byte ed25519 public key\r\n * @throws {Error} If address format is invalid or checksum fails\r\n *\r\n * @example\r\n * ```typescript\r\n * const address = \"GABC...XYZ\";\r\n * const pubKey = decodePublicKey(address);\r\n * console.log(pubKey.length); // 32\r\n * ```\r\n */\r\nexport function decodePublicKey(address: string): Uint8Array {\r\n if (!address.startsWith('G')) {\r\n throw new Error('Invalid Stellar address: must start with G');\r\n }\r\n\r\n const decoded = base32Decode(address);\r\n if (decoded.length !== 35) {\r\n throw new Error('Invalid Stellar address: incorrect length');\r\n }\r\n\r\n const versionByte = decoded[0]!;\r\n if (versionByte !== VERSION_BYTE_PUBLIC_KEY) {\r\n throw new Error('Invalid Stellar address: wrong version byte');\r\n }\r\n\r\n const versionedPayload = decoded.slice(0, 33);\r\n const providedChecksum = (decoded[34]! << 8) | decoded[33]!;\r\n const calculatedChecksum = crc16XModem(versionedPayload);\r\n\r\n if (providedChecksum !== calculatedChecksum) {\r\n throw new Error('Invalid Stellar address: checksum mismatch');\r\n }\r\n\r\n return decoded.slice(1, 33);\r\n}","import type { Announcement, StealthAddress } from './types.js';\r\nimport { scalarMult, pointAdd, scalarMultBase } from './ed25519.js';\r\nimport { hashToScalar, viewTag } from './hash.js';\r\nimport { encodePublicKey } from './stellar-keys.js';\r\n\r\n/**\r\n * Check if a view tag matches for a given ephemeral public key.\r\n *\r\n * This is a fast pre-filter before doing the expensive EC operations.\r\n * Only computes the shared secret and extracts the first byte for comparison.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @param expectedTag - Expected view tag from announcement (0-255)\r\n * @returns Object with match result and shared secret if matched\r\n * @throws {Error} If key lengths are invalid or tag is out of range\r\n *\r\n * @example\r\n * ```typescript\r\n * // Fast filtering before full verification\r\n * const result = checkViewTag(viewPrivKey, announcement.ephemeralPubKey, announcement.viewTag);\r\n * if (result.matches) {\r\n * // Use the shared secret for further verification\r\n * const s = hashToScalar(result.sharedSecret);\r\n * }\r\n * ```\r\n */\r\nexport function checkViewTag(\r\n viewPrivKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array,\r\n expectedTag: number\r\n): { matches: boolean; sharedSecret?: Uint8Array } {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n if (expectedTag < 0 || expectedTag > 255) {\r\n throw new Error('Invalid view tag');\r\n }\r\n\r\n // Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Extract and compare view tag (first byte of SHA256(S))\r\n const computedTag = viewTag(S);\r\n\r\n if (computedTag === expectedTag) {\r\n return { matches: true, sharedSecret: S };\r\n }\r\n return { matches: false };\r\n}\r\n\r\n/**\r\n * Scan announcements to find stealth addresses belonging to the receiver.\r\n *\r\n * This implements an optimized two-pass scanning algorithm:\r\n * - Pass 1: Filter by view tag (cheap byte comparison)\r\n * - Pass 2: Full EC math (scalarMult + pointAdd) only on tag matches\r\n *\r\n * This optimization provides ~25x speedup for large announcement sets\r\n * by avoiding expensive EC operations on non-matching announcements.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param announcements - List of announcements to scan\r\n * @returns Array of stealth addresses belonging to the receiver\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Scan blockchain announcements\r\n * const announcements = await fetchAnnouncements();\r\n * const myAddresses = scanAnnouncements(\r\n * keys.viewPrivKey,\r\n * keys.metaAddress.spendPubKey,\r\n * announcements\r\n * );\r\n *\r\n * // Check balances of discovered addresses\r\n * for (const addr of myAddresses) {\r\n * const balance = await getBalance(addr.address);\r\n * console.log(`${addr.address}: ${balance} XLM`);\r\n * }\r\n * ```\r\n */\r\nexport function scanAnnouncements(\r\n viewPrivKey: Uint8Array,\r\n spendPubKey: Uint8Array,\r\n announcements: Announcement[]\r\n): StealthAddress[] {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (spendPubKey.length !== 32) {\r\n throw new Error('Invalid spend public key length');\r\n }\r\n\r\n const results: StealthAddress[] = [];\r\n\r\n // Two-pass scanning for optimization\r\n // Pass 1: Quick view tag filtering with shared secret caching\r\n const tagMatches: Array<{ announcement: Announcement; sharedSecret: Uint8Array }> = [];\r\n for (const announcement of announcements) {\r\n const tagResult = checkViewTag(viewPrivKey, announcement.ephemeralPubKey, announcement.viewTag);\r\n if (tagResult.matches && tagResult.sharedSecret) {\r\n tagMatches.push({ announcement, sharedSecret: tagResult.sharedSecret });\r\n }\r\n }\r\n\r\n // Pass 2: Full verification only on tag matches (reusing shared secrets)\r\n for (const { announcement, sharedSecret } of tagMatches) {\r\n // Hash to scalar s = SHA256(S) mod L (using cached shared secret)\r\n const s = hashToScalar(sharedSecret);\r\n\r\n // Compute expected stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Convert to Stellar address and compare\r\n const computedAddress = encodePublicKey(P);\r\n\r\n if (computedAddress === announcement.stealthAddress) {\r\n results.push({\r\n publicKey: P,\r\n address: computedAddress,\r\n });\r\n }\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Check if a specific stealth address belongs to the receiver.\r\n *\r\n * Performs full DKSAP verification to determine ownership of a stealth address.\r\n *\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @param stealthAddress - Stellar address to check (G... format)\r\n * @returns True if the stealth address belongs to the receiver\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Check if a payment is for you\r\n * const isMine = isMyStealthAddress(\r\n * keys.viewPrivKey,\r\n * keys.metaAddress.spendPubKey,\r\n * announcement.ephemeralPubKey,\r\n * announcement.stealthAddress\r\n * );\r\n *\r\n * if (isMine) {\r\n * console.log('Found payment to:', announcement.stealthAddress);\r\n * }\r\n * ```\r\n */\r\nexport function isMyStealthAddress(\r\n viewPrivKey: Uint8Array,\r\n spendPubKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array,\r\n stealthAddress: string\r\n): boolean {\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (spendPubKey.length !== 32) {\r\n throw new Error('Invalid spend public key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n\r\n // Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Hash to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Compute expected stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Convert to Stellar address and compare\r\n const computedAddress = encodePublicKey(P);\r\n\r\n return computedAddress === stealthAddress;\r\n}","import { scalarMult, scalarAdd } from './ed25519.js';\r\nimport { hashToScalar } from './hash.js';\r\n\r\n/**\r\n * Recover the stealth private key for a stealth address.\r\n *\r\n * This implements the receiver's private key recovery:\r\n * 1. Compute shared secret S = k_view * R\r\n * 2. Hash to scalar s = SHA256(S) mod L\r\n * 3. Compute stealth private key p = k_spend + s mod L\r\n *\r\n * The recovered private key can be used to:\r\n * - Sign transactions from the stealth address\r\n * - Derive the corresponding public key for verification\r\n *\r\n * @param spendPrivKey - Receiver's 32-byte spend private key\r\n * @param viewPrivKey - Receiver's 32-byte view private key\r\n * @param ephemeralPubKey - 32-byte ephemeral public key from announcement\r\n * @returns 32-byte stealth private key for signing transactions\r\n * @throws {Error} If key lengths are invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Recover private key to withdraw funds\r\n * const stealthPrivKey = recoverStealthPrivateKey(\r\n * keys.spendPrivKey,\r\n * keys.viewPrivKey,\r\n * announcement.ephemeralPubKey\r\n * );\r\n *\r\n * // Use with Stellar SDK to sign transaction\r\n * const keypair = Keypair.fromRawEd25519Seed(stealthPrivKey);\r\n * transaction.sign(keypair);\r\n *\r\n * // IMPORTANT: Clear private key from memory after use\r\n * stealthPrivKey.fill(0);\r\n * ```\r\n */\r\nexport function recoverStealthPrivateKey(\r\n spendPrivKey: Uint8Array,\r\n viewPrivKey: Uint8Array,\r\n ephemeralPubKey: Uint8Array\r\n): Uint8Array {\r\n if (spendPrivKey.length !== 32) {\r\n throw new Error('Invalid spend private key length');\r\n }\r\n if (viewPrivKey.length !== 32) {\r\n throw new Error('Invalid view private key length');\r\n }\r\n if (ephemeralPubKey.length !== 32) {\r\n throw new Error('Invalid ephemeral public key length');\r\n }\r\n\r\n // Step 1: Compute shared secret S = k_view * R\r\n const S = scalarMult(viewPrivKey, ephemeralPubKey);\r\n\r\n // Step 2: Hash shared secret to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Step 3: Compute stealth private key p = k_spend + s mod L\r\n const stealthPrivKey = scalarAdd(spendPrivKey, s);\r\n\r\n return stealthPrivKey;\r\n}","import { ed25519 } from '@noble/curves/ed25519';\r\nimport { sha512 } from '@noble/hashes/sha512';\r\nimport { bytesToNumberLE, numberToBytesLE } from '@noble/curves/abstract/utils';\r\nimport { L, scalarMultBase } from './ed25519.js';\r\n\r\n/**\r\n * Sign a message using a raw ed25519 scalar (stealth private key).\r\n *\r\n * Standard ed25519.sign() hashes the seed to derive the signing scalar,\r\n * but stealth private keys are already raw scalars from modular addition\r\n * (k_spend + s mod L). This function constructs a valid ed25519 signature\r\n * directly from the raw scalar, producing signatures that verify with\r\n * standard ed25519.verify() against the corresponding public key (scalar * G).\r\n *\r\n * @param message - The message to sign\r\n * @param privateScalar - 32-byte raw scalar (stealth private key)\r\n * @returns 64-byte ed25519 signature (R || S)\r\n */\r\nexport function signWithStealthKey(message: Uint8Array, privateScalar: Uint8Array): Uint8Array {\r\n if (privateScalar.length !== 32) {\r\n throw new Error('Invalid stealth private key length');\r\n }\r\n if (message.length === 0) {\r\n throw new Error('Message cannot be empty');\r\n }\r\n\r\n const a = bytesToNumberLE(privateScalar) % L;\r\n const pubKeyBytes = scalarMultBase(privateScalar);\r\n\r\n // Deterministic nonce: r = SHA-512(privateScalar || message) mod L\r\n const nonceInput = new Uint8Array(32 + message.length);\r\n nonceInput.set(privateScalar, 0);\r\n nonceInput.set(message, 32);\r\n const r = bytesToNumberLE(sha512(nonceInput)) % L;\r\n\r\n const R = ed25519.ExtendedPoint.BASE.multiply(r);\r\n const Rbytes = R.toRawBytes();\r\n\r\n // Challenge: k = SHA-512(R || pubKey || message) mod L\r\n const challengeInput = new Uint8Array(32 + 32 + message.length);\r\n challengeInput.set(Rbytes, 0);\r\n challengeInput.set(pubKeyBytes, 32);\r\n challengeInput.set(message, 64);\r\n const k = bytesToNumberLE(sha512(challengeInput)) % L;\r\n\r\n // Response: S = (r + k * a) mod L\r\n const S = (r + k * a) % L;\r\n\r\n const sig = new Uint8Array(64);\r\n sig.set(Rbytes, 0);\r\n sig.set(numberToBytesLE(S, 32), 32);\r\n return sig;\r\n}\r\n\r\n/**\r\n * Prove ownership of a stealth address by signing a challenge.\r\n *\r\n * Uses raw-scalar ed25519 signing so the signature verifies against\r\n * the stealth public key (privateScalar * G), not the hashed-seed public key.\r\n *\r\n * @param stealthPrivKey - The 32-byte stealth private key (raw scalar)\r\n * @param challenge - The challenge to sign (typically a nonce or timestamp)\r\n * @returns The 64-byte ed25519 signature\r\n * @throws {Error} If private key is not 32 bytes or challenge is empty\r\n */\r\nexport function proveOwnership(\r\n stealthPrivKey: Uint8Array,\r\n challenge: Uint8Array\r\n): Uint8Array {\r\n return signWithStealthKey(challenge, stealthPrivKey);\r\n}\r\n\r\n/**\r\n * Verify ownership proof of a stealth address.\r\n *\r\n * Verifies a standard ed25519 signature against the stealth public key.\r\n * Works with signatures produced by signWithStealthKey/proveOwnership.\r\n *\r\n * @param stealthPubKey - The 32-byte stealth public key (scalar * G)\r\n * @param challenge - The challenge that was signed\r\n * @param signature - The 64-byte signature to verify\r\n * @returns True if the signature is valid, false otherwise\r\n */\r\nexport function verifyOwnership(\r\n stealthPubKey: Uint8Array,\r\n challenge: Uint8Array,\r\n signature: Uint8Array,\r\n): boolean {\r\n if (stealthPubKey.length !== 32) {\r\n throw new Error('Invalid stealth public key length');\r\n }\r\n if (challenge.length === 0) {\r\n throw new Error('Challenge cannot be empty');\r\n }\r\n if (signature.length !== 64) {\r\n throw new Error('Invalid signature length');\r\n }\r\n\r\n try {\r\n return ed25519.verify(signature, challenge, stealthPubKey);\r\n } catch {\r\n return false;\r\n }\r\n}","// Advanced stealth address functions\r\nimport type { StealthDerivation } from './stealth.js';\r\nimport { scalarMult, scalarMultBase, pointAdd } from './ed25519.js';\r\nimport { hashToScalar, viewTag } from './hash.js';\r\nimport { encodePublicKey } from './stellar-keys.js';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\n\r\n/**\r\n * Encrypt an amount using the shared secret.\r\n *\r\n * Uses XOR encryption with SHA256(sharedSecret || \"amount\") as the key.\r\n * This provides confidential amounts in stealth transactions.\r\n *\r\n * @param amount - The amount to encrypt\r\n * @param sharedSecret - The 32-byte shared secret from ECDH\r\n * @returns 8-byte encrypted amount\r\n */\r\nexport function encryptAmount(amount: number, sharedSecret: Uint8Array): Uint8Array {\r\n if (sharedSecret.length !== 32) {\r\n throw new Error(`Invalid shared secret: expected 32 bytes, got ${sharedSecret.length}`);\r\n }\r\n\r\n // Create key material\r\n const keyInput = new Uint8Array(32 + 6);\r\n keyInput.set(sharedSecret, 0);\r\n keyInput.set(new TextEncoder().encode('amount'), 32);\r\n const key = sha256(keyInput);\r\n\r\n // Convert amount to 8-byte little-endian\r\n const amountBytes = new Uint8Array(8);\r\n const view = new DataView(amountBytes.buffer);\r\n view.setFloat64(0, amount, true); // little-endian\r\n\r\n // XOR encrypt\r\n const encrypted = new Uint8Array(8);\r\n for (let i = 0; i < 8; i++) {\r\n encrypted[i] = amountBytes[i]! ^ key[i]!;\r\n }\r\n\r\n return encrypted;\r\n}\r\n\r\n/**\r\n * Decrypt an amount using the shared secret.\r\n *\r\n * @param encrypted - The 8-byte encrypted amount\r\n * @param sharedSecret - The 32-byte shared secret from ECDH\r\n * @returns The decrypted amount\r\n * @throws {Error} If encrypted is not exactly 8 bytes\r\n * @throws {Error} If sharedSecret is not exactly 32 bytes\r\n */\r\nexport function decryptAmount(encrypted: Uint8Array, sharedSecret: Uint8Array): number {\r\n // Validate inputs\r\n if (encrypted.length !== 8) {\r\n throw new Error(`Invalid encrypted amount: expected 8 bytes, got ${encrypted.length}`);\r\n }\r\n if (sharedSecret.length !== 32) {\r\n throw new Error(`Invalid shared secret: expected 32 bytes, got ${sharedSecret.length}`);\r\n }\r\n\r\n // Create key material\r\n const keyInput = new Uint8Array(32 + 6);\r\n keyInput.set(sharedSecret, 0);\r\n keyInput.set(new TextEncoder().encode('amount'), 32);\r\n const key = sha256(keyInput);\r\n\r\n // XOR decrypt\r\n const decrypted = new Uint8Array(8);\r\n for (let i = 0; i < 8; i++) {\r\n decrypted[i] = encrypted[i]! ^ key[i]!;\r\n }\r\n\r\n // Convert from little-endian to number\r\n const view = new DataView(decrypted.buffer);\r\n return view.getFloat64(0, true); // little-endian\r\n}\r\n\r\nexport interface StealthDerivationWithSecret extends StealthDerivation {\r\n sharedSecret: Uint8Array;\r\n}\r\n\r\n/**\r\n * Derive a stealth address with the shared secret exposed.\r\n *\r\n * Similar to deriveStealthAddress but also returns the shared secret,\r\n * useful for applications that need amount encryption or other\r\n * shared secret-based features.\r\n *\r\n * @param spendPubKey - Receiver's 32-byte spend public key\r\n * @param viewPubKey - Receiver's 32-byte view public key\r\n * @param ephemeralPrivKey - Sender's 32-byte ephemeral private key\r\n * @returns Stealth derivation including the shared secret\r\n */\r\nexport function deriveStealthAddressWithSecret(\r\n spendPubKey: Uint8Array,\r\n viewPubKey: Uint8Array,\r\n ephemeralPrivKey: Uint8Array\r\n): StealthDerivationWithSecret {\r\n // Compute ephemeral public key R = r*G\r\n const R = scalarMultBase(ephemeralPrivKey);\r\n\r\n // Compute shared secret S = r*K_view\r\n const S = scalarMult(ephemeralPrivKey, viewPubKey);\r\n\r\n // Hash shared secret to scalar s = SHA256(S) mod L\r\n const s = hashToScalar(S);\r\n\r\n // Compute stealth public key P = K_spend + s*G\r\n const sG = scalarMultBase(s);\r\n const P = pointAdd(spendPubKey, sG);\r\n\r\n // Get view tag\r\n const tag = viewTag(S);\r\n\r\n return {\r\n stealthPubKey: P,\r\n stealthAddress: encodePublicKey(P),\r\n ephemeralPubKey: R,\r\n viewTag: tag,\r\n ephemeralPrivKey: ephemeralPrivKey,\r\n sharedSecret: S\r\n };\r\n}","import { generateMnemonic as _generateMnemonic, validateMnemonic as _validateMnemonic, mnemonicToSeedSync } from '@scure/bip39';\r\nimport { wordlist } from '@scure/bip39/wordlists/english';\r\nimport type { StealthKeys } from './types.js';\r\nimport { scalarMultBase } from './ed25519.js';\r\nimport { hashToScalar } from './hash.js';\r\n\r\nconst textEncoder = new TextEncoder();\r\n\r\n/**\r\n * Generate a 12-word BIP-39 mnemonic phrase.\r\n */\r\nexport function generateMnemonic(): string {\r\n return _generateMnemonic(wordlist);\r\n}\r\n\r\n/**\r\n * Validate a mnemonic phrase against the BIP-39 english wordlist.\r\n */\r\nexport function validateMnemonic(mnemonic: string): boolean {\r\n return _validateMnemonic(mnemonic, wordlist);\r\n}\r\n\r\n/**\r\n * Derive stealth spend and view keys from a BIP-39 mnemonic.\r\n *\r\n * Uses domain-separated SHA-256 hashing of the BIP-39 seed to derive\r\n * two independent ed25519 scalars for the spend and view key pairs.\r\n */\r\nexport function mnemonicToStealthKeys(mnemonic: string, passphrase?: string): StealthKeys {\r\n if (!_validateMnemonic(mnemonic, wordlist)) {\r\n throw new Error('Invalid mnemonic phrase');\r\n }\r\n\r\n const seed = mnemonicToSeedSync(mnemonic, passphrase || '');\r\n\r\n const spendTag = textEncoder.encode('stealth-spend');\r\n const viewTag = textEncoder.encode('stealth-view');\r\n\r\n const spendInput = new Uint8Array(spendTag.length + seed.length);\r\n spendInput.set(spendTag, 0);\r\n spendInput.set(seed, spendTag.length);\r\n\r\n const viewInput = new Uint8Array(viewTag.length + seed.length);\r\n viewInput.set(viewTag, 0);\r\n viewInput.set(seed, viewTag.length);\r\n\r\n const spendPrivKey = hashToScalar(spendInput);\r\n const viewPrivKey = hashToScalar(viewInput);\r\n\r\n // Zero sensitive intermediates\r\n seed.fill(0);\r\n spendInput.fill(0);\r\n viewInput.fill(0);\r\n\r\n const spendPubKey = scalarMultBase(spendPrivKey);\r\n const viewPubKey = scalarMultBase(viewPrivKey);\r\n\r\n return {\r\n spendPrivKey,\r\n viewPrivKey,\r\n metaAddress: { spendPubKey, viewPubKey },\r\n };\r\n}\r\n","import {\r\n Networks,\r\n Contract,\r\n nativeToScVal,\r\n Asset,\r\n TransactionBuilder,\r\n StrKey,\r\n} from '@stellar/stellar-sdk';\r\nimport * as StellarSdk from '@stellar/stellar-sdk';\r\nimport { sha256 } from '@noble/hashes/sha256';\r\n\r\n/** Network configuration resolved from a network name. */\r\nexport interface NetworkConfig {\r\n networkPassphrase: string;\r\n rpcUrl: string;\r\n server: StellarSdk.rpc.Server;\r\n}\r\n\r\n/** Build network config from a network name. */\r\nexport function getNetworkConfig(network: 'local' | 'testnet'): NetworkConfig {\r\n const networkPassphrase = network === 'local'\r\n ? Networks.STANDALONE\r\n : Networks.TESTNET;\r\n\r\n const rpcUrl = network === 'local'\r\n ? 'http://localhost:8000/soroban/rpc'\r\n : 'https://soroban-testnet.stellar.org';\r\n\r\n const server = new StellarSdk.rpc.Server(rpcUrl, {\r\n allowHttp: network === 'local',\r\n });\r\n\r\n return { networkPassphrase, rpcUrl, server };\r\n}\r\n\r\n/** Create a dummy transaction for read-only contract simulation. */\r\nexport function createSimulationTx(\r\n operation: StellarSdk.xdr.Operation,\r\n networkPassphrase: string,\r\n): StellarSdk.Transaction {\r\n return new TransactionBuilder(\r\n new StellarSdk.Account('GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF', '0'),\r\n { fee: '100', networkPassphrase },\r\n )\r\n .addOperation(operation)\r\n .setTimeout(30)\r\n .build();\r\n}\r\n\r\n/** Execute a read-only contract call via simulation. Returns the decoded native result. */\r\nexport async function simulateReadOnly(\r\n contractId: string,\r\n method: string,\r\n args: StellarSdk.xdr.ScVal[],\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<unknown | null> {\r\n const contract = new Contract(contractId);\r\n const op = contract.call(method, ...args);\r\n const sim = await server.simulateTransaction(\r\n createSimulationTx(op, networkPassphrase),\r\n );\r\n\r\n if (StellarSdk.rpc.Api.isSimulationSuccess(sim) && sim.result?.retval) {\r\n return StellarSdk.scValToNative(sim.result.retval);\r\n }\r\n return null;\r\n}\r\n\r\n/** Resolve an asset string (\"native\", \"XLM\", or \"CODE:ISSUER\") to a SAC contract address. */\r\nexport function resolveTokenAddress(\r\n assetArg: string | undefined,\r\n networkPassphrase: string,\r\n): string {\r\n if (!assetArg || assetArg === 'native' || assetArg === 'XLM') {\r\n return Asset.native().contractId(networkPassphrase);\r\n }\r\n const parts = assetArg.split(':');\r\n if (parts.length !== 2 || !parts[0] || !parts[1]) {\r\n throw new Error('Invalid asset format. Use CODE:ISSUER or \"native\"');\r\n }\r\n return new Asset(parts[0], parts[1]).contractId(networkPassphrase);\r\n}\r\n\r\n/** Poll for transaction confirmation. Throws on failure or timeout. */\r\nexport async function waitForTransaction(\r\n server: StellarSdk.rpc.Server,\r\n hash: string,\r\n): Promise<void> {\r\n let attempts = 0;\r\n while (attempts < 30) {\r\n await new Promise(resolve => setTimeout(resolve, 1000));\r\n try {\r\n const result = await server.getTransaction(hash);\r\n if (result.status === 'SUCCESS') return;\r\n if (result.status === 'FAILED') throw new Error('Transaction failed on-chain');\r\n } catch (e: unknown) {\r\n const msg = e instanceof Error ? e.message : String(e);\r\n if (msg === 'Transaction failed on-chain') throw e;\r\n }\r\n attempts++;\r\n }\r\n throw new Error('Transaction confirmation timed out');\r\n}\r\n\r\n/** Fetch announcements from the stealth pool contract. */\r\nexport async function fetchAnnouncements(\r\n contractId: string,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<RawAnnouncement[]> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_announcements',\r\n [nativeToScVal(0, { type: 'u64' }), nativeToScVal(1000, { type: 'u64' })],\r\n server,\r\n networkPassphrase,\r\n );\r\n\r\n if (!result || !Array.isArray(result)) return [];\r\n\r\n return (result as unknown[]).map((ann: unknown) => {\r\n const a = ann as Record<string, unknown>;\r\n const stealthPk = new Uint8Array(a.stealth_pk as ArrayLike<number>);\r\n return {\r\n ephemeralPubKey: new Uint8Array(a.ephemeral_pk as ArrayLike<number>),\r\n viewTag: a.view_tag as number,\r\n stealthPubKey: stealthPk,\r\n stealthAddress: StrKey.encodeEd25519PublicKey(Buffer.from(stealthPk)),\r\n token: (a.token as { toString(): string })?.toString?.() || 'unknown',\r\n amount: BigInt((a.amount as string | number) || 0),\r\n };\r\n });\r\n}\r\n\r\nexport interface RawAnnouncement {\r\n ephemeralPubKey: Uint8Array;\r\n viewTag: number;\r\n stealthPubKey: Uint8Array;\r\n stealthAddress: string;\r\n token: string;\r\n amount: bigint;\r\n}\r\n\r\n/** Query the contract balance for a stealth key + token pair. */\r\nexport async function queryBalance(\r\n contractId: string,\r\n stealthPk: Uint8Array,\r\n tokenAddress: string,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<bigint> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_balance',\r\n [nativeToScVal(Buffer.from(stealthPk)), new StellarSdk.Address(tokenAddress).toScVal()],\r\n server,\r\n networkPassphrase,\r\n );\r\n if (result !== null) return BigInt(result as string | number);\r\n return 0n;\r\n}\r\n\r\n/** Query the nonce for a stealth key. */\r\nexport async function queryNonce(\r\n contractId: string,\r\n stealthPk: Uint8Array,\r\n server: StellarSdk.rpc.Server,\r\n networkPassphrase: string,\r\n): Promise<bigint> {\r\n const result = await simulateReadOnly(\r\n contractId,\r\n 'get_nonce',\r\n [nativeToScVal(Buffer.from(stealthPk))],\r\n server,\r\n networkPassphrase,\r\n );\r\n if (result !== null) return BigInt(result as string | number);\r\n return 0n;\r\n}\r\n\r\nfunction i128ToBigEndian(value: bigint): Uint8Array {\r\n const buf = new Uint8Array(16);\r\n const dv = new DataView(buf.buffer);\r\n dv.setBigInt64(0, value >> 64n);\r\n dv.setBigUint64(8, value & 0xFFFFFFFFFFFFFFFFn);\r\n return buf;\r\n}\r\n\r\nfunction u64ToBigEndian(value: bigint): Uint8Array {\r\n const buf = new Uint8Array(8);\r\n const dv = new DataView(buf.buffer);\r\n dv.setBigUint64(0, value);\r\n return buf;\r\n}\r\n\r\n/** Build the withdraw message hash. Must be byte-identical to the contract's build_withdraw_message. */\r\nexport function buildWithdrawMessage(\r\n stealthPk: Uint8Array,\r\n tokenAddress: string,\r\n amount: bigint,\r\n destination: string,\r\n nonce: bigint,\r\n): Uint8Array {\r\n const tokenBytes = Buffer.from(tokenAddress, 'utf-8');\r\n const destBytes = Buffer.from(destination, 'utf-8');\r\n if (tokenBytes.length !== 56) throw new Error(`Token address must be 56 bytes StrKey, got ${tokenBytes.length}`);\r\n if (destBytes.length !== 56) throw new Error(`Destination must be 56 bytes StrKey, got ${destBytes.length}`);\r\n\r\n const amountBytes = i128ToBigEndian(amount);\r\n const nonceBytes = u64ToBigEndian(nonce);\r\n\r\n const msg = new Uint8Array(32 + 56 + 16 + 56 + 8);\r\n let offset = 0;\r\n msg.set(stealthPk, offset); offset += 32;\r\n msg.set(tokenBytes, offset); offset += 56;\r\n msg.set(amountBytes, offset); offset += 16;\r\n msg.set(destBytes, offset); offset += 56;\r\n msg.set(nonceBytes, offset);\r\n\r\n return sha256(msg);\r\n}\r\n","import {\r\n generateMetaAddress,\r\n encodeMetaAddress,\r\n decodeMetaAddress,\r\n deriveStealthAddressWithSecret,\r\n scanAnnouncements,\r\n recoverStealthPrivateKey,\r\n signWithStealthKey,\r\n generateMnemonic,\r\n mnemonicToStealthKeys,\r\n} from '@stealth/crypto';\r\nimport {\r\n Keypair,\r\n TransactionBuilder,\r\n Contract,\r\n nativeToScVal,\r\n StrKey,\r\n} from '@stellar/stellar-sdk';\r\nimport * as StellarSdk from '@stellar/stellar-sdk';\r\nimport { randomBytes } from '@noble/hashes/utils';\r\nimport {\r\n getNetworkConfig,\r\n resolveTokenAddress,\r\n fetchAnnouncements,\r\n queryBalance,\r\n queryNonce,\r\n buildWithdrawMessage,\r\n waitForTransaction,\r\n} from './soroban.js';\r\nimport type {\r\n ClientConfig,\r\n StealthKeys,\r\n SendReceipt,\r\n SendOpts,\r\n Payment,\r\n Balance,\r\n WithdrawReceipt,\r\n WithdrawOpts,\r\n TransactionSigner,\r\n} from './types.js';\r\n\r\n/** Default contract addresses per network. */\r\nconst DEFAULT_CONTRACTS: Record<string, string> = {\r\n local: 'CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGABAX',\r\n};\r\n\r\n/**\r\n * High-level client for stealth payments on Stellar.\r\n *\r\n * Wraps DKSAP cryptography and Soroban contract interaction into a simple API.\r\n * Developers don't need to understand the underlying protocol to use this.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new StealthClient({ network: 'local', contractId: 'CXXX...' });\r\n *\r\n * // Generate keys\r\n * const keys = StealthClient.keygen();\r\n *\r\n * // Send 100 XLM to a stealth address\r\n * const receipt = await client.send(keys.metaAddress, 100, 'SXXX...');\r\n *\r\n * // Scan for received payments\r\n * const payments = await client.scan(keys);\r\n *\r\n * // Withdraw\r\n * await client.withdraw(payments[0].stealthAddress, 'GDEST...', {\r\n * keys,\r\n * feePayer: 'SXXX...',\r\n * });\r\n * ```\r\n */\r\nexport class StealthClient {\r\n private readonly contractId: string;\r\n private readonly networkPassphrase: string;\r\n private readonly server: StellarSdk.rpc.Server;\r\n\r\n constructor(config: ClientConfig) {\r\n this.contractId = config.contractId || DEFAULT_CONTRACTS[config.network] || '';\r\n const netConfig = getNetworkConfig(config.network);\r\n this.networkPassphrase = netConfig.networkPassphrase;\r\n this.server = netConfig.server;\r\n }\r\n\r\n /**\r\n * Generate a new random stealth key pair.\r\n * No network connection needed.\r\n */\r\n static keygen(): StealthKeys {\r\n const keys = generateMetaAddress();\r\n const metaAddress = encodeMetaAddress(keys.metaAddress);\r\n\r\n return {\r\n metaAddress,\r\n spendPubKey: Buffer.from(keys.metaAddress.spendPubKey).toString('hex'),\r\n spendPrivKey: Buffer.from(keys.spendPrivKey).toString('hex'),\r\n viewPubKey: Buffer.from(keys.metaAddress.viewPubKey).toString('hex'),\r\n viewPrivKey: Buffer.from(keys.viewPrivKey).toString('hex'),\r\n };\r\n }\r\n\r\n /**\r\n * Generate stealth keys from a BIP-39 mnemonic.\r\n * Returns the mnemonic alongside the keys for backup.\r\n * No network connection needed.\r\n */\r\n static fromMnemonic(mnemonic?: string): StealthKeys & { mnemonic: string } {\r\n const phrase = mnemonic || generateMnemonic();\r\n const keys = mnemonicToStealthKeys(phrase);\r\n const metaAddress = encodeMetaAddress(keys.metaAddress);\r\n\r\n return {\r\n mnemonic: phrase,\r\n metaAddress,\r\n spendPubKey: Buffer.from(keys.metaAddress.spendPubKey).toString('hex'),\r\n spendPrivKey: Buffer.from(keys.spendPrivKey).toString('hex'),\r\n viewPubKey: Buffer.from(keys.metaAddress.viewPubKey).toString('hex'),\r\n viewPrivKey: Buffer.from(keys.viewPrivKey).toString('hex'),\r\n };\r\n }\r\n\r\n /**\r\n * Send tokens to a stealth address.\r\n *\r\n * Derives a one-time stealth address from the recipient's meta-address,\r\n * deposits tokens into the pool contract, and records the announcement.\r\n *\r\n * Signing: by default the transaction is signed with `senderSecret` (a\r\n * Stellar secret key). If `opts.signTransaction` is provided, signing is\r\n * delegated to that external signer (e.g. a browser wallet) and the\r\n * `senderSecret` argument is treated as the sender's public key instead.\r\n *\r\n * @param metaAddress - Recipient's meta-address (st:stellar:... format)\r\n * @param amount - Amount in whole units (e.g. 100 = 100 XLM)\r\n * @param senderSecret - Sender's secret key, or public key when using `opts.signTransaction`\r\n * @param opts - Optional: asset to send, external signer\r\n */\r\n async send(\r\n metaAddress: string,\r\n amount: number,\r\n senderSecret: string,\r\n opts?: SendOpts,\r\n ): Promise<SendReceipt> {\r\n if (amount <= 0) throw new Error('Amount must be positive');\r\n\r\n const { spendPubKey, viewPubKey } = decodeMetaAddress(metaAddress);\r\n // With an external signer, `senderSecret` carries the public key (G...);\r\n // otherwise derive the public key from the secret as before.\r\n const senderPublicKey = opts?.signTransaction\r\n ? senderSecret\r\n : Keypair.fromSecret(senderSecret).publicKey();\r\n const tokenAddress = resolveTokenAddress(opts?.asset, this.networkPassphrase);\r\n const stroops = BigInt(Math.round(amount * 1e7));\r\n\r\n // Derive stealth address\r\n const ephemeralPrivKey = new Uint8Array(randomBytes(32));\r\n const stealth = deriveStealthAddressWithSecret(\r\n spendPubKey,\r\n viewPubKey,\r\n ephemeralPrivKey,\r\n );\r\n\r\n // Build and submit deposit transaction\r\n const contract = new Contract(this.contractId);\r\n const account = await this.server.getAccount(senderPublicKey);\r\n\r\n const depositTx = new TransactionBuilder(account, {\r\n fee: '100',\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(\r\n contract.call(\r\n 'deposit',\r\n new StellarSdk.Address(senderPublicKey).toScVal(),\r\n new StellarSdk.Address(tokenAddress).toScVal(),\r\n nativeToScVal(stroops, { type: 'i128' }),\r\n nativeToScVal(Buffer.from(stealth.stealthPubKey)),\r\n nativeToScVal(Buffer.from(stealth.ephemeralPubKey)),\r\n nativeToScVal(stealth.viewTag, { type: 'u32' }),\r\n ),\r\n )\r\n .setTimeout(30)\r\n .build();\r\n\r\n const prepared = await this.server.prepareTransaction(depositTx);\r\n const signed = await this.signTx(\r\n prepared,\r\n senderSecret,\r\n senderPublicKey,\r\n opts?.signTransaction,\r\n );\r\n const result = await this.server.sendTransaction(signed);\r\n\r\n if (result.status === 'ERROR') {\r\n throw new Error('Transaction submission failed');\r\n }\r\n if (result.status === 'PENDING') {\r\n await waitForTransaction(this.server, result.hash);\r\n }\r\n\r\n return {\r\n stealthAddress: stealth.stealthAddress,\r\n txHash: result.hash,\r\n };\r\n }\r\n\r\n /**\r\n * Sign a prepared transaction either with a local secret key (legacy path)\r\n * or by delegating to an external signer that returns signed XDR.\r\n *\r\n * @param prepared - The prepared transaction to sign\r\n * @param secretOrPublic - Secret key (local signing) or public key (external)\r\n * @param publicKey - Signer's public key (G...)\r\n * @param signer - Optional external signer; when present, no secret is used\r\n */\r\n private async signTx(\r\n prepared: StellarSdk.Transaction,\r\n secretOrPublic: string,\r\n publicKey: string,\r\n signer?: TransactionSigner,\r\n ): Promise<StellarSdk.Transaction> {\r\n if (signer) {\r\n const signedXdr = await signer(prepared.toXDR(), {\r\n networkPassphrase: this.networkPassphrase,\r\n address: publicKey,\r\n });\r\n const tx = TransactionBuilder.fromXDR(signedXdr, this.networkPassphrase);\r\n return tx as StellarSdk.Transaction;\r\n }\r\n prepared.sign(Keypair.fromSecret(secretOrPublic));\r\n return prepared;\r\n }\r\n\r\n /**\r\n * Scan for stealth payments you received.\r\n *\r\n * Uses the view key to detect which announcements are yours,\r\n * then queries the contract for current balances.\r\n *\r\n * @param keys - Your stealth keys (needs viewPrivKey + spendPubKey)\r\n */\r\n async scan(keys: StealthKeys): Promise<Payment[]> {\r\n const viewPrivKey = Buffer.from(keys.viewPrivKey, 'hex');\r\n const spendPubKey = Buffer.from(keys.spendPubKey, 'hex');\r\n\r\n const announcements = await fetchAnnouncements(\r\n this.contractId,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n if (announcements.length === 0) return [];\r\n\r\n const matches = scanAnnouncements(\r\n viewPrivKey,\r\n spendPubKey,\r\n announcements.map(a => ({\r\n ephemeralPubKey: a.ephemeralPubKey,\r\n viewTag: a.viewTag,\r\n stealthAddress: a.stealthAddress,\r\n })),\r\n );\r\n\r\n const payments: Payment[] = [];\r\n\r\n for (const match of matches) {\r\n if (!match) continue;\r\n const ann = announcements.find(a => a.stealthAddress === match.address);\r\n if (!ann) continue;\r\n\r\n const balance = await queryBalance(\r\n this.contractId,\r\n ann.stealthPubKey,\r\n ann.token,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n if (balance <= 0n) continue;\r\n\r\n payments.push({\r\n stealthAddress: ann.stealthAddress,\r\n ephemeralPubKey: Buffer.from(ann.ephemeralPubKey).toString('hex'),\r\n token: ann.token,\r\n amount: Number(balance) / 1e7,\r\n });\r\n }\r\n\r\n return payments;\r\n }\r\n\r\n /**\r\n * Get balances for all your stealth addresses in the pool.\r\n *\r\n * @param keys - Your stealth keys (needs viewPrivKey + spendPubKey)\r\n */\r\n async balance(keys: StealthKeys): Promise<Balance[]> {\r\n const payments = await this.scan(keys);\r\n return payments.map(p => ({\r\n stealthAddress: p.stealthAddress,\r\n token: p.token,\r\n amount: p.amount,\r\n }));\r\n }\r\n\r\n /**\r\n * Withdraw tokens from the stealth pool.\r\n *\r\n * Recovers the stealth private key, signs a withdraw message,\r\n * and submits the transaction. Use `opts.relay` for privacy-preserving\r\n * withdrawal via a relayer.\r\n *\r\n * @param stealthAddress - The stealth address to withdraw from\r\n * @param destination - Destination Stellar address (G...)\r\n * @param opts - Withdraw options (keys, feePayer, optional relay/asset/amount)\r\n */\r\n async withdraw(\r\n stealthAddress: string,\r\n destination: string,\r\n opts: WithdrawOpts,\r\n ): Promise<WithdrawReceipt> {\r\n if (!StrKey.isValidEd25519PublicKey(stealthAddress)) {\r\n throw new Error('Invalid stealth address');\r\n }\r\n if (!StrKey.isValidEd25519PublicKey(destination)) {\r\n throw new Error('Invalid destination address');\r\n }\r\n\r\n const viewPrivKey = Buffer.from(opts.keys.viewPrivKey, 'hex');\r\n const spendPrivKey = Buffer.from(opts.keys.spendPrivKey, 'hex');\r\n const spendPubKey = Buffer.from(opts.keys.spendPubKey, 'hex');\r\n const tokenAddress = resolveTokenAddress(opts.asset, this.networkPassphrase);\r\n\r\n // Find matching announcement\r\n const announcements = await fetchAnnouncements(\r\n this.contractId,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n const allMatches = scanAnnouncements(\r\n viewPrivKey,\r\n spendPubKey,\r\n announcements.map(a => ({\r\n ephemeralPubKey: a.ephemeralPubKey,\r\n viewTag: a.viewTag,\r\n stealthAddress: a.stealthAddress,\r\n })),\r\n );\r\n\r\n const matchedAnn = announcements.find(a => {\r\n if (a.stealthAddress !== stealthAddress) return false;\r\n return allMatches.some(m => m?.address === stealthAddress);\r\n });\r\n\r\n if (!matchedAnn) {\r\n throw new Error('Could not find announcement for this stealth address');\r\n }\r\n\r\n // Recover stealth private key\r\n const stealthPrivKey = recoverStealthPrivateKey(\r\n spendPrivKey,\r\n viewPrivKey,\r\n matchedAnn.ephemeralPubKey,\r\n );\r\n\r\n // Get balance\r\n const balance = await queryBalance(\r\n this.contractId,\r\n matchedAnn.stealthPubKey,\r\n tokenAddress,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n\r\n if (balance <= 0n) throw new Error('Stealth address has no balance in the pool');\r\n\r\n // Determine amount\r\n let withdrawAmount: bigint;\r\n if (opts.amount !== undefined) {\r\n withdrawAmount = BigInt(Math.round(opts.amount * 1e7));\r\n if (withdrawAmount > balance) {\r\n throw new Error(`Requested ${opts.amount} but balance is ${Number(balance) / 1e7}`);\r\n }\r\n } else {\r\n withdrawAmount = balance;\r\n }\r\n\r\n // Get nonce and build signed message\r\n const currentNonce = await queryNonce(\r\n this.contractId,\r\n matchedAnn.stealthPubKey,\r\n this.server,\r\n this.networkPassphrase,\r\n );\r\n const nonce = currentNonce + 1n;\r\n\r\n const messageHash = buildWithdrawMessage(\r\n matchedAnn.stealthPubKey,\r\n tokenAddress,\r\n withdrawAmount,\r\n destination,\r\n nonce,\r\n );\r\n\r\n const signature = signWithStealthKey(messageHash, stealthPrivKey);\r\n\r\n // Resolve the fee payer. With an external signer we use feePayerAddress\r\n // (a public key); otherwise we derive it from the feePayer secret.\r\n if (!opts.signTransaction && !opts.feePayer) {\r\n throw new Error('Provide either opts.feePayer or opts.signTransaction + opts.feePayerAddress');\r\n }\r\n if (opts.signTransaction && !opts.feePayerAddress) {\r\n throw new Error('opts.feePayerAddress is required when using opts.signTransaction');\r\n }\r\n const feePayerPublicKey = opts.signTransaction\r\n ? (opts.feePayerAddress as string)\r\n : Keypair.fromSecret(opts.feePayer as string).publicKey();\r\n\r\n // Build transaction\r\n const contract = new Contract(this.contractId);\r\n const feePayerAccount = await this.server.getAccount(feePayerPublicKey);\r\n\r\n const withdrawTx = new TransactionBuilder(feePayerAccount, {\r\n fee: '100',\r\n networkPassphrase: this.networkPassphrase,\r\n })\r\n .addOperation(\r\n contract.call(\r\n 'withdraw',\r\n nativeToScVal(Buffer.from(matchedAnn.stealthPubKey)),\r\n new StellarSdk.Address(tokenAddress).toScVal(),\r\n nativeToScVal(withdrawAmount, { type: 'i128' }),\r\n new StellarSdk.Address(destination).toScVal(),\r\n nativeToScVal(nonce, { type: 'u64' }),\r\n nativeToScVal(Buffer.from(signature)),\r\n ),\r\n )\r\n .setTimeout(30)\r\n .build();\r\n\r\n const prepared = await this.server.prepareTransaction(withdrawTx);\r\n const signedTx = await this.signTx(\r\n prepared,\r\n opts.feePayer ?? '',\r\n feePayerPublicKey,\r\n opts.signTransaction,\r\n );\r\n\r\n // Submit (direct or via relay)\r\n let txHash: string;\r\n\r\n if (opts.relay) {\r\n const url = opts.relay.endsWith('/relay') ? opts.relay : `${opts.relay}/relay`;\r\n const res = await fetch(url, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ xdr: signedTx.toEnvelope().toXDR('base64') }),\r\n });\r\n if (!res.ok) {\r\n const err = await res.json() as { error?: string };\r\n throw new Error(`Relay error: ${err.error || 'unknown'}`);\r\n }\r\n const data = await res.json() as { txHash: string };\r\n txHash = data.txHash;\r\n } else {\r\n const result = await this.server.sendTransaction(signedTx);\r\n if (result.status === 'ERROR') throw new Error('Transaction submission failed');\r\n if (result.status === 'PENDING') {\r\n await waitForTransaction(this.server, result.hash);\r\n }\r\n txHash = result.hash;\r\n }\r\n\r\n return {\r\n txHash,\r\n amount: Number(withdrawAmount) / 1e7,\r\n };\r\n }\r\n}\r\n"]}
|