bsv-bap 0.1.21 → 0.1.22

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.
@@ -2,15 +2,15 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/api.ts", "../src/constants.ts", "../src/MasterID.ts", "../src/utils.ts", "../src/MemberID.ts", "../src/BaseClass.ts"],
4
4
  "sourcesContent": [
5
- "import {\n BSM,\n BigNumber,\n ECIES,\n HD,\n OP,\n type PublicKey,\n Signature,\n PrivateKey,\n} from \"@bsv/sdk\";\n\nimport { Utils as BSVUtils } from \"@bsv/sdk\";\nimport { type APIFetcher, apiFetcher } from \"./api\";\nimport type {\n AttestationValidResponse,\n GetAttestationResponse,\n GetIdentityByAddressResponse,\n GetIdentityResponse,\n} from \"./apiTypes\";\nimport {\n AIP_BITCOM_ADDRESS,\n BAP_BITCOM_ADDRESS,\n BAP_BITCOM_ADDRESS_HEX,\n BAP_SERVER,\n ENCRYPTION_PATH,\n} from \"./constants\";\nimport { MasterID } from \"./MasterID\";\nimport type {\n Attestation,\n Identity,\n IdentityAttributes,\n MemberIdentity,\n OldIdentity,\n PathPrefix,\n} from \"./interface\";\nimport { Utils } from \"./utils\";\nimport { MemberID } from \"./MemberID\";\nconst { toArray, toUTF8, toBase64, toHex } = BSVUtils;\nconst { electrumEncrypt, electrumDecrypt } = ECIES;\n\ntype Identities = { lastIdPath: string; ids: Identity[] };\n\n/** Backup format for Type 42 mode (rootPk-based) */\nexport interface Type42MasterBackup {\n ids: string;\n rootPk: string;\n mnemonic?: string;\n label?: string;\n createdAt: string;\n}\n\n/** Backup format for BIP32 mode (xprv-based, legacy) */\nexport interface Bip32MasterBackup {\n ids: string;\n xprv: string;\n mnemonic?: string;\n label?: string;\n createdAt: string;\n}\n\n// Type 42 parameters\ninterface Type42Params {\n rootPk: string; // WIF format private key\n}\n\n/**\n * BAP class\n *\n * Creates an instance of the BAP class and uses the given HDPrivateKey for all BAP operations.\n * Supports both BIP32 (HD) and Type 42 key derivation methods.\n *\n * @deprecated When initializing with a string (xprv), the BIP32 format is used which is deprecated \n * for new implementations. Use Type 42 initialization with { rootPk: wifKey } instead.\n * \n * @param keySource Either an HDPrivateKey string (xprv) for BIP32 or Type42Params for Type 42\n */\nexport class BAP {\n #HDPrivateKey: HD | undefined;\n #masterPrivateKey: PrivateKey | undefined;\n #isType42: boolean;\n #ids: { [key: string]: MasterID } = {};\n #BAP_SERVER = BAP_SERVER;\n #BAP_TOKEN = \"\";\n #lastIdPath = \"\";\n #identityCounter = 0;\n getApiData: APIFetcher;\n\n constructor(keySource: string | Type42Params, token = \"\", server = \"\") {\n if (!keySource) {\n throw new Error(\"No key source given\");\n }\n\n // Determine if we're using Type 42 or BIP32\n if (typeof keySource === \"string\") {\n // BIP32 mode\n this.#HDPrivateKey = HD.fromString(keySource);\n this.#isType42 = false;\n } else {\n // Type 42 mode\n this.#masterPrivateKey = PrivateKey.fromWif(keySource.rootPk);\n this.#isType42 = true;\n }\n\n if (token) {\n this.#BAP_TOKEN = token;\n }\n\n if (server) {\n this.#BAP_SERVER = server;\n }\n\n this.getApiData = apiFetcher(this.#BAP_SERVER, this.#BAP_TOKEN);\n }\n\n get lastIdPath(): string {\n return this.#lastIdPath;\n }\n\n /**\n * Get the public key of the given childPath, or of the current HDPrivateKey of childPath is empty\n *\n * @param childPath Full derivation path for this child (BIP32) or invoice number (Type 42)\n * @returns {*}\n */\n getPublicKey(childPath = \"\"): string {\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n if (childPath) {\n // In Type 42, we use the path as an invoice number\n const derivedKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n childPath\n );\n return derivedKey.toPublicKey().toString();\n }\n return this.#masterPrivateKey.toPublicKey().toString();\n }\n \n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n if (childPath) {\n return this.#HDPrivateKey.derive(childPath).pubKey.toString();\n }\n return this.#HDPrivateKey.pubKey.toString();\n }\n\n /**\n * Get the HD public key of the given childPath (BIP32 only)\n *\n * @param childPath Full derivation path for this child\n * @returns {*}\n */\n getHdPublicKey(childPath = \"\"): string {\n if (this.#isType42) {\n throw new Error(\"HD public keys are not available in Type 42 mode\");\n }\n \n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n if (childPath) {\n return this.#HDPrivateKey.derive(childPath).toPublic().toString();\n }\n return this.#HDPrivateKey.toPublic().toString();\n }\n\n set BAP_SERVER(bapServer) {\n this.#BAP_SERVER = bapServer;\n for (const key in this.#ids) {\n this.#ids[key].BAP_SERVER = bapServer;\n }\n }\n\n get BAP_SERVER(): string {\n return this.#BAP_SERVER;\n }\n\n set BAP_TOKEN(token) {\n this.#BAP_TOKEN = token;\n for (const key in this.#ids) {\n // @ts-ignore - does not recognize private fields that can be set\n this.#ids[key].BAP_TOKEN = token;\n }\n }\n\n get BAP_TOKEN(): string {\n return this.#BAP_TOKEN;\n }\n\n /**\n * This function verifies that the given bapId matches the given root address\n * This is used as a data integrity check\n *\n * @param bapId MasterID instance\n */\n checkIdBelongs(bapId: MasterID): boolean {\n let checkRootAddress: string;\n \n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // In Type 42, we derive using the path as invoice number\n const derivedKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n bapId.rootPath\n );\n checkRootAddress = derivedKey.toPublicKey().toAddress();\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const derivedChild = this.#HDPrivateKey.derive(bapId.rootPath);\n checkRootAddress = derivedChild.pubKey.toAddress();\n }\n \n if (checkRootAddress !== bapId.rootAddress) {\n throw new Error(\"ID does not belong to this private key\");\n }\n\n return true;\n }\n\n /**\n * Returns a list of all the identity keys that are stored in this instance\n *\n * @returns {string[]}\n */\n listIds(): string[] {\n return Object.keys(this.#ids);\n }\n\n /**\n * Create a new Id and link it to this BAP instance\n *\n * For Type 42 mode, uses simple counter for derivation: bap:{counter}\n * For BIP32 mode (legacy), uses traditional HD paths or provided customPath\n *\n * New signature: newId(idName, customPath?, identityAttributes?, idSeed?)\n * Legacy signature: newId(path?, identityAttributes?, idSeed?) - for backward compatibility\n *\n * @param idNameOrPath The human-readable name for this identity OR legacy path parameter\n * @param customPathOrAttributes Optional custom derivation path OR legacy identityAttributes\n * @param identityAttributes Optional identity attributes\n * @param idSeed Optional seed for deterministic key generation\n * @returns {MasterID} The created identity\n */\n newId(\n idNameOrPath?: string | IdentityAttributes,\n customPathOrAttributes?: string | IdentityAttributes,\n identityAttributes: IdentityAttributes = {},\n idSeed = \"\"\n ): MasterID {\n // Handle backward compatibility - detect old vs new signature\n let idName: string;\n let customPath: string | undefined;\n let finalAttributes: IdentityAttributes;\n \n if (typeof idNameOrPath === 'object' || idNameOrPath === undefined || \n (typeof idNameOrPath === 'string' && idNameOrPath.startsWith('/'))) {\n // Legacy signature: newId(path?, identityAttributes?, idSeed?)\n // First param is path (undefined, starts with '/') or identityAttributes (object)\n customPath = typeof idNameOrPath === 'string' ? idNameOrPath : undefined;\n finalAttributes = (typeof idNameOrPath === 'object' ? idNameOrPath : \n typeof customPathOrAttributes === 'object' ? customPathOrAttributes : {});\n idName = \"Default Identity\";\n } else {\n // New signature: newId(idName, customPath?, identityAttributes?, idSeed?)\n idName = idNameOrPath;\n customPath = typeof customPathOrAttributes === 'string' ? customPathOrAttributes : undefined;\n finalAttributes = typeof customPathOrAttributes === 'object' ? customPathOrAttributes : identityAttributes;\n }\n let pathToUse: string;\n \n if (customPath) {\n // Use provided custom path\n pathToUse = customPath;\n } else if (this.#isType42) {\n // Type 42: Use simple counter for discovery - name is just UX\n pathToUse = `bap:${this.#identityCounter}`;\n this.#identityCounter++;\n } else {\n // BIP32: Use traditional HD path\n pathToUse = this.getNextValidPath();\n }\n\n let newIdentity: MasterID;\n if (this.#isType42) {\n if (!this.#masterPrivateKey) {\n throw new Error(\"Type 42 parameters not initialized\");\n }\n // For Type 42, pass the key source object\n newIdentity = new MasterID(\n {\n rootPk: this.#masterPrivateKey\n },\n finalAttributes,\n idSeed\n );\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n newIdentity = new MasterID(\n this.#HDPrivateKey,\n finalAttributes,\n idSeed\n );\n }\n \n newIdentity.BAP_SERVER = this.#BAP_SERVER;\n newIdentity.BAP_TOKEN = this.#BAP_TOKEN;\n newIdentity.idName = idName;\n newIdentity.rootPath = pathToUse;\n \n // Set current path based on mode\n if (this.#isType42) {\n // For Type 42, current path is same as root path (invoice number)\n newIdentity.currentPath = pathToUse;\n } else {\n // For BIP32, calculate next path\n newIdentity.currentPath = Utils.getNextPath(pathToUse);\n }\n\n const idKey = newIdentity.getIdentityKey();\n this.#ids[idKey] = newIdentity;\n this.#lastIdPath = pathToUse;\n\n return this.#ids[idKey];\n }\n\n /**\n * Remove identity\n *\n * @param idKey\n * @returns {*}\n */\n removeId(idKey: string): void {\n delete this.#ids[idKey];\n }\n\n /**\n * Get the next valid path for the used HDPrivateKey and loaded #ids\n *\n * @returns {string}\n */\n getNextValidPath(): PathPrefix {\n // prefer hardened paths\n if (this.#lastIdPath) {\n return Utils.getNextIdentityPath(this.#lastIdPath);\n }\n\n return `/0'/${Object.keys(this.#ids).length}'/0'`;\n }\n\n /**\n * Create an identity with a specific counter value (useful for discovery)\n * Only works in Type 42 mode\n *\n * @param counter The specific counter value to use\n * @param idName Optional name for the identity\n * @returns {MasterID} The created identity\n */\n newIdWithCounter(\n counter: number,\n idName = `Identity ${counter}`\n ): MasterID {\n if (!this.#isType42) {\n throw new Error(\"newIdWithCounter only works in Type 42 mode\");\n }\n \n const customPath = `bap:${counter}`;\n return this.newId(idName, customPath);\n }\n\n /**\n * Get a certain Id\n *\n * @param identityKey\n * @returns {null}\n */\n getId(identityKey: string): MasterID | null {\n return this.#ids[identityKey] || null;\n }\n\n /**\n * This function is used when manipulating ID's, adding or removing attributes etc\n * First create an id through this class and then use getId to get it. Then you can add/edit or\n * increment the signing path and then re-set it with this function.\n *\n * Note: when you getId() from this class, you will be working on the same object as this class\n * has and any changes made will be propagated to the id in this class. When you call exportIds\n * your new changes will also be included, without having to setId().\n *\n * @param bapId\n */\n setId(bapId: MasterID): void {\n this.checkIdBelongs(bapId);\n this.#ids[bapId.getIdentityKey()] = bapId;\n }\n\n /**\n * This function is used to import IDs and attributes from some external storage\n *\n * The ID information should NOT be stored together with the HD private key !\n *\n * @param idData Array of ids that have been exported\n * @param encrypted Whether the data should be treated as being encrypted (default true)\n */\n importIds(idData: Identities | string, encrypted = true): void {\n if (encrypted && typeof idData === \"string\") {\n this.importEncryptedIds(idData);\n return;\n }\n const identity = idData as Identities;\n if (!identity.lastIdPath) {\n throw new Error(\"ID cannot be imported as it is not complete\");\n }\n\n if (!identity.ids) {\n throw new Error(`ID data is not in the correct format: ${idData}`);\n }\n\n let lastIdPath = (idData as Identities).lastIdPath;\n for (const id of identity.ids) {\n if (!id.identityKey || !id.identityAttributes || !id.rootAddress) {\n throw new Error(\"ID cannot be imported as it is not complete\");\n }\n \n let importId: MasterID;\n if (this.#isType42) {\n if (!this.#masterPrivateKey) {\n throw new Error(\"Type 42 parameters not initialized\");\n }\n importId = new MasterID(\n {\n rootPk: this.#masterPrivateKey\n },\n {},\n id.idSeed\n );\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n importId = new MasterID(this.#HDPrivateKey, {}, id.idSeed);\n }\n \n importId.BAP_SERVER = this.#BAP_SERVER;\n importId.BAP_TOKEN = this.#BAP_TOKEN;\n importId.import(id);\n if (lastIdPath === \"\") {\n lastIdPath = importId.currentPath;\n }\n\n this.checkIdBelongs(importId);\n this.#ids[importId.getIdentityKey()] = importId;\n \n // For Type 42, update identity counter based on imported paths\n if (this.#isType42 && importId.rootPath.startsWith('bap:')) {\n const pathParts = importId.rootPath.split(':');\n if (pathParts.length >= 2) {\n const counter = Number.parseInt(pathParts[1], 10);\n if (!Number.isNaN(counter)) {\n this.#identityCounter = Math.max(this.#identityCounter, counter + 1);\n }\n }\n }\n }\n\n this.#lastIdPath = lastIdPath;\n }\n\n importEncryptedIds(idData: string): void {\n // decrypt the ids array using ECIES\n const decrypted = this.decrypt(idData);\n const ids = JSON.parse(decrypted) as Identities;\n\n const isOldFormat = Array.isArray(ids);\n if (isOldFormat) {\n console.log(\"Importing old format:\\n\", ids);\n this.importOldIds(ids);\n return;\n }\n if (typeof ids !== \"object\") {\n throw new Error(\"decrypted, but found unrecognized identities format\");\n }\n this.importIds(ids, false);\n }\n\n importOldIds(idData: OldIdentity[]): void {\n for (const id of idData) {\n let importId: MasterID;\n if (this.#isType42) {\n if (!this.#masterPrivateKey) {\n throw new Error(\"Type 42 parameters not initialized\");\n }\n importId = new MasterID(\n {\n rootPk: this.#masterPrivateKey\n },\n {},\n id.idSeed ?? \"\"\n );\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n importId = new MasterID(this.#HDPrivateKey, {}, id.idSeed ?? \"\");\n }\n \n importId.BAP_SERVER = this.#BAP_SERVER;\n importId.BAP_TOKEN = this.#BAP_TOKEN;\n importId.import(id);\n\n this.checkIdBelongs(importId);\n this.#ids[importId.getIdentityKey()] = importId;\n this.#lastIdPath = importId.currentPath;\n }\n }\n\n /**\n * Export identities. If no idKeys are provided, exports all identities.\n * @param idKeys Optional array of identity keys to export. If omitted, exports all identities.\n * @param encrypted Whether to encrypt the export data\n */\n // Overload signatures\n exportIds(idKeys?: string[], encrypted?: true): string;\n exportIds(idKeys: string[] | undefined, encrypted: false): Identities;\n exportIds(idKeys?: string[], encrypted = true): Identities | string {\n const idData: Identities = {\n lastIdPath: this.#lastIdPath,\n ids: [] as Identity[],\n };\n\n const keysToExport = idKeys || Object.keys(this.#ids);\n\n for (const key of keysToExport) {\n if (!this.#ids[key]) {\n throw new Error(`Identity ${key} not found`);\n }\n idData.ids.push(this.#ids[key].export());\n }\n\n if (encrypted) {\n return this.encrypt(JSON.stringify(idData));\n }\n return idData;\n }\n\n /**\n * Export a given ID from this instance for external storage\n *\n * By default this function will encrypt the data, using a derivative child of the main HD key\n *\n * @param idKey The key of the identity to export\n * @param encrypted Whether the data should be encrypted (default true)\n * @returns {[]|*}\n */\n // Overload signatures\n exportId(idKey: string, encrypted?: true): string;\n exportId(idKey: string, encrypted: false): Identities;\n exportId(idKey: string, encrypted = true): Identities | string {\n const idData: Identities = {\n lastIdPath: this.#lastIdPath,\n ids: [] as Identity[],\n };\n\n idData.ids.push(this.#ids[idKey].export());\n\n if (encrypted) {\n return this.encrypt(JSON.stringify(idData));\n }\n\n return idData;\n }\n\n /**\n * Encrypt a string of data\n *\n * @param string\n * @returns {string}\n */\n encrypt(string: string): string {\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // For Type 42, we use the encryption path as an invoice number\n const encryptionKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n ENCRYPTION_PATH\n );\n return toBase64(\n // @ts-ignore - you can remove the null when this is merged https://github.com/bitcoin-sv/ts-sdk/pull/123\n electrumEncrypt(toArray(string), encryptionKey.toPublicKey(), null)\n );\n }\n \n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const derivedChild = this.#HDPrivateKey.derive(ENCRYPTION_PATH);\n return toBase64(\n // @ts-ignore - you can remove the null when this is merged https://github.com/bitcoin-sv/ts-sdk/pull/123\n electrumEncrypt(toArray(string), derivedChild.pubKey, null)\n );\n }\n\n /**\n * Decrypt a string of data\n *\n * @param string\n * @returns {string}\n */\n decrypt(string: string): string {\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // For Type 42, we use the encryption path as an invoice number\n const encryptionKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n ENCRYPTION_PATH\n );\n return toUTF8(\n electrumDecrypt(toArray(string, \"base64\"), encryptionKey)\n );\n }\n \n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const derivedChild = this.#HDPrivateKey.derive(ENCRYPTION_PATH);\n return toUTF8(\n electrumDecrypt(toArray(string, \"base64\"), derivedChild.privKey)\n );\n }\n\n /**\n * Sign an attestation for a user\n *\n * @param attestationHash The computed attestation hash for the user - this should be calculated with the MasterID class for an identity for the user\n * @param identityKey The identity key we are using for the signing\n * @param counter\n * @param dataString Optional data string that will be appended to the BAP attestation\n * @returns {string[]}\n */\n signAttestationWithAIP(\n attestationHash: string,\n identityKey: string,\n counter = 0,\n dataString = \"\"\n ) {\n const id = this.getId(identityKey);\n if (!id) {\n throw new Error(\"Could not find identity to attest with\");\n }\n\n const attestationBuffer = this.getAttestationBuffer(\n attestationHash,\n counter,\n dataString\n );\n const { address, signature } = id.signMessage(attestationBuffer);\n\n return this.createAttestationTransaction(\n attestationHash,\n counter,\n address,\n signature,\n dataString\n );\n }\n\n /**\n * Verify an AIP signed attestation for a user\n *\n * [\n * '0x6a',\n * '0x31424150537561506e66476e53424d33474c56397968785564596534764762644d54',\n * '0x415454455354',\n * '0x33656166366361396334313936356538353831366439336439643034333136393032376633396661623034386333633031333663343364663635376462383761',\n * '0x30',\n * '0x7c',\n * '0x313550636948473232534e4c514a584d6f5355615756693757537163376843667661',\n * '0x424954434f494e5f4543445341',\n * '0x31477531796d52567a595557634638776f6f506a7a4a4c764d383550795a64655876',\n * '0x20ef60c5555001ddb1039bb0f215e46571fcb39ee46f48b089d1c08b0304dbcb3366d8fdf8bafd82be24b5ac42dcd6a5e96c90705dd42e3ad918b1b47ac3ce6ac2'\n * ]\n *\n * @param tx Array of hex values for the OP_RETURN values\n * @returns {{}}\n */\n verifyAttestationWithAIP(tx: number[][]): Attestation {\n if (\n !tx.every((t) => Array.isArray(t)) ||\n tx[0][0] !== OP.OP_RETURN ||\n toHex(tx[1]) !== BAP_BITCOM_ADDRESS_HEX\n ) {\n throw new Error(\"Not a valid BAP transaction\");\n }\n const dataOffset = toHex(tx[7]) === \"44415441\" ? 5 : 0; // DATA\n const attestation: Attestation = {\n type: toUTF8(tx[2]),\n hash: toHex(tx[3]),\n sequence: toUTF8(tx[4]),\n signingProtocol: toUTF8(tx[7 + dataOffset]),\n signingAddress: toUTF8(tx[8 + dataOffset]),\n signature: toBase64(tx[9 + dataOffset]),\n };\n\n if (dataOffset && tx[3] === tx[8]) {\n // valid data addition\n attestation.data = toHex(tx[9]);\n }\n\n console.log({ attestation });\n\n try {\n const signatureBufferStatements: number[][] = [];\n for (let i = 0; i < 6 + dataOffset; i++) {\n signatureBufferStatements.push(tx[i]);\n }\n // const attestationBuffer = Buffer.concat(signatureBufferStatements as unknown as Uint8Array[]);\n attestation.verified = this.verifySignature(\n signatureBufferStatements.flat(),\n attestation.signingAddress,\n attestation.signature\n );\n } catch {\n attestation.verified = false;\n }\n\n return attestation;\n }\n\n /**\n * For BAP attestations we use all fields for the attestation\n *\n * @param attestationHash\n * @param counter\n * @param address\n * @param signature\n * @param dataString Optional data string that will be appended to the BAP attestation\n * @returns {number[]}\n */\n createAttestationTransaction(\n attestationHash: string,\n counter: number,\n address: string,\n signature: string,\n dataString = \"\"\n ): number[][] {\n const elements: number[][] = [\n [OP.OP_RETURN],\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"ATTEST\"),\n toArray(attestationHash),\n toArray(`${counter}`),\n toArray(\"|\"),\n ];\n\n if (dataString) {\n // data should be a string, either encrypted or stringified JSON if applicable\n elements.push(\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"DATA\"),\n toArray(attestationHash),\n toArray(dataString),\n toArray(\"|\")\n );\n }\n\n elements.push(\n toArray(AIP_BITCOM_ADDRESS),\n toArray(\"BITCOIN_ECDSA\"),\n toArray(address),\n toArray(signature, \"base64\")\n );\n\n console.log({ elements });\n return elements;\n }\n\n /**\n * This is a re-creation of how the bitcoinfiles-sdk creates a hash to sign for AIP\n *\n * @param attestationHash\n * @param counter\n * @param dataString Optional data string\n * @returns {number[]}\n */\n getAttestationBuffer(\n attestationHash: string,\n counter = 0,\n dataString = \"\"\n ): number[] {\n // re-create how AIP creates the buffer to sign\n const elements = [\n [OP.OP_RETURN],\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"ATTEST\"),\n toArray(attestationHash),\n toArray(`${counter}`),\n toArray(\"|\"),\n ];\n\n if (dataString) {\n elements.push(\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"DATA\"),\n toArray(attestationHash),\n toArray(dataString),\n toArray(\"|\")\n );\n }\n\n return elements.flat();\n }\n\n /**\n * Verify that the identity challenge is signed by the address\n *\n * @param message Buffer, number[] or utf-8 string\n * @param address Bitcoin address of signee\n * @param signature Signature base64 string\n *\n * @return boolean\n */\n verifySignature(\n message: string | number[],\n address: string,\n signature: string\n ): boolean {\n // Convert message to number[]\n let msg: number[];\n if (Array.isArray(message)) {\n msg = message;\n } else if (Buffer.isBuffer(message)) {\n msg = [...message];\n } else {\n msg = toArray(message, \"utf8\");\n }\n\n const sig = Signature.fromCompact(signature, \"base64\");\n let publicKey: PublicKey | undefined;\n\n for (let recovery = 0; recovery < 4; recovery++) {\n try {\n publicKey = sig.RecoverPublicKey(\n recovery,\n new BigNumber(BSM.magicHash(msg))\n );\n const sigFitsPubkey = BSM.verify(msg, sig, publicKey);\n if (sigFitsPubkey && publicKey.toAddress() === address) {\n return true;\n }\n } catch {\n // try next recovery\n \n }\n }\n return false;\n }\n\n /**\n * Check whether the given transaction (BAP OP_RETURN) is valid, is signed and that the\n * identity signing is also valid at the time of signing\n *\n * @param idKey\n * @param address\n * @param challenge\n * @param signature\n *\n * @returns {Promise<boolean|*>}\n */\n async verifyChallengeSignature(\n idKey: string,\n address: string,\n challenge: string,\n signature: string\n ): Promise<boolean> {\n // first we test locally before sending to server\n const localVerification = this.verifySignature(\n challenge,\n address,\n signature\n );\n\n if (!localVerification) {\n return false;\n }\n\n try {\n const response = await this.getApiData<AttestationValidResponse>(\n \"/attestation/valid\",\n {\n idKey,\n address,\n challenge,\n signature,\n }\n );\n\n // Ensure we have a valid response with the expected structure\n if (response?.status === \"success\" && response?.result?.valid === true) {\n return true;\n }\n\n return false;\n } catch (error) {\n console.error(\"API call failed:\", error);\n return false;\n }\n }\n\n /**\n * Check whether the given transaction (BAP OP_RETURN) is valid, is signed and that the\n * identity signing is also valid at the time of signing\n *\n * @param tx\n * @returns {Promise<boolean|*>}\n */\n async isValidAttestationTransaction(\n tx: number[][]\n ): Promise<AttestationValidResponse | false> {\n if (this.verifyAttestationWithAIP(tx)) {\n return this.getApiData<AttestationValidResponse>(\"/attestation/valid\", {\n tx,\n });\n }\n return false;\n }\n\n /**\n * Get all signing keys for the given idKey\n *\n * @param address\n * @returns {Promise<*>}\n */\n async getIdentityFromAddress(\n address: string\n ): Promise<GetIdentityByAddressResponse> {\n return this.getApiData<GetIdentityByAddressResponse>(\n \"/identity/validByAddress\",\n {\n address,\n }\n );\n }\n\n /**\n * Get all signing keys for the given idKey\n *\n * @param idKey\n * @returns {Promise<*>}\n */\n async getIdentity(idKey: string): Promise<GetIdentityResponse> {\n return this.getApiData<GetIdentityResponse>(\"/identity/get\", {\n idKey,\n });\n }\n\n /**\n * Get all attestations for the given attestation hash\n *\n * @param attestationHash\n */\n async getAttestationsForHash(\n attestationHash: string\n ): Promise<GetAttestationResponse> {\n // get all BAP ATTEST records for the given attestationHash\n return this.getApiData<GetAttestationResponse>(\"/attestations\", {\n hash: attestationHash,\n });\n }\n\n /**\n * Export master BAP data in bitcoin-backup compatible format\n * Automatically handles both BIP32 and Type 42 modes\n * \n * @deprecated BIP32 format export (when initialized with xprv) is deprecated. \n * Use Type 42 initialization with { rootPk: wifKey } for new implementations.\n * \n * @param label Optional user-defined label\n * @param xprv Extended private key (BIP32 mode only - if not provided, the HDPrivateKey will be used)\n * @param mnemonic BIP39 mnemonic phrase (BIP32 mode only - optional)\n * @returns BapMasterBackup compatible object (format depends on key type)\n */\n exportForBackup(\n label?: string,\n xprv?: string,\n mnemonic?: string\n ): Type42MasterBackup | Bip32MasterBackup {\n const ids = this.exportIds(); // This returns encrypted string by default\n const baseBackup = {\n ids,\n ...(label && { label }),\n createdAt: new Date().toISOString(),\n };\n\n if (this.#isType42) {\n // Type 42 mode\n if (!this.#masterPrivateKey) {\n throw new Error(\"Type 42 parameters not initialized\");\n }\n return {\n ...baseBackup,\n rootPk: this.#masterPrivateKey.toWif(),\n };\n }\n // BIP32 mode\n if (!this.#HDPrivateKey) {\n throw new Error(\"HD private key not initialized\");\n }\n return {\n ...baseBackup,\n xprv: xprv || this.#HDPrivateKey.toString(),\n mnemonic: mnemonic || \"\",\n };\n }\n\n /**\n * Export a specific member ID in bitcoin-backup compatible format\n * @param idKey The key of the identity to export\n * @param label Optional user-defined label\n * @returns BapMemberBackup compatible object\n */\n exportMemberForBackup(\n idKey: string,\n label?: string\n ): {\n wif: string;\n id: string;\n label?: string;\n createdAt: string;\n } {\n const memberID = this.#ids[idKey];\n if (!memberID) {\n throw new Error(`Identity ${idKey} not found`);\n }\n\n // Get the member export and derive the WIF\n const memberExport = memberID.exportMember();\n\n return {\n wif: memberExport.wif,\n id: memberExport.encryptedData,\n ...(label && { label }),\n createdAt: new Date().toISOString(),\n };\n }\n}\n\nexport { MasterID, MemberID };\nexport type {\n Attestation,\n Identity,\n MemberIdentity,\n IdentityAttributes,\n PathPrefix,\n Type42Params,\n};\nexport * from \"./apiTypes\";\n",
5
+ "import {\n BSM,\n BigNumber,\n ECIES,\n HD,\n OP,\n type PublicKey,\n Signature,\n PrivateKey,\n} from \"@bsv/sdk\";\n\nimport { Utils as BSVUtils } from \"@bsv/sdk\";\nimport { type APIFetcher, apiFetcher } from \"./api\";\nimport type {\n AttestationValidResponse,\n GetAttestationResponse,\n GetIdentityByAddressResponse,\n GetIdentityResponse,\n} from \"./apiTypes\";\nimport {\n AIP_BITCOM_ADDRESS,\n BAP_BITCOM_ADDRESS,\n BAP_BITCOM_ADDRESS_HEX,\n BAP_SERVER,\n ENCRYPTION_PATH,\n} from \"./constants\";\nimport { MasterID } from \"./MasterID\";\nimport type {\n Attestation,\n Identity,\n IdentityAttributes,\n MemberIdentity,\n OldIdentity,\n PathPrefix,\n} from \"./interface\";\nimport { Utils } from \"./utils\";\nimport { MemberID } from \"./MemberID\";\nconst { toArray, toUTF8, toBase64, toHex } = BSVUtils;\nconst { electrumEncrypt, electrumDecrypt } = ECIES;\n\ntype Identities = { lastIdPath: string; ids: Identity[] };\n\n/** Backup format for Type 42 mode (rootPk-based) */\nexport interface Type42MasterBackup {\n ids: string;\n rootPk: string;\n mnemonic?: string;\n label?: string;\n createdAt: string;\n}\n\n/** Backup format for BIP32 mode (xprv-based, legacy) */\nexport interface Bip32MasterBackup {\n ids: string;\n xprv: string;\n mnemonic?: string;\n label?: string;\n createdAt: string;\n}\n\n// Type 42 parameters\ninterface Type42Params {\n rootPk: string; // WIF format private key\n}\n\n/**\n * BAP class\n *\n * Creates an instance of the BAP class and uses the given HDPrivateKey for all BAP operations.\n * Supports both BIP32 (HD) and Type 42 key derivation methods.\n *\n * @deprecated When initializing with a string (xprv), the BIP32 format is used which is deprecated \n * for new implementations. Use Type 42 initialization with { rootPk: wifKey } instead.\n * \n * @param keySource Either an HDPrivateKey string (xprv) for BIP32 or Type42Params for Type 42\n */\nexport class BAP {\n #HDPrivateKey: HD | undefined;\n #masterPrivateKey: PrivateKey | undefined;\n #isType42: boolean;\n #ids: { [key: string]: MasterID } = {};\n #BAP_SERVER = BAP_SERVER;\n #BAP_TOKEN = \"\";\n #lastIdPath = \"\";\n #identityCounter = 0;\n getApiData: APIFetcher;\n\n constructor(keySource: string | Type42Params, token = \"\", server = \"\") {\n if (!keySource) {\n throw new Error(\"No key source given\");\n }\n\n // Determine if we're using Type 42 or BIP32\n if (typeof keySource === \"string\") {\n // BIP32 mode\n this.#HDPrivateKey = HD.fromString(keySource);\n this.#isType42 = false;\n } else {\n // Type 42 mode\n this.#masterPrivateKey = PrivateKey.fromWif(keySource.rootPk);\n this.#isType42 = true;\n }\n\n if (token) {\n this.#BAP_TOKEN = token;\n }\n\n if (server) {\n this.#BAP_SERVER = server;\n }\n\n this.getApiData = apiFetcher(this.#BAP_SERVER, this.#BAP_TOKEN);\n }\n\n get lastIdPath(): string {\n return this.#lastIdPath;\n }\n\n /**\n * Get the public key of the given childPath, or of the current HDPrivateKey of childPath is empty\n *\n * @param childPath Full derivation path for this child (BIP32) or invoice number (Type 42)\n * @returns {*}\n */\n getPublicKey(childPath = \"\"): string {\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n if (childPath) {\n // In Type 42, we use the path as an invoice number\n const derivedKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n childPath\n );\n return derivedKey.toPublicKey().toString();\n }\n return this.#masterPrivateKey.toPublicKey().toString();\n }\n \n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n if (childPath) {\n return this.#HDPrivateKey.derive(childPath).pubKey.toString();\n }\n return this.#HDPrivateKey.pubKey.toString();\n }\n\n /**\n * Get the HD public key of the given childPath (BIP32 only)\n *\n * @param childPath Full derivation path for this child\n * @returns {*}\n */\n getHdPublicKey(childPath = \"\"): string {\n if (this.#isType42) {\n throw new Error(\"HD public keys are not available in Type 42 mode\");\n }\n \n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n if (childPath) {\n return this.#HDPrivateKey.derive(childPath).toPublic().toString();\n }\n return this.#HDPrivateKey.toPublic().toString();\n }\n\n set BAP_SERVER(bapServer) {\n this.#BAP_SERVER = bapServer;\n for (const key in this.#ids) {\n this.#ids[key].BAP_SERVER = bapServer;\n }\n }\n\n get BAP_SERVER(): string {\n return this.#BAP_SERVER;\n }\n\n set BAP_TOKEN(token) {\n this.#BAP_TOKEN = token;\n for (const key in this.#ids) {\n // @ts-ignore - does not recognize private fields that can be set\n this.#ids[key].BAP_TOKEN = token;\n }\n }\n\n get BAP_TOKEN(): string {\n return this.#BAP_TOKEN;\n }\n\n /**\n * This function verifies that the given bapId matches the given root address\n * This is used as a data integrity check\n *\n * @param bapId MasterID instance\n */\n checkIdBelongs(bapId: MasterID): boolean {\n let checkRootAddress: string;\n \n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // In Type 42, we derive using the path as invoice number\n const derivedKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n bapId.rootPath\n );\n checkRootAddress = derivedKey.toPublicKey().toAddress();\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const derivedChild = this.#HDPrivateKey.derive(bapId.rootPath);\n checkRootAddress = derivedChild.pubKey.toAddress();\n }\n \n if (checkRootAddress !== bapId.rootAddress) {\n throw new Error(\"ID does not belong to this private key\");\n }\n\n return true;\n }\n\n /**\n * Returns a list of all the identity keys that are stored in this instance\n *\n * @returns {string[]}\n */\n listIds(): string[] {\n return Object.keys(this.#ids);\n }\n\n /**\n * Create a new Id and link it to this BAP instance\n *\n * For Type 42 mode, uses simple counter for derivation: bap:{counter}\n * For BIP32 mode (legacy), uses traditional HD paths or provided customPath\n *\n * New signature: newId(idName, customPath?, identityAttributes?, idSeed?)\n * Legacy signature: newId(path?, identityAttributes?, idSeed?) - for backward compatibility\n *\n * @param idNameOrPath The human-readable name for this identity OR legacy path parameter\n * @param customPathOrAttributes Optional custom derivation path OR legacy identityAttributes\n * @param identityAttributes Optional identity attributes\n * @param idSeed Optional seed for deterministic key generation\n * @returns {MasterID} The created identity\n */\n newId(\n idNameOrPath?: string | IdentityAttributes,\n customPathOrAttributes?: string | IdentityAttributes,\n identityAttributes: IdentityAttributes = {},\n idSeed = \"\"\n ): MasterID {\n // Handle backward compatibility - detect old vs new signature\n let idName: string;\n let customPath: string | undefined;\n let finalAttributes: IdentityAttributes;\n \n if (typeof idNameOrPath === 'object' || idNameOrPath === undefined || \n (typeof idNameOrPath === 'string' && idNameOrPath.startsWith('/'))) {\n // Legacy signature: newId(path?, identityAttributes?, idSeed?)\n // First param is path (undefined, starts with '/') or identityAttributes (object)\n customPath = typeof idNameOrPath === 'string' ? idNameOrPath : undefined;\n finalAttributes = (typeof idNameOrPath === 'object' ? idNameOrPath : \n typeof customPathOrAttributes === 'object' ? customPathOrAttributes : {});\n idName = \"Default Identity\";\n } else {\n // New signature: newId(idName, customPath?, identityAttributes?, idSeed?)\n idName = idNameOrPath;\n customPath = typeof customPathOrAttributes === 'string' ? customPathOrAttributes : undefined;\n finalAttributes = typeof customPathOrAttributes === 'object' ? customPathOrAttributes : identityAttributes;\n }\n let pathToUse: string;\n \n if (customPath) {\n // Use provided custom path\n pathToUse = customPath;\n } else if (this.#isType42) {\n // Type 42: Use simple counter for discovery - name is just UX\n pathToUse = `bap:${this.#identityCounter}`;\n this.#identityCounter++;\n } else {\n // BIP32: Use traditional HD path\n pathToUse = this.getNextValidPath();\n }\n\n let newIdentity: MasterID;\n if (this.#isType42) {\n if (!this.#masterPrivateKey) {\n throw new Error(\"Type 42 parameters not initialized\");\n }\n // For Type 42, pass the key source object\n newIdentity = new MasterID(\n {\n rootPk: this.#masterPrivateKey\n },\n finalAttributes,\n idSeed\n );\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n newIdentity = new MasterID(\n this.#HDPrivateKey,\n finalAttributes,\n idSeed\n );\n }\n \n newIdentity.BAP_SERVER = this.#BAP_SERVER;\n newIdentity.BAP_TOKEN = this.#BAP_TOKEN;\n newIdentity.idName = idName;\n newIdentity.rootPath = pathToUse;\n \n // Set current path based on mode\n if (this.#isType42) {\n // For Type 42, current path is same as root path (invoice number)\n newIdentity.currentPath = pathToUse;\n } else {\n // For BIP32, calculate next path\n newIdentity.currentPath = Utils.getNextPath(pathToUse);\n }\n\n const idKey = newIdentity.getIdentityKey();\n this.#ids[idKey] = newIdentity;\n this.#lastIdPath = pathToUse;\n\n return this.#ids[idKey];\n }\n\n /**\n * Remove identity\n *\n * @param idKey\n * @returns {*}\n */\n removeId(idKey: string): void {\n delete this.#ids[idKey];\n }\n\n /**\n * Get the next valid path for the used HDPrivateKey and loaded #ids\n *\n * @returns {string}\n */\n getNextValidPath(): PathPrefix {\n // prefer hardened paths\n if (this.#lastIdPath) {\n return Utils.getNextIdentityPath(this.#lastIdPath);\n }\n\n return `/0'/${Object.keys(this.#ids).length}'/0'`;\n }\n\n /**\n * Create an identity with a specific counter value (useful for discovery)\n * Only works in Type 42 mode\n *\n * @param counter The specific counter value to use\n * @param idName Optional name for the identity\n * @returns {MasterID} The created identity\n */\n newIdWithCounter(\n counter: number,\n idName = `Identity ${counter}`\n ): MasterID {\n if (!this.#isType42) {\n throw new Error(\"newIdWithCounter only works in Type 42 mode\");\n }\n \n const customPath = `bap:${counter}`;\n return this.newId(idName, customPath);\n }\n\n /**\n * Get a certain Id\n *\n * @param identityKey\n * @returns {null}\n */\n getId(identityKey: string): MasterID | null {\n return this.#ids[identityKey] || null;\n }\n\n /**\n * This function is used when manipulating ID's, adding or removing attributes etc\n * First create an id through this class and then use getId to get it. Then you can add/edit or\n * increment the signing path and then re-set it with this function.\n *\n * Note: when you getId() from this class, you will be working on the same object as this class\n * has and any changes made will be propagated to the id in this class. When you call exportIds\n * your new changes will also be included, without having to setId().\n *\n * @param bapId\n */\n setId(bapId: MasterID): void {\n this.checkIdBelongs(bapId);\n this.#ids[bapId.getIdentityKey()] = bapId;\n }\n\n /**\n * This function is used to import IDs and attributes from some external storage\n *\n * The ID information should NOT be stored together with the HD private key !\n *\n * @param idData Array of ids that have been exported\n * @param encrypted Whether the data should be treated as being encrypted (default true)\n */\n importIds(idData: Identities | string, encrypted = true): void {\n if (encrypted && typeof idData === \"string\") {\n this.importEncryptedIds(idData);\n return;\n }\n const identity = idData as Identities;\n if (!identity.lastIdPath) {\n throw new Error(\"ID cannot be imported as it is not complete\");\n }\n\n if (!identity.ids) {\n throw new Error(`ID data is not in the correct format: ${idData}`);\n }\n\n let lastIdPath = (idData as Identities).lastIdPath;\n for (const id of identity.ids) {\n if (!id.identityKey || !id.identityAttributes || !id.rootAddress) {\n throw new Error(\"ID cannot be imported as it is not complete\");\n }\n \n let importId: MasterID;\n if (this.#isType42) {\n if (!this.#masterPrivateKey) {\n throw new Error(\"Type 42 parameters not initialized\");\n }\n importId = new MasterID(\n {\n rootPk: this.#masterPrivateKey\n },\n {},\n id.idSeed\n );\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n importId = new MasterID(this.#HDPrivateKey, {}, id.idSeed);\n }\n \n importId.BAP_SERVER = this.#BAP_SERVER;\n importId.BAP_TOKEN = this.#BAP_TOKEN;\n importId.import(id);\n if (lastIdPath === \"\") {\n lastIdPath = importId.currentPath;\n }\n\n this.checkIdBelongs(importId);\n this.#ids[importId.getIdentityKey()] = importId;\n \n // For Type 42, update identity counter based on imported paths\n if (this.#isType42 && importId.rootPath.startsWith('bap:')) {\n const pathParts = importId.rootPath.split(':');\n if (pathParts.length >= 2) {\n const counter = Number.parseInt(pathParts[1], 10);\n if (!Number.isNaN(counter)) {\n this.#identityCounter = Math.max(this.#identityCounter, counter + 1);\n }\n }\n }\n }\n\n this.#lastIdPath = lastIdPath;\n }\n\n importEncryptedIds(idData: string): void {\n // decrypt the ids array using ECIES\n const decrypted = this.decrypt(idData);\n const ids = JSON.parse(decrypted) as Identities;\n\n const isOldFormat = Array.isArray(ids);\n if (isOldFormat) {\n console.log(\"Importing old format:\\n\", ids);\n this.importOldIds(ids);\n return;\n }\n if (typeof ids !== \"object\") {\n throw new Error(\"decrypted, but found unrecognized identities format\");\n }\n this.importIds(ids, false);\n }\n\n importOldIds(idData: OldIdentity[]): void {\n for (const id of idData) {\n let importId: MasterID;\n if (this.#isType42) {\n if (!this.#masterPrivateKey) {\n throw new Error(\"Type 42 parameters not initialized\");\n }\n importId = new MasterID(\n {\n rootPk: this.#masterPrivateKey\n },\n {},\n id.idSeed ?? \"\"\n );\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n importId = new MasterID(this.#HDPrivateKey, {}, id.idSeed ?? \"\");\n }\n \n importId.BAP_SERVER = this.#BAP_SERVER;\n importId.BAP_TOKEN = this.#BAP_TOKEN;\n importId.import(id);\n\n this.checkIdBelongs(importId);\n this.#ids[importId.getIdentityKey()] = importId;\n this.#lastIdPath = importId.currentPath;\n }\n }\n\n /**\n * Export identities. If no idKeys are provided, exports all identities.\n * @param idKeys Optional array of identity keys to export. If omitted, exports all identities.\n * @param encrypted Whether to encrypt the export data\n */\n // Overload signatures\n exportIds(idKeys?: string[], encrypted?: true): string;\n exportIds(idKeys: string[] | undefined, encrypted: false): Identities;\n exportIds(idKeys?: string[], encrypted = true): Identities | string {\n const idData: Identities = {\n lastIdPath: this.#lastIdPath,\n ids: [] as Identity[],\n };\n\n const keysToExport = idKeys || Object.keys(this.#ids);\n\n for (const key of keysToExport) {\n if (!this.#ids[key]) {\n throw new Error(`Identity ${key} not found`);\n }\n idData.ids.push(this.#ids[key].export());\n }\n\n if (encrypted) {\n return this.encrypt(JSON.stringify(idData));\n }\n return idData;\n }\n\n /**\n * Export a given ID from this instance for external storage\n *\n * By default this function will encrypt the data, using a derivative child of the main HD key\n *\n * @param idKey The key of the identity to export\n * @param encrypted Whether the data should be encrypted (default true)\n * @returns {[]|*}\n */\n // Overload signatures\n exportId(idKey: string, encrypted?: true): string;\n exportId(idKey: string, encrypted: false): Identities;\n exportId(idKey: string, encrypted = true): Identities | string {\n const idData: Identities = {\n lastIdPath: this.#lastIdPath,\n ids: [] as Identity[],\n };\n\n idData.ids.push(this.#ids[idKey].export());\n\n if (encrypted) {\n return this.encrypt(JSON.stringify(idData));\n }\n\n return idData;\n }\n\n /**\n * Encrypt a string of data\n *\n * @param string\n * @returns {string}\n */\n encrypt(string: string): string {\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // For Type 42, we use the encryption path as an invoice number\n const encryptionKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n ENCRYPTION_PATH\n );\n return toBase64(\n // @ts-ignore - you can remove the null when this is merged https://github.com/bitcoin-sv/ts-sdk/pull/123\n electrumEncrypt(toArray(string), encryptionKey.toPublicKey(), null)\n );\n }\n \n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const derivedChild = this.#HDPrivateKey.derive(ENCRYPTION_PATH);\n return toBase64(\n // @ts-ignore - you can remove the null when this is merged https://github.com/bitcoin-sv/ts-sdk/pull/123\n electrumEncrypt(toArray(string), derivedChild.pubKey, null)\n );\n }\n\n /**\n * Decrypt a string of data\n *\n * @param string\n * @returns {string}\n */\n decrypt(string: string): string {\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // For Type 42, we use the encryption path as an invoice number\n const encryptionKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n ENCRYPTION_PATH\n );\n return toUTF8(\n electrumDecrypt(toArray(string, \"base64\"), encryptionKey)\n );\n }\n \n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const derivedChild = this.#HDPrivateKey.derive(ENCRYPTION_PATH);\n return toUTF8(\n electrumDecrypt(toArray(string, \"base64\"), derivedChild.privKey)\n );\n }\n\n /**\n * Sign an attestation for a user\n *\n * @param attestationHash The computed attestation hash for the user - this should be calculated with the MasterID class for an identity for the user\n * @param identityKey The identity key we are using for the signing\n * @param counter\n * @param dataString Optional data string that will be appended to the BAP attestation\n * @returns {string[]}\n */\n signAttestationWithAIP(\n attestationHash: string,\n identityKey: string,\n counter = 0,\n dataString = \"\"\n ) {\n const id = this.getId(identityKey);\n if (!id) {\n throw new Error(\"Could not find identity to attest with\");\n }\n\n const attestationBuffer = this.getAttestationBuffer(\n attestationHash,\n counter,\n dataString\n );\n const { address, signature } = id.signMessage(attestationBuffer);\n\n return this.createAttestationTransaction(\n attestationHash,\n counter,\n address,\n signature,\n dataString\n );\n }\n\n /**\n * Verify an AIP signed attestation for a user\n *\n * [\n * '0x6a',\n * '0x31424150537561506e66476e53424d33474c56397968785564596534764762644d54',\n * '0x415454455354',\n * '0x33656166366361396334313936356538353831366439336439643034333136393032376633396661623034386333633031333663343364663635376462383761',\n * '0x30',\n * '0x7c',\n * '0x313550636948473232534e4c514a584d6f5355615756693757537163376843667661',\n * '0x424954434f494e5f4543445341',\n * '0x31477531796d52567a595557634638776f6f506a7a4a4c764d383550795a64655876',\n * '0x20ef60c5555001ddb1039bb0f215e46571fcb39ee46f48b089d1c08b0304dbcb3366d8fdf8bafd82be24b5ac42dcd6a5e96c90705dd42e3ad918b1b47ac3ce6ac2'\n * ]\n *\n * @param tx Array of hex values for the OP_RETURN values\n * @returns {{}}\n */\n verifyAttestationWithAIP(tx: number[][]): Attestation {\n if (\n !tx.every((t) => Array.isArray(t)) ||\n tx[0][0] !== OP.OP_RETURN ||\n toHex(tx[1]) !== BAP_BITCOM_ADDRESS_HEX\n ) {\n throw new Error(\"Not a valid BAP transaction\");\n }\n const dataOffset = toHex(tx[7]) === \"44415441\" ? 5 : 0; // DATA\n const attestation: Attestation = {\n type: toUTF8(tx[2]),\n hash: toHex(tx[3]),\n sequence: toUTF8(tx[4]),\n signingProtocol: toUTF8(tx[7 + dataOffset]),\n signingAddress: toUTF8(tx[8 + dataOffset]),\n signature: toBase64(tx[9 + dataOffset]),\n };\n\n if (dataOffset && tx[3] === tx[8]) {\n // valid data addition\n attestation.data = toHex(tx[9]);\n }\n\n console.log({ attestation });\n\n try {\n const signatureBufferStatements: number[][] = [];\n for (let i = 0; i < 6 + dataOffset; i++) {\n signatureBufferStatements.push(tx[i]);\n }\n // const attestationBuffer = Buffer.concat(signatureBufferStatements as unknown as Uint8Array[]);\n attestation.verified = this.verifySignature(\n signatureBufferStatements.flat(),\n attestation.signingAddress,\n attestation.signature\n );\n } catch {\n attestation.verified = false;\n }\n\n return attestation;\n }\n\n /**\n * For BAP attestations we use all fields for the attestation\n *\n * @param attestationHash\n * @param counter\n * @param address\n * @param signature\n * @param dataString Optional data string that will be appended to the BAP attestation\n * @returns {number[]}\n */\n createAttestationTransaction(\n attestationHash: string,\n counter: number,\n address: string,\n signature: string,\n dataString = \"\"\n ): number[][] {\n const elements: number[][] = [\n [OP.OP_RETURN],\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"ATTEST\"),\n toArray(attestationHash),\n toArray(`${counter}`),\n toArray(\"|\"),\n ];\n\n if (dataString) {\n // data should be a string, either encrypted or stringified JSON if applicable\n elements.push(\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"DATA\"),\n toArray(attestationHash),\n toArray(dataString),\n toArray(\"|\")\n );\n }\n\n elements.push(\n toArray(AIP_BITCOM_ADDRESS),\n toArray(\"BITCOIN_ECDSA\"),\n toArray(address),\n toArray(signature, \"base64\")\n );\n\n console.log({ elements });\n return elements;\n }\n\n /**\n * This is a re-creation of how the bitcoinfiles-sdk creates a hash to sign for AIP\n *\n * @param attestationHash\n * @param counter\n * @param dataString Optional data string\n * @returns {number[]}\n */\n getAttestationBuffer(\n attestationHash: string,\n counter = 0,\n dataString = \"\"\n ): number[] {\n // re-create how AIP creates the buffer to sign\n const elements = [\n [OP.OP_RETURN],\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"ATTEST\"),\n toArray(attestationHash),\n toArray(`${counter}`),\n toArray(\"|\"),\n ];\n\n if (dataString) {\n elements.push(\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"DATA\"),\n toArray(attestationHash),\n toArray(dataString),\n toArray(\"|\")\n );\n }\n\n return elements.flat();\n }\n\n /**\n * Verify that the identity challenge is signed by the address\n *\n * @param message Buffer, number[] or utf-8 string\n * @param address Bitcoin address of signee\n * @param signature Signature base64 string\n *\n * @return boolean\n */\n verifySignature(\n message: string | number[],\n address: string,\n signature: string\n ): boolean {\n // Convert message to number[]\n let msg: number[];\n if (Array.isArray(message)) {\n msg = message;\n } else if (Buffer.isBuffer(message)) {\n msg = [...message];\n } else {\n msg = toArray(message, \"utf8\");\n }\n\n const sig = Signature.fromCompact(signature, \"base64\");\n let publicKey: PublicKey | undefined;\n\n for (let recovery = 0; recovery < 4; recovery++) {\n try {\n publicKey = sig.RecoverPublicKey(\n recovery,\n new BigNumber(BSM.magicHash(msg))\n );\n const sigFitsPubkey = BSM.verify(msg, sig, publicKey);\n if (sigFitsPubkey && publicKey.toAddress() === address) {\n return true;\n }\n } catch {\n // try next recovery\n \n }\n }\n return false;\n }\n\n /**\n * Check whether the given transaction (BAP OP_RETURN) is valid, is signed and that the\n * identity signing is also valid at the time of signing\n *\n * @param idKey\n * @param address\n * @param challenge\n * @param signature\n *\n * @returns {Promise<boolean|*>}\n */\n async verifyChallengeSignature(\n idKey: string,\n address: string,\n challenge: string,\n signature: string\n ): Promise<boolean> {\n // first we test locally before sending to server\n const localVerification = this.verifySignature(\n challenge,\n address,\n signature\n );\n\n if (!localVerification) {\n return false;\n }\n\n try {\n const response = await this.getApiData<AttestationValidResponse>(\n \"/attestation/valid\",\n {\n idKey,\n address,\n challenge,\n signature,\n }\n );\n\n // Ensure we have a valid response with the expected structure\n if (response?.status === \"success\" && response?.result?.valid === true) {\n return true;\n }\n\n return false;\n } catch (error) {\n console.error(\"API call failed:\", error);\n return false;\n }\n }\n\n /**\n * Check whether the given transaction (BAP OP_RETURN) is valid, is signed and that the\n * identity signing is also valid at the time of signing\n *\n * @param tx\n * @returns {Promise<boolean|*>}\n */\n async isValidAttestationTransaction(\n tx: number[][]\n ): Promise<AttestationValidResponse | false> {\n if (this.verifyAttestationWithAIP(tx)) {\n return this.getApiData<AttestationValidResponse>(\"/attestation/valid\", {\n tx,\n });\n }\n return false;\n }\n\n /**\n * Get all signing keys for the given idKey\n *\n * @param address\n * @returns {Promise<*>}\n */\n async getIdentityFromAddress(\n address: string\n ): Promise<GetIdentityByAddressResponse> {\n return this.getApiData<GetIdentityByAddressResponse>(\n \"/identity/validByAddress\",\n {\n address,\n }\n );\n }\n\n /**\n * Get all signing keys for the given idKey\n *\n * @param idKey\n * @returns {Promise<*>}\n */\n async getIdentity(idKey: string): Promise<GetIdentityResponse> {\n return this.getApiData<GetIdentityResponse>(\"/identity/get\", {\n idKey,\n });\n }\n\n /**\n * Get all attestations for the given attestation hash\n *\n * @param attestationHash\n */\n async getAttestationsForHash(\n attestationHash: string\n ): Promise<GetAttestationResponse> {\n // get all BAP ATTEST records for the given attestationHash\n return this.getApiData<GetAttestationResponse>(\"/attestations\", {\n hash: attestationHash,\n });\n }\n\n /**\n * Export master BAP data in bitcoin-backup compatible format\n * Automatically handles both BIP32 and Type 42 modes\n * \n * @deprecated BIP32 format export (when initialized with xprv) is deprecated. \n * Use Type 42 initialization with { rootPk: wifKey } for new implementations.\n * \n * @param label Optional user-defined label\n * @param xprv Extended private key (BIP32 mode only - if not provided, the HDPrivateKey will be used)\n * @param mnemonic BIP39 mnemonic phrase (BIP32 mode only - optional)\n * @returns BapMasterBackup compatible object (format depends on key type)\n */\n exportForBackup(\n label?: string,\n xprv?: string,\n mnemonic?: string\n ): Type42MasterBackup | Bip32MasterBackup {\n const ids = this.exportIds(); // This returns encrypted string by default\n const baseBackup = {\n ids,\n ...(label && { label }),\n createdAt: new Date().toISOString(),\n };\n\n if (this.#isType42) {\n // Type 42 mode\n if (!this.#masterPrivateKey) {\n throw new Error(\"Type 42 parameters not initialized\");\n }\n return {\n ...baseBackup,\n rootPk: this.#masterPrivateKey.toWif(),\n };\n }\n // BIP32 mode\n if (!this.#HDPrivateKey) {\n throw new Error(\"HD private key not initialized\");\n }\n return {\n ...baseBackup,\n xprv: xprv || this.#HDPrivateKey.toString(),\n mnemonic: mnemonic || \"\",\n };\n }\n\n /**\n * Export a specific member ID in bitcoin-backup compatible format\n * @param idKey The key of the identity to export\n * @param label Optional user-defined label\n * @returns BapMemberBackup compatible object\n */\n exportMemberForBackup(\n idKey: string,\n label?: string\n ): {\n wif: string;\n id: string;\n label?: string;\n createdAt: string;\n } {\n const memberID = this.#ids[idKey];\n if (!memberID) {\n throw new Error(`Identity ${idKey} not found`);\n }\n\n // Get the member export and derive the WIF\n const memberExport = memberID.exportMember();\n\n return {\n wif: memberExport.wif,\n id: memberExport.encryptedData,\n ...(label && { label }),\n createdAt: new Date().toISOString(),\n };\n }\n}\n\nexport { MasterID, MemberID };\nexport { bapIdFromAddress, bapIdFromPubkey } from \"./utils\";\nexport type {\n Attestation,\n Identity,\n MemberIdentity,\n IdentityAttributes,\n PathPrefix,\n Type42Params,\n};\nexport * from \"./apiTypes\";\n",
6
6
  "/**\n * Helper function to get attestation from a BAP API server\n *\n * @param apiUrl\n * @param apiData\n * @returns {Promise<any>}\n */\nexport const getApiData = async <T>(\n apiUrl: string,\n apiData: unknown,\n server: string,\n token: string\n): Promise<T> => {\n const url = `${server}${apiUrl}`;\n const response = await fetch(url, {\n method: \"post\",\n headers: {\n \"Content-type\": \"application/json; charset=utf-8\",\n token,\n format: \"json\",\n },\n body: JSON.stringify(apiData),\n });\n\n return response.json();\n};\n\nexport type APIFetcher = <T>(url: string, data: unknown) => Promise<T>;\n\nexport const apiFetcher =\n (host: string, token: string): APIFetcher =>\n async <T>(url: string, data: unknown): Promise<T> => {\n return getApiData<T>(url, data, host, token);\n };\n",
7
7
  "import { Utils } from \"@bsv/sdk\";\nconst { toHex, toArray } = Utils;\n\nexport const BAP_BITCOM_ADDRESS = \"1BAPSuaPnfGnSBM3GLV9yhxUdYe4vGbdMT\";\nexport const BAP_BITCOM_ADDRESS_HEX = toHex(toArray(BAP_BITCOM_ADDRESS));\nexport const AIP_BITCOM_ADDRESS = \"15PciHG22SNLQJXMoSUaWVi7WSqc7hCfva\";\nexport const AIP_BITCOM_ADDRESS_HEX = toHex(toArray(AIP_BITCOM_ADDRESS));\nexport const BAP_SERVER = \"https://api.sigmaidentity.com/v1\";\nexport const MAX_INT = 2147483648 - 1; // 0x80000000\n\n// This is just a choice for this library and could be anything else if so needed/wanted\n// but it is advisable to use the same derivation between libraries for compatibility\nexport const SIGNING_PATH_PREFIX = \"m/424150'/0'/0'\"; // BAP in hex\nexport const ENCRYPTION_PATH = `m/424150'/${MAX_INT}'/${MAX_INT}'`;\n\n// BAP identity signing key derivation constants\n// Uses Type 42 (BRC-42) derivation pattern: invoiceNumber = `${securityLevel}-${protocolName}-${keyID}`\nexport const BAP_PROTOCOL_ID: [1, string] = [1, \"bap\"];\nexport const BAP_KEY_ID = \"identity\";\nexport const BAP_INVOICE_NUMBER = \"1-bap-identity\"; // Pre-computed for Type42 deriveChild\n\n// Friend encryption key derivation constants\n// Security level 2: counterparty-specific keys requiring user approval\n// Format: `2-friend-${sha256(friendBapId)}`\nexport const FRIEND_SECURITY_LEVEL = 2;\nexport const FRIEND_PROTOCOL = \"friend\";\n",
8
- "import {\n Utils as BSVUtils,\n ECIES,\n Hash,\n PublicKey,\n type PrivateKey,\n HD,\n} from \"@bsv/sdk\";\n\nimport { type APIFetcher, apiFetcher } from \"./api\";\nimport type {\n GetAttestationResponse,\n GetSigningKeysResponse,\n} from \"./apiTypes\";\nimport {\n BAP_BITCOM_ADDRESS,\n BAP_SERVER,\n ENCRYPTION_PATH,\n MAX_INT,\n SIGNING_PATH_PREFIX,\n BAP_INVOICE_NUMBER,\n} from \"./constants\";\nimport type {\n Identity,\n IdentityAttributes,\n OldIdentity,\n MemberIdentity,\n} from \"./interface\";\nimport { Utils } from \"./utils\";\nimport { MemberID } from \"./MemberID\";\nimport { BaseClass } from \"./BaseClass\";\nconst { toArray, toHex, toBase58, toUTF8, toBase64 } = BSVUtils;\nconst { electrumDecrypt, electrumEncrypt } = ECIES;\n\n// Type 42 key source\ninterface Type42KeySource {\n rootPk: PrivateKey;\n}\n\n/**\n * MasterID class\n *\n * This class should be used in conjunction with the BAP class\n * Supports both BIP32 (HD) and Type 42 key derivation\n *\n * @type {MasterID}\n */\nclass MasterID extends BaseClass {\n #HDPrivateKey: HD | undefined;\n #masterPrivateKey: PrivateKey | undefined;\n #isType42: boolean;\n #BAP_SERVER: string = BAP_SERVER;\n #BAP_TOKEN = \"\";\n #rootPath: string;\n #previousPath: string;\n #currentPath: string;\n #idSeed: string;\n\n idName: string;\n description: string;\n\n rootAddress: string;\n identityKey: string;\n identityAttributes: IdentityAttributes;\n\n getApiData: APIFetcher;\n\n constructor(\n keySource: HD | Type42KeySource,\n identityAttributes: IdentityAttributes = {},\n idSeed = \"\"\n ) {\n super();\n\n // Determine if we're using Type 42 or BIP32\n if (keySource instanceof HD) {\n // BIP32 mode\n this.#isType42 = false;\n if (idSeed) {\n // create a new HDPrivateKey based on the seed\n const seedHex = toHex(Hash.sha256(idSeed, \"utf8\"));\n const seedPath = Utils.getSigningPathFromHex(seedHex);\n this.#HDPrivateKey = keySource.derive(seedPath);\n } else {\n this.#HDPrivateKey = keySource;\n }\n } else {\n // Type 42 mode\n this.#isType42 = true;\n this.#masterPrivateKey = keySource.rootPk;\n \n if (idSeed) {\n // For Type 42 with seed, we derive a new master key using the seed as invoice number\n const seedHex = toHex(Hash.sha256(idSeed, \"utf8\"));\n this.#masterPrivateKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n seedHex\n );\n }\n }\n\n this.#idSeed = idSeed;\n this.idName = \"ID 1\";\n this.description = \"\";\n\n this.#rootPath = `${SIGNING_PATH_PREFIX}/0/0/0`;\n this.#previousPath = `${SIGNING_PATH_PREFIX}/0/0/0`;\n this.#currentPath = `${SIGNING_PATH_PREFIX}/0/0/1`;\n\n // Derive root address based on mode\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // In Type 42, we use the path as invoice number\n const rootKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n this.#rootPath\n );\n this.rootAddress = rootKey.toPublicKey().toAddress();\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const rootChild = this.#HDPrivateKey.derive(this.#rootPath);\n this.rootAddress = rootChild.privKey.toPublicKey().toAddress();\n }\n \n this.identityKey = this.deriveIdentityKey(this.rootAddress);\n\n // unlink the object\n const attributes = { ...identityAttributes };\n this.identityAttributes = this.parseAttributes(attributes);\n\n this.getApiData = apiFetcher(this.#BAP_SERVER, this.#BAP_TOKEN);\n }\n\n set BAP_SERVER(bapServer) {\n this.#BAP_SERVER = bapServer;\n }\n\n get BAP_SERVER(): string {\n return this.#BAP_SERVER;\n }\n\n set BAP_TOKEN(token) {\n this.#BAP_TOKEN = token;\n }\n\n get BAP_TOKEN(): string {\n return this.#BAP_TOKEN;\n }\n\n deriveIdentityKey(address: string): string {\n // base58( ripemd160 ( sha256 ( rootAddress ) ) )\n const rootAddressHash = toHex(Hash.sha256(address, \"utf8\"));\n return toBase58(Hash.ripemd160(rootAddressHash, \"hex\"));\n }\n\n /**\n * Helper function to parse identity attributes\n *\n * @param identityAttributes\n * @returns {{}}\n */\n parseAttributes(\n identityAttributes: IdentityAttributes | string\n ): IdentityAttributes {\n if (typeof identityAttributes === \"string\") {\n return this.parseStringUrns(identityAttributes);\n }\n\n for (const key in identityAttributes) {\n if (!identityAttributes[key].value || !identityAttributes[key].nonce) {\n throw new Error(\"Invalid identity attribute\");\n }\n }\n\n return identityAttributes || {};\n }\n\n /**\n * Parse a text of urn string into identity attributes\n *\n * urn:bap:id:name:John Doe:e2c6fb4063cc04af58935737eaffc938011dff546d47b7fbb18ed346f8c4d4fa\n * urn:bap:id:birthday:1990-05-22:e61f23cbbb2284842d77965e2b0e32f0ca890b1894ca4ce652831347ee3596d9\n * urn:bap:id:over18:1:480ca17ccaacd671b28dc811332525f2f2cd594d8e8e7825de515ce5d52d30e8\n *\n * @param urnIdentityAttributes\n */\n parseStringUrns(urnIdentityAttributes: string): IdentityAttributes {\n const identityAttributes: IdentityAttributes = {};\n // avoid forEach\n\n const attributesRaw = urnIdentityAttributes\n .replace(/^\\s+/g, \"\")\n .replace(/\\r/gm, \"\")\n .split(\"\\n\");\n\n for (const line of attributesRaw) {\n // remove any whitespace from the string (trim)\n const attribute = line.replace(/^\\s+/g, \"\").replace(/\\s+$/g, \"\");\n const urn = attribute.split(\":\");\n if (\n urn[0] === \"urn\" &&\n urn[1] === \"bap\" &&\n urn[2] === \"id\" &&\n urn[3] &&\n urn[4] &&\n urn[5]\n ) {\n identityAttributes[urn[3]] = {\n value: urn[4],\n nonce: urn[5],\n };\n }\n }\n\n return identityAttributes;\n }\n\n /**\n * Returns the identity key\n *\n * @returns {*|string}\n */\n getIdentityKey(): string {\n return this.identityKey;\n }\n\n /**\n * This should be called with the last part of the signing path (/.../.../...)\n * This library assumes the first part is m/424150'/0'/0' as defined at the top of this file\n *\n * @param path The second path of the signing path in the format [0-9]{0,9}/[0-9]{0,9}/[0-9]{0,9}\n */\n set rootPath(path: string) {\n if (this.#isType42) {\n // Type 42 mode: use path directly as invoice number\n this.#rootPath = path;\n \n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n const derivedKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n path // Use original path as invoice number\n );\n this.rootAddress = derivedKey.toPublicKey().toAddress();\n \n // For Type 42, paths don't need BIP32 formatting\n this.#previousPath = path;\n this.#currentPath = path;\n } else {\n // BIP32 mode: validate and format HD path\n let pathToUse = path;\n if (path.split(\"/\").length < 5) {\n pathToUse = `${SIGNING_PATH_PREFIX}${path}`;\n }\n\n if (!this.validatePath(pathToUse)) {\n throw new Error(`invalid signing path given ${pathToUse}`);\n }\n\n this.#rootPath = pathToUse;\n\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const derivedChild = this.#HDPrivateKey.derive(pathToUse);\n this.rootAddress = derivedChild.pubKey.toAddress();\n \n // Set paths for BIP32\n this.#previousPath = pathToUse;\n this.#currentPath = pathToUse;\n }\n\n // Identity keys should be derivatives of the root address - this allows checking\n // of the creation transaction\n this.identityKey = this.deriveIdentityKey(this.rootAddress);\n }\n\n get rootPath(): string {\n return this.#rootPath;\n }\n\n getRootPath(): string {\n return this.#rootPath;\n }\n\n /**\n * This should be called with the last part of the signing path (/.../.../...)\n * This library assumes the first part is m/424150'/0'/0' as defined at the top of this file\n *\n * @param path The second path of the signing path in the format [0-9]{0,9}/[0-9]{0,9}/[0-9]{0,9}\n */\n set currentPath(path) {\n if (this.#isType42) {\n // Type 42 mode: use path directly as invoice number\n this.#previousPath = this.#currentPath;\n this.#currentPath = path;\n } else {\n // BIP32 mode: validate and format HD path\n let pathToUse = path;\n if (path.split(\"/\").length < 5) {\n pathToUse = `${SIGNING_PATH_PREFIX}${path}`;\n }\n\n if (!this.validatePath(pathToUse)) {\n throw new Error(\"invalid signing path given\");\n }\n\n this.#previousPath = this.#currentPath;\n this.#currentPath = pathToUse;\n }\n }\n\n get currentPath(): string {\n return this.#currentPath;\n }\n\n get previousPath(): string {\n return this.#previousPath;\n }\n\n /**\n * This can be used to break the deterministic way child keys are created to make it harder for\n * an attacker to steal the identites when the root key is compromised. This does however require\n * the seeds to be stored at all times. If the seed is lost, the identity will not be recoverable.\n */\n get idSeed(): string {\n return this.#idSeed;\n }\n\n /**\n * Increment current path to a new path\n *\n * @returns {*}\n */\n incrementPath(): void {\n this.currentPath = Utils.getNextPath(this.currentPath);\n }\n\n /**\n * Check whether the given path is a valid path for use with this class\n * The signing paths used here always have a length of 3\n *\n * @param path The last part of the signing path (example \"/0/0/1\")\n * @returns {boolean}\n */\n validatePath(path: string) {\n /* eslint-disable max-len */\n if (\n path.match(\n /\\/[0-9]{1,10}'?\\/[0-9]{1,10}'?\\/[0-9]{1,10}'?\\/[0-9]{1,10}'?\\/[0-9]{1,10}'?\\/[0-9]{1,10}'?/\n )\n ) {\n const pathValues = path.split(\"/\");\n if (\n pathValues.length === 7 &&\n Number(pathValues[1].replace(\"'\", \"\")) <= MAX_INT &&\n Number(pathValues[2].replace(\"'\", \"\")) <= MAX_INT &&\n Number(pathValues[3].replace(\"'\", \"\")) <= MAX_INT &&\n Number(pathValues[4].replace(\"'\", \"\")) <= MAX_INT &&\n Number(pathValues[5].replace(\"'\", \"\")) <= MAX_INT &&\n Number(pathValues[6].replace(\"'\", \"\")) <= MAX_INT\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get the OP_RETURN for the initial ID transaction (signed with root address)\n *\n * @returns {[]}\n */\n getInitialIdTransaction() {\n return this.getIdTransaction(this.#rootPath);\n }\n\n /**\n * Get the OP_RETURN for the ID transaction of the current address / path\n *\n * @returns {[]}\n */\n getIdTransaction(previousPath = \"\") {\n if (this.#currentPath === this.#rootPath) {\n throw new Error(\n \"Current path equals rootPath. ID was probably not initialized properly\"\n );\n }\n\n const opReturn = [\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"ID\"),\n toArray(this.identityKey),\n toArray(this.getCurrentAddress()),\n ];\n\n return this.signOpReturnWithAIP(\n opReturn,\n previousPath || this.#previousPath\n );\n }\n\n /**\n * Get the private key for a given path (before identity signing key derivation)\n * This is the \"member key\" for the path\n */\n private getPathDerivedKey(path: string): PrivateKey {\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n return this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n path\n );\n }\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n return this.#HDPrivateKey.derive(path).privKey;\n }\n\n /**\n * Get the identity signing key for a given path\n * This is derived from the path key using the BAP protocol pattern\n */\n private getIdentitySigningKeyForPath(path: string): PrivateKey {\n const pathKey = this.getPathDerivedKey(path);\n return pathKey.deriveChild(pathKey.toPublicKey(), BAP_INVOICE_NUMBER);\n }\n\n /**\n * Get the member key's public key for the given path\n * This is the root key before signing key derivation\n */\n public getMemberKey(path?: string): string {\n const pathToUse = path || this.#currentPath;\n return this.getPathDerivedKey(pathToUse).toPublicKey().toString();\n }\n\n /**\n * Get the legacy (pre-signing-key-derivation) address for a path\n * This is the address without the extra \"1-bap-identity\" derivation\n */\n public getLegacyAddress(path?: string): string {\n const pathToUse = path || this.#currentPath;\n const pathKey = this.getPathDerivedKey(pathToUse);\n return pathKey.toPublicKey().toAddress();\n }\n\n /**\n * Check if the on-chain signing address uses legacy derivation\n * @param registeredAddress The address registered on-chain (optional, defaults to rootAddress)\n * @returns true if the registered address matches legacy derivation\n */\n public needsRotation(registeredAddress?: string): boolean {\n const addressToCheck = registeredAddress || this.rootAddress;\n const legacyAddress = this.getLegacyAddress(this.#rootPath);\n return addressToCheck === legacyAddress;\n }\n\n /**\n * Get OP_RETURN for migrating from legacy to new signing address derivation\n * Signs with the LEGACY key to prove ownership of the old address\n * Caller handles funding and broadcast\n * @returns OP_RETURN data as number[][]\n */\n public getLegacyRotationTransaction(): number[][] {\n // New address is the derived address at root path\n const newAddress = this.getAddress(this.#rootPath);\n\n const opReturn = [\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"ID\"),\n toArray(this.identityKey),\n toArray(newAddress),\n ];\n\n // Must sign with LEGACY key (not the new derived key)\n // to prove ownership of the old legacy address\n const aipMessageBuffer = this.getAIPMessageBuffer(opReturn);\n const legacyKey = this.getPathDerivedKey(this.#rootPath);\n const { address, signature } = this.signWithBSM(aipMessageBuffer.flat(), legacyKey);\n\n return this.formatAIPOutput(opReturn, address, signature);\n }\n\n /**\n * Get address for given path\n * Returns the identity signing address (derived from member key)\n *\n * @param path\n * @returns {*}\n */\n getAddress(path: string): string {\n // Get the identity signing key and return its address\n const identitySigningKey = this.getIdentitySigningKeyForPath(path);\n return identitySigningKey.toPublicKey().toAddress();\n }\n\n /**\n * Get current signing address\n *\n * @returns {*}\n */\n getCurrentAddress(): string {\n return this.getAddress(this.#currentPath);\n }\n\n /**\n * Get the encryption key pair for this identity\n */\n getEncryptionKey(): { privKey: PrivateKey; pubKey: PublicKey } {\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // First derive to root path, then to encryption path\n const rootKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n this.#rootPath\n );\n const encryptionKey = rootKey.deriveChild(\n rootKey.toPublicKey(),\n ENCRYPTION_PATH\n );\n return {\n privKey: encryptionKey,\n pubKey: encryptionKey.toPublicKey(),\n };\n }\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const HDPrivateKey = this.#HDPrivateKey.derive(this.#rootPath);\n const encryptionKey = HDPrivateKey.derive(ENCRYPTION_PATH).privKey;\n return {\n privKey: encryptionKey,\n pubKey: encryptionKey.toPublicKey(),\n };\n }\n\n /**\n * Get the encryption key using type 42 (different key / incompatible with above)\n * @deprecated Use getEncryptionKey() which now handles both BIP32 and Type 42\n */\n getEncryptionKeyType42(): { privKey: PrivateKey; pubKey: PublicKey } {\n if (this.#isType42) {\n // If already in Type 42 mode, just use the regular method\n return this.getEncryptionKey();\n }\n \n // Legacy behavior for BIP32 keys wanting Type 42 style derivation\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const HDPrivateKey = this.#HDPrivateKey.derive(this.#rootPath);\n const encryptionKey = HDPrivateKey.privKey.deriveChild(\n HDPrivateKey.toPublic().pubKey,\n ENCRYPTION_PATH\n );\n return {\n privKey: encryptionKey,\n pubKey: encryptionKey.toPublicKey(),\n };\n }\n /**\n * Get the public key for encrypting data for this identity\n */\n getEncryptionPublicKey(): string {\n const { pubKey } = this.getEncryptionKey();\n return pubKey.toString();\n }\n\n /**\n * Get the public key for encrypting data for this identity, using a seed for the encryption\n */\n getEncryptionPublicKeyWithSeed(seed: string): string {\n const encryptionKey = this.getEncryptionPrivateKeyWithSeed(seed);\n return encryptionKey.toPublicKey().toString();\n }\n\n /**\n * Encrypt the given string data with the identity encryption key\n * @param stringData\n * @param counterPartyPublicKey Optional public key of the counterparty\n * @return string Base64\n */\n encrypt(stringData: string, counterPartyPublicKey?: string): string {\n const { privKey: encryptionKey, pubKey: publicKey } = this.getEncryptionKey();\n const pubKey = counterPartyPublicKey\n ? PublicKey.fromString(counterPartyPublicKey)\n : publicKey;\n return toBase64(electrumEncrypt(toArray(stringData), pubKey, encryptionKey));\n }\n\n /**\n * Decrypt the given ciphertext with the identity encryption key\n * @param ciphertext\n */\n decrypt(ciphertext: string, counterPartyPublicKey?: string): string {\n const { privKey: encryptionKey } = this.getEncryptionKey();\n let pubKey: PublicKey | undefined;\n if (counterPartyPublicKey) {\n pubKey = PublicKey.fromString(counterPartyPublicKey);\n }\n return toUTF8(\n electrumDecrypt(toArray(ciphertext, \"base64\"), encryptionKey, pubKey)\n );\n }\n\n /**\n * Encrypt the given string data with the identity encryption key\n * @param stringData\n * @param seed String seed\n * @param counterPartyPublicKey Optional public key of the counterparty\n * @return string Base64\n */\n encryptWithSeed(\n stringData: string,\n seed: string,\n counterPartyPublicKey?: string\n ): string {\n const encryptionKey = this.getEncryptionPrivateKeyWithSeed(seed);\n const publicKey = encryptionKey.toPublicKey();\n const pubKey = counterPartyPublicKey\n ? PublicKey.fromString(counterPartyPublicKey)\n : publicKey;\n return toBase64(\n electrumEncrypt(toArray(stringData), pubKey, encryptionKey)\n );\n }\n\n /**\n * Decrypt the given ciphertext with the identity encryption key\n * @param ciphertext\n * @param seed String seed\n // * @param counterPartyPublicKey Public key of the counterparty\n */\n decryptWithSeed(\n ciphertext: string,\n seed: string,\n counterPartyPublicKey?: string\n ): string {\n const encryptionKey = this.getEncryptionPrivateKeyWithSeed(seed);\n let pubKey: PublicKey | undefined;\n if (counterPartyPublicKey) {\n pubKey = PublicKey.fromString(counterPartyPublicKey);\n }\n return toUTF8(\n electrumDecrypt(toArray(ciphertext, \"base64\"), encryptionKey, pubKey)\n );\n }\n\n private getEncryptionPrivateKeyWithSeed(seed: string): PrivateKey {\n const pathHex = toHex(Hash.sha256(seed, \"utf8\"));\n \n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // First derive to root path\n const rootKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n this.#rootPath\n );\n // Then derive with seed as invoice number\n return rootKey.deriveChild(rootKey.toPublicKey(), pathHex);\n }\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const path = Utils.getSigningPathFromHex(pathHex);\n const HDPrivateKey = this.#HDPrivateKey.derive(this.#rootPath);\n return HDPrivateKey.derive(path).privKey;\n }\n\n /**\n * Get an attestation string for the given urn for this identity\n *\n * @param urn\n * @returns {string}\n */\n getAttestation(urn: string) {\n const urnHash = Hash.sha256(urn, \"utf8\");\n return `bap:attest:${toHex(urnHash)}:${this.getIdentityKey()}`;\n }\n\n /**\n * Generate and return the attestation hash for the given attribute of this identity\n *\n * @param attribute Attribute name (name, email etc.)\n * @returns {string}\n */\n getAttestationHash(attribute: string) {\n const urn = this.getAttributeUrn(attribute);\n if (!urn) return null;\n\n const attestation = this.getAttestation(urn);\n const attestationHash = Hash.sha256(attestation, \"utf8\");\n\n return toHex(attestationHash);\n }\n\n /**\n * Sign a message with the current signing address of this identity\n * Uses the derived identity signing key\n *\n * @param message\n * @param signingPath\n * @returns {{address: string, signature: string}}\n */\n signMessage(\n message: number[],\n signingPath?: string\n ): { address: string; signature: string } {\n const pathToUse = signingPath || this.#currentPath;\n const signingKey = this.getIdentitySigningKeyForPath(pathToUse);\n return this.signWithBSM(message, signingKey);\n }\n\n /**\n * Sign a message using a key based on the given string seed\n *\n * This works by creating a private key from the root key of this identity. It will always\n * work with the rootPath / rootKey, to be deterministic. It will not change even if the keys\n * are rotated for this ID.\n *\n * This is used in for instance deterministic login systems, that do not support BAP.\n * The signing address is derived from the seed-derived key.\n *\n * @param message\n * @param seed {string} String seed that will be used to generate a path\n */\n signMessageWithSeed(\n message: string,\n seed: string\n ): { address: string; signature: string } {\n const pathHex = toHex(Hash.sha256(seed, \"utf8\"));\n let seedDerivedKey: PrivateKey;\n\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // First derive to root path\n const rootKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n this.#rootPath\n );\n // Then derive with seed hex as invoice number\n seedDerivedKey = rootKey.deriveChild(rootKey.toPublicKey(), pathHex);\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const path = Utils.getSigningPathFromHex(pathHex);\n const HDPrivateKey = this.#HDPrivateKey.derive(this.#rootPath);\n const derivedChild = HDPrivateKey.derive(path);\n seedDerivedKey = derivedChild.privKey;\n }\n\n // Apply identity signing key derivation to the seed-derived key\n const signingKey = seedDerivedKey.deriveChild(\n seedDerivedKey.toPublicKey(),\n BAP_INVOICE_NUMBER\n );\n\n return this.signWithBSM(toArray(message, \"utf8\"), signingKey);\n }\n\n /**\n * Sign an op_return hex array with AIP\n * @param opReturn {array}\n * @param signingPath {string}\n * @return {number[]}\n */\n signOpReturnWithAIP(opReturn: number[][], signingPath = \"\"): number[][] {\n const aipMessageBuffer = this.getAIPMessageBuffer(opReturn);\n const { address, signature } = this.signMessage(\n aipMessageBuffer.flat(),\n signingPath\n );\n return this.formatAIPOutput(opReturn, address, signature);\n }\n\n /**\n * Get all signing keys for this identity\n */\n async getIdSigningKeys(): Promise<GetSigningKeysResponse> {\n const signingKeys = await this.getApiData<GetSigningKeysResponse>(\n \"/signing-keys\",\n {\n idKey: this.identityKey,\n }\n );\n console.log(\"getIdSigningKeys\", signingKeys);\n\n return signingKeys;\n }\n\n /**\n * Get all attestations for the given attribute\n *\n * @param attribute\n */\n async getAttributeAttestations(\n attribute: string\n ): Promise<GetAttestationResponse> {\n // This function needs to make a call to a BAP server to get all the attestations for this\n // identity for the given attribute\n const attestationHash = this.getAttestationHash(attribute);\n\n // get all BAP ATTEST records for the given attestationHash\n const attestations = await this.getApiData<GetAttestationResponse>(\n \"/attestation/get\",\n {\n hash: attestationHash,\n }\n );\n console.log(\"getAttestations\", attribute, attestationHash, attestations);\n\n return attestations;\n }\n\n /**\n * Import an identity from a JSON object\n *\n * @param identity{{}}\n */\n import(identity: Identity | OldIdentity): void {\n this.idName = identity.name;\n this.description = identity.description || \"\";\n this.identityKey = identity.identityKey;\n this.#rootPath = identity.rootPath;\n this.rootAddress = identity.rootAddress;\n this.#previousPath = identity.previousPath;\n this.#currentPath = identity.currentPath;\n this.#idSeed = (\"idSeed\" in identity ? identity.idSeed : \"\") || \"\";\n this.identityAttributes = this.parseAttributes(identity.identityAttributes);\n }\n\n /**\n * Export this identity to a JSON object\n * @returns {{}}\n */\n export(): Identity {\n return {\n name: this.idName,\n description: this.description,\n identityKey: this.identityKey,\n rootPath: this.#rootPath,\n rootAddress: this.rootAddress,\n previousPath: this.#previousPath,\n currentPath: this.#currentPath,\n idSeed: this.#idSeed,\n identityAttributes: this.getAttributes(),\n lastIdPath: \"\",\n };\n }\n\n // Export a member-friendly backup, containing only the derived member key\n // The derivedPrivateKey is the member key (root for signing key derivation)\n // The address is the derived identity signing address\n exportMemberBackup(): MemberIdentity {\n // Get the path-derived key (member key)\n const derivedKey = this.getPathDerivedKey(this.#currentPath);\n // Get the derived identity signing key for the address\n const identitySigningKey = this.getIdentitySigningKeyForPath(this.#currentPath);\n\n return {\n name: this.idName,\n description: this.description,\n derivedPrivateKey: derivedKey.toWif(),\n address: identitySigningKey.toPublicKey().toAddress(),\n identityAttributes: this.getAttributes(),\n identityKey: this.identityKey,\n };\n }\n\n // Derive a new member ID from the master HD key\n // The path-derived key becomes the MemberID's key (member root)\n // MemberID handles signing key derivation internally\n public newId(): MemberID {\n // Assuming incrementPath updates the internal current path\n this.incrementPath();\n\n // Get the path-derived key (member key)\n const derivedKey = this.getPathDerivedKey(this.#currentPath);\n\n return new MemberID(derivedKey);\n }\n\n /**\n * Export member data in bitcoin-backup compatible format\n * @returns Object with wif and encrypted member data\n */\n exportMember(): { wif: string; encryptedData: string } {\n const memberExport = this.exportMemberBackup();\n\n // Get the path-derived key (member key)\n const derivedKey = this.getPathDerivedKey(this.#currentPath);\n\n // Encrypt the member data using ECIES\n const encryptedData = toBase64(\n electrumEncrypt(\n toArray(JSON.stringify(memberExport)),\n derivedKey.toPublicKey()\n )\n );\n\n return {\n wif: memberExport.derivedPrivateKey,\n encryptedData,\n };\n }\n}\nexport { MasterID };\n",
9
- "import type { PathPrefix } from \"./interface.js\";\n\nexport const Utils = {\n /**\n * Helper function to generate cryptographically secure random bytes\n * \n * This follows the pattern used by BSV SDK and other Bitcoin libraries.\n * Uses crypto.getRandomValues() which is available in browsers and modern Node.js.\n *\n * @param {number} byteLength - Number of random bytes to generate (default: 32)\n * @returns {Uint8Array} Array of cryptographically secure random bytes\n */\n getRandomBytes(byteLength = 32): Uint8Array {\n // Use crypto.getRandomValues() - available in browsers and Node.js 15+\n if (typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.getRandomValues) {\n const array = new Uint8Array(byteLength);\n globalThis.crypto.getRandomValues(array);\n return array;\n }\n\n // Fallback error - crypto operations require secure randomness\n throw new Error(\n 'Secure random number generation not available. ' +\n 'crypto.getRandomValues() is required for cryptographic operations. ' +\n 'This environment may not be suitable for secure key generation.'\n );\n },\n\n /**\n * Helper function to generate a random hex string\n *\n * @param {number} byteLength - Number of random bytes to generate (default: 32)\n * @returns {string} Hex string of random bytes\n */\n getRandomString(byteLength = 32): string {\n const bytes = this.getRandomBytes(byteLength);\n return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');\n },\n\n /**\n * Get a signing path from a hex number\n *\n * @param hexString {string}\n * @param hardened {boolean} Whether to return a hardened path\n * @returns {string}\n */\n getSigningPathFromHex(hexString: string, hardened = true) {\n // \"m/0/0/1\"\n let signingPath = \"m\";\n const signingHex = hexString.match(/.{1,8}/g);\n if (!signingHex) {\n throw new Error(\"Invalid hex string\");\n }\n const maxNumber = 2147483648 - 1; // 0x80000000\n for (const hexNumber of signingHex) {\n let number = Number(`0x${hexNumber}`);\n if (number > maxNumber) number -= maxNumber;\n signingPath += `/${number}${hardened ? \"'\" : \"\"}`;\n }\n\n return signingPath;\n },\n\n /**\n * Increment that second to last part from the given part, set the last part to 0\n *\n * @param path string\n * @returns {*}\n */\n getNextIdentityPath(path: string): PathPrefix {\n const pathValues = path.split(\"/\");\n const secondToLastPart = pathValues[pathValues.length - 2];\n\n let hardened = false;\n if (secondToLastPart.match(\"'\")) {\n hardened = true;\n }\n\n const nextPath = (\n Number(secondToLastPart.replace(/[^0-9]/g, \"\")) + 1\n ).toString();\n pathValues[pathValues.length - 2] = nextPath + (hardened ? \"'\" : \"\");\n pathValues[pathValues.length - 1] = `0${hardened ? \"'\" : \"\"}`;\n\n return pathValues.join(\"/\") as PathPrefix;\n },\n\n /**\n * Increment that last part of the given path\n *\n * @param path string\n * @returns {*}\n */\n getNextPath(path: string) {\n const pathValues = path.split(\"/\");\n const lastPart = pathValues[pathValues.length - 1];\n let hardened = false;\n if (lastPart.match(\"'\")) {\n hardened = true;\n }\n const nextPath = (Number(lastPart.replace(/[^0-9]/g, \"\")) + 1).toString();\n pathValues[pathValues.length - 1] = nextPath + (hardened ? \"'\" : \"\");\n return pathValues.join(\"/\");\n },\n};\n",
8
+ "import {\n Utils as BSVUtils,\n ECIES,\n Hash,\n PublicKey,\n type PrivateKey,\n HD,\n} from \"@bsv/sdk\";\n\nimport { type APIFetcher, apiFetcher } from \"./api\";\nimport type {\n GetAttestationResponse,\n GetSigningKeysResponse,\n} from \"./apiTypes\";\nimport {\n BAP_BITCOM_ADDRESS,\n BAP_SERVER,\n ENCRYPTION_PATH,\n MAX_INT,\n SIGNING_PATH_PREFIX,\n BAP_INVOICE_NUMBER,\n} from \"./constants\";\nimport type {\n Identity,\n IdentityAttributes,\n OldIdentity,\n MemberIdentity,\n} from \"./interface\";\nimport { Utils, bapIdFromAddress } from \"./utils\";\nimport { MemberID } from \"./MemberID\";\nimport { BaseClass } from \"./BaseClass\";\nconst { toArray, toHex, toBase58, toUTF8, toBase64 } = BSVUtils;\nconst { electrumDecrypt, electrumEncrypt } = ECIES;\n\n// Type 42 key source\ninterface Type42KeySource {\n rootPk: PrivateKey;\n}\n\n/**\n * MasterID class\n *\n * This class should be used in conjunction with the BAP class\n * Supports both BIP32 (HD) and Type 42 key derivation\n *\n * @type {MasterID}\n */\nclass MasterID extends BaseClass {\n #HDPrivateKey: HD | undefined;\n #masterPrivateKey: PrivateKey | undefined;\n #isType42: boolean;\n #BAP_SERVER: string = BAP_SERVER;\n #BAP_TOKEN = \"\";\n #rootPath: string;\n #previousPath: string;\n #currentPath: string;\n #idSeed: string;\n\n idName: string;\n description: string;\n\n rootAddress: string;\n identityKey: string;\n identityAttributes: IdentityAttributes;\n\n getApiData: APIFetcher;\n\n constructor(\n keySource: HD | Type42KeySource,\n identityAttributes: IdentityAttributes = {},\n idSeed = \"\"\n ) {\n super();\n\n // Determine if we're using Type 42 or BIP32\n if (keySource instanceof HD) {\n // BIP32 mode\n this.#isType42 = false;\n if (idSeed) {\n // create a new HDPrivateKey based on the seed\n const seedHex = toHex(Hash.sha256(idSeed, \"utf8\"));\n const seedPath = Utils.getSigningPathFromHex(seedHex);\n this.#HDPrivateKey = keySource.derive(seedPath);\n } else {\n this.#HDPrivateKey = keySource;\n }\n } else {\n // Type 42 mode\n this.#isType42 = true;\n this.#masterPrivateKey = keySource.rootPk;\n \n if (idSeed) {\n // For Type 42 with seed, we derive a new master key using the seed as invoice number\n const seedHex = toHex(Hash.sha256(idSeed, \"utf8\"));\n this.#masterPrivateKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n seedHex\n );\n }\n }\n\n this.#idSeed = idSeed;\n this.idName = \"ID 1\";\n this.description = \"\";\n\n this.#rootPath = `${SIGNING_PATH_PREFIX}/0/0/0`;\n this.#previousPath = `${SIGNING_PATH_PREFIX}/0/0/0`;\n this.#currentPath = `${SIGNING_PATH_PREFIX}/0/0/1`;\n\n // Derive root address based on mode\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // In Type 42, we use the path as invoice number\n const rootKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n this.#rootPath\n );\n this.rootAddress = rootKey.toPublicKey().toAddress();\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const rootChild = this.#HDPrivateKey.derive(this.#rootPath);\n this.rootAddress = rootChild.privKey.toPublicKey().toAddress();\n }\n \n this.identityKey = this.deriveIdentityKey(this.rootAddress);\n\n // unlink the object\n const attributes = { ...identityAttributes };\n this.identityAttributes = this.parseAttributes(attributes);\n\n this.getApiData = apiFetcher(this.#BAP_SERVER, this.#BAP_TOKEN);\n }\n\n set BAP_SERVER(bapServer) {\n this.#BAP_SERVER = bapServer;\n }\n\n get BAP_SERVER(): string {\n return this.#BAP_SERVER;\n }\n\n set BAP_TOKEN(token) {\n this.#BAP_TOKEN = token;\n }\n\n get BAP_TOKEN(): string {\n return this.#BAP_TOKEN;\n }\n\n deriveIdentityKey(address: string): string {\n return bapIdFromAddress(address);\n }\n\n /**\n * Helper function to parse identity attributes\n *\n * @param identityAttributes\n * @returns {{}}\n */\n parseAttributes(\n identityAttributes: IdentityAttributes | string\n ): IdentityAttributes {\n if (typeof identityAttributes === \"string\") {\n return this.parseStringUrns(identityAttributes);\n }\n\n for (const key in identityAttributes) {\n if (!identityAttributes[key].value || !identityAttributes[key].nonce) {\n throw new Error(\"Invalid identity attribute\");\n }\n }\n\n return identityAttributes || {};\n }\n\n /**\n * Parse a text of urn string into identity attributes\n *\n * urn:bap:id:name:John Doe:e2c6fb4063cc04af58935737eaffc938011dff546d47b7fbb18ed346f8c4d4fa\n * urn:bap:id:birthday:1990-05-22:e61f23cbbb2284842d77965e2b0e32f0ca890b1894ca4ce652831347ee3596d9\n * urn:bap:id:over18:1:480ca17ccaacd671b28dc811332525f2f2cd594d8e8e7825de515ce5d52d30e8\n *\n * @param urnIdentityAttributes\n */\n parseStringUrns(urnIdentityAttributes: string): IdentityAttributes {\n const identityAttributes: IdentityAttributes = {};\n // avoid forEach\n\n const attributesRaw = urnIdentityAttributes\n .replace(/^\\s+/g, \"\")\n .replace(/\\r/gm, \"\")\n .split(\"\\n\");\n\n for (const line of attributesRaw) {\n // remove any whitespace from the string (trim)\n const attribute = line.replace(/^\\s+/g, \"\").replace(/\\s+$/g, \"\");\n const urn = attribute.split(\":\");\n if (\n urn[0] === \"urn\" &&\n urn[1] === \"bap\" &&\n urn[2] === \"id\" &&\n urn[3] &&\n urn[4] &&\n urn[5]\n ) {\n identityAttributes[urn[3]] = {\n value: urn[4],\n nonce: urn[5],\n };\n }\n }\n\n return identityAttributes;\n }\n\n /**\n * Returns the identity key\n *\n * @returns {*|string}\n */\n getIdentityKey(): string {\n return this.identityKey;\n }\n\n /**\n * This should be called with the last part of the signing path (/.../.../...)\n * This library assumes the first part is m/424150'/0'/0' as defined at the top of this file\n *\n * @param path The second path of the signing path in the format [0-9]{0,9}/[0-9]{0,9}/[0-9]{0,9}\n */\n set rootPath(path: string) {\n if (this.#isType42) {\n // Type 42 mode: use path directly as invoice number\n this.#rootPath = path;\n \n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n const derivedKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n path // Use original path as invoice number\n );\n this.rootAddress = derivedKey.toPublicKey().toAddress();\n \n // For Type 42, paths don't need BIP32 formatting\n this.#previousPath = path;\n this.#currentPath = path;\n } else {\n // BIP32 mode: validate and format HD path\n let pathToUse = path;\n if (path.split(\"/\").length < 5) {\n pathToUse = `${SIGNING_PATH_PREFIX}${path}`;\n }\n\n if (!this.validatePath(pathToUse)) {\n throw new Error(`invalid signing path given ${pathToUse}`);\n }\n\n this.#rootPath = pathToUse;\n\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const derivedChild = this.#HDPrivateKey.derive(pathToUse);\n this.rootAddress = derivedChild.pubKey.toAddress();\n \n // Set paths for BIP32\n this.#previousPath = pathToUse;\n this.#currentPath = pathToUse;\n }\n\n // Identity keys should be derivatives of the root address - this allows checking\n // of the creation transaction\n this.identityKey = this.deriveIdentityKey(this.rootAddress);\n }\n\n get rootPath(): string {\n return this.#rootPath;\n }\n\n getRootPath(): string {\n return this.#rootPath;\n }\n\n /**\n * This should be called with the last part of the signing path (/.../.../...)\n * This library assumes the first part is m/424150'/0'/0' as defined at the top of this file\n *\n * @param path The second path of the signing path in the format [0-9]{0,9}/[0-9]{0,9}/[0-9]{0,9}\n */\n set currentPath(path) {\n if (this.#isType42) {\n // Type 42 mode: use path directly as invoice number\n this.#previousPath = this.#currentPath;\n this.#currentPath = path;\n } else {\n // BIP32 mode: validate and format HD path\n let pathToUse = path;\n if (path.split(\"/\").length < 5) {\n pathToUse = `${SIGNING_PATH_PREFIX}${path}`;\n }\n\n if (!this.validatePath(pathToUse)) {\n throw new Error(\"invalid signing path given\");\n }\n\n this.#previousPath = this.#currentPath;\n this.#currentPath = pathToUse;\n }\n }\n\n get currentPath(): string {\n return this.#currentPath;\n }\n\n get previousPath(): string {\n return this.#previousPath;\n }\n\n /**\n * This can be used to break the deterministic way child keys are created to make it harder for\n * an attacker to steal the identites when the root key is compromised. This does however require\n * the seeds to be stored at all times. If the seed is lost, the identity will not be recoverable.\n */\n get idSeed(): string {\n return this.#idSeed;\n }\n\n /**\n * Increment current path to a new path\n *\n * @returns {*}\n */\n incrementPath(): void {\n this.currentPath = Utils.getNextPath(this.currentPath);\n }\n\n /**\n * Check whether the given path is a valid path for use with this class\n * The signing paths used here always have a length of 3\n *\n * @param path The last part of the signing path (example \"/0/0/1\")\n * @returns {boolean}\n */\n validatePath(path: string) {\n /* eslint-disable max-len */\n if (\n path.match(\n /\\/[0-9]{1,10}'?\\/[0-9]{1,10}'?\\/[0-9]{1,10}'?\\/[0-9]{1,10}'?\\/[0-9]{1,10}'?\\/[0-9]{1,10}'?/\n )\n ) {\n const pathValues = path.split(\"/\");\n if (\n pathValues.length === 7 &&\n Number(pathValues[1].replace(\"'\", \"\")) <= MAX_INT &&\n Number(pathValues[2].replace(\"'\", \"\")) <= MAX_INT &&\n Number(pathValues[3].replace(\"'\", \"\")) <= MAX_INT &&\n Number(pathValues[4].replace(\"'\", \"\")) <= MAX_INT &&\n Number(pathValues[5].replace(\"'\", \"\")) <= MAX_INT &&\n Number(pathValues[6].replace(\"'\", \"\")) <= MAX_INT\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get the OP_RETURN for the initial ID transaction (signed with root address)\n *\n * @returns {[]}\n */\n getInitialIdTransaction() {\n return this.getIdTransaction(this.#rootPath);\n }\n\n /**\n * Get the OP_RETURN for the ID transaction of the current address / path\n *\n * @returns {[]}\n */\n getIdTransaction(previousPath = \"\") {\n if (this.#currentPath === this.#rootPath) {\n throw new Error(\n \"Current path equals rootPath. ID was probably not initialized properly\"\n );\n }\n\n const opReturn = [\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"ID\"),\n toArray(this.identityKey),\n toArray(this.getCurrentAddress()),\n ];\n\n return this.signOpReturnWithAIP(\n opReturn,\n previousPath || this.#previousPath\n );\n }\n\n /**\n * Get the private key for a given path (before identity signing key derivation)\n * This is the \"member key\" for the path\n */\n private getPathDerivedKey(path: string): PrivateKey {\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n return this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n path\n );\n }\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n return this.#HDPrivateKey.derive(path).privKey;\n }\n\n /**\n * Get the identity signing key for a given path\n * This is derived from the path key using the BAP protocol pattern\n */\n private getIdentitySigningKeyForPath(path: string): PrivateKey {\n const pathKey = this.getPathDerivedKey(path);\n return pathKey.deriveChild(pathKey.toPublicKey(), BAP_INVOICE_NUMBER);\n }\n\n /**\n * Get the member key's public key for the given path\n * This is the root key before signing key derivation\n */\n public getMemberKey(path?: string): string {\n const pathToUse = path || this.#currentPath;\n return this.getPathDerivedKey(pathToUse).toPublicKey().toString();\n }\n\n /**\n * Get the legacy (pre-signing-key-derivation) address for a path\n * This is the address without the extra \"1-bap-identity\" derivation\n */\n public getLegacyAddress(path?: string): string {\n const pathToUse = path || this.#currentPath;\n const pathKey = this.getPathDerivedKey(pathToUse);\n return pathKey.toPublicKey().toAddress();\n }\n\n /**\n * Check if the on-chain signing address uses legacy derivation\n * @param registeredAddress The address registered on-chain (optional, defaults to rootAddress)\n * @returns true if the registered address matches legacy derivation\n */\n public needsRotation(registeredAddress?: string): boolean {\n const addressToCheck = registeredAddress || this.rootAddress;\n const legacyAddress = this.getLegacyAddress(this.#rootPath);\n return addressToCheck === legacyAddress;\n }\n\n /**\n * Get OP_RETURN for migrating from legacy to new signing address derivation\n * Signs with the LEGACY key to prove ownership of the old address\n * Caller handles funding and broadcast\n * @returns OP_RETURN data as number[][]\n */\n public getLegacyRotationTransaction(): number[][] {\n // New address is the derived address at root path\n const newAddress = this.getAddress(this.#rootPath);\n\n const opReturn = [\n toArray(BAP_BITCOM_ADDRESS),\n toArray(\"ID\"),\n toArray(this.identityKey),\n toArray(newAddress),\n ];\n\n // Must sign with LEGACY key (not the new derived key)\n // to prove ownership of the old legacy address\n const aipMessageBuffer = this.getAIPMessageBuffer(opReturn);\n const legacyKey = this.getPathDerivedKey(this.#rootPath);\n const { address, signature } = this.signWithBSM(aipMessageBuffer.flat(), legacyKey);\n\n return this.formatAIPOutput(opReturn, address, signature);\n }\n\n /**\n * Get address for given path\n * Returns the identity signing address (derived from member key)\n *\n * @param path\n * @returns {*}\n */\n getAddress(path: string): string {\n // Get the identity signing key and return its address\n const identitySigningKey = this.getIdentitySigningKeyForPath(path);\n return identitySigningKey.toPublicKey().toAddress();\n }\n\n /**\n * Get current signing address\n *\n * @returns {*}\n */\n getCurrentAddress(): string {\n return this.getAddress(this.#currentPath);\n }\n\n /**\n * Get the encryption key pair for this identity\n */\n getEncryptionKey(): { privKey: PrivateKey; pubKey: PublicKey } {\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // First derive to root path, then to encryption path\n const rootKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n this.#rootPath\n );\n const encryptionKey = rootKey.deriveChild(\n rootKey.toPublicKey(),\n ENCRYPTION_PATH\n );\n return {\n privKey: encryptionKey,\n pubKey: encryptionKey.toPublicKey(),\n };\n }\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const HDPrivateKey = this.#HDPrivateKey.derive(this.#rootPath);\n const encryptionKey = HDPrivateKey.derive(ENCRYPTION_PATH).privKey;\n return {\n privKey: encryptionKey,\n pubKey: encryptionKey.toPublicKey(),\n };\n }\n\n /**\n * Get the encryption key using type 42 (different key / incompatible with above)\n * @deprecated Use getEncryptionKey() which now handles both BIP32 and Type 42\n */\n getEncryptionKeyType42(): { privKey: PrivateKey; pubKey: PublicKey } {\n if (this.#isType42) {\n // If already in Type 42 mode, just use the regular method\n return this.getEncryptionKey();\n }\n \n // Legacy behavior for BIP32 keys wanting Type 42 style derivation\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const HDPrivateKey = this.#HDPrivateKey.derive(this.#rootPath);\n const encryptionKey = HDPrivateKey.privKey.deriveChild(\n HDPrivateKey.toPublic().pubKey,\n ENCRYPTION_PATH\n );\n return {\n privKey: encryptionKey,\n pubKey: encryptionKey.toPublicKey(),\n };\n }\n /**\n * Get the public key for encrypting data for this identity\n */\n getEncryptionPublicKey(): string {\n const { pubKey } = this.getEncryptionKey();\n return pubKey.toString();\n }\n\n /**\n * Get the public key for encrypting data for this identity, using a seed for the encryption\n */\n getEncryptionPublicKeyWithSeed(seed: string): string {\n const encryptionKey = this.getEncryptionPrivateKeyWithSeed(seed);\n return encryptionKey.toPublicKey().toString();\n }\n\n /**\n * Encrypt the given string data with the identity encryption key\n * @param stringData\n * @param counterPartyPublicKey Optional public key of the counterparty\n * @return string Base64\n */\n encrypt(stringData: string, counterPartyPublicKey?: string): string {\n const { privKey: encryptionKey, pubKey: publicKey } = this.getEncryptionKey();\n const pubKey = counterPartyPublicKey\n ? PublicKey.fromString(counterPartyPublicKey)\n : publicKey;\n return toBase64(electrumEncrypt(toArray(stringData), pubKey, encryptionKey));\n }\n\n /**\n * Decrypt the given ciphertext with the identity encryption key\n * @param ciphertext\n */\n decrypt(ciphertext: string, counterPartyPublicKey?: string): string {\n const { privKey: encryptionKey } = this.getEncryptionKey();\n let pubKey: PublicKey | undefined;\n if (counterPartyPublicKey) {\n pubKey = PublicKey.fromString(counterPartyPublicKey);\n }\n return toUTF8(\n electrumDecrypt(toArray(ciphertext, \"base64\"), encryptionKey, pubKey)\n );\n }\n\n /**\n * Encrypt the given string data with the identity encryption key\n * @param stringData\n * @param seed String seed\n * @param counterPartyPublicKey Optional public key of the counterparty\n * @return string Base64\n */\n encryptWithSeed(\n stringData: string,\n seed: string,\n counterPartyPublicKey?: string\n ): string {\n const encryptionKey = this.getEncryptionPrivateKeyWithSeed(seed);\n const publicKey = encryptionKey.toPublicKey();\n const pubKey = counterPartyPublicKey\n ? PublicKey.fromString(counterPartyPublicKey)\n : publicKey;\n return toBase64(\n electrumEncrypt(toArray(stringData), pubKey, encryptionKey)\n );\n }\n\n /**\n * Decrypt the given ciphertext with the identity encryption key\n * @param ciphertext\n * @param seed String seed\n // * @param counterPartyPublicKey Public key of the counterparty\n */\n decryptWithSeed(\n ciphertext: string,\n seed: string,\n counterPartyPublicKey?: string\n ): string {\n const encryptionKey = this.getEncryptionPrivateKeyWithSeed(seed);\n let pubKey: PublicKey | undefined;\n if (counterPartyPublicKey) {\n pubKey = PublicKey.fromString(counterPartyPublicKey);\n }\n return toUTF8(\n electrumDecrypt(toArray(ciphertext, \"base64\"), encryptionKey, pubKey)\n );\n }\n\n private getEncryptionPrivateKeyWithSeed(seed: string): PrivateKey {\n const pathHex = toHex(Hash.sha256(seed, \"utf8\"));\n \n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // First derive to root path\n const rootKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n this.#rootPath\n );\n // Then derive with seed as invoice number\n return rootKey.deriveChild(rootKey.toPublicKey(), pathHex);\n }\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const path = Utils.getSigningPathFromHex(pathHex);\n const HDPrivateKey = this.#HDPrivateKey.derive(this.#rootPath);\n return HDPrivateKey.derive(path).privKey;\n }\n\n /**\n * Get an attestation string for the given urn for this identity\n *\n * @param urn\n * @returns {string}\n */\n getAttestation(urn: string) {\n const urnHash = Hash.sha256(urn, \"utf8\");\n return `bap:attest:${toHex(urnHash)}:${this.getIdentityKey()}`;\n }\n\n /**\n * Generate and return the attestation hash for the given attribute of this identity\n *\n * @param attribute Attribute name (name, email etc.)\n * @returns {string}\n */\n getAttestationHash(attribute: string) {\n const urn = this.getAttributeUrn(attribute);\n if (!urn) return null;\n\n const attestation = this.getAttestation(urn);\n const attestationHash = Hash.sha256(attestation, \"utf8\");\n\n return toHex(attestationHash);\n }\n\n /**\n * Sign a message with the current signing address of this identity\n * Uses the derived identity signing key\n *\n * @param message\n * @param signingPath\n * @returns {{address: string, signature: string}}\n */\n signMessage(\n message: number[],\n signingPath?: string\n ): { address: string; signature: string } {\n const pathToUse = signingPath || this.#currentPath;\n const signingKey = this.getIdentitySigningKeyForPath(pathToUse);\n return this.signWithBSM(message, signingKey);\n }\n\n /**\n * Sign a message using a key based on the given string seed\n *\n * This works by creating a private key from the root key of this identity. It will always\n * work with the rootPath / rootKey, to be deterministic. It will not change even if the keys\n * are rotated for this ID.\n *\n * This is used in for instance deterministic login systems, that do not support BAP.\n * The signing address is derived from the seed-derived key.\n *\n * @param message\n * @param seed {string} String seed that will be used to generate a path\n */\n signMessageWithSeed(\n message: string,\n seed: string\n ): { address: string; signature: string } {\n const pathHex = toHex(Hash.sha256(seed, \"utf8\"));\n let seedDerivedKey: PrivateKey;\n\n if (this.#isType42) {\n if (!this.#masterPrivateKey) throw new Error(\"Master private key not initialized\");\n // First derive to root path\n const rootKey = this.#masterPrivateKey.deriveChild(\n this.#masterPrivateKey.toPublicKey(),\n this.#rootPath\n );\n // Then derive with seed hex as invoice number\n seedDerivedKey = rootKey.deriveChild(rootKey.toPublicKey(), pathHex);\n } else {\n if (!this.#HDPrivateKey) throw new Error(\"HD private key not initialized\");\n const path = Utils.getSigningPathFromHex(pathHex);\n const HDPrivateKey = this.#HDPrivateKey.derive(this.#rootPath);\n const derivedChild = HDPrivateKey.derive(path);\n seedDerivedKey = derivedChild.privKey;\n }\n\n // Apply identity signing key derivation to the seed-derived key\n const signingKey = seedDerivedKey.deriveChild(\n seedDerivedKey.toPublicKey(),\n BAP_INVOICE_NUMBER\n );\n\n return this.signWithBSM(toArray(message, \"utf8\"), signingKey);\n }\n\n /**\n * Sign an op_return hex array with AIP\n * @param opReturn {array}\n * @param signingPath {string}\n * @return {number[]}\n */\n signOpReturnWithAIP(opReturn: number[][], signingPath = \"\"): number[][] {\n const aipMessageBuffer = this.getAIPMessageBuffer(opReturn);\n const { address, signature } = this.signMessage(\n aipMessageBuffer.flat(),\n signingPath\n );\n return this.formatAIPOutput(opReturn, address, signature);\n }\n\n /**\n * Get all signing keys for this identity\n */\n async getIdSigningKeys(): Promise<GetSigningKeysResponse> {\n const signingKeys = await this.getApiData<GetSigningKeysResponse>(\n \"/signing-keys\",\n {\n idKey: this.identityKey,\n }\n );\n console.log(\"getIdSigningKeys\", signingKeys);\n\n return signingKeys;\n }\n\n /**\n * Get all attestations for the given attribute\n *\n * @param attribute\n */\n async getAttributeAttestations(\n attribute: string\n ): Promise<GetAttestationResponse> {\n // This function needs to make a call to a BAP server to get all the attestations for this\n // identity for the given attribute\n const attestationHash = this.getAttestationHash(attribute);\n\n // get all BAP ATTEST records for the given attestationHash\n const attestations = await this.getApiData<GetAttestationResponse>(\n \"/attestation/get\",\n {\n hash: attestationHash,\n }\n );\n console.log(\"getAttestations\", attribute, attestationHash, attestations);\n\n return attestations;\n }\n\n /**\n * Import an identity from a JSON object\n *\n * @param identity{{}}\n */\n import(identity: Identity | OldIdentity): void {\n this.idName = identity.name;\n this.description = identity.description || \"\";\n this.identityKey = identity.identityKey;\n this.#rootPath = identity.rootPath;\n this.rootAddress = identity.rootAddress;\n this.#previousPath = identity.previousPath;\n this.#currentPath = identity.currentPath;\n this.#idSeed = (\"idSeed\" in identity ? identity.idSeed : \"\") || \"\";\n this.identityAttributes = this.parseAttributes(identity.identityAttributes);\n }\n\n /**\n * Export this identity to a JSON object\n * @returns {{}}\n */\n export(): Identity {\n return {\n name: this.idName,\n description: this.description,\n identityKey: this.identityKey,\n rootPath: this.#rootPath,\n rootAddress: this.rootAddress,\n previousPath: this.#previousPath,\n currentPath: this.#currentPath,\n idSeed: this.#idSeed,\n identityAttributes: this.getAttributes(),\n lastIdPath: \"\",\n };\n }\n\n // Export a member-friendly backup, containing only the derived member key\n // The derivedPrivateKey is the member key (root for signing key derivation)\n // The address is the derived identity signing address\n exportMemberBackup(): MemberIdentity {\n // Get the path-derived key (member key)\n const derivedKey = this.getPathDerivedKey(this.#currentPath);\n // Get the derived identity signing key for the address\n const identitySigningKey = this.getIdentitySigningKeyForPath(this.#currentPath);\n\n return {\n name: this.idName,\n description: this.description,\n derivedPrivateKey: derivedKey.toWif(),\n address: identitySigningKey.toPublicKey().toAddress(),\n identityAttributes: this.getAttributes(),\n identityKey: this.identityKey,\n };\n }\n\n // Derive a new member ID from the master HD key\n // The path-derived key becomes the MemberID's key (member root)\n // MemberID handles signing key derivation internally\n public newId(): MemberID {\n // Assuming incrementPath updates the internal current path\n this.incrementPath();\n\n // Get the path-derived key (member key)\n const derivedKey = this.getPathDerivedKey(this.#currentPath);\n\n return new MemberID(derivedKey);\n }\n\n /**\n * Export member data in bitcoin-backup compatible format\n * @returns Object with wif and encrypted member data\n */\n exportMember(): { wif: string; encryptedData: string } {\n const memberExport = this.exportMemberBackup();\n\n // Get the path-derived key (member key)\n const derivedKey = this.getPathDerivedKey(this.#currentPath);\n\n // Encrypt the member data using ECIES\n const encryptedData = toBase64(\n electrumEncrypt(\n toArray(JSON.stringify(memberExport)),\n derivedKey.toPublicKey()\n )\n );\n\n return {\n wif: memberExport.derivedPrivateKey,\n encryptedData,\n };\n }\n}\nexport { MasterID };\n",
9
+ "import { Hash, PublicKey, Utils as BSVUtils } from \"@bsv/sdk\";\nimport type { PathPrefix } from \"./interface.js\";\n\nconst { toHex, toBase58 } = BSVUtils;\n\n/**\n * Derive a BAP ID from a Bitcoin address (rootAddress).\n *\n * BAP ID = base58(ripemd160(sha256(rootAddress)))\n *\n * This is the canonical derivation used by MasterID.deriveIdentityKey().\n * The address MUST be the rootAddress (from the BAP member key), not a\n * signing key address.\n */\nexport function bapIdFromAddress(address: string): string {\n const rootAddressHash = toHex(Hash.sha256(address, \"utf8\"));\n return toBase58(Hash.ripemd160(rootAddressHash, \"hex\"));\n}\n\n/**\n * Derive a BAP ID from a compressed public key (hex).\n *\n * Converts the pubkey to a Bitcoin address, then derives the BAP ID.\n *\n * IMPORTANT: This only produces a correct BAP ID when the pubkey is the\n * BAP member key's public key. It does NOT work with signing keys or\n * arbitrary public keys.\n *\n * In BRC-100 wallets, the BRC-31 identity key IS the member key's pubkey,\n * so this correctly bridges BRC-31 auth to BAP identity lookups.\n */\nexport function bapIdFromPubkey(pubkeyHex: string): string {\n const pubkey = PublicKey.fromString(pubkeyHex);\n return bapIdFromAddress(pubkey.toAddress());\n}\n\nexport const Utils = {\n /**\n * Helper function to generate cryptographically secure random bytes\n * \n * This follows the pattern used by BSV SDK and other Bitcoin libraries.\n * Uses crypto.getRandomValues() which is available in browsers and modern Node.js.\n *\n * @param {number} byteLength - Number of random bytes to generate (default: 32)\n * @returns {Uint8Array} Array of cryptographically secure random bytes\n */\n getRandomBytes(byteLength = 32): Uint8Array {\n // Use crypto.getRandomValues() - available in browsers and Node.js 15+\n if (typeof globalThis !== 'undefined' && globalThis.crypto && globalThis.crypto.getRandomValues) {\n const array = new Uint8Array(byteLength);\n globalThis.crypto.getRandomValues(array);\n return array;\n }\n\n // Fallback error - crypto operations require secure randomness\n throw new Error(\n 'Secure random number generation not available. ' +\n 'crypto.getRandomValues() is required for cryptographic operations. ' +\n 'This environment may not be suitable for secure key generation.'\n );\n },\n\n /**\n * Helper function to generate a random hex string\n *\n * @param {number} byteLength - Number of random bytes to generate (default: 32)\n * @returns {string} Hex string of random bytes\n */\n getRandomString(byteLength = 32): string {\n const bytes = this.getRandomBytes(byteLength);\n return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');\n },\n\n /**\n * Get a signing path from a hex number\n *\n * @param hexString {string}\n * @param hardened {boolean} Whether to return a hardened path\n * @returns {string}\n */\n getSigningPathFromHex(hexString: string, hardened = true) {\n // \"m/0/0/1\"\n let signingPath = \"m\";\n const signingHex = hexString.match(/.{1,8}/g);\n if (!signingHex) {\n throw new Error(\"Invalid hex string\");\n }\n const maxNumber = 2147483648 - 1; // 0x80000000\n for (const hexNumber of signingHex) {\n let number = Number(`0x${hexNumber}`);\n if (number > maxNumber) number -= maxNumber;\n signingPath += `/${number}${hardened ? \"'\" : \"\"}`;\n }\n\n return signingPath;\n },\n\n /**\n * Increment that second to last part from the given part, set the last part to 0\n *\n * @param path string\n * @returns {*}\n */\n getNextIdentityPath(path: string): PathPrefix {\n const pathValues = path.split(\"/\");\n const secondToLastPart = pathValues[pathValues.length - 2];\n\n let hardened = false;\n if (secondToLastPart.match(\"'\")) {\n hardened = true;\n }\n\n const nextPath = (\n Number(secondToLastPart.replace(/[^0-9]/g, \"\")) + 1\n ).toString();\n pathValues[pathValues.length - 2] = nextPath + (hardened ? \"'\" : \"\");\n pathValues[pathValues.length - 1] = `0${hardened ? \"'\" : \"\"}`;\n\n return pathValues.join(\"/\") as PathPrefix;\n },\n\n /**\n * Increment that last part of the given path\n *\n * @param path string\n * @returns {*}\n */\n getNextPath(path: string) {\n const pathValues = path.split(\"/\");\n const lastPart = pathValues[pathValues.length - 1];\n let hardened = false;\n if (lastPart.match(\"'\")) {\n hardened = true;\n }\n const nextPath = (Number(lastPart.replace(/[^0-9]/g, \"\")) + 1).toString();\n pathValues[pathValues.length - 1] = nextPath + (hardened ? \"'\" : \"\");\n return pathValues.join(\"/\");\n },\n};\n",
10
10
  "import {\n PublicKey,\n PrivateKey,\n Hash,\n Utils as BSVUtils,\n ECIES,\n} from \"@bsv/sdk\";\nimport { BaseClass } from \"./BaseClass\";\nimport type { IdentityAttributes, MemberIdentity } from \"./interface\";\nimport { ENCRYPTION_PATH, BAP_INVOICE_NUMBER, FRIEND_SECURITY_LEVEL, FRIEND_PROTOCOL } from \"./constants\";\nconst { toArray, toUTF8, toBase64, toHex } = BSVUtils;\nconst { electrumDecrypt, electrumEncrypt } = ECIES;\n\nexport class MemberID extends BaseClass {\n private key: PrivateKey;\n public idName: string;\n public description: string;\n public address: string;\n public identityKey: string;\n\n constructor(key: PrivateKey, identityAttributes: IdentityAttributes = {}) {\n super();\n this.key = key;\n // Address is derived from the identity signing key\n // The member key is the root, signing address is derived one level deeper\n this.address = this.getIdentitySigningKey().toPublicKey().toAddress();\n this.idName = \"Member ID 1\";\n this.description = \"\";\n this.identityKey = \"\";\n this.identityAttributes = this.parseAttributes(identityAttributes);\n }\n\n /**\n * Get the derived identity signing key\n * This is derived from the member key using the BAP protocol pattern\n * invoiceNumber = \"1-bap-identity\" (securityLevel-protocolName-keyID)\n */\n private getIdentitySigningKey(): PrivateKey {\n return this.key.deriveChild(this.key.toPublicKey(), BAP_INVOICE_NUMBER);\n }\n\n /**\n * Get the member key's public key\n * This is the root key for this member before signing key derivation\n * @returns The member's public key hex string\n */\n public getMemberKey(): string {\n return this.key.toPublicKey().toString();\n }\n\n /**\n * Get the legacy (pre-signing-key-derivation) address\n * This is the address without the extra \"1-bap-identity\" derivation\n */\n public getLegacyAddress(): string {\n return this.key.toPublicKey().toAddress();\n }\n\n // Implement the abstract signMessage method from BaseClass\n // Signs with the derived identity signing key\n public signMessage(\n message: number[],\n _signingPath?: string\n ): { address: string; signature: string } {\n const signingKey = this.getIdentitySigningKey();\n return this.signWithBSM(message, signingKey);\n }\n\n // Implement signOpReturnWithAIP - MemberID ignores signing path\n public signOpReturnWithAIP(opReturn: number[][]): number[][] {\n const aipMessageBuffer = this.getAIPMessageBuffer(opReturn);\n const { address, signature } = this.signMessage(aipMessageBuffer.flat());\n return this.formatAIPOutput(aipMessageBuffer, address, signature);\n }\n\n // Return the derived identity signing public key\n // This matches the address used for on-chain operations\n public getPublicKey(): string {\n return this.getIdentitySigningKey().toPublicKey().toString();\n }\n\n // Import the member identity from an object containing the derived private key and identity data\n public import(identity: MemberIdentity): void {\n this.idName = identity.name;\n this.description = identity.description;\n this.key = PrivateKey.fromWif(identity.derivedPrivateKey);\n // Address is derived from the identity signing key\n this.address = this.getIdentitySigningKey().toPublicKey().toAddress();\n this.identityAttributes = identity.identityAttributes || {};\n this.identityKey = identity.identityKey;\n }\n\n static fromMemberIdentity(identity: MemberIdentity): MemberID {\n const member = new MemberID(PrivateKey.fromWif(identity.derivedPrivateKey));\n member.import(identity);\n return member;\n }\n\n static fromBackup(singleBackup: { wif: string; id: string }): MemberID {\n // decrypt the id and set the details\n const member = new MemberID(PrivateKey.fromWif(singleBackup.wif));\n const id = JSON.parse(member.decrypt(singleBackup.id));\n member.import(id);\n return member;\n }\n\n // Export the member identity as an object containing the derived private key and identity data\n public export(): MemberIdentity {\n return {\n name: this.idName,\n description: this.description,\n derivedPrivateKey: this.key.toWif(),\n address: this.address,\n identityAttributes: this.getAttributes(),\n identityKey: this.identityKey,\n };\n }\n\n /**\n * Get the encryption key pair for this identity\n * We use the same key for both signing and encryption for simplicity\n */\n getEncryptionKey(): { privKey: PrivateKey; pubKey: PublicKey } {\n // Derive the encryption key from the private key using the ENCRYPTION_PATH\n // Since member keys are not HD keys, we use the path as the invoice number,\n // and use our own public key as the other party's public key\n return {\n privKey: this.key.deriveChild(this.key.toPublicKey(), ENCRYPTION_PATH),\n pubKey: this.key\n .deriveChild(this.key.toPublicKey(), ENCRYPTION_PATH)\n .toPublicKey(),\n };\n }\n\n /**\n * Get the public key for encrypting data for this identity\n */\n getEncryptionPublicKey(): string {\n const { pubKey } = this.getEncryptionKey();\n return pubKey.toString();\n }\n\n /**\n * Get a derived encryption key using a seed string (Type42 derivation)\n * This allows deriving unique encryption keys per friend/conversation\n * Uses BRC-43 format: `${securityLevel}-${protocol}-${keyID}`\n * @param seed - The seed string (e.g., friend's BAP ID)\n * @returns The derived private key for this seed\n */\n private getEncryptionPrivateKeyWithSeed(seed: string): PrivateKey {\n // Hash the seed to get a deterministic key ID\n const seedHash = toHex(Hash.sha256(seed, \"utf8\"));\n // BRC-43 format: security level 2 (counterparty-specific)\n const invoiceNumber = `${FRIEND_SECURITY_LEVEL}-${FRIEND_PROTOCOL}-${seedHash}`;\n // Use Type42 derivation: deriveChild(publicKey, invoice)\n return this.key.deriveChild(this.key.toPublicKey(), invoiceNumber);\n }\n\n /**\n * Get the encryption key pair for a specific seed\n * @param seed - The seed string (e.g., friend's BAP ID)\n */\n getEncryptionKeyWithSeed(seed: string): { privKey: PrivateKey; pubKey: PublicKey } {\n const privKey = this.getEncryptionPrivateKeyWithSeed(seed);\n return {\n privKey,\n pubKey: privKey.toPublicKey(),\n };\n }\n\n /**\n * Get the public key for encrypting data for a specific seed\n * This is the public key to include in friend requests\n * @param seed - The seed string (e.g., friend's BAP ID)\n */\n getEncryptionPublicKeyWithSeed(seed: string): string {\n return this.getEncryptionPrivateKeyWithSeed(seed).toPublicKey().toString();\n }\n\n /**\n * Encrypt data using a seed-derived key\n * @param stringData - The data to encrypt\n * @param seed - The seed string for key derivation (e.g., friend's BAP ID)\n * @param counterPartyPublicKey - Optional public key of the recipient\n * @returns Base64 encoded encrypted data\n */\n encryptWithSeed(stringData: string, seed: string, counterPartyPublicKey?: string): string {\n const derivedKey = this.getEncryptionPrivateKeyWithSeed(seed);\n const pubKey = derivedKey.toPublicKey();\n // Import PublicKey type-safely - counterPartyPublicKey is already a hex pubkey string\n const PublicKeyClass = this.key.toPublicKey().constructor as typeof import(\"@bsv/sdk\").PublicKey;\n const targetPubKey = counterPartyPublicKey\n ? PublicKeyClass.fromString(counterPartyPublicKey)\n : pubKey;\n return toBase64(electrumEncrypt(toArray(stringData), targetPubKey, derivedKey));\n }\n\n /**\n * Decrypt data using a seed-derived key\n * @param ciphertext - Base64 encoded encrypted data\n * @param seed - The seed string for key derivation (e.g., friend's BAP ID)\n * @param counterPartyPublicKey - Optional public key of the sender\n * @returns Decrypted string\n */\n decryptWithSeed(ciphertext: string, seed: string, counterPartyPublicKey?: string): string {\n const derivedKey = this.getEncryptionPrivateKeyWithSeed(seed);\n let senderPubKey: PublicKey | undefined;\n if (counterPartyPublicKey) {\n senderPubKey = PublicKey.fromString(counterPartyPublicKey);\n }\n return toUTF8(electrumDecrypt(toArray(ciphertext, \"base64\"), derivedKey, senderPubKey));\n }\n\n /**\n * Export member data in bitcoin-backup compatible format\n * @param label Optional user-defined label\n * @returns BapMemberBackup compatible object\n */\n exportForBackup(label?: string): {\n wif: string;\n id: string;\n label?: string;\n createdAt: string;\n } {\n const memberData = this.export();\n const encryptedData = this.encrypt(JSON.stringify(memberData));\n\n return {\n wif: this.key.toWif(),\n id: encryptedData,\n ...(label && { label }),\n createdAt: new Date().toISOString(),\n };\n }\n}\n",
11
11
  "import { ECIES, Utils as BSVUtils, OP, PublicKey, BSM, BigNumber } from \"@bsv/sdk\";\nimport type { PrivateKey, Signature } from \"@bsv/sdk\";\nimport { AIP_BITCOM_ADDRESS } from \"./constants\";\nimport type { IdentityAttribute, IdentityAttributes } from \"./interface\";\nimport { Utils } from \"./utils\";\nconst { toArray, toUTF8, toBase64 } = BSVUtils;\nconst { magicHash } = BSM;\nconst { electrumDecrypt, electrumEncrypt } = ECIES;\n\nabstract class BaseClass {\n protected identityAttributes: IdentityAttributes = {};\n\n /**\n * Abstract method that must be implemented by derived classes to sign messages\n * @param message - The message to sign\n * @param signingPath - Optional signing path for HD wallets\n * @returns Object containing address and signature\n */\n abstract signMessage(\n message: number[],\n signingPath?: string\n ): { address: string; signature: string };\n\n /**\n * Abstract method that must be implemented by derived classes to get encryption key\n */\n abstract getEncryptionKey(): { privKey: PrivateKey; pubKey: PublicKey };\n\n /**\n * Low-level BSM signing helper - signs a message with the given private key\n * This consolidates the BSM signing logic used across all signing methods\n * @param message - The message to sign as number array\n * @param signingKey - The private key to sign with\n * @returns Object containing address and base64 signature\n */\n protected signWithBSM(\n message: number[],\n signingKey: PrivateKey\n ): { address: string; signature: string } {\n const address = signingKey.toPublicKey().toAddress();\n const dummySig = BSM.sign(message, signingKey, \"raw\") as Signature;\n const h = new BigNumber(magicHash(message));\n const r = dummySig.CalculateRecoveryFactor(signingKey.toPublicKey(), h);\n const signature = (\n BSM.sign(message, signingKey, \"raw\") as Signature\n ).toCompact(r, true, \"base64\") as string;\n\n return { address, signature };\n }\n\n /**\n * Encrypt the given string data with the identity encryption key\n * @param stringData\n * @param counterPartyPublicKey Optional public key of the counterparty\n * @return string Base64\n */\n encrypt(stringData: string, counterPartyPublicKey?: string): string {\n const { privKey, pubKey } = this.getEncryptionKey();\n const targetPubKey = counterPartyPublicKey\n ? PublicKey.fromString(counterPartyPublicKey)\n : pubKey;\n return toBase64(\n electrumEncrypt(toArray(stringData), targetPubKey, privKey)\n );\n }\n\n /**\n * Decrypt the given ciphertext with the identity encryption key\n * @param ciphertext\n * @param counterPartyPublicKey Optional public key of the counterparty\n */\n decrypt(ciphertext: string, counterPartyPublicKey?: string): string {\n const { privKey } = this.getEncryptionKey();\n let pubKey: PublicKey | undefined;\n if (counterPartyPublicKey) {\n pubKey = PublicKey.fromString(counterPartyPublicKey);\n }\n return toUTF8(\n electrumDecrypt(toArray(ciphertext, \"base64\"), privKey, pubKey)\n );\n }\n\n /**\n * Sign an op_return hex array with AIP\n * Each implementation must handle its own signing path logic\n * @param opReturn {array}\n * @param signingPath {string}\n * @return {number[]}\n */\n signOpReturnWithAIP(opReturn: number[][], signingPath?: string): number[][] {\n const aipMessageBuffer = this.getAIPMessageBuffer(opReturn);\n const { address, signature } = this.signMessage(\n aipMessageBuffer.flat(),\n signingPath\n );\n return this.formatAIPOutput(aipMessageBuffer, address, signature);\n }\n\n /**\n * Returns all the attributes in the identity\n * @returns {IdentityAttributes}\n */\n getAttributes(): IdentityAttributes {\n return this.identityAttributes;\n }\n\n /**\n * Get the value of the given attribute\n * @param attributeName\n * @returns {IdentityAttribute | null}\n */\n getAttribute(attributeName: string): IdentityAttribute | null {\n if (this.identityAttributes[attributeName]) {\n return this.identityAttributes[attributeName];\n }\n return null;\n }\n\n /**\n * Set the value of the given attribute\n * If an empty value ('' || null || false) is given, the attribute is removed from the ID\n * @param attributeName string\n * @param attributeValue any\n */\n setAttribute(\n attributeName: string,\n attributeValue: string | Record<string, string>\n ): void {\n if (!attributeValue) {\n return;\n }\n\n if (this.identityAttributes[attributeName]) {\n this.updateExistingAttribute(attributeName, attributeValue);\n } else {\n this.createNewAttribute(attributeName, attributeValue);\n }\n }\n\n /**\n * Unset the given attribute from the ID\n * @param attributeName\n */\n unsetAttribute(attributeName: string): void {\n delete this.identityAttributes[attributeName];\n }\n\n /**\n * Add an attribute to this identity\n * @param attributeName\n * @param value\n * @param nonce\n */\n addAttribute(attributeName: string, value: string, nonce = \"\"): void {\n let nonceToUse = nonce;\n if (!nonce) {\n nonceToUse = Utils.getRandomString();\n }\n\n this.identityAttributes[attributeName] = {\n value,\n nonce: nonceToUse,\n };\n }\n\n /**\n * Get all attribute URNs for this ID\n * @returns {string}\n */\n getAttributeUrns(): string {\n let urns = \"\";\n for (const key in this.identityAttributes) {\n const urn = this.getAttributeUrn(key);\n if (urn) {\n urns += `${urn}\\n`;\n }\n }\n return urns;\n }\n\n /**\n * Create and return the attribute URN for the given attribute\n * @param attributeName\n * @returns {string|null}\n */\n getAttributeUrn(attributeName: string): string | null {\n const attribute = this.identityAttributes[attributeName];\n if (attribute) {\n return `urn:bap:id:${attributeName}:${attribute.value}:${attribute.nonce}`;\n }\n return null;\n }\n\n /**\n * Parse a text of URN string into identity attributes\n * @param urnIdentityAttributes\n */\n protected parseStringUrns(urnIdentityAttributes: string): IdentityAttributes {\n const identityAttributes: IdentityAttributes = {};\n const attributesRaw = urnIdentityAttributes\n .replace(/^\\s+/g, \"\")\n .replace(/\\r/gm, \"\")\n .split(\"\\n\");\n\n for (const line of attributesRaw) {\n const attribute = line.replace(/^\\s+/g, \"\").replace(/\\s+$/g, \"\");\n const urn = attribute.split(\":\");\n if (\n urn[0] === \"urn\" &&\n urn[1] === \"bap\" &&\n urn[2] === \"id\" &&\n urn[3] &&\n urn[4] &&\n urn[5]\n ) {\n identityAttributes[urn[3]] = {\n value: urn[4],\n nonce: urn[5],\n };\n }\n }\n\n return identityAttributes;\n }\n\n /**\n * Helper function to parse identity attributes\n * @param identityAttributes\n * @returns {IdentityAttributes}\n */\n protected parseAttributes(\n identityAttributes: IdentityAttributes | string\n ): IdentityAttributes {\n if (typeof identityAttributes === \"string\") {\n return this.parseStringUrns(identityAttributes);\n }\n\n for (const key in identityAttributes) {\n if (!identityAttributes[key].value || !identityAttributes[key].nonce) {\n throw new Error(\"Invalid identity attribute\");\n }\n }\n\n return identityAttributes || {};\n }\n\n /**\n * Helper method to update an existing attribute\n */\n protected updateExistingAttribute(\n attributeName: string,\n attributeValue: string | Record<string, string>\n ): void {\n if (typeof attributeValue === \"string\") {\n this.identityAttributes[attributeName].value = attributeValue;\n return;\n }\n\n this.identityAttributes[attributeName].value = attributeValue.value || \"\";\n if (attributeValue.nonce) {\n this.identityAttributes[attributeName].nonce = attributeValue.nonce;\n }\n }\n\n /**\n * Helper method to create a new attribute\n */\n protected createNewAttribute(\n attributeName: string,\n attributeValue: string | Record<string, string>\n ): void {\n if (typeof attributeValue === \"string\") {\n this.addAttribute(attributeName, attributeValue);\n return;\n }\n\n this.addAttribute(\n attributeName,\n attributeValue.value || \"\",\n attributeValue.nonce\n );\n }\n\n /**\n * Construct an AIP buffer from the op return data\n * @param opReturn\n * @returns {number[]} Array of numbers representing the buffer\n */\n protected getAIPMessageBuffer(\n opReturn: number[][],\n indicies?: number[]\n ): number[][] {\n // locate the position of OP_RETURN in the opReturn array\n let opReturnIndex = opReturn.findIndex((op) => op[0] === OP.OP_RETURN);\n const buffers: number[][] = [];\n\n // include OP_RETURN in constructing the signature buffer\n if (opReturnIndex === -1) {\n buffers.push([OP.OP_RETURN]);\n opReturnIndex = 0;\n }\n\n // if indicies is specified, only include the specified indicies in the buffer\n // relative to the position of OP_RETURN as \"0\"\n if (indicies) {\n for (const index of indicies) {\n buffers.push(opReturn[opReturnIndex + index]);\n }\n } else {\n for (const op of opReturn) {\n buffers.push(op);\n }\n }\n\n return buffers;\n }\n\n /**\n * Helper method to format AIP output\n * @param opReturn Original OP_RETURN data\n * @param address Signing address\n * @param signature Base64 signature\n * @returns Formatted AIP output as number[]\n */\n protected formatAIPOutput(\n opReturnBuffers: number[][],\n address: string,\n signature: string\n ): number[][] {\n // Add AIP protocol elements\n const aipElements = [\n toArray(\"|\"),\n toArray(AIP_BITCOM_ADDRESS),\n toArray(\"BITCOIN_ECDSA\"),\n toArray(address),\n toArray(signature, \"base64\"),\n ];\n\n // Concatenate all buffers\n return [...opReturnBuffers, ...aipElements];\n }\n}\n\nexport { BaseClass };\n"
12
12
  ],
13
- "mappings": "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",
14
- "debugId": "306220F242D9E24D64756E2164756E21",
13
+ "mappings": "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",
14
+ "debugId": "EC17FE5341FA56FC64756E2164756E21",
15
15
  "names": []
16
16
  }
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,27 @@
1
1
  import type { PathPrefix } from "./interface.js";
2
+ /**
3
+ * Derive a BAP ID from a Bitcoin address (rootAddress).
4
+ *
5
+ * BAP ID = base58(ripemd160(sha256(rootAddress)))
6
+ *
7
+ * This is the canonical derivation used by MasterID.deriveIdentityKey().
8
+ * The address MUST be the rootAddress (from the BAP member key), not a
9
+ * signing key address.
10
+ */
11
+ export declare function bapIdFromAddress(address: string): string;
12
+ /**
13
+ * Derive a BAP ID from a compressed public key (hex).
14
+ *
15
+ * Converts the pubkey to a Bitcoin address, then derives the BAP ID.
16
+ *
17
+ * IMPORTANT: This only produces a correct BAP ID when the pubkey is the
18
+ * BAP member key's public key. It does NOT work with signing keys or
19
+ * arbitrary public keys.
20
+ *
21
+ * In BRC-100 wallets, the BRC-31 identity key IS the member key's pubkey,
22
+ * so this correctly bridges BRC-31 auth to BAP identity lookups.
23
+ */
24
+ export declare function bapIdFromPubkey(pubkeyHex: string): string;
2
25
  export declare const Utils: {
3
26
  /**
4
27
  * Helper function to generate cryptographically secure random bytes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bsv-bap",
3
- "version": "0.1.21",
3
+ "version": "0.1.22",
4
4
  "description": "BAP npm module",
5
5
  "repository": {
6
6
  "type": "git",