From f35afb7787b3eb34374362c6396eda6c6775c0a3 Mon Sep 17 00:00:00 2001 From: ChanceBarimbao Date: Tue, 9 Sep 2025 13:53:59 -0700 Subject: [PATCH 1/7] set originator --- src/auth/clients/AuthFetch.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/auth/clients/AuthFetch.ts b/src/auth/clients/AuthFetch.ts index 24a0d940..54a7dd84 100644 --- a/src/auth/clients/AuthFetch.ts +++ b/src/auth/clients/AuthFetch.ts @@ -55,6 +55,7 @@ export class AuthFetch { this.wallet = wallet this.requestedCertificates = requestedCertificates this.sessionManager = sessionManager ?? new SessionManager() + this.originator = originator } /** From 1b06115684129f64ad0e764d500c50a45f67fde0 Mon Sep 17 00:00:00 2001 From: ChanceBarimbao Date: Tue, 9 Sep 2025 14:17:53 -0700 Subject: [PATCH 2/7] 1.7.6 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b5f375a3..1868fbf8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@bsv/sdk", - "version": "1.7.5", + "version": "1.7.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@bsv/sdk", - "version": "1.7.5", + "version": "1.7.6", "license": "SEE LICENSE IN LICENSE.txt", "devDependencies": { "@eslint/js": "^9.23.0", diff --git a/package.json b/package.json index 56b92012..fc13419b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bsv/sdk", - "version": "1.7.5", + "version": "1.7.6", "type": "module", "description": "BSV Blockchain Software Development Kit", "main": "dist/cjs/mod.js", From 1b0e1f8de787fdb3d5cead2e64cebde6e1ac8390 Mon Sep 17 00:00:00 2001 From: ChanceBarimbao Date: Tue, 9 Sep 2025 14:25:40 -0700 Subject: [PATCH 3/7] Update CHANGELOG --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c3a40c5..40b266ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. The format ## Table of Contents - [Unreleased](#unreleased) +- [1.7.6 - 2025-09-09](#176---2025-09-08) - [1.7.5 - 2025-09-08](#175---2025-09-08) - [1.7.4 - 2025-09-08](#174---2025-09-08) - [1.7.3 - 2025-09-05](#173---2025-09-05) @@ -156,6 +157,13 @@ All notable changes to this project will be documented in this file. The format ### Security +--- +### [1.7.6] - 2025-09-09 + +### Fixed + +- Set the originator of AuthFetch within the constructor so it properly uses originator. + --- ### [1.7.5] - 2025-09-08 From 4daa5a970f824c3499d5cdaa2e4ebe963280625a Mon Sep 17 00:00:00 2001 From: ChanceBarimbao Date: Tue, 9 Sep 2025 14:25:48 -0700 Subject: [PATCH 4/7] lint --- src/auth/__tests/Peer.test.ts | 18 +- src/auth/certificates/Certificate.ts | 12 +- src/auth/certificates/MasterCertificate.ts | 26 +- .../certificates/VerifiableCertificate.ts | 8 +- .../__tests/CompletedProtoWallet.ts | 44 +- .../__tests/VerifiableCertificate.test.ts | 4 +- src/auth/clients/AuthFetch.ts | 45 +- src/auth/utils/createNonce.ts | 2 +- src/auth/utils/verifyNonce.ts | 2 +- src/identity/__tests/IdentityClient.test.ts | 66 +-- src/identity/types/index.ts | 2 +- src/kvstore/__tests/LocalKVStore.test.ts | 41 +- .../__tests/SymmetricKeyCompatibility.test.ts | 8 +- src/primitives/__tests/utils.test.ts | 14 +- src/registry/__tests/RegistryClient.test.ts | 61 ++- src/registry/types/index.ts | 2 +- src/script/templates/P2PKH.ts | 12 +- src/script/templates/PushDrop.ts | 16 +- src/script/templates/RPuzzle.ts | 24 +- src/storage/__tests/StorageDownloader.test.ts | 402 +++++++++--------- src/storage/__tests/StorageUploader.test.ts | 4 +- src/transaction/__tests/Beef.test.ts | 4 +- src/transaction/__tests/Transaction.test.ts | 30 +- src/transaction/broadcasters/ARC.ts | 14 +- .../broadcasters/DefaultBroadcaster.ts | 2 +- src/transaction/broadcasters/Teranode.ts | 4 +- .../broadcasters/WhatsOnChainBroadcaster.ts | 4 +- .../chaintrackers/BlockHeadersService.ts | 26 +- .../chaintrackers/DefaultChainTracker.ts | 2 +- src/transaction/chaintrackers/WhatsOnChain.ts | 8 +- .../fee-models/SatoshisPerKilobyte.ts | 4 +- src/transaction/http/BinaryFetchClient.ts | 10 +- src/transaction/http/DefaultHttpClient.ts | 4 +- src/transaction/http/FetchHttpClient.ts | 2 +- src/transaction/http/NodejsHttpClient.ts | 4 +- src/wallet/substrates/HTTPWalletJSON.ts | 94 ++-- src/wallet/substrates/HTTPWalletWire.ts | 4 +- src/wallet/substrates/ReactNativeWebView.ts | 349 ++++++++------- src/wallet/substrates/WalletWireProcessor.ts | 18 +- .../substrates/WalletWireTransceiver.ts | 110 ++--- src/wallet/substrates/XDM.ts | 346 +++++++-------- .../substrates/__tests/toOriginHeader.test.ts | 26 +- src/wallet/substrates/utils/toOriginHeader.ts | 4 +- src/wallet/substrates/window.CWI.ts | 346 +++++++-------- 44 files changed, 1113 insertions(+), 1115 deletions(-) diff --git a/src/auth/__tests/Peer.test.ts b/src/auth/__tests/Peer.test.ts index 8c82339b..ba3edbc2 100644 --- a/src/auth/__tests/Peer.test.ts +++ b/src/auth/__tests/Peer.test.ts @@ -18,12 +18,12 @@ class LocalTransport implements Transport { private peerTransport?: LocalTransport private onDataCallback?: (message: AuthMessage) => void - connect(peerTransport: LocalTransport): void { + connect (peerTransport: LocalTransport): void { this.peerTransport = peerTransport peerTransport.peerTransport = this } - async send(message: AuthMessage): Promise { + async send (message: AuthMessage): Promise { if ( this.peerTransport?.onDataCallback !== undefined && this.peerTransport?.onDataCallback !== null @@ -37,18 +37,18 @@ class LocalTransport implements Transport { } } - async onData( + async onData ( callback: (message: AuthMessage) => void ): Promise { this.onDataCallback = callback } } -function waitForNextGeneralMessage ( +async function waitForNextGeneralMessage ( peer: Peer, handler?: (senderPublicKey: string, payload: number[]) => void ): Promise { - return new Promise(resolve => { + return await new Promise(resolve => { const listenerId = peer.listenForGeneralMessages((senderPublicKey, payload) => { peer.stopListeningForGeneralMessages(listenerId) if (handler !== undefined) handler(senderPublicKey, payload) @@ -84,7 +84,7 @@ describe('Peer class mutual authentication and certificate exchange', () => { libraryCardNumber: 'B654321' } - async function createMasterCertificate( + async function createMasterCertificate ( subjectWallet: WalletInterface, fields: Record ): Promise { @@ -111,7 +111,7 @@ describe('Peer class mutual authentication and certificate exchange', () => { return masterCertificate } - async function createVerifiableCertificate( + async function createVerifiableCertificate ( masterCertificate: MasterCertificate, wallet: WalletInterface, verifierIdentityKey: string, @@ -144,7 +144,7 @@ describe('Peer class mutual authentication and certificate exchange', () => { ) } - function setupPeers( + function setupPeers ( aliceRequests: boolean, bobRequests: boolean, options: { @@ -185,7 +185,7 @@ describe('Peer class mutual authentication and certificate exchange', () => { return { aliceReceivedCertificates, bobReceivedCertificates } } - async function mockGetVerifiableCertificates( + async function mockGetVerifiableCertificates ( aliceCertificate: VerifiableCertificate | undefined, bobCertificate: VerifiableCertificate | undefined, alicePubKey: string, diff --git a/src/auth/certificates/Certificate.ts b/src/auth/certificates/Certificate.ts index ff17e638..3616954c 100644 --- a/src/auth/certificates/Certificate.ts +++ b/src/auth/certificates/Certificate.ts @@ -62,7 +62,7 @@ export default class Certificate { * @param {Record} fields - All the fields present in the certificate. * @param {HexString} signature - Certificate signature by the certifier's private key, DER encoded hex string. */ - constructor( + constructor ( type: Base64String, serialNumber: Base64String, subject: PubKeyHex, @@ -86,7 +86,7 @@ export default class Certificate { * @param {boolean} [includeSignature=true] - Whether to include the signature in the serialization. * @returns {number[]} - The serialized certificate in binary format. */ - toBinary(includeSignature: boolean = true): number[] { + toBinary (includeSignature: boolean = true): number[] { const writer = new Utils.Writer() // Write type (Base64String, 32 bytes) @@ -144,7 +144,7 @@ export default class Certificate { * @param {number[]} bin - The binary data representing the certificate. * @returns {Certificate} - The deserialized Certificate object. */ - static fromBinary(bin: number[]): Certificate { + static fromBinary (bin: number[]): Certificate { const reader = new Utils.Reader(bin) // Read type @@ -210,7 +210,7 @@ export default class Certificate { * * @returns {Promise} - A promise that resolves to true if the signature is valid. */ - async verify(): Promise { + async verify (): Promise { // A verifier can be any wallet capable of verifying signatures const verifier = new ProtoWallet('anyone') const verificationData = this.toBinary(false) // Exclude the signature from the verification data @@ -234,7 +234,7 @@ export default class Certificate { * @param {Wallet} certifierWallet - The wallet representing the certifier. * @returns {Promise} */ - async sign(certifierWallet: ProtoWallet): Promise { + async sign (certifierWallet: ProtoWallet): Promise { if (this.signature != null && this.signature.length > 0) { // ✅ Explicitly checking for null/undefined throw new Error( `Certificate has already been signed! Signature present: ${this.signature}` @@ -271,7 +271,7 @@ export default class Certificate { * - `keyID` (string): A unique key identifier. It is the `fieldName` if `serialNumber` is undefined, * otherwise it is a combination of `serialNumber` and `fieldName`. */ - static getCertificateFieldEncryptionDetails( + static getCertificateFieldEncryptionDetails ( fieldName: string, serialNumber?: string ): { protocolID: WalletProtocol, keyID: string } { diff --git a/src/auth/certificates/MasterCertificate.ts b/src/auth/certificates/MasterCertificate.ts index 89da9ee2..e57212df 100644 --- a/src/auth/certificates/MasterCertificate.ts +++ b/src/auth/certificates/MasterCertificate.ts @@ -4,7 +4,7 @@ import { HexString, OutpointString, PubKeyHex, - WalletCounterparty, + WalletCounterparty } from '../../wallet/Wallet.interfaces.js' import Certificate from './Certificate.js' import * as Utils from '../../primitives/utils.js' @@ -36,7 +36,7 @@ export class MasterCertificate extends Certificate { masterKeyring: Record - constructor( + constructor ( type: Base64String, serialNumber: Base64String, subject: PubKeyHex, @@ -77,14 +77,14 @@ export class MasterCertificate extends Certificate { * @param {WalletCounterparty} certifierOrSubject - The certifier or subject who will validate the certificate fields. * @param {Record} fields - A record of certificate field names (under 50 bytes) mapped to their values. * @param {BooleanDefaultFalse} [privileged] - Whether this is a privileged request. - * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. * + * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. * * @returns {Promise} A promise resolving to an object containing: * - `certificateFields` {Record}: * The encrypted certificate fields. * - `masterKeyring` {Record}: * The master keyring containing encrypted revelation keys for each field. */ - static async createCertificateFields( + static async createCertificateFields ( creatorWallet: ProtoWallet, certifierOrSubject: WalletCounterparty, fields: Record, @@ -92,12 +92,12 @@ export class MasterCertificate extends Certificate { privilegedReason?: string ): Promise { const certificateFields: Record< - CertificateFieldNameUnder50Bytes, - Base64String + CertificateFieldNameUnder50Bytes, + Base64String > = {} const masterKeyring: Record< - CertificateFieldNameUnder50Bytes, - Base64String + CertificateFieldNameUnder50Bytes, + Base64String > = {} for (const [fieldName, fieldValue] of Object.entries(fields)) { const fieldSymmetricKey = SymmetricKey.fromRandom() @@ -139,13 +139,13 @@ export class MasterCertificate extends Certificate { * @param {string} [originator] - Optional originator identifier, used if additional context is needed for decryption and encryption operations. * @returns {Promise>} - A keyring mapping field names to encrypted field revelation keys, allowing the verifier to decrypt specified fields. * @param {BooleanDefaultFalse} [privileged] - Whether this is a privileged request. - * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. * + * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. * * @throws {Error} Throws an error if: * - fieldsToReveal is not an array of strings. * - A field in `fieldsToReveal` does not exist in the certificate. * - The decrypted master field key fails to decrypt the corresponding field (indicating an invalid key). */ - static async createKeyringForVerifier( + static async createKeyringForVerifier ( subjectWallet: ProtoWallet, certifier: WalletCounterparty, verifier: WalletCounterparty, @@ -225,7 +225,7 @@ export class MasterCertificate extends Certificate { * * @throws {Error} Throws an error if any operation (e.g., encryption, signing) fails during certificate issuance. */ - static async issueCertificateForSubject( + static async issueCertificateForSubject ( certifierWallet: ProtoWallet, subject: WalletCounterparty, fields: Record, @@ -281,7 +281,7 @@ export class MasterCertificate extends Certificate { * * @throws {Error} Throws an error if the `masterKeyring` is invalid or if decryption fails for any field. */ - static async decryptFields( + static async decryptFields ( subjectOrCertifierWallet: ProtoWallet, masterKeyring: Record, fields: Record, @@ -315,7 +315,7 @@ export class MasterCertificate extends Certificate { } } - static async decryptField( + static async decryptField ( subjectOrCertifierWallet: ProtoWallet, masterKeyring: Record, fieldName: Base64String, diff --git a/src/auth/certificates/VerifiableCertificate.ts b/src/auth/certificates/VerifiableCertificate.ts index e9be8c0f..28b9278b 100644 --- a/src/auth/certificates/VerifiableCertificate.ts +++ b/src/auth/certificates/VerifiableCertificate.ts @@ -5,7 +5,7 @@ import type { HexString, OutpointString, WalletCertificate, - OriginatorDomainNameStringUnder250Bytes, + OriginatorDomainNameStringUnder250Bytes } from '../../wallet/Wallet.interfaces.js' import SymmetricKey from '../../primitives/SymmetricKey.js' import * as Utils from '../../primitives/utils.js' @@ -28,7 +28,7 @@ export class VerifiableCertificate extends Certificate { keyring: Record decryptedFields?: Record - constructor( + constructor ( type: Base64String, serialNumber: Base64String, subject: PubKeyHex, @@ -59,7 +59,7 @@ export class VerifiableCertificate extends Certificate { * @returns {VerifiableCertificate} – A fully-formed instance containing the * original certificate data plus the supplied keyring. */ - static fromCertificate( + static fromCertificate ( certificate: WalletCertificate, keyring: Record ): VerifiableCertificate { @@ -83,7 +83,7 @@ export class VerifiableCertificate extends Certificate { * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. * @throws {Error} Throws an error if any of the decryption operations fail, with a message indicating the failure context. */ - async decryptFields( + async decryptFields ( verifierWallet: ProtoWallet, privileged?: boolean, privilegedReason?: string, diff --git a/src/auth/certificates/__tests/CompletedProtoWallet.ts b/src/auth/certificates/__tests/CompletedProtoWallet.ts index 41ad6495..28a1d910 100644 --- a/src/auth/certificates/__tests/CompletedProtoWallet.ts +++ b/src/auth/certificates/__tests/CompletedProtoWallet.ts @@ -1,4 +1,4 @@ -//@ts-nocheck +// @ts-nocheck import PrivateKey from '../../../primitives/PrivateKey.js' import { ProtoWallet, @@ -33,7 +33,7 @@ export class CompletedProtoWallet extends ProtoWallet implements WalletInterface { keyDeriver: KeyDeriver - constructor(rootKeyOrKeyDeriver: PrivateKey | 'anyone' | KeyDeriverApi) { + constructor (rootKeyOrKeyDeriver: PrivateKey | 'anyone' | KeyDeriverApi) { super(rootKeyOrKeyDeriver) if (rootKeyOrKeyDeriver instanceof KeyDeriver) { @@ -48,30 +48,30 @@ export class CompletedProtoWallet } } - async isAuthenticated( + async isAuthenticated ( ): Promise { throw new Error('not implemented') } - async waitForAuthentication( + async waitForAuthentication ( ): Promise { throw new Error('not implemented') } - async getNetwork( + async getNetwork ( ): Promise { throw new Error('not implemented') } - async getVersion( + async getVersion ( ): Promise { throw new Error('not implemented') } - async getPublicKey( + async getPublicKey ( args: GetPublicKeyArgs ): Promise<{ publicKey: PubKeyHex }> { if (args.privileged === true) { @@ -110,91 +110,91 @@ export class CompletedProtoWallet } } - async createAction( + async createAction ( ): Promise { throw new Error('not implemented') } - async signAction( + async signAction ( ): Promise { throw new Error('not implemented') } - async abortAction( + async abortAction ( ): Promise { throw new Error('not implemented') } - async listActions( + async listActions ( ): Promise { throw new Error('not implemented') } - async internalizeAction( + async internalizeAction ( ): Promise { throw new Error('not implemented') } - async listOutputs( + async listOutputs ( ): Promise { throw new Error('not implemented') } - async relinquishOutput( + async relinquishOutput ( ): Promise { throw new Error('not implemented') } - async acquireCertificate( + async acquireCertificate ( ): Promise { throw new Error('not implemented') } - async listCertificates( + async listCertificates ( ): Promise { throw new Error('not implemented') } - async proveCertificate( + async proveCertificate ( ): Promise { throw new Error('not implemented') } - async relinquishCertificate( + async relinquishCertificate ( ): Promise { throw new Error('not implemented') } - async discoverByIdentityKey( + async discoverByIdentityKey ( ): Promise { throw new Error('not implemented') } - async discoverByAttributes( + async discoverByAttributes ( ): Promise { throw new Error('not implemented') } - async getHeight( + async getHeight ( ): Promise { throw new Error('not implemented') } - async getHeaderForHeight( + async getHeaderForHeight ( ): Promise { throw new Error('not implemented') diff --git a/src/auth/certificates/__tests/VerifiableCertificate.test.ts b/src/auth/certificates/__tests/VerifiableCertificate.test.ts index e3b8761b..7b1c0c2d 100644 --- a/src/auth/certificates/__tests/VerifiableCertificate.test.ts +++ b/src/auth/certificates/__tests/VerifiableCertificate.test.ts @@ -150,7 +150,7 @@ describe('VerifiableCertificate', () => { expect(decrypted).toEqual(plaintextFields) }) }) - + describe('fromCertificate', () => { it('should create an equivalent VerifiableCertificate and decrypt correctly', async () => { const baseCert = new Certificate( @@ -160,7 +160,7 @@ describe('VerifiableCertificate', () => { verifiableCert.certifier, verifiableCert.revocationOutpoint, verifiableCert.fields, - verifiableCert.signature + verifiableCert.signature ) as WalletCertificate const verifiable = VerifiableCertificate.fromCertificate( diff --git a/src/auth/clients/AuthFetch.ts b/src/auth/clients/AuthFetch.ts index 54a7dd84..0e3d6cb0 100644 --- a/src/auth/clients/AuthFetch.ts +++ b/src/auth/clients/AuthFetch.ts @@ -33,7 +33,7 @@ const PAYMENT_VERSION = '1.0' * AuthFetch provides a lightweight fetch client for interacting with servers * over a simplified HTTP transport mechanism. It integrates session management, peer communication, * and certificate handling to enable secure and mutually-authenticated requests. - * + * * Additionally, it automatically handles 402 Payment Required responses by creating * and sending BSV payment transactions when necessary. */ @@ -51,7 +51,7 @@ export class AuthFetch { * @param wallet - The wallet instance for signing and authentication. * @param requestedCertificates - Optional set of certificates to request from peers. */ - constructor(wallet: WalletInterface, requestedCertificates?: RequestedCertificateSet, sessionManager?: SessionManager, originator?: OriginatorDomainNameStringUnder250Bytes) { + constructor (wallet: WalletInterface, requestedCertificates?: RequestedCertificateSet, sessionManager?: SessionManager, originator?: OriginatorDomainNameStringUnder250Bytes) { this.wallet = wallet this.requestedCertificates = requestedCertificates this.sessionManager = sessionManager ?? new SessionManager() @@ -60,18 +60,18 @@ export class AuthFetch { /** * Mutually authenticates and sends a HTTP request to a server. - * + * * 1) Attempt the request. * 2) If 402 Payment Required, automatically create and send payment. * 3) Return the final response. - * + * * @param url - The URL to send the request to. * @param config - Configuration options for the request, including method, headers, and body. * @returns A promise that resolves with the server's response, structured as a Response-like object. - * + * * @throws Will throw an error if unsupported headers are used or other validation fails. */ - async fetch(url: string, config: SimplifiedFetchRequestOptions = {}): Promise { + async fetch (url: string, config: SimplifiedFetchRequestOptions = {}): Promise { if (typeof config.retryCounter === 'number') { if (config.retryCounter <= 0) { throw new Error('Request failed after maximum number of retries.') @@ -189,7 +189,7 @@ export class AuthFetch { // Create the Response object const responseValue = new Response( - responseBody ? new Uint8Array(responseBody) : null, + (responseBody != null) ? new Uint8Array(responseBody) : null, { status: statusCode, statusText: `${statusCode}`, @@ -231,7 +231,6 @@ export class AuthFetch { try { const response = await this.handleFetchAndValidate(url, config, peerToUse) resolve(response) - return } catch (fetchError) { reject(fetchError) } @@ -254,14 +253,14 @@ export class AuthFetch { /** * Request Certificates from a Peer - * @param baseUrl - * @param certificatesToRequest + * @param baseUrl + * @param certificatesToRequest */ - async sendCertificateRequest(baseUrl: string, certificatesToRequest: RequestedCertificateSet): Promise { + async sendCertificateRequest (baseUrl: string, certificatesToRequest: RequestedCertificateSet): Promise { const parsedUrl = new URL(baseUrl) const baseURL = parsedUrl.origin - let peerToUse: { peer: Peer; identityKey?: string } + let peerToUse: { peer: Peer, identityKey?: string } if (typeof this.peers[baseURL] !== 'undefined') { peerToUse = { peer: this.peers[baseURL].peer } } else { @@ -300,7 +299,7 @@ export class AuthFetch { /** * Return any certificates we've collected thus far, then clear them out. */ - public consumeReceivedCertificates(): VerifiableCertificate[] { + public consumeReceivedCertificates (): VerifiableCertificate[] { return this.certificatesReceived.splice(0) } @@ -316,7 +315,7 @@ export class AuthFetch { * * @throws Will throw an error if unsupported headers are used or serialization fails. */ - private async serializeRequest( + private async serializeRequest ( method: string, headers: Record, body: any, @@ -399,7 +398,7 @@ export class AuthFetch { if (methodsThatTypicallyHaveBody.includes(method.toUpperCase()) && body === undefined) { // Check if content-type is application/json const contentTypeHeader = includedHeaders.find(([k]) => k === 'content-type') - if (contentTypeHeader && contentTypeHeader[1].includes('application/json')) { + if ((contentTypeHeader != null) && contentTypeHeader[1].includes('application/json')) { body = '{}' } else { body = '' @@ -417,10 +416,10 @@ export class AuthFetch { return writer } - /** + /** * Handles a non-authenticated fetch requests and validates that the server is not claiming to be authenticated. */ - private async handleFetchAndValidate(url: string, config: RequestInit, peerToUse: AuthPeer): Promise { + private async handleFetchAndValidate (url: string, config: RequestInit, peerToUse: AuthPeer): Promise { const response = await fetch(url, config) response.headers.forEach(header => { if (header.toLocaleLowerCase().startsWith('x-bsv')) { @@ -440,7 +439,7 @@ export class AuthFetch { * If we get 402 Payment Required, we build a transaction via wallet.createAction() * and re-attempt the request with an x-bsv-payment header. */ - private async handlePaymentAndRetry( + private async handlePaymentAndRetry ( url: string, config: SimplifiedFetchRequestOptions = {}, originalResponse: Response @@ -498,10 +497,8 @@ export class AuthFetch { } }, this.originator) - - // Attach the payment to the request headers - config.headers = config.headers || {} + config.headers = (config.headers != null) || {} config.headers['x-bsv-payment'] = JSON.stringify({ derivationPrefix, derivationSuffix, @@ -510,10 +507,10 @@ export class AuthFetch { config.retryCounter ??= 3 // Re-attempt request with payment attached - return this.fetch(url, config) + return await this.fetch(url, config) } - private async normalizeBodyToNumberArray(body: BodyInit | null | undefined): Promise { + private async normalizeBodyToNumberArray (body: BodyInit | null | undefined): Promise { // 0. Null / undefined if (body == null) { return [] @@ -548,7 +545,7 @@ export class AuthFetch { // 6. FormData if (body instanceof FormData) { - const entries: [string, string][] = [] + const entries: Array<[string, string]> = [] body.forEach((value, key) => { entries.push([key, value.toString()]) }) diff --git a/src/auth/utils/createNonce.ts b/src/auth/utils/createNonce.ts index 1f4c9450..840275b0 100644 --- a/src/auth/utils/createNonce.ts +++ b/src/auth/utils/createNonce.ts @@ -13,7 +13,7 @@ import Random from '../../primitives/Random.js' * @param counterparty - The counterparty to the nonce creation. Defaults to 'self'. * @returns A random nonce derived with a wallet */ -export async function createNonce( +export async function createNonce ( wallet: WalletInterface, counterparty: WalletCounterparty = 'self', originator?: OriginatorDomainNameStringUnder250Bytes diff --git a/src/auth/utils/verifyNonce.ts b/src/auth/utils/verifyNonce.ts index a4835fc2..dad80805 100644 --- a/src/auth/utils/verifyNonce.ts +++ b/src/auth/utils/verifyNonce.ts @@ -8,7 +8,7 @@ import { WalletInterface, WalletCounterparty, Base64String, OriginatorDomainName * @param counterparty - The counterparty to the nonce creation. Defaults to 'self'. * @returns The status of the validation */ -export async function verifyNonce( +export async function verifyNonce ( nonce: Base64String, wallet: WalletInterface, counterparty: WalletCounterparty = 'self', diff --git a/src/identity/__tests/IdentityClient.test.ts b/src/identity/__tests/IdentityClient.test.ts index 3d65f02f..a51b7f91 100644 --- a/src/identity/__tests/IdentityClient.test.ts +++ b/src/identity/__tests/IdentityClient.test.ts @@ -256,7 +256,7 @@ describe('IdentityClient', () => { } // Mock ContactsManager to return contact for the specific identity key - const mockContactsManager = identityClient['contactsManager'] + const mockContactsManager = identityClient.contactsManager mockContactsManager.getContacts = jest.fn().mockResolvedValue([contact]) walletMock.discoverByIdentityKey = jest.fn().mockResolvedValue({ certificates: [discoveredCertificate] }) @@ -352,7 +352,7 @@ describe('IdentityClient', () => { } // Mock the ContactsManager's getContacts method instead of the IdentityClient method - const mockContactsManager = identityClient['contactsManager'] + const mockContactsManager = identityClient.contactsManager mockContactsManager.getContacts = jest.fn().mockResolvedValue([contact]) walletMock.discoverByAttributes = jest.fn().mockResolvedValue({ certificates: [discoveredCertificate] }) @@ -367,11 +367,15 @@ describe('IdentityClient', () => { { name: 'Alice Smith', identityKey: 'alice-key', - avatarURL: '', abbreviatedKey: 'alice-i...', badgeIconURL: '', badgeLabel: '', badgeClickURL: '' + avatarURL: '', + abbreviatedKey: 'alice-i...', + badgeIconURL: '', + badgeLabel: '', + badgeClickURL: '' } ] - const mockContactsManager = identityClient['contactsManager'] + const mockContactsManager = identityClient.contactsManager mockContactsManager.getContacts = jest.fn().mockResolvedValue(contacts) const identities = await identityClient.resolveByAttributes({ attributes: { name: '', email: ' ' } }) @@ -384,7 +388,11 @@ describe('IdentityClient', () => { { name: 'Alice Smith (Personal)', identityKey: 'alice-key', - avatarURL: '', abbreviatedKey: 'alice-i...', badgeIconURL: '', badgeLabel: '', badgeClickURL: '' + avatarURL: '', + abbreviatedKey: 'alice-i...', + badgeIconURL: '', + badgeLabel: '', + badgeClickURL: '' } ] @@ -402,7 +410,7 @@ describe('IdentityClient', () => { } } - const mockContactsManager = identityClient['contactsManager'] + const mockContactsManager = identityClient.contactsManager mockContactsManager.getContacts = jest.fn().mockResolvedValue(contacts) walletMock.discoverByAttributes = jest.fn().mockResolvedValue({ certificates: [discoveredCertificate] }) @@ -566,13 +574,13 @@ describe('IdentityClient', () => { } ; (walletMock.listOutputs as jest.Mock).mockResolvedValueOnce({ - outputs: [existingOutput], - BEEF: [1, 2, 3] - }) + outputs: [existingOutput], + BEEF: [1, 2, 3] + }) - ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ - plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) - }) + ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ + plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) + }) const updatedContact = { ...mockContact, name: 'Alice Updated' } await identityClient.saveContact(updatedContact) @@ -622,13 +630,13 @@ describe('IdentityClient', () => { } ; (walletMock.listOutputs as jest.Mock).mockResolvedValue({ - outputs: [mockOutput], - BEEF: [1, 2, 3] - }) + outputs: [mockOutput], + BEEF: [1, 2, 3] + }) - ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ - plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) - }) + ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ + plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) + }) const result = await identityClient.getContacts() @@ -656,11 +664,11 @@ describe('IdentityClient', () => { }) await identityClient.saveContact(mockContact) - // Mock empty result for force refresh - ; (walletMock.listOutputs as jest.Mock).mockResolvedValue({ - outputs: [], - BEEF: [] - }) + // Mock empty result for force refresh + ; (walletMock.listOutputs as jest.Mock).mockResolvedValue({ + outputs: [], + BEEF: [] + }) const result = await identityClient.getContacts(undefined, true) @@ -719,13 +727,13 @@ describe('IdentityClient', () => { } ; (walletMock.listOutputs as jest.Mock).mockResolvedValue({ - outputs: [mockOutput], - BEEF: [1, 2, 3] - }) + outputs: [mockOutput], + BEEF: [1, 2, 3] + }) - ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ - plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) - }) + ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ + plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) + }) await identityClient.removeContact(mockContact.identityKey) diff --git a/src/identity/types/index.ts b/src/identity/types/index.ts index 5fae0150..092539d6 100644 --- a/src/identity/types/index.ts +++ b/src/identity/types/index.ts @@ -1,4 +1,4 @@ -import { WalletProtocol } from "../../wallet/index.js" +import { WalletProtocol } from '../../wallet/index.js' export const defaultIdentity: DisplayableIdentity = { name: 'Unknown Identity', diff --git a/src/kvstore/__tests/LocalKVStore.test.ts b/src/kvstore/__tests/LocalKVStore.test.ts index 839d73f1..abe5f547 100644 --- a/src/kvstore/__tests/LocalKVStore.test.ts +++ b/src/kvstore/__tests/LocalKVStore.test.ts @@ -157,16 +157,15 @@ describe('localKVStore', () => { BEEF: undefined } - const lookupValueReal = kvStore['lookupValue'] - kvStore['lookupValue'] = jest.fn().mockResolvedValue({ + const lookupValueReal = kvStore.lookupValue + kvStore.lookupValue = jest.fn().mockResolvedValue({ value: defaultValue, outpoint: undefined, lor: mockedLor }) - const result = await kvStore.get(testKey, defaultValue) - kvStore['lookupValue'] = lookupValueReal + kvStore.lookupValue = lookupValueReal expect(result).toBe(defaultValue) }) @@ -180,16 +179,15 @@ describe('localKVStore', () => { BEEF: undefined } - const lookupValueReal = kvStore['lookupValue'] - kvStore['lookupValue'] = jest.fn().mockResolvedValue({ + const lookupValueReal = kvStore.lookupValue + kvStore.lookupValue = jest.fn().mockResolvedValue({ value: defaultValue, outpoint: undefined, lor: mockedLor }) - const result = await kvStore.get(testKey, defaultValue) - kvStore['lookupValue'] = lookupValueReal + kvStore.lookupValue = lookupValueReal expect(result).toBe(defaultValue) }) @@ -233,7 +231,7 @@ describe('localKVStore', () => { testKey, 'self' ) - //expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions' }) + // expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions' }) // Verify createAction for NEW output expect(mockWallet.createAction).toHaveBeenCalledWith({ description: `Update ${testKey} in ${testContext}`, @@ -277,13 +275,13 @@ describe('localKVStore', () => { testKey, 'self' ) - //expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions' }) + // expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions' }) expect(mockWallet.createAction).toHaveBeenCalledWith({ description: `Update ${testKey} in ${testContext}`, inputBEEF: undefined, inputs: [], outputs: [{ - basket: "test-kv-context", + basket: 'test-kv-context', tags: ['myTestKey'], lockingScript: testLockingScriptHex, // From mock lock satoshis: 1, @@ -301,7 +299,7 @@ describe('localKVStore', () => { it('should update an existing output (spend and create)', async () => { const existingOutpoint = 'oldTxId.0' const existingOutput = { outpoint: existingOutpoint, txid: 'oldTxId', vout: 0, lockingScript: 'oldScriptHex' } // Added script - const mockBEEF = [1,2,3,4,5,6] + const mockBEEF = [1, 2, 3, 4, 5, 6] const signableRef = 'signableTxRef123' const signableTx = [] const updatedTxId = 'updatedTxId' @@ -337,8 +335,8 @@ describe('localKVStore', () => { BEEF: mockBEEF } - const lookupValueReal = kvStore['lookupValue'] - kvStore['lookupValue'] = jest.fn().mockResolvedValue({ + const lookupValueReal = kvStore.lookupValue + kvStore.lookupValue = jest.fn().mockResolvedValue({ value: 'oldValue', outpoint: existingOutpoint, lor: mockedLor @@ -350,7 +348,7 @@ describe('localKVStore', () => { */ const result = await kvStore.set(testKey, testValue) - kvStore['lookupValue'] = lookupValueReal + kvStore.lookupValue = lookupValueReal expect(result).toBe(`${updatedTxId}.0`) // Assuming output 0 is the new KV token expect(mockWallet.encrypt).toHaveBeenCalled() @@ -395,7 +393,7 @@ describe('localKVStore', () => { const existingOutpoint2 = 'oldTxId2.1' const existingOutput1 = { outpoint: existingOutpoint1, txid: 'oldTxId1', vout: 0, lockingScript: 's1' } const existingOutput2 = { outpoint: existingOutpoint2, txid: 'oldTxId2', vout: 1, lockingScript: 's2' } - const mockBEEF = [1,2,3,4,5,6] + const mockBEEF = [1, 2, 3, 4, 5, 6] const signableRef = 'signableTxRefMulti' const signableTx = [] const updatedTxId = 'updatedTxIdMulti' @@ -433,15 +431,15 @@ describe('localKVStore', () => { BEEF: mockBEEF } - const lookupValueReal = kvStore['lookupValue'] - kvStore['lookupValue'] = jest.fn().mockResolvedValue({ + const lookupValueReal = kvStore.lookupValue + kvStore.lookupValue = jest.fn().mockResolvedValue({ value: 'oldValue', outpoint: existingOutpoint2, lor: mockedLor }) const result = await kvStore.set(testKey, testValue) - kvStore['lookupValue'] = lookupValueReal + kvStore.lookupValue = lookupValueReal expect(result).toBe(`${updatedTxId}.0`) expect(mockWallet.encrypt).toHaveBeenCalled() @@ -536,7 +534,7 @@ describe('localKVStore', () => { const result = await kvStore.remove(testKey) expect(result).toEqual([removalTxId]) - //expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions', limit: undefined, tagsQueryMode: 'all' }) + // expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions', limit: undefined, tagsQueryMode: 'all' }) // Verify createAction for REMOVE (no outputs in the action) expect(mockWallet.createAction).toHaveBeenCalledWith({ @@ -604,11 +602,10 @@ describe('localKVStore', () => { expect(mockWallet.listOutputs).toHaveBeenCalled() expect(mockWallet.createAction).toHaveBeenCalled() // createAction called for removal attempt expect(MockedTransaction.fromAtomicBEEF).toHaveBeenCalled() - //expect(mockPDInstance.unlock).toHaveBeenCalledTimes(1) // unlock was called + // expect(mockPDInstance.unlock).toHaveBeenCalledTimes(1) // unlock was called const mockUnlocker = (mockPDInstance.unlock as jest.Mock).mock.results[0].value expect(mockUnlocker.sign).toHaveBeenCalledTimes(1) // sign was called expect(mockWallet.signAction).toHaveBeenCalled() // Called but failed - }) }) }) diff --git a/src/primitives/__tests/SymmetricKeyCompatibility.test.ts b/src/primitives/__tests/SymmetricKeyCompatibility.test.ts index 24e61b25..bbd8b117 100644 --- a/src/primitives/__tests/SymmetricKeyCompatibility.test.ts +++ b/src/primitives/__tests/SymmetricKeyCompatibility.test.ts @@ -33,7 +33,7 @@ describe('Cross-SDK Compatibility Tests', () => { } ] - testCases.forEach(({name, ciphertextHex}) => { + testCases.forEach(({ name, ciphertextHex }) => { // Convert hex to byte array const ciphertext: number[] = [] for (let i = 0; i < ciphertextHex.length; i += 2) { @@ -79,7 +79,7 @@ describe('Cross-SDK Compatibility Tests', () => { } ] - testCases.forEach(({name, ciphertextHex}) => { + testCases.forEach(({ name, ciphertextHex }) => { // Convert hex to byte array const ciphertext: number[] = [] for (let i = 0; i < ciphertextHex.length; i += 2) { @@ -112,7 +112,7 @@ describe('Cross-SDK Compatibility Tests', () => { } ] - testCases.forEach(({name, wif, expectedKeyLength, goCiphertext, tsCiphertext}) => { + testCases.forEach(({ name, wif, expectedKeyLength, goCiphertext, tsCiphertext }) => { // Create symmetric key const privKey = PrivateKey.fromWif(wif) const pubKey = privKey.toPublicKey() @@ -147,4 +147,4 @@ describe('Cross-SDK Compatibility Tests', () => { }) }) }) -}) \ No newline at end of file +}) diff --git a/src/primitives/__tests/utils.test.ts b/src/primitives/__tests/utils.test.ts index a0303f81..5e5f1852 100644 --- a/src/primitives/__tests/utils.test.ts +++ b/src/primitives/__tests/utils.test.ts @@ -159,33 +159,33 @@ describe('utils', () => { }) test('should return an empty array for an empty string', () => { - expect(toArray("")).toEqual([]) + expect(toArray('')).toEqual([]) }) test('should encode ASCII characters correctly', () => { - const input = "Hello, World!" + const input = 'Hello, World!' const expected = [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33] expect(toArray(input)).toEqual(expected) }) test('should encode 2-byte characters correctly', () => { // "é" (U+00E9) should encode to [0xC3, 0xA9] - expect(toArray("é")).toEqual([0xC3, 0xA9]) + expect(toArray('é')).toEqual([0xC3, 0xA9]) }) test('should encode 3-byte characters correctly', () => { // "€" (U+20AC) should encode to [0xE2, 0x82, 0xAC] - expect(toArray("€")).toEqual([0xE2, 0x82, 0xAC]) + expect(toArray('€')).toEqual([0xE2, 0x82, 0xAC]) }) test('should encode 4-byte characters correctly', () => { // "😃" (U+1F603) should encode to [0xF0, 0x9F, 0x98, 0x83] - expect(toArray("😃")).toEqual([0xF0, 0x9F, 0x98, 0x83]) + expect(toArray('😃')).toEqual([0xF0, 0x9F, 0x98, 0x83]) }) test('should encode mixed content correctly', () => { // "Hello, 😃! €" contains ASCII, an emoji, and a 3-byte character. - const input = "Hello, 😃! €" + const input = 'Hello, 😃! €' const expected = [ // "Hello, " => ASCII bytes: 72, 101, 108, 108, 111, 44, 32, @@ -202,7 +202,7 @@ describe('utils', () => { test('should replace lone surrogates with the replacement character', () => { // An unpaired high surrogate "\uD800" should be replaced with U+FFFD, // which is encoded in UTF-8 as [0xEF, 0xBF, 0xBD] - const input = "\uD800" + const input = '\uD800' const expected = [0xEF, 0xBF, 0xBD] expect(toArray(input)).toEqual(expected) }) diff --git a/src/registry/__tests/RegistryClient.test.ts b/src/registry/__tests/RegistryClient.test.ts index 18147eac..73d9168f 100644 --- a/src/registry/__tests/RegistryClient.test.ts +++ b/src/registry/__tests/RegistryClient.test.ts @@ -99,7 +99,7 @@ let walletMock: Partial /** * Build minimal valid DefinitionData for each type */ -function buildDefinitionData(type: DefinitionType): DefinitionData { +function buildDefinitionData (type: DefinitionType): DefinitionData { switch (type) { case 'basket': { const data: BasketDefinitionData = { @@ -288,23 +288,23 @@ describe('RegistryClient', () => { }) })) - // The code expects 7 fields for basket (6 definition fields + 1 extra signature field) - ; (PushDrop.decode as jest.Mock).mockReturnValue({ - fields: [ - [98], // 'b' - [97], // 'a' - [115], // 's' - [107], // 'k' - [101], // 'e' - [116], // 't' => operator - [111] // extra signature field - ] - }) + // The code expects 7 fields for basket (6 definition fields + 1 extra signature field) + ; (PushDrop.decode as jest.Mock).mockReturnValue({ + fields: [ + [98], // 'b' + [97], // 'a' + [115], // 's' + [107], // 'k' + [101], // 'e' + [116], // 't' => operator + [111] // extra signature field + ] + }) - // The final field must match the current wallet pubkey => 'mockPublicKey' - ; (walletMock.getPublicKey as jest.Mock).mockResolvedValueOnce({ - publicKey: 't' - }) + // The final field must match the current wallet pubkey => 'mockPublicKey' + ; (walletMock.getPublicKey as jest.Mock).mockResolvedValueOnce({ + publicKey: 't' + }) const result = await registryClient.resolve('basket', { basketID: 'whatever' }) expect(result).toHaveLength(1) @@ -330,10 +330,10 @@ describe('RegistryClient', () => { }) })) - // Return empty fields so parseLockingScript fails the length check - ; (PushDrop.decode as jest.Mock) - .mockReturnValueOnce({ fields: [] }) // fail - .mockReturnValueOnce({ fields: [] }) // fail again + // Return empty fields so parseLockingScript fails the length check + ; (PushDrop.decode as jest.Mock) + .mockReturnValueOnce({ fields: [] }) // fail + .mockReturnValueOnce({ fields: [] }) // fail again const result = await registryClient.resolve('basket', { name: 'fooAgain' }) expect(result).toEqual([]) @@ -376,35 +376,34 @@ describe('RegistryClient', () => { (PushDrop.decode as jest.Mock).mockImplementation((scriptObj) => { return { fields: [ - [98], // 'b' - [97], // 'a' + [98], // 'b' + [97], // 'a' [115], // 's' [107], // 'k' [101], // 'e' [116], // 't' - [111] // extra signature field + [111] // extra signature field ] } }); - (walletMock.getPublicKey as jest.Mock).mockResolvedValue({ publicKey: 't' }); // <-- Semicolon + (walletMock.getPublicKey as jest.Mock).mockResolvedValue({ publicKey: 't' }) // <-- Semicolon - const records = await registryClient.listOwnRegistryEntries('basket'); + const records = await registryClient.listOwnRegistryEntries('basket') expect(walletMock.listOutputs).toHaveBeenCalledWith({ basket: 'basketmap', include: 'entire transactions' - }); + }) // Only one spendable item should be returned if parsing succeeds. - expect(records).toHaveLength(1); + expect(records).toHaveLength(1) expect(records[0]).toMatchObject({ definitionType: 'basket', txid: 'skipMe', outputIndex: 2, satoshis: 200, lockingScript: 'decodedLockScript1AsHex' - }); - }); - + }) + }) }) // ------------------------------------------------------------------ diff --git a/src/registry/types/index.ts b/src/registry/types/index.ts index 42132f7d..ce84bfd3 100644 --- a/src/registry/types/index.ts +++ b/src/registry/types/index.ts @@ -71,7 +71,7 @@ export interface TokenData { txid: string outputIndex: number satoshis: number - lockingScript: string, + lockingScript: string beef: BEEF } diff --git a/src/script/templates/P2PKH.ts b/src/script/templates/P2PKH.ts index aa567ff9..bda8d7c0 100644 --- a/src/script/templates/P2PKH.ts +++ b/src/script/templates/P2PKH.ts @@ -9,7 +9,7 @@ import TransactionSignature from '../../primitives/TransactionSignature.js' import { sha256 } from '../../primitives/Hash.js' import Script from '../Script.js' -function verifyTruthy(v: T | undefined): T { +function verifyTruthy (v: T | undefined): T { if (v == null) throw new Error('must have value') return v } @@ -26,7 +26,7 @@ export default class P2PKH implements ScriptTemplate { * @param {number[] | string} pubkeyhash or address - An array or address representing the public key hash. * @returns {LockingScript} - A P2PKH locking script. */ - lock(pubkeyhash: string | number[]): LockingScript { + lock (pubkeyhash: string | number[]): LockingScript { let data: number[] if (typeof pubkeyhash === 'string') { const hash = fromBase58Check(pubkeyhash) @@ -64,16 +64,16 @@ export default class P2PKH implements ScriptTemplate { * @param {Script} lockingScript - Optional. The lockinScript. Otherwise the input.sourceTransaction is required. * @returns {Object} - An object containing the `sign` and `estimateLength` functions. */ - unlock( + unlock ( privateKey: PrivateKey, signOutputs: 'all' | 'none' | 'single' = 'all', anyoneCanPay: boolean = false, sourceSatoshis?: number, lockingScript?: Script ): { - sign: (tx: Transaction, inputIndex: number) => Promise - estimateLength: () => Promise<108> - } { + sign: (tx: Transaction, inputIndex: number) => Promise + estimateLength: () => Promise<108> + } { return { sign: async (tx: Transaction, inputIndex: number) => { let signatureScope = TransactionSignature.SIGHASH_FORKID diff --git a/src/script/templates/PushDrop.ts b/src/script/templates/PushDrop.ts index a2ac6cb9..54dd7780 100644 --- a/src/script/templates/PushDrop.ts +++ b/src/script/templates/PushDrop.ts @@ -9,7 +9,7 @@ import { import { WalletInterface, SecurityLevel } from '../../wallet/Wallet.interfaces.js' import { Transaction } from '../../transaction/index.js' -function verifyTruthy(v: T | undefined): T { +function verifyTruthy (v: T | undefined): T { if (v == null) throw new Error('must have value') return v } @@ -65,7 +65,7 @@ export default class PushDrop implements ScriptTemplate { * @param script PushDrop script to decode back into token fields * @returns An object containing PushDrop token fields and the locking public key. If a signature was included, it will be the last field. */ - static decode(script: LockingScript): { + static decode (script: LockingScript): { lockingPublicKey: PublicKey fields: number[][] } { @@ -108,7 +108,7 @@ export default class PushDrop implements ScriptTemplate { * @param {WalletInterface} wallet - The wallet interface used for creating signatures and accessing public keys. * @param {string} originator — The originator to use with Wallet requests */ - constructor(wallet: WalletInterface, originator?: string) { + constructor (wallet: WalletInterface, originator?: string) { this.wallet = wallet this.originator = originator } @@ -124,7 +124,7 @@ export default class PushDrop implements ScriptTemplate { * @param {boolean} [includeSignature=true] - Flag indicating if a signature should be included in the script (default yes). * @returns {Promise} The generated PushDrop locking script. */ - async lock( + async lock ( fields: number[][], protocolID: [SecurityLevel, string], keyID: string, @@ -187,7 +187,7 @@ export default class PushDrop implements ScriptTemplate { * @param {boolean} [anyoneCanPay=false] - Specifies if the anyone-can-pay flag is set. * @returns {Object} An object containing functions to sign the transaction and estimate the script length. */ - unlock( + unlock ( protocolID: [SecurityLevel, string], keyID: string, counterparty: string, @@ -196,9 +196,9 @@ export default class PushDrop implements ScriptTemplate { sourceSatoshis?: number, lockingScript?: LockingScript ): { - sign: (tx: Transaction, inputIndex: number) => Promise - estimateLength: () => Promise<73> - } { + sign: (tx: Transaction, inputIndex: number) => Promise + estimateLength: () => Promise<73> + } { return { sign: async ( tx: Transaction, diff --git a/src/script/templates/RPuzzle.ts b/src/script/templates/RPuzzle.ts index 993f32d1..f4dd4ef5 100644 --- a/src/script/templates/RPuzzle.ts +++ b/src/script/templates/RPuzzle.ts @@ -24,14 +24,14 @@ export default class RPuzzle implements ScriptTemplate { * * @param {'raw'|'SHA1'|'SHA256'|'HASH256'|'RIPEMD160'|'HASH160'} type Denotes the type of puzzle to create */ - constructor( + constructor ( type: - | 'raw' - | 'SHA1' - | 'SHA256' - | 'HASH256' - | 'RIPEMD160' - | 'HASH160' = 'raw' + | 'raw' + | 'SHA1' + | 'SHA256' + | 'HASH256' + | 'RIPEMD160' + | 'HASH160' = 'raw' ) { this.type = type } @@ -42,7 +42,7 @@ export default class RPuzzle implements ScriptTemplate { * @param {number[]} value - An array representing the R value or its hash. * @returns {LockingScript} - An R puzzle locking script. */ - lock(value: number[]): LockingScript { + lock (value: number[]): LockingScript { const chunks: ScriptChunk[] = [ { op: OP.OP_OVER }, { op: OP.OP_3 }, @@ -79,15 +79,15 @@ export default class RPuzzle implements ScriptTemplate { * @param {boolean} anyoneCanPay - Flag indicating if the signature allows for other inputs to be added later. * @returns {Object} - An object containing the `sign` and `estimateLength` functions. */ - unlock( + unlock ( k: BigNumber, privateKey: PrivateKey, signOutputs: 'all' | 'none' | 'single' = 'all', anyoneCanPay: boolean = false ): { - sign: (tx: Transaction, inputIndex: number) => Promise - estimateLength: () => Promise<108> - } { + sign: (tx: Transaction, inputIndex: number) => Promise + estimateLength: () => Promise<108> + } { return { sign: async (tx: Transaction, inputIndex: number) => { if (typeof privateKey === 'undefined') { diff --git a/src/storage/__tests/StorageDownloader.test.ts b/src/storage/__tests/StorageDownloader.test.ts index 13fe769f..28bf1fe4 100644 --- a/src/storage/__tests/StorageDownloader.test.ts +++ b/src/storage/__tests/StorageDownloader.test.ts @@ -3,234 +3,232 @@ import { StorageUtils } from '../index.js' import { LookupResolver } from '../../overlay-tools/index.js' import Transaction from '../../transaction/Transaction.js' import PushDrop from '../../script/templates/PushDrop.js' -import { PublicKey } from '../../primitives/index.js' -import { Utils } from '../../primitives/index.js' +import { PublicKey, Utils } from '../../primitives/index.js' + import { ReadableStream } from 'stream/web' beforeEach(() => { - jest.restoreAllMocks() + jest.restoreAllMocks() }) describe('StorageDownloader', () => { - let downloader: StorageDownloader - - beforeEach(() => { - // Create a fresh instance - downloader = new StorageDownloader() + let downloader: StorageDownloader + + beforeEach(() => { + // Create a fresh instance + downloader = new StorageDownloader() + }) + + describe('resolve()', () => { + it('throws if the lookup response is not "output-list"', async () => { + // Mock the LookupResolver to return something invalid + jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ + type: 'something-else', + outputs: [] + } as any) + + await expect(downloader.resolve('fakeUhrpUrl')) + .rejects + .toThrow('Lookup answer must be an output list') }) - describe('resolve()', () => { - it('throws if the lookup response is not "output-list"', async () => { - // Mock the LookupResolver to return something invalid - jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ - type: 'something-else', - outputs: [] - } as any) - - await expect(downloader.resolve('fakeUhrpUrl')) - .rejects - .toThrow('Lookup answer must be an output list') - }) - - it('decodes each output with Transaction.fromBEEF and PushDrop.decode', async () => { - // 1) Mock lookup response - jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ - type: 'output-list', - outputs: [ - { beef: 'fake-beef-a', outputIndex: 0 }, - { beef: 'fake-beef-b', outputIndex: 1 } - ] - } as any) - - // 2) Mock Transaction.fromBEEF -> returns a dummy transaction - jest.spyOn(Transaction, 'fromBEEF').mockImplementation(() => { - // Each transaction might have multiple outputs; we only care about `outputIndex` - return { - outputs: [ - { lockingScript: {} }, // index 0 - { lockingScript: {} } // index 1 - ] - } as any - }) - - // 3) Mock PushDrop.decode -> returns { fields: number[][] } - jest.spyOn(PushDrop, 'decode').mockImplementation(() => { - // The decode function returns an object with `fields`, - return { - lockingPublicKey: {} as PublicKey, - fields: [ - [11], - [22], - [104, 116, 116, 112, 58, 47, 47, 97, 46, 99, 111, 109] - ] - } - }) - - // 4) Mock Utils.toUTF8 to convert that number[] to a string - jest.spyOn(Utils, 'toUTF8').mockReturnValue('http://a.com') - - const resolved = await downloader.resolve('fakeUhrpUrl') - expect(resolved).toEqual(['http://a.com', 'http://a.com']) - }) + it('decodes each output with Transaction.fromBEEF and PushDrop.decode', async () => { + // 1) Mock lookup response + jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ + type: 'output-list', + outputs: [ + { beef: 'fake-beef-a', outputIndex: 0 }, + { beef: 'fake-beef-b', outputIndex: 1 } + ] + } as any) + + // 2) Mock Transaction.fromBEEF -> returns a dummy transaction + jest.spyOn(Transaction, 'fromBEEF').mockImplementation(() => { + // Each transaction might have multiple outputs; we only care about `outputIndex` + return { + outputs: [ + { lockingScript: {} }, // index 0 + { lockingScript: {} } // index 1 + ] + } as any + }) + + // 3) Mock PushDrop.decode -> returns { fields: number[][] } + jest.spyOn(PushDrop, 'decode').mockImplementation(() => { + // The decode function returns an object with `fields`, + return { + lockingPublicKey: {} as PublicKey, + fields: [ + [11], + [22], + [104, 116, 116, 112, 58, 47, 47, 97, 46, 99, 111, 109] + ] + } + }) + + // 4) Mock Utils.toUTF8 to convert that number[] to a string + jest.spyOn(Utils, 'toUTF8').mockReturnValue('http://a.com') + + const resolved = await downloader.resolve('fakeUhrpUrl') + expect(resolved).toEqual(['http://a.com', 'http://a.com']) + }) + }) + describe('download()', () => { + it('throws if UHRP URL is invalid', async () => { + jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(false) + await expect(downloader.download('invalidUrl')) + .rejects + .toThrow('Invalid parameter UHRP url') }) - describe('download()', () => { - it('throws if UHRP URL is invalid', async () => { - jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(false) - - await expect(downloader.download('invalidUrl')) - .rejects - .toThrow('Invalid parameter UHRP url') - }) + it('throws if no hosts are found', async () => { + // Valid UHRP URL + jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) + // Return some random 32-byte hash so we can pass the check + jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) - it('throws if no hosts are found', async () => { - // Valid UHRP URL - jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) - // Return some random 32-byte hash so we can pass the check - jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) + // Force resolve() to return an empty array + jest.spyOn(downloader, 'resolve').mockResolvedValue([]) - // Force resolve() to return an empty array - jest.spyOn(downloader, 'resolve').mockResolvedValue([]) + await expect(downloader.download('validButUnhostedUrl')) + .rejects + .toThrow('No one currently hosts this file!') + }) - await expect(downloader.download('validButUnhostedUrl')) - .rejects - .toThrow('No one currently hosts this file!') - }) + it('downloads successfully from the first working host', async () => { + jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) + const knownHash = [ + 102, 104, 122, 173, 248, 98, 189, 119, 108, 143, + 193, 139, 142, 159, 142, 32, 8, 151, 20, 133, + 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, + 41, 37 + ] + jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(knownHash) + + // Suppose two possible download URLs + jest.spyOn(downloader, 'resolve').mockResolvedValue([ + 'http://host1/404', + 'http://host2/ok' + ]) + + // The first fetch -> 404, second fetch -> success + const fetchSpy = jest.spyOn(global, 'fetch') + .mockResolvedValueOnce(new Response(null, { status: 404 })) + .mockResolvedValueOnce(new Response(new Uint8Array(32).fill(0), { + status: 200, + headers: { 'Content-Type': 'application/test' } + })) + + const result = await downloader.download('validUrl') + expect(fetchSpy).toHaveBeenCalledTimes(2) + expect(result).toEqual({ + data: new Uint8Array(32).fill(0), + mimeType: 'application/test' + }) + }) - it('downloads successfully from the first working host', async () => { - jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) - const knownHash = [ - 102, 104, 122, 173, 248, 98, 189, 119, 108, 143, - 193, 139, 142, 159, 142, 32, 8, 151, 20, 133, - 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, - 41, 37 - ] - jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(knownHash) - - // Suppose two possible download URLs - jest.spyOn(downloader, 'resolve').mockResolvedValue([ - 'http://host1/404', - 'http://host2/ok' - ]) - - // The first fetch -> 404, second fetch -> success - const fetchSpy = jest.spyOn(global, 'fetch') - .mockResolvedValueOnce(new Response(null, { status: 404 })) - .mockResolvedValueOnce(new Response(new Uint8Array(32).fill(0), { - status: 200, - headers: { 'Content-Type': 'application/test' } - })) - - const result = await downloader.download('validUrl') - expect(fetchSpy).toHaveBeenCalledTimes(2) - expect(result).toEqual({ - data: new Uint8Array(32).fill(0), - mimeType: 'application/test' - }) - }) + it('throws if content hash mismatches the UHRP hash', async () => { + jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) + // The expected hash is all zeros + jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) - it('throws if content hash mismatches the UHRP hash', async () => { - jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) - // The expected hash is all zeros - jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) + // One potential host + jest.spyOn(downloader, 'resolve').mockResolvedValue([ + 'http://bad-content.test' + ]) - // One potential host - jest.spyOn(downloader, 'resolve').mockResolvedValue([ - 'http://bad-content.test' - ]) + // The fetch returns 32 bytes of all 1's => hash mismatch + jest.spyOn(global, 'fetch').mockResolvedValue( + new Response(new Uint8Array(32).fill(1), { status: 200 }) + ) - // The fetch returns 32 bytes of all 1's => hash mismatch - jest.spyOn(global, 'fetch').mockResolvedValue( - new Response(new Uint8Array(32).fill(1), { status: 200 }) - ) + await expect(downloader.download('validButBadHashUrl')) + .rejects + .toThrow() + }) - await expect(downloader.download('validButBadHashUrl')) - .rejects - .toThrow() - }) + it('throws if all hosts fail or mismatch', async () => { + jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) + jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) - it('throws if all hosts fail or mismatch', async () => { - jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) - jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) + jest.spyOn(downloader, 'resolve').mockResolvedValue([ + 'http://host1.test', + 'http://host2.test' + ]) - jest.spyOn(downloader, 'resolve').mockResolvedValue([ - 'http://host1.test', - 'http://host2.test' - ]) + // Both fetches fail with 500 or something >=400 + jest.spyOn(global, 'fetch').mockResolvedValue( + new Response(null, { status: 500 }) + ) - // Both fetches fail with 500 or something >=400 - jest.spyOn(global, 'fetch').mockResolvedValue( - new Response(null, { status: 500 }) - ) + await expect(downloader.download('validButNoGoodHostUrl')) + .rejects + .toThrow('Unable to download content from validButNoGoodHostUrl') + }) - await expect(downloader.download('validButNoGoodHostUrl')) - .rejects - .toThrow('Unable to download content from validButNoGoodHostUrl') - }) + it('throws if all entries are expired', async () => { + const currentTime = Math.floor(Date.now()) + + jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ + type: 'output-list', + outputs: [ + { beef: 'fake-beef-a', outputIndex: 0 }, + { beef: 'fake-beef-b', outputIndex: 1 } + ] + } as any) + + jest.spyOn(Transaction, 'fromBEEF').mockImplementation(() => { + return { + outputs: [ + { lockingScript: {} }, + { lockingScript: {} } + ] + } as any + }) + + jest.spyOn(PushDrop, 'decode').mockImplementation(() => { + return { + lockingPublicKey: {} as PublicKey, + fields: [[], [], [], [currentTime - 100]] + } + }) + + await expect(downloader.resolve('expiredUhrpUrl')) + .resolves + .toEqual(['', '']) + }) - it('throws if all entries are expired', async () => { - const currentTime = Math.floor(Date.now()) - - jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ - type: 'output-list', - outputs: [ - { beef: 'fake-beef-a', outputIndex: 0 }, - { beef: 'fake-beef-b', outputIndex: 1 } - ] - } as any) - - jest.spyOn(Transaction, 'fromBEEF').mockImplementation(() => { - return { - outputs: [ - { lockingScript: {} }, - { lockingScript: {} } - ] - } as any - }) - - jest.spyOn(PushDrop, 'decode').mockImplementation(() => { - return { - lockingPublicKey: {} as PublicKey, - fields: [[], [], [], [currentTime - 100]] - } - }) - - await expect(downloader.resolve('expiredUhrpUrl')) - .resolves - .toEqual(["", ""]) + it.skip('downloads and verifies large streamed content', async () => { + const size = 5 * 1024 * 1024 + const data = new Uint8Array(size) + for (let i = 0; i < size; i++) data[i] = i % 256 + const uhrpUrl = StorageUtils.getURLForFile(data) + + jest.spyOn(downloader, 'resolve').mockResolvedValue(['http://large-file']) + + const chunkSize = 64 * 1024 + const stream = new ReadableStream({ + start (controller) { + for (let offset = 0; offset < data.length; offset += chunkSize) { + controller.enqueue(data.subarray(offset, offset + chunkSize)) + } + controller.close() + } + }) + + jest.spyOn(global, 'fetch').mockResolvedValue( + new Response(stream as any, { + status: 200, + headers: { 'Content-Type': 'application/octet-stream' } }) + ) - it.skip('downloads and verifies large streamed content', async () => { - const size = 5 * 1024 * 1024 - const data = new Uint8Array(size) - for (let i = 0; i < size; i++) data[i] = i % 256 - const uhrpUrl = StorageUtils.getURLForFile(data) - - jest.spyOn(downloader, 'resolve').mockResolvedValue(['http://large-file']) - - const chunkSize = 64 * 1024 - const stream = new ReadableStream({ - start (controller) { - for (let offset = 0; offset < data.length; offset += chunkSize) { - controller.enqueue(data.subarray(offset, offset + chunkSize)) - } - controller.close() - } - }) - - jest.spyOn(global, 'fetch').mockResolvedValue( - new Response(stream as any, { - status: 200, - headers: { 'Content-Type': 'application/octet-stream' } - }) - ) - - const result = await downloader.download(uhrpUrl) - expect(result.mimeType).toBe('application/octet-stream') - expect(result.data.length).toBe(size) - expect(result.data).toEqual(data) - }) + const result = await downloader.download(uhrpUrl) + expect(result.mimeType).toBe('application/octet-stream') + expect(result.data.length).toBe(size) + expect(result.data).toEqual(data) }) + }) }) diff --git a/src/storage/__tests/StorageUploader.test.ts b/src/storage/__tests/StorageUploader.test.ts index 3b3cf87c..8aed612b 100644 --- a/src/storage/__tests/StorageUploader.test.ts +++ b/src/storage/__tests/StorageUploader.test.ts @@ -6,7 +6,7 @@ import { createHash } from 'crypto' /** * A helper for converting a string to a number[] of UTF-8 bytes */ -function stringToUtf8Array(str: string): number[] { +function stringToUtf8Array (str: string): number[] { return Array.from(new TextEncoder().encode(str)) } @@ -27,7 +27,7 @@ describe('StorageUploader Tests', () => { // 1) Spy on the "authFetch.fetch" calls for /find, /list, /renew authFetchSpy = jest - .spyOn(uploader['authFetch'], 'fetch') + .spyOn(uploader.authFetch, 'fetch') .mockResolvedValue(new Response(null, { status: 200 })) // 2) Spy on the global "fetch" calls for file upload (uploadFile) diff --git a/src/transaction/__tests/Beef.test.ts b/src/transaction/__tests/Beef.test.ts index d07c8ee3..7db05bec 100644 --- a/src/transaction/__tests/Beef.test.ts +++ b/src/transaction/__tests/Beef.test.ts @@ -26,7 +26,7 @@ describe('Beef tests', () => { 875732: 'a19c54129ab996c72cda7721b4555b47d11b21e1fe67aa63c59843edb302b6c2', 1651724: - '0fa8e6a2a8860eaec7365217c1cf64a905dc7936342b36a86566f933187f8c62', + '0fa8e6a2a8860eaec7365217c1cf64a905dc7936342b36a86566f933187f8c62' } if (knownRoots[height] !== undefined) { @@ -497,4 +497,4 @@ const log2 = `BEEF with 1 BUMPS and 2 Transactions, isValid true const wrongBumpTxid = '0100beef01fe4e6d0c001002fd909002088a382ec07a8cf47c6158b68e5822852362102d8571482d1257e0b7527e1882fd91900065cb01218f2506bb51155d243e4d6b32d69d1b5f2221c52e26963cfd8cf7283201fd4948008d7a44ae384797b0ae84db0c857e8c1083425d64d09ef8bc5e2e9d270677260501fd25240060f38aa33631c8d70adbac1213e7a5b418c90414e919e3a12ced63dd152fd85a01fd1312005ff132ee64a7a0c79150a29f66ef861e552d3a05b47d6303f5d8a2b2a09bc61501fd080900cc0baf21cf06b9439dfe05dce9bdb14ddc2ca2d560b1138296ef5769851a84b301fd85040063ccb26232a6e1d3becdb47a0f19a67a562b754e8894155b3ae7bba10335ce5101fd430200e153fc455a0f2c8372885c11af70af904dcf44740b9ebf3b3e5b2234cce550bc01fd20010077d5ea69d1dcc379dde65d6adcebde1838190118a8fae928c037275e78bd87910191000263e4f31684a25169857f2788aeef603504931f92585f02c4c9e023b2aa43d1014900de72292e0b3e5eeacfa2b657bf4d46c885559b081ee78632a99b318c1148d85c01250068a5f831ca99b9e7f3720920d6ea977fd2ab52b83d1a6567dafa4c8cafd941ed0113006a0b91d83f9056b702d6a8056af6365c7da626fc3818b815dd4b0de22d05450f0108009876ce56b68545a75859e93d200bdde7880d46f39384818b259ed847a9664ddf010500990bc5e95cacbc927b5786ec39a183f983fe160d52829cf47521c7eb369771c30103004fe794e50305f590b6010a51d050bf47dfeaabfdb949c5ee0673f577a59537d70100004dad44a358aea4d8bc1917912539901f5ae44e07a4748e1a9d3018814b0759d00201000000027b0a1b12c7c9e48015e78d3a08a4d62e439387df7e0d7a810ebd4af37661daaa000000006a47304402207d972759afba7c0ffa6cfbbf39a31c2aeede1dae28d8841db56c6dd1197d56a20220076a390948c235ba8e72b8e43a7b4d4119f1a81a77032aa6e7b7a51be5e13845412103f78ec31cf94ca8d75fb1333ad9fc884e2d489422034a1efc9d66a3b72eddca0fffffffff7f36874f858fb43ffcf4f9e3047825619bad0e92d4b9ad4ba5111d1101cbddfe010000006a473044022043f048043d56eb6f75024808b78f18808b7ab45609e4c4c319e3a27f8246fc3002204b67766b62f58bf6f30ea608eaba76b8524ed49f67a90f80ac08a9b96a6922cd41210254a583c1c51a06e10fab79ddf922915da5f5c1791ef87739f40cb68638397248ffffffff03e8030000000000001976a914b08f70bc5010fb026de018f19e7792385a146b4a88acf3010000000000001976a9147d48635f889372c3da12d75ce246c59f4ab907ed88acf7000000000000001976a914b8fbd58685b6920d8f9a8f1b274d8696708b51b088ac00000000010001000000018ae36502fdc82837319362c488fb9cb978e064daf600bbfc48389663fc5c160c000000006a47304402204a04841f6f626d30e21200e1c404ea80e319b643fe86f08e709413a89a493a4b022038a2e3e25a813d8d540c1a572fa8ec5fa2d2434bcea78d17902dcccddcc1c9484121028fd1afeee81361e801800afb264e35cdce3037ec6f7dc4f1d1eaba7ad519c948ffffffff01c8000000000000001976a9148ce2d21f9a75e98600be76b25b91c4fef6b40bcd88ac0000000000' -const bumpIndexEncoding = '0100beef01fe6e621900010200008cdbd6fe227cfafa6be4500cae6140c84b2ead61318063e92bdb6974f869cf33010259617a9d17562f7c9765e5dfa6a9a393aa2809ca6166a3d7a31c09efcc50701402010000000159617a9d17562f7c9765e5dfa6a9a393aa2809ca6166a3d7a31c09efcc507014130000006b4830450221009399820c643e5f2699b07ffa3289b22c6124e1317fd1ec41fb2431047dcf552f02201b7ee3ee3422fe1c33d8869a34a28fadddb9b790b3c5b332b7fafaaa8d4b413c4121029b15053bc379e2378cd6a84fb40b761b4e400faa4efd09280443731d4b3f8a8cffffffff0201000000000000001976a91423f2562a8092ed24eddc77c74387b44c561692a188ac03000000000000001976a9144ed83e2b3aae481f7fa48321024eb3d8e1f7417888ac00000000000100000001ee353cb1f4cb2b19bf7d2328f3c0a5fa2bd1aa94d0795934dd1d63756583b0ac000000006b4830450221009e779c3f04bb056da180b50ad3972b6fd552c52bd6337f572f08ca656625a4530220648e1fc5872d9bc3846f78edd79b4dc406dfecbab359e46b53c7d478747141684121022280e60c665907fb88a97f5e74dd4e1db0eba60a4dad18158ea8eb9495e242daffffffff2005000000000000001976a914e073bf1bf7b6160f7f68403a374717fdc4cce86d88ac4a000000000000001976a9145bbe83249067ec745d8e270c121c651f56ec2cf188ac42030000000000001976a914983a29113517769da9eace0ec25b760ad09c5f5988ac05000000000000001976a91402c75f3ec99db76e6cd2658a7c83c8bf21a0d14b88ac05000000000000001976a914de454fbce4e1be341d11cd5545664771f72d184088ac25000000000000001976a914b5c2a6831b5cdbc8985517f5d912064449ad118088ac3d010000000000001976a914e4566d91c063f99f7418f12d670b5da320160c8188ac05000000000000001976a914616dc74c3945895eafdac8da9174f95b4d91d75b88ac03010000000000001976a91476ae1c3f2c01a9a5f2aa7696cc9b89ea55b0d01688ac0d000000000000001976a9146d805d21013cc20351e5cd55ecaa7dcee59f2fde88ac05000000000000001976a914613408f68bdde1ff3f77a96abd4956a472766acf88ac21000000000000001976a914d7f0bcfa5b5cad93574a960627db60af8dac277c88ac05000000000000001976a9147e088fe21413442569fa59b6a5bf7e8fe6db71e388ac05000000000000001976a914e5ff336cbffc4ffef544ff4d131de68bf9b0aa1488ac05000000000000001976a9142145b563cd2766ba08d33ca0ecb5a6679268dfb788ac05000000000000001976a914da990487dff4910c8891cebcd00a569011f4f05188ac05000000000000001976a914100daf8fa5add521fb87b46ff51657728626c5fe88ac07000000000000001976a914de900668ddecd73f498c8560b8770231bef9616b88ac05000000000000001976a914dd08ccc14ebdcc534bb2320e7d3dba624a7ecd5388ac05000000000000001976a9141c5b5915e67a840fdcefd0db0ca1a1dfaaf4f3cf88ac06000000000000001976a91441815c6352756937fe6b2b17586dd6b39560321188ac05000000000000001976a91471dca8f8631f145ad5721f8387a764ae0ef2599888ac1d000000000000001976a9147e2621372c66ca3c6e6fca8cdb7eac42405d37fe88ac05000000000000001976a914d745ec07218bde8d179d49e4a6feca7f744f57e388ac05000000000000001976a91499456246822c4270ae73d6c7d8e1af690d1d31dd88ac05000000000000001976a914176dc7f479059d28593021e63bcb66bae6c2cc5388ac05000000000000001976a914a48809ce3c763a0a34c24ab2646fdf10cffdbc6588ac05000000000000001976a914e314da9f12f6bd888da53faa616890a2dce9eeb488ac05000000000000001976a91418f9185bb0ca144d934bd4845b3968d545e7ec8188ac17010000000000001976a9149db831932668077f8eebf597976ec61fc6ab90d588ac09000000000000001976a91479b349601390a6216994d44ca618db71e6e811ef88ac06000000000000001976a91451d25ac626a4b7c281b4200a3dcf34caae43f0df88ac000000000100' \ No newline at end of file +const bumpIndexEncoding = '0100beef01fe6e621900010200008cdbd6fe227cfafa6be4500cae6140c84b2ead61318063e92bdb6974f869cf33010259617a9d17562f7c9765e5dfa6a9a393aa2809ca6166a3d7a31c09efcc50701402010000000159617a9d17562f7c9765e5dfa6a9a393aa2809ca6166a3d7a31c09efcc507014130000006b4830450221009399820c643e5f2699b07ffa3289b22c6124e1317fd1ec41fb2431047dcf552f02201b7ee3ee3422fe1c33d8869a34a28fadddb9b790b3c5b332b7fafaaa8d4b413c4121029b15053bc379e2378cd6a84fb40b761b4e400faa4efd09280443731d4b3f8a8cffffffff0201000000000000001976a91423f2562a8092ed24eddc77c74387b44c561692a188ac03000000000000001976a9144ed83e2b3aae481f7fa48321024eb3d8e1f7417888ac00000000000100000001ee353cb1f4cb2b19bf7d2328f3c0a5fa2bd1aa94d0795934dd1d63756583b0ac000000006b4830450221009e779c3f04bb056da180b50ad3972b6fd552c52bd6337f572f08ca656625a4530220648e1fc5872d9bc3846f78edd79b4dc406dfecbab359e46b53c7d478747141684121022280e60c665907fb88a97f5e74dd4e1db0eba60a4dad18158ea8eb9495e242daffffffff2005000000000000001976a914e073bf1bf7b6160f7f68403a374717fdc4cce86d88ac4a000000000000001976a9145bbe83249067ec745d8e270c121c651f56ec2cf188ac42030000000000001976a914983a29113517769da9eace0ec25b760ad09c5f5988ac05000000000000001976a91402c75f3ec99db76e6cd2658a7c83c8bf21a0d14b88ac05000000000000001976a914de454fbce4e1be341d11cd5545664771f72d184088ac25000000000000001976a914b5c2a6831b5cdbc8985517f5d912064449ad118088ac3d010000000000001976a914e4566d91c063f99f7418f12d670b5da320160c8188ac05000000000000001976a914616dc74c3945895eafdac8da9174f95b4d91d75b88ac03010000000000001976a91476ae1c3f2c01a9a5f2aa7696cc9b89ea55b0d01688ac0d000000000000001976a9146d805d21013cc20351e5cd55ecaa7dcee59f2fde88ac05000000000000001976a914613408f68bdde1ff3f77a96abd4956a472766acf88ac21000000000000001976a914d7f0bcfa5b5cad93574a960627db60af8dac277c88ac05000000000000001976a9147e088fe21413442569fa59b6a5bf7e8fe6db71e388ac05000000000000001976a914e5ff336cbffc4ffef544ff4d131de68bf9b0aa1488ac05000000000000001976a9142145b563cd2766ba08d33ca0ecb5a6679268dfb788ac05000000000000001976a914da990487dff4910c8891cebcd00a569011f4f05188ac05000000000000001976a914100daf8fa5add521fb87b46ff51657728626c5fe88ac07000000000000001976a914de900668ddecd73f498c8560b8770231bef9616b88ac05000000000000001976a914dd08ccc14ebdcc534bb2320e7d3dba624a7ecd5388ac05000000000000001976a9141c5b5915e67a840fdcefd0db0ca1a1dfaaf4f3cf88ac06000000000000001976a91441815c6352756937fe6b2b17586dd6b39560321188ac05000000000000001976a91471dca8f8631f145ad5721f8387a764ae0ef2599888ac1d000000000000001976a9147e2621372c66ca3c6e6fca8cdb7eac42405d37fe88ac05000000000000001976a914d745ec07218bde8d179d49e4a6feca7f744f57e388ac05000000000000001976a91499456246822c4270ae73d6c7d8e1af690d1d31dd88ac05000000000000001976a914176dc7f479059d28593021e63bcb66bae6c2cc5388ac05000000000000001976a914a48809ce3c763a0a34c24ab2646fdf10cffdbc6588ac05000000000000001976a914e314da9f12f6bd888da53faa616890a2dce9eeb488ac05000000000000001976a91418f9185bb0ca144d934bd4845b3968d545e7ec8188ac17010000000000001976a9149db831932668077f8eebf597976ec61fc6ab90d588ac09000000000000001976a91479b349601390a6216994d44ca618db71e6e811ef88ac06000000000000001976a91451d25ac626a4b7c281b4200a3dcf34caae43f0df88ac000000000100' diff --git a/src/transaction/__tests/Transaction.test.ts b/src/transaction/__tests/Transaction.test.ts index 9182055d..151ef6d0 100644 --- a/src/transaction/__tests/Transaction.test.ts +++ b/src/transaction/__tests/Transaction.test.ts @@ -743,7 +743,7 @@ describe('Transaction', () => { status: 200, statusText: 'OK', headers: { - get(key: string) { + get (key: string) { if (key === 'Content-Type') { return 'application/json' } @@ -844,7 +844,7 @@ describe('Transaction', () => { status: 200, statusText: 'OK', headers: { - get(key: string) { + get (key: string) { if (key === 'Content-Type') { return 'application/json' } @@ -1069,7 +1069,7 @@ describe('Transaction', () => { // Create two transactions, one depending on the other const privateKey = new PrivateKey(1) const publicKey = new Curve().g.mul(privateKey) - const publicKeyHash = hash160(publicKey.encode(true)) as number[] + const publicKeyHash = hash160(publicKey.encode(true)) const p2pkh = new P2PKH() const sourceTx = new Transaction( @@ -1166,7 +1166,7 @@ describe('Transaction', () => { it('should serialize a transaction to Atomic BEEF format correctly', async () => { const privateKey = new PrivateKey(1) const publicKey = new Curve().g.mul(privateKey) - const publicKeyHash = hash160(publicKey.encode(true)) as number[] + const publicKeyHash = hash160(publicKey.encode(true)) const p2pkh = new P2PKH() // Create a simple transaction @@ -1237,7 +1237,7 @@ describe('Transaction', () => { // Create two transactions, one depending on the other const privateKey = new PrivateKey(1) const publicKey = new Curve().g.mul(privateKey) - const publicKeyHash = hash160(publicKey.encode(true)) as number[] + const publicKeyHash = hash160(publicKey.encode(true)) const p2pkh = new P2PKH() const sourceTx = new Transaction(1, [], [{ @@ -1294,7 +1294,7 @@ describe('Transaction', () => { tx.addInput({ sourceTXID: '00'.repeat(32), sourceOutputIndex: 0, - unlockingScriptTemplate: new P2PKH().unlock(testPrivateKey), + unlockingScriptTemplate: new P2PKH().unlock(testPrivateKey) }) }) }) @@ -1305,11 +1305,11 @@ describe('Transaction', () => { sourceTransaction.addInput({ sourceTXID: '00'.repeat(32), sourceOutputIndex: 0, - unlockingScript: Script.fromASM('OP_TRUE'), + unlockingScript: Script.fromASM('OP_TRUE') }) sourceTransaction.addOutput({ satoshis: 2, - lockingScript: Script.fromASM('OP_2 OP_MUL ' + 'OP_DUP OP_MUL '.repeat(22) + 'OP_DROP'), + lockingScript: Script.fromASM('OP_2 OP_MUL ' + 'OP_DUP OP_MUL '.repeat(22) + 'OP_DROP') }) await sourceTransaction.sign() @@ -1328,7 +1328,7 @@ describe('Transaction', () => { }) tx.addOutput({ satoshis: 1, - lockingScript: Script.fromASM('OP_NOP'), + lockingScript: Script.fromASM('OP_NOP') }) await tx.fee() await tx.sign() @@ -1345,11 +1345,11 @@ describe('Transaction', () => { sourceTransaction.addInput({ sourceTXID: '00'.repeat(32), sourceOutputIndex: 0, - unlockingScript: Script.fromASM('OP_TRUE'), + unlockingScript: Script.fromASM('OP_TRUE') }) sourceTransaction.addOutput({ satoshis: 2, - lockingScript: new P2PKH().lock(key.toAddress()), + lockingScript: new P2PKH().lock(key.toAddress()) }) await sourceTransaction.sign() @@ -1368,7 +1368,7 @@ describe('Transaction', () => { }) tx.addOutput({ satoshis: 1, - lockingScript: Script.fromASM('OP_NOP'), + lockingScript: Script.fromASM('OP_NOP') }) await tx.fee() await tx.sign() @@ -1384,11 +1384,11 @@ describe('Transaction', () => { sourceTransaction.addInput({ sourceTXID: '00'.repeat(32), sourceOutputIndex: 0, - unlockingScript: Script.fromASM('OP_TRUE'), + unlockingScript: Script.fromASM('OP_TRUE') }) sourceTransaction.addOutput({ satoshis: 2, - lockingScript: Script.fromASM('OP_2 OP_MUL OP_DUP OP_MUL OP_DUP OP_MUL OP_DROP'), + lockingScript: Script.fromASM('OP_2 OP_MUL OP_DUP OP_MUL OP_DUP OP_MUL OP_DROP') }) await sourceTransaction.sign() @@ -1407,7 +1407,7 @@ describe('Transaction', () => { }) tx.addOutput({ satoshis: 1, - lockingScript: Script.fromASM('OP_NOP'), + lockingScript: Script.fromASM('OP_NOP') }) await tx.fee() await tx.sign() diff --git a/src/transaction/broadcasters/ARC.ts b/src/transaction/broadcasters/ARC.ts index 8b899f0e..67b9776c 100644 --- a/src/transaction/broadcasters/ARC.ts +++ b/src/transaction/broadcasters/ARC.ts @@ -25,7 +25,7 @@ export interface ArcConfig { headers?: Record } -function defaultDeploymentId(): string { +function defaultDeploymentId (): string { return `ts-sdk-${toHex(Random(16))}` } @@ -47,16 +47,16 @@ export default class ARC implements Broadcaster { * @param {string} URL - The URL endpoint for the ARC API. * @param {ArcConfig} config - Configuration options for the ARC broadcaster. */ - constructor(URL: string, config?: ArcConfig) + constructor (URL: string, config?: ArcConfig) /** * Constructs an instance of the ARC broadcaster. * * @param {string} URL - The URL endpoint for the ARC API. * @param {string} apiKey - The API key used for authorization with the ARC API. */ - constructor(URL: string, apiKey?: string) + constructor (URL: string, apiKey?: string) - constructor(URL: string, config?: string | ArcConfig) { + constructor (URL: string, config?: string | ArcConfig) { this.URL = URL if (typeof config === 'string') { this.apiKey = config @@ -86,7 +86,7 @@ export default class ARC implements Broadcaster { /** * Constructs a dictionary of the default & supplied request headers. */ - private requestHeaders(): Record { + private requestHeaders (): Record { const headers: Record = { 'Content-Type': 'application/json', 'XDeployment-ID': this.deploymentId @@ -119,7 +119,7 @@ export default class ARC implements Broadcaster { * @param {Transaction} tx - The transaction to be broadcasted. * @returns {Promise} A promise that resolves to either a success or failure response. */ - async broadcast( + async broadcast ( tx: Transaction ): Promise { let rawTx @@ -208,7 +208,7 @@ export default class ARC implements Broadcaster { * @param {Transaction[]} txs - Array of transactions to be broadcasted. * @returns {Promise>} A promise that resolves to an array of objects. */ - async broadcastMany(txs: Transaction[]): Promise { + async broadcastMany (txs: Transaction[]): Promise { const rawTxs = txs.map((tx) => { try { return { rawTx: tx.toHexEF() } diff --git a/src/transaction/broadcasters/DefaultBroadcaster.ts b/src/transaction/broadcasters/DefaultBroadcaster.ts index 89837d66..6363bec4 100644 --- a/src/transaction/broadcasters/DefaultBroadcaster.ts +++ b/src/transaction/broadcasters/DefaultBroadcaster.ts @@ -1,7 +1,7 @@ import { Broadcaster } from '../Broadcaster.js' import ARC, { ArcConfig } from './ARC.js' -export function defaultBroadcaster( +export function defaultBroadcaster ( isTestnet: boolean = false, config: ArcConfig = {} ): Broadcaster { diff --git a/src/transaction/broadcasters/Teranode.ts b/src/transaction/broadcasters/Teranode.ts index cc8edf98..75364685 100644 --- a/src/transaction/broadcasters/Teranode.ts +++ b/src/transaction/broadcasters/Teranode.ts @@ -19,7 +19,7 @@ export default class Teranode implements Broadcaster { * @param {string} URL - The URL endpoint for the Teranode API. * @param {HttpClient} httpClient - The HTTP client used to make requests to the API, binaryHttpClient by default. */ - constructor( + constructor ( URL: string, httpClient: HttpClient = binaryHttpClient() ) { @@ -33,7 +33,7 @@ export default class Teranode implements Broadcaster { * @param {Transaction} tx - The transaction to be broadcasted. * @returns {Promise} A promise that resolves to either a success or failure response. */ - async broadcast( + async broadcast ( tx: Transaction ): Promise { const rawTx = tx.toEF() diff --git a/src/transaction/broadcasters/WhatsOnChainBroadcaster.ts b/src/transaction/broadcasters/WhatsOnChainBroadcaster.ts index 8217324c..e3a97bae 100644 --- a/src/transaction/broadcasters/WhatsOnChainBroadcaster.ts +++ b/src/transaction/broadcasters/WhatsOnChainBroadcaster.ts @@ -21,7 +21,7 @@ export default class WhatsOnChainBroadcaster implements Broadcaster { * @param {'main' | 'test' | 'stn'} network - The BSV network to use when calling the WhatsOnChain API. * @param {HttpClient} httpClient - The HTTP client used to make requests to the API. */ - constructor( + constructor ( network: 'main' | 'test' | 'stn' = 'main', httpClient: HttpClient = defaultHttpClient() ) { @@ -36,7 +36,7 @@ export default class WhatsOnChainBroadcaster implements Broadcaster { * @param {Transaction} tx - The transaction to be broadcasted. * @returns {Promise} A promise that resolves to either a success or failure response. */ - async broadcast( + async broadcast ( tx: Transaction ): Promise { const rawTx = tx.toHex() diff --git a/src/transaction/chaintrackers/BlockHeadersService.ts b/src/transaction/chaintrackers/BlockHeadersService.ts index 0fb9d1ed..1a6ceafd 100644 --- a/src/transaction/chaintrackers/BlockHeadersService.ts +++ b/src/transaction/chaintrackers/BlockHeadersService.ts @@ -30,7 +30,7 @@ interface MerkleRootVerificationResponse { /** * Represents a chain tracker based on a BlockHeadersService API. - * + * * @example * ```typescript * const chainTracker = new BlockHeadersService('https://headers.spv.money', { @@ -45,11 +45,11 @@ export class BlockHeadersService implements ChainTracker { /** * Constructs an instance of the BlockHeadersService ChainTracker. - * + * * @param {string} baseUrl - The base URL for the BlockHeadersService API (e.g. https://headers.spv.money) * @param {BlockHeadersServiceConfig} config - Configuration options for the BlockHeadersService ChainTracker. */ - constructor( + constructor ( baseUrl: string, config: BlockHeadersServiceConfig = {} ) { @@ -61,18 +61,18 @@ export class BlockHeadersService implements ChainTracker { /** * Verifies if a given merkle root is valid for a specific block height. - * + * * @param {string} root - The merkle root to verify. * @param {number} height - The block height to check against. * @returns {Promise} - A promise that resolves to true if the merkle root is valid for the specified block height, false otherwise. */ - async isValidRootForHeight(root: string, height: number): Promise { + async isValidRootForHeight (root: string, height: number): Promise { const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Authorization': `Bearer ${this.apiKey}` + Accept: 'application/json', + Authorization: `Bearer ${this.apiKey}` }, data: [ { @@ -88,7 +88,7 @@ export class BlockHeadersService implements ChainTracker { requestOptions ) - if (response.ok) { + if (response.ok) { return response.data.confirmationState === 'CONFIRMED' } else { throw new Error( @@ -104,15 +104,15 @@ export class BlockHeadersService implements ChainTracker { /** * Gets the current block height from the BlockHeadersService API. - * + * * @returns {Promise} - A promise that resolves to the current block height. */ - async currentHeight(): Promise { + async currentHeight (): Promise { const requestOptions = { method: 'GET', headers: { - 'Accept': 'application/json', - 'Authorization': `Bearer ${this.apiKey}` + Accept: 'application/json', + Authorization: `Bearer ${this.apiKey}` } } @@ -121,7 +121,7 @@ export class BlockHeadersService implements ChainTracker { `${this.baseUrl}/api/v1/chain/tip/longest`, requestOptions ) - + if (response.ok && response.data && typeof response.data.height === 'number') { return response.data.height } else { diff --git a/src/transaction/chaintrackers/DefaultChainTracker.ts b/src/transaction/chaintrackers/DefaultChainTracker.ts index 3de887dd..f5488744 100644 --- a/src/transaction/chaintrackers/DefaultChainTracker.ts +++ b/src/transaction/chaintrackers/DefaultChainTracker.ts @@ -1,6 +1,6 @@ import WhatsOnChain from './WhatsOnChain.js' import ChainTracker from '../ChainTracker.js' -export function defaultChainTracker(): ChainTracker { +export function defaultChainTracker (): ChainTracker { return new WhatsOnChain() } diff --git a/src/transaction/chaintrackers/WhatsOnChain.ts b/src/transaction/chaintrackers/WhatsOnChain.ts index 4e615010..41041b52 100644 --- a/src/transaction/chaintrackers/WhatsOnChain.ts +++ b/src/transaction/chaintrackers/WhatsOnChain.ts @@ -30,7 +30,7 @@ export default class WhatsOnChain implements ChainTracker { * @param {'main' | 'test' | 'stn'} network - The BSV network to use when calling the WhatsOnChain API. * @param {WhatsOnChainConfig} config - Configuration options for the WhatsOnChain ChainTracker. */ - constructor( + constructor ( network: 'main' | 'test' | 'stn' = 'main', config: WhatsOnChainConfig = {} ) { @@ -41,7 +41,7 @@ export default class WhatsOnChain implements ChainTracker { this.apiKey = apiKey ?? '' } - async isValidRootForHeight(root: string, height: number): Promise { + async isValidRootForHeight (root: string, height: number): Promise { const requestOptions = { method: 'GET', headers: this.getHttpHeaders() @@ -63,7 +63,7 @@ export default class WhatsOnChain implements ChainTracker { } } - async currentHeight(): Promise { + async currentHeight (): Promise { try { const requestOptions = { method: 'GET', @@ -88,7 +88,7 @@ export default class WhatsOnChain implements ChainTracker { } } - protected getHttpHeaders(): Record { + protected getHttpHeaders (): Record { const headers: Record = { Accept: 'application/json' } diff --git a/src/transaction/fee-models/SatoshisPerKilobyte.ts b/src/transaction/fee-models/SatoshisPerKilobyte.ts index 760f8dd3..6cba8e6b 100644 --- a/src/transaction/fee-models/SatoshisPerKilobyte.ts +++ b/src/transaction/fee-models/SatoshisPerKilobyte.ts @@ -16,7 +16,7 @@ export default class SatoshisPerKilobyte implements FeeModel { * * @param {number} value - The number of satoshis per kilobyte to charge as a fee. */ - constructor(value: number) { + constructor (value: number) { this.value = value } @@ -26,7 +26,7 @@ export default class SatoshisPerKilobyte implements FeeModel { * @param tx The transaction for which a fee is to be computed. * @returns The fee in satoshis for the transaction, as a BigNumber. */ - async computeFee(tx: Transaction): Promise { + async computeFee (tx: Transaction): Promise { const getVarIntSize = (i: number): number => { if (i > 2 ** 32) { return 9 diff --git a/src/transaction/http/BinaryFetchClient.ts b/src/transaction/http/BinaryFetchClient.ts index 58325ede..f0bd3613 100644 --- a/src/transaction/http/BinaryFetchClient.ts +++ b/src/transaction/http/BinaryFetchClient.ts @@ -26,9 +26,9 @@ export interface BinaryNodejsHttpClientRequest { * Adapter for Node Https module to be used as HttpClient */ export class BinaryNodejsHttpClient implements HttpClient { - constructor(private readonly https: BinaryHttpsNodejs) { } + constructor (private readonly https: BinaryHttpsNodejs) { } - async request( + async request ( url: string, requestOptions: HttpClientRequestOptions ): Promise { @@ -91,7 +91,7 @@ export interface FetchOptions { * Adapter for Node Https module to be used as HttpClient */ export class BinaryFetchClient implements HttpClient { - constructor(private readonly fetch: Fetch) { } + constructor (private readonly fetch: Fetch) { } async request( url: string, @@ -115,9 +115,9 @@ export class BinaryFetchClient implements HttpClient { } } -export function binaryHttpClient(): HttpClient { +export function binaryHttpClient (): HttpClient { const noHttpClient: HttpClient = { - async request(..._): Promise { + async request (..._): Promise { throw new Error('No method available to perform HTTP request') } } diff --git a/src/transaction/http/DefaultHttpClient.ts b/src/transaction/http/DefaultHttpClient.ts index 5d2be4d1..92ae7b10 100644 --- a/src/transaction/http/DefaultHttpClient.ts +++ b/src/transaction/http/DefaultHttpClient.ts @@ -7,9 +7,9 @@ import { FetchHttpClient } from './FetchHttpClient.js' * This method will attempt to use `window.fetch` if available (in browser environments). * If running in a Node environment, it falls back to using the Node `https` module */ -export function defaultHttpClient(): HttpClient { +export function defaultHttpClient (): HttpClient { const noHttpClient: HttpClient = { - async request(..._): Promise { + async request (..._): Promise { throw new Error('No method available to perform HTTP request') } } diff --git a/src/transaction/http/FetchHttpClient.ts b/src/transaction/http/FetchHttpClient.ts index 61eaa86f..9ce0a00e 100644 --- a/src/transaction/http/FetchHttpClient.ts +++ b/src/transaction/http/FetchHttpClient.ts @@ -29,7 +29,7 @@ export interface FetchOptions { * Adapter for Node Https module to be used as HttpClient */ export class FetchHttpClient implements HttpClient { - constructor(private readonly fetch: Fetch) { } + constructor (private readonly fetch: Fetch) { } async request( url: string, diff --git a/src/transaction/http/NodejsHttpClient.ts b/src/transaction/http/NodejsHttpClient.ts index a27e0527..09ebff1d 100644 --- a/src/transaction/http/NodejsHttpClient.ts +++ b/src/transaction/http/NodejsHttpClient.ts @@ -26,9 +26,9 @@ export interface NodejsHttpClientRequest { * Adapter for Node Https module to be used as HttpClient */ export class NodejsHttpClient implements HttpClient { - constructor(private readonly https: HttpsNodejs) { } + constructor (private readonly https: HttpsNodejs) { } - async request( + async request ( url: string, requestOptions: HttpClientRequestOptions ): Promise { diff --git a/src/wallet/substrates/HTTPWalletJSON.ts b/src/wallet/substrates/HTTPWalletJSON.ts index 20ab5d96..6c13d0cb 100644 --- a/src/wallet/substrates/HTTPWalletJSON.ts +++ b/src/wallet/substrates/HTTPWalletJSON.ts @@ -33,7 +33,7 @@ import { SecurityLevel, SignActionArgs, SignActionResult, - VersionString7To30Bytes, + VersionString7To30Bytes } from '../Wallet.interfaces.js' import { WERR_REVIEW_ACTIONS } from '../WERR_REVIEW_ACTIONS.js' import { toOriginHeader } from './utils/toOriginHeader.js' @@ -44,7 +44,7 @@ export default class HTTPWalletJSON implements WalletInterface { originator: OriginatorDomainNameStringUnder250Bytes | undefined api: (call: string, args: object) => Promise // Fixed `any` types - constructor( + constructor ( originator: OriginatorDomainNameStringUnder250Bytes | undefined, baseUrl: string = 'http://localhost:3321', httpClient = fetch @@ -74,7 +74,7 @@ export default class HTTPWalletJSON implements WalletInterface { Accept: 'application/json', 'Content-Type': 'application/json', ...(origin ? { Origin: origin } : {}), - ...(origin ? { Originator: origin } : {}), + ...(origin ? { Originator: origin } : {}) }, body: JSON.stringify(args) }) @@ -100,42 +100,42 @@ export default class HTTPWalletJSON implements WalletInterface { } } - async createAction(args: CreateActionArgs): Promise { + async createAction (args: CreateActionArgs): Promise { return await this.api('createAction', args) as CreateActionResult } - async signAction(args: SignActionArgs): Promise { + async signAction (args: SignActionArgs): Promise { return await this.api('signAction', args) as SignActionResult } - async abortAction(args: { + async abortAction (args: { reference: Base64String }): Promise<{ aborted: true }> { return await this.api('abortAction', args) as { aborted: true } } - async listActions(args: ListActionsArgs): Promise { + async listActions (args: ListActionsArgs): Promise { return await this.api('listActions', args) as ListActionsResult } - async internalizeAction( + async internalizeAction ( args: InternalizeActionArgs ): Promise<{ accepted: true }> { return await this.api('internalizeAction', args) as { accepted: true } } - async listOutputs(args: ListOutputsArgs): Promise { + async listOutputs (args: ListOutputsArgs): Promise { return await this.api('listOutputs', args) as ListOutputsResult } - async relinquishOutput(args: { + async relinquishOutput (args: { basket: BasketStringUnder300Bytes output: OutpointString }): Promise<{ relinquished: true }> { return await this.api('relinquishOutput', args) as { relinquished: true } } - async getPublicKey(args: { + async getPublicKey (args: { seekPermission?: BooleanDefaultTrue identityKey?: true protocolID?: [SecurityLevel, ProtocolString5To400Bytes] @@ -148,19 +148,19 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('getPublicKey', args) as { publicKey: PubKeyHex } } - async revealCounterpartyKeyLinkage(args: { + async revealCounterpartyKeyLinkage (args: { counterparty: PubKeyHex verifier: PubKeyHex privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - revelationTime: ISOTimestampString - encryptedLinkage: Byte[] - encryptedLinkageProof: number[] - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + revelationTime: ISOTimestampString + encryptedLinkage: Byte[] + encryptedLinkageProof: number[] + }> { return await this.api('revealCounterpartyKeyLinkage', args) as { prover: PubKeyHex verifier: PubKeyHex @@ -171,7 +171,7 @@ export default class HTTPWalletJSON implements WalletInterface { } } - async revealSpecificKeyLinkage(args: { + async revealSpecificKeyLinkage (args: { counterparty: PubKeyHex verifier: PubKeyHex protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -179,15 +179,15 @@ export default class HTTPWalletJSON implements WalletInterface { privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - protocolID: [SecurityLevel, ProtocolString5To400Bytes] - keyID: KeyIDStringUnder800Bytes - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - proofType: Byte - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + protocolID: [SecurityLevel, ProtocolString5To400Bytes] + keyID: KeyIDStringUnder800Bytes + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + proofType: Byte + }> { return await this.api('revealSpecificKeyLinkage', args) as { prover: PubKeyHex verifier: PubKeyHex @@ -200,7 +200,7 @@ export default class HTTPWalletJSON implements WalletInterface { } } - async encrypt(args: { + async encrypt (args: { seekPermission?: BooleanDefaultTrue plaintext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -212,7 +212,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('encrypt', args) as { ciphertext: Byte[] } } - async decrypt(args: { + async decrypt (args: { seekPermission?: BooleanDefaultTrue ciphertext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -224,7 +224,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('decrypt', args) as { plaintext: Byte[] } } - async createHmac(args: { + async createHmac (args: { seekPermission?: BooleanDefaultTrue data: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -236,7 +236,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('createHmac', args) as { hmac: Byte[] } } - async verifyHmac(args: { + async verifyHmac (args: { seekPermission?: BooleanDefaultTrue data: Byte[] hmac: Byte[] @@ -249,7 +249,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('verifyHmac', args) as { valid: true } } - async createSignature(args: { + async createSignature (args: { seekPermission?: BooleanDefaultTrue data?: Byte[] hashToDirectlySign?: Byte[] @@ -262,7 +262,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('createSignature', args) as { signature: Byte[] } } - async verifySignature(args: { + async verifySignature (args: { seekPermission?: BooleanDefaultTrue data?: Byte[] hashToDirectlyVerify?: Byte[] @@ -277,13 +277,13 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('verifySignature', args) as { valid: true } } - async acquireCertificate( + async acquireCertificate ( args: AcquireCertificateArgs ): Promise { return await this.api('acquireCertificate', args) as AcquireCertificateResult } - async listCertificates(args: { + async listCertificates (args: { certifiers: PubKeyHex[] types: Base64String[] limit?: PositiveIntegerDefault10Max10000 @@ -294,13 +294,13 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('listCertificates', args) as ListCertificatesResult } - async proveCertificate( + async proveCertificate ( args: ProveCertificateArgs ): Promise { return await this.api('proveCertificate', args) as ProveCertificateResult } - async relinquishCertificate(args: { + async relinquishCertificate (args: { type: Base64String serialNumber: Base64String certifier: PubKeyHex @@ -308,7 +308,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('relinquishCertificate', args) as { relinquished: true } } - async discoverByIdentityKey(args: { + async discoverByIdentityKey (args: { seekPermission?: BooleanDefaultTrue identityKey: PubKeyHex limit?: PositiveIntegerDefault10Max10000 @@ -317,7 +317,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('discoverByIdentityKey', args) as DiscoverCertificatesResult } - async discoverByAttributes(args: { + async discoverByAttributes (args: { seekPermission?: BooleanDefaultTrue attributes: Record limit?: PositiveIntegerDefault10Max10000 @@ -326,29 +326,29 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('discoverByAttributes', args) as DiscoverCertificatesResult } - async isAuthenticated(args: object): Promise<{ authenticated: true }> { + async isAuthenticated (args: object): Promise<{ authenticated: true }> { return await this.api('isAuthenticated', args) as { authenticated: true } } - async waitForAuthentication(args: object): Promise<{ authenticated: true }> { + async waitForAuthentication (args: object): Promise<{ authenticated: true }> { return await this.api('waitForAuthentication', args) as { authenticated: true } } - async getHeight(args: object): Promise<{ height: PositiveInteger }> { + async getHeight (args: object): Promise<{ height: PositiveInteger }> { return await this.api('getHeight', args) as { height: PositiveInteger } } - async getHeaderForHeight(args: { + async getHeaderForHeight (args: { height: PositiveInteger }): Promise<{ header: HexString }> { return await this.api('getHeaderForHeight', args) as { header: HexString } } - async getNetwork(args: object): Promise<{ network: 'mainnet' | 'testnet' }> { + async getNetwork (args: object): Promise<{ network: 'mainnet' | 'testnet' }> { return await this.api('getNetwork', args) as { network: 'mainnet' | 'testnet' } } - async getVersion(args: object): Promise<{ version: VersionString7To30Bytes }> { + async getVersion (args: object): Promise<{ version: VersionString7To30Bytes }> { return await this.api('getVersion', args) as { version: VersionString7To30Bytes } } } diff --git a/src/wallet/substrates/HTTPWalletWire.ts b/src/wallet/substrates/HTTPWalletWire.ts index d46fe7fd..7cf5f13b 100644 --- a/src/wallet/substrates/HTTPWalletWire.ts +++ b/src/wallet/substrates/HTTPWalletWire.ts @@ -7,7 +7,7 @@ export default class HTTPWalletWire implements WalletWire { httpClient: typeof fetch originator: string | undefined - constructor( + constructor ( originator: string | undefined, baseUrl: string = 'http://localhost:3301', httpClient = fetch @@ -17,7 +17,7 @@ export default class HTTPWalletWire implements WalletWire { this.originator = originator } - async transmitToWallet(message: number[]): Promise { + async transmitToWallet (message: number[]): Promise { const messageReader = new Utils.Reader(message) // Read call code const callCode = messageReader.readUInt8() diff --git a/src/wallet/substrates/ReactNativeWebView.ts b/src/wallet/substrates/ReactNativeWebView.ts index f6718aea..c5911acf 100644 --- a/src/wallet/substrates/ReactNativeWebView.ts +++ b/src/wallet/substrates/ReactNativeWebView.ts @@ -44,12 +44,11 @@ type ReactNativeWindow = Window & { export default class ReactNativeWebView implements WalletInterface { private readonly domain: string - - constructor(domain: string = '*') { + constructor (domain: string = '*') { if (typeof window !== 'object') { throw new Error('The XDM substrate requires a global window object.') } - if (!(window as unknown as ReactNativeWindow).hasOwnProperty("ReactNativeWebView")) { + if (!(window as unknown as ReactNativeWindow).hasOwnProperty('ReactNativeWebView')) { throw new Error( 'The window object does not have a ReactNativeWebView property.' ) @@ -62,7 +61,7 @@ export default class ReactNativeWebView implements WalletInterface { this.domain = domain } - async invoke(call: CallType, args: any): Promise { + async invoke (call: CallType, args: any): Promise { return await new Promise((resolve, reject) => { const id = Utils.toBase64(Random(12)) const listener = (e: MessageEvent): void => { @@ -97,7 +96,7 @@ export default class ReactNativeWebView implements WalletInterface { }) } - async createAction(args: { + async createAction (args: { description: DescriptionString5to50Bytes inputs?: Array<{ tx?: BEEF @@ -129,22 +128,22 @@ export default class ReactNativeWebView implements WalletInterface { sendWith?: TXIDHexString[] } }): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - signableTransaction?: { tx: BEEF, reference: Base64String } - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + signableTransaction?: { tx: BEEF, reference: Base64String } + }> { return await this.invoke('createAction', args) } - async signAction(args: { + async signAction (args: { spends: Record< - PositiveIntegerOrZero, - { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } + PositiveIntegerOrZero, + { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } > reference: Base64String options?: { @@ -155,24 +154,24 @@ export default class ReactNativeWebView implements WalletInterface { sendWith: TXIDHexString[] } }): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + }> { return await this.invoke('signAction', args) } - async abortAction(args: { + async abortAction (args: { reference: Base64String }): Promise<{ aborted: true }> { return await this.invoke('abortAction', args) } - async listActions(args: { + async listActions (args: { labels: LabelStringUnder300Bytes[] labelQueryMode?: 'any' | 'all' includeLabels?: BooleanDefaultFalse @@ -184,47 +183,47 @@ export default class ReactNativeWebView implements WalletInterface { limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalActions: PositiveIntegerOrZero - actions: Array<{ - txid: TXIDHexString - satoshis: SatoshiValue - status: - | 'completed' - | 'unprocessed' - | 'sending' - | 'unproven' - | 'unsigned' - | 'nosend' - | 'nonfinal' - isOutgoing: boolean - description: DescriptionString5to50Bytes - labels?: LabelStringUnder300Bytes[] - version: PositiveIntegerOrZero - lockTime: PositiveIntegerOrZero - inputs?: Array<{ - sourceOutpoint: OutpointString - sourceSatoshis: SatoshiValue - sourceLockingScript?: HexString - unlockingScript?: HexString - inputDescription: DescriptionString5to50Bytes - sequenceNumber: PositiveIntegerOrZero - }> - outputs?: Array<{ - outputIndex: PositiveIntegerOrZero + totalActions: PositiveIntegerOrZero + actions: Array<{ + txid: TXIDHexString satoshis: SatoshiValue - lockingScript?: HexString - spendable: boolean - outputDescription: DescriptionString5to50Bytes - basket: BasketStringUnder300Bytes - tags: OutputTagStringUnder300Bytes[] - customInstructions?: string + status: + | 'completed' + | 'unprocessed' + | 'sending' + | 'unproven' + | 'unsigned' + | 'nosend' + | 'nonfinal' + isOutgoing: boolean + description: DescriptionString5to50Bytes + labels?: LabelStringUnder300Bytes[] + version: PositiveIntegerOrZero + lockTime: PositiveIntegerOrZero + inputs?: Array<{ + sourceOutpoint: OutpointString + sourceSatoshis: SatoshiValue + sourceLockingScript?: HexString + unlockingScript?: HexString + inputDescription: DescriptionString5to50Bytes + sequenceNumber: PositiveIntegerOrZero + }> + outputs?: Array<{ + outputIndex: PositiveIntegerOrZero + satoshis: SatoshiValue + lockingScript?: HexString + spendable: boolean + outputDescription: DescriptionString5to50Bytes + basket: BasketStringUnder300Bytes + tags: OutputTagStringUnder300Bytes[] + customInstructions?: string + }> }> - }> - }> { + }> { return await this.invoke('listActions', args) } - async internalizeAction(args: { + async internalizeAction (args: { tx: BEEF outputs: Array<{ outputIndex: PositiveIntegerOrZero @@ -246,7 +245,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('internalizeAction', args) } - async listOutputs(args: { + async listOutputs (args: { basket: BasketStringUnder300Bytes tags?: OutputTagStringUnder300Bytes[] tagQueryMode?: 'all' | 'any' @@ -257,29 +256,29 @@ export default class ReactNativeWebView implements WalletInterface { limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalOutputs: PositiveIntegerOrZero - outputs: Array<{ - outpoint: OutpointString - satoshis: SatoshiValue - lockingScript?: HexString - tx?: BEEF - spendable: boolean - customInstructions?: string - tags?: OutputTagStringUnder300Bytes[] - labels?: LabelStringUnder300Bytes[] - }> - }> { + totalOutputs: PositiveIntegerOrZero + outputs: Array<{ + outpoint: OutpointString + satoshis: SatoshiValue + lockingScript?: HexString + tx?: BEEF + spendable: boolean + customInstructions?: string + tags?: OutputTagStringUnder300Bytes[] + labels?: LabelStringUnder300Bytes[] + }> + }> { return await this.invoke('listOutputs', args) } - async relinquishOutput(args: { + async relinquishOutput (args: { basket: BasketStringUnder300Bytes output: OutpointString }): Promise<{ relinquished: true }> { return await this.invoke('relinquishOutput', args) } - async getPublicKey(args: { + async getPublicKey (args: { identityKey?: true protocolID?: [SecurityLevel, ProtocolString5To400Bytes] keyID?: KeyIDStringUnder800Bytes @@ -291,23 +290,23 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('getPublicKey', args) } - async revealCounterpartyKeyLinkage(args: { + async revealCounterpartyKeyLinkage (args: { counterparty: PubKeyHex verifier: PubKeyHex privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - revelationTime: ISOTimestampString - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + revelationTime: ISOTimestampString + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + }> { return await this.invoke('revealCounterpartyKeyLinkage', args) } - async revealSpecificKeyLinkage(args: { + async revealSpecificKeyLinkage (args: { counterparty: PubKeyHex verifier: PubKeyHex protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -315,19 +314,19 @@ export default class ReactNativeWebView implements WalletInterface { privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - protocolID: [SecurityLevel, ProtocolString5To400Bytes] - keyID: KeyIDStringUnder800Bytes - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - proofType: Byte - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + protocolID: [SecurityLevel, ProtocolString5To400Bytes] + keyID: KeyIDStringUnder800Bytes + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + proofType: Byte + }> { return await this.invoke('revealSpecificKeyLinkage', args) } - async encrypt(args: { + async encrypt (args: { plaintext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -338,7 +337,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('encrypt', args) } - async decrypt(args: { + async decrypt (args: { ciphertext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -349,7 +348,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('decrypt', args) } - async createHmac(args: { + async createHmac (args: { data: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -360,7 +359,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('createHmac', args) } - async verifyHmac(args: { + async verifyHmac (args: { data: Byte[] hmac: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -372,7 +371,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('verifyHmac', args) } - async createSignature(args: { + async createSignature (args: { data?: Byte[] hashToDirectlySign?: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -384,7 +383,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('createSignature', args) } - async verifySignature(args: { + async verifySignature (args: { data?: Byte[] hashToDirectlyVerify?: Byte[] signature: Byte[] @@ -398,7 +397,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('verifySignature', args) } - async acquireCertificate(args: { + async acquireCertificate (args: { type: Base64String subject: PubKeyHex serialNumber: Base64String @@ -411,18 +410,18 @@ export default class ReactNativeWebView implements WalletInterface { acquisitionProtocol: 'direct' | 'issuance' certifierUrl?: string }): Promise<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> { + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> { return await this.invoke('acquireCertificate', args) } - async listCertificates(args: { + async listCertificates (args: { certifiers: PubKeyHex[] types: Base64String[] limit?: PositiveIntegerDefault10Max10000 @@ -430,21 +429,21 @@ export default class ReactNativeWebView implements WalletInterface { privileged?: BooleanDefaultFalse privilegedReason?: DescriptionString5to50Bytes }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> - }> { + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> + }> { return await this.invoke('listCertificates', args) } - async proveCertificate(args: { + async proveCertificate (args: { certificate: { type: Base64String subject: PubKeyHex @@ -459,12 +458,12 @@ export default class ReactNativeWebView implements WalletInterface { privileged?: BooleanDefaultFalse privilegedReason?: DescriptionString5to50Bytes }): Promise<{ - keyringForVerifier: Record - }> { + keyringForVerifier: Record + }> { return await this.invoke('proveCertificate', args) } - async relinquishCertificate(args: { + async relinquishCertificate (args: { type: Base64String serialNumber: Base64String certifier: PubKeyHex @@ -472,89 +471,89 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('relinquishCertificate', args) } - async discoverByIdentityKey(args: { + async discoverByIdentityKey (args: { identityKey: PubKeyHex limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.invoke('discoverByIdentityKey', args) } - async discoverByAttributes(args: { + async discoverByAttributes (args: { attributes: Record limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.invoke('discoverByAttributes', args) } - async isAuthenticated(args: {}): Promise<{ authenticated: true }> { + async isAuthenticated (args: {}): Promise<{ authenticated: true }> { return await this.invoke('isAuthenticated', args) } - async waitForAuthentication(args: {}): Promise<{ authenticated: true }> { + async waitForAuthentication (args: {}): Promise<{ authenticated: true }> { return await this.invoke('waitForAuthentication', args) } - async getHeight(args: {}): Promise<{ height: PositiveInteger }> { + async getHeight (args: {}): Promise<{ height: PositiveInteger }> { return await this.invoke('getHeight', args) } - async getHeaderForHeight(args: { + async getHeaderForHeight (args: { height: PositiveInteger }): Promise<{ header: HexString }> { return await this.invoke('getHeaderForHeight', args) } - async getNetwork(args: {}): Promise<{ network: 'mainnet' | 'testnet' }> { + async getNetwork (args: {}): Promise<{ network: 'mainnet' | 'testnet' }> { return await this.invoke('getNetwork', args) } - async getVersion(args: {}): Promise<{ version: VersionString7To30Bytes }> { + async getVersion (args: {}): Promise<{ version: VersionString7To30Bytes }> { return await this.invoke('getVersion', args) } } diff --git a/src/wallet/substrates/WalletWireProcessor.ts b/src/wallet/substrates/WalletWireProcessor.ts index 243400dd..6d152e39 100644 --- a/src/wallet/substrates/WalletWireProcessor.ts +++ b/src/wallet/substrates/WalletWireProcessor.ts @@ -10,18 +10,18 @@ import Certificate from '../../auth/certificates/Certificate.js' export default class WalletWireProcessor implements WalletWire { wallet: WalletInterface - constructor(wallet: WalletInterface) { + constructor (wallet: WalletInterface) { this.wallet = wallet } - private decodeOutpoint(reader: Utils.Reader): string { + private decodeOutpoint (reader: Utils.Reader): string { const txidBytes = reader.read(32) const txid = Utils.toHex(txidBytes) const index = reader.readVarIntNum() return `${txid}.${index}` } - private encodeOutpoint(outpoint: string): number[] { + private encodeOutpoint (outpoint: string): number[] { const writer = new Utils.Writer() const [txid, index] = outpoint.split('.') writer.write(Utils.toArray(txid, 'hex')) @@ -29,7 +29,7 @@ export default class WalletWireProcessor implements WalletWire { return writer.toArray() } - async transmitToWallet(message: number[]): Promise { + async transmitToWallet (message: number[]): Promise { const messageReader = new Utils.Reader(message) try { // Read call code @@ -2048,7 +2048,7 @@ export default class WalletWireProcessor implements WalletWire { } } - private decodeProtocolID(reader: Utils.Reader): [SecurityLevel, string] { + private decodeProtocolID (reader: Utils.Reader): [SecurityLevel, string] { const securityLevel = reader.readUInt8() as SecurityLevel const protocolLength = reader.readVarIntNum() const protocolBytes = reader.read(protocolLength) @@ -2056,13 +2056,13 @@ export default class WalletWireProcessor implements WalletWire { return [securityLevel, protocolString] } - private decodeString(reader: Utils.Reader): string { + private decodeString (reader: Utils.Reader): string { const length = reader.readVarIntNum() const bytes = reader.read(length) return Utils.toUTF8(bytes) } - private decodeCounterparty( + private decodeCounterparty ( reader: Utils.Reader ): string | 'self' | 'anyone' | undefined { const counterpartyFlag = reader.readUInt8() @@ -2078,7 +2078,7 @@ export default class WalletWireProcessor implements WalletWire { } } - private serializeDiscoveryResult(discoverResult: any): number[] { + private serializeDiscoveryResult (discoverResult: any): number[] { const resultWriter = new Utils.Writer() // totalCertificates @@ -2150,7 +2150,7 @@ export default class WalletWireProcessor implements WalletWire { return resultWriter.toArray() } - private decodeKeyRelatedParams(paramsReader: Utils.Reader): any { + private decodeKeyRelatedParams (paramsReader: Utils.Reader): any { const args: any = {} // Read protocolID diff --git a/src/wallet/substrates/WalletWireTransceiver.ts b/src/wallet/substrates/WalletWireTransceiver.ts index 7dcbdafd..67122a6f 100644 --- a/src/wallet/substrates/WalletWireTransceiver.ts +++ b/src/wallet/substrates/WalletWireTransceiver.ts @@ -58,11 +58,11 @@ import { WalletError } from '../WalletError.js' export default class WalletWireTransceiver implements WalletInterface { wire: WalletWire - constructor(wire: WalletWire) { + constructor (wire: WalletWire) { this.wire = wire } - private async transmit( + private async transmit ( call: CallType, originator: OriginatorDomainNameStringUnder250Bytes = '', params: number[] = [] @@ -99,7 +99,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async createAction( + async createAction ( args: CreateActionArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -399,7 +399,7 @@ export default class WalletWireTransceiver implements WalletInterface { return response } - async signAction( + async signAction ( args: SignActionArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -518,7 +518,7 @@ export default class WalletWireTransceiver implements WalletInterface { return response } - async abortAction( + async abortAction ( args: { reference: Base64String }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ aborted: true }> { @@ -530,7 +530,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { aborted: true } } - async listActions( + async listActions ( args: ListActionsArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -823,7 +823,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async internalizeAction( + async internalizeAction ( args: InternalizeActionArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ accepted: true }> { @@ -910,7 +910,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { accepted: true } } - async listOutputs( + async listOutputs ( args: ListOutputsArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -1053,7 +1053,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async relinquishOutput( + async relinquishOutput ( args: { basket: BasketStringUnder300Bytes, output: OutpointString }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ relinquished: true }> { @@ -1066,7 +1066,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { relinquished: true } } - private encodeOutpoint(outpoint: OutpointString): number[] { + private encodeOutpoint (outpoint: OutpointString): number[] { const writer = new Utils.Writer() const [txid, index] = outpoint.split('.') writer.write(Utils.toArray(txid, 'hex')) @@ -1074,13 +1074,13 @@ export default class WalletWireTransceiver implements WalletInterface { return writer.toArray() } - private readOutpoint(reader: Utils.Reader): OutpointString { + private readOutpoint (reader: Utils.Reader): OutpointString { const txid = Utils.toHex(reader.read(32)) const index = reader.readVarIntNum() return `${txid}.${index}` } - async getPublicKey( + async getPublicKey ( args: { seekPermission?: BooleanDefaultTrue identityKey?: true @@ -1135,7 +1135,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async revealCounterpartyKeyLinkage( + async revealCounterpartyKeyLinkage ( args: { counterparty: PubKeyHex verifier: PubKeyHex @@ -1144,13 +1144,13 @@ export default class WalletWireTransceiver implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - revelationTime: ISOTimestampString - encryptedLinkage: Byte[] - encryptedLinkageProof: number[] - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + revelationTime: ISOTimestampString + encryptedLinkage: Byte[] + encryptedLinkageProof: number[] + }> { const paramWriter = new Utils.Writer() paramWriter.write( this.encodePrivilegedParams(args.privileged, args.privilegedReason) @@ -1186,7 +1186,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async revealSpecificKeyLinkage( + async revealSpecificKeyLinkage ( args: { counterparty: PubKeyHex verifier: PubKeyHex @@ -1197,15 +1197,15 @@ export default class WalletWireTransceiver implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - protocolID: [SecurityLevel, ProtocolString5To400Bytes] - keyID: KeyIDStringUnder800Bytes - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - proofType: Byte - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + protocolID: [SecurityLevel, ProtocolString5To400Bytes] + keyID: KeyIDStringUnder800Bytes + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + proofType: Byte + }> { const paramWriter = new Utils.Writer() paramWriter.write( this.encodeKeyRelatedParams( @@ -1250,7 +1250,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async encrypt( + async encrypt ( args: { seekPermission?: BooleanDefaultTrue plaintext: Byte[] @@ -1291,7 +1291,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async decrypt( + async decrypt ( args: { seekPermission?: BooleanDefaultTrue ciphertext: Byte[] @@ -1332,7 +1332,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async createHmac( + async createHmac ( args: { seekPermission?: BooleanDefaultTrue data: Byte[] @@ -1373,7 +1373,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async verifyHmac( + async verifyHmac ( args: { seekPermission?: BooleanDefaultTrue data: Byte[] @@ -1411,7 +1411,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { valid: true } } - async createSignature( + async createSignature ( args: { seekPermission?: BooleanDefaultTrue data?: Byte[] @@ -1459,7 +1459,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async verifySignature( + async verifySignature ( args: { seekPermission?: BooleanDefaultTrue data?: Byte[] @@ -1511,7 +1511,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { valid: true } } - private encodeKeyRelatedParams( + private encodeKeyRelatedParams ( protocolID: [SecurityLevel, ProtocolString5To400Bytes], keyID: KeyIDStringUnder800Bytes, counterparty?: PubKeyHex | 'self' | 'anyone', @@ -1541,7 +1541,7 @@ export default class WalletWireTransceiver implements WalletInterface { return paramWriter.toArray() } - async acquireCertificate( + async acquireCertificate ( args: AcquireCertificateArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -1611,7 +1611,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - private encodePrivilegedParams( + private encodePrivilegedParams ( privileged?: boolean, privilegedReason?: string ): number[] { @@ -1631,7 +1631,7 @@ export default class WalletWireTransceiver implements WalletInterface { return paramWriter.toArray() } - async listCertificates( + async listCertificates ( args: { certifiers: PubKeyHex[] types: Base64String[] @@ -1696,7 +1696,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async proveCertificate( + async proveCertificate ( args: ProveCertificateArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -1760,7 +1760,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async relinquishCertificate( + async relinquishCertificate ( args: { type: Base64String serialNumber: Base64String @@ -1783,7 +1783,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { relinquished: true } } - private parseDiscoveryResult(result: number[]): { + private parseDiscoveryResult (result: number[]): { totalCertificates: number certificates: Array<{ type: Base64String @@ -1800,8 +1800,8 @@ export default class WalletWireTransceiver implements WalletInterface { trust: PositiveIntegerMax10 } publiclyRevealedKeyring: Record< - CertificateFieldNameUnder50Bytes, - Base64String + CertificateFieldNameUnder50Bytes, + Base64String > decryptedFields: Record }> @@ -1823,8 +1823,8 @@ export default class WalletWireTransceiver implements WalletInterface { trust: PositiveIntegerMax10 } publiclyRevealedKeyring: Record< - CertificateFieldNameUnder50Bytes, - Base64String + CertificateFieldNameUnder50Bytes, + Base64String > decryptedFields: Record }> = [] @@ -1871,7 +1871,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async discoverByIdentityKey( + async discoverByIdentityKey ( args: { seekPermission?: BooleanDefaultTrue identityKey: PubKeyHex @@ -1908,7 +1908,7 @@ export default class WalletWireTransceiver implements WalletInterface { return this.parseDiscoveryResult(result) } - async discoverByAttributes( + async discoverByAttributes ( args: { seekPermission?: BooleanDefaultTrue attributes: Record @@ -1954,7 +1954,7 @@ export default class WalletWireTransceiver implements WalletInterface { return this.parseDiscoveryResult(result) } - async isAuthenticated( + async isAuthenticated ( args: {}, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ authenticated: true }> { @@ -1963,7 +1963,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { authenticated: result[0] === 1 } } - async waitForAuthentication( + async waitForAuthentication ( args: {}, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ authenticated: true }> { @@ -1971,7 +1971,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { authenticated: true } } - async getHeight( + async getHeight ( args: {}, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ height: PositiveInteger }> { @@ -1982,7 +1982,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async getHeaderForHeight( + async getHeaderForHeight ( args: { height: PositiveInteger }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ header: HexString }> { @@ -1998,7 +1998,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async getNetwork( + async getNetwork ( args: {}, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ network: 'mainnet' | 'testnet' }> { @@ -2008,7 +2008,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async getVersion( + async getVersion ( args: {}, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ version: VersionString7To30Bytes }> { diff --git a/src/wallet/substrates/XDM.ts b/src/wallet/substrates/XDM.ts index 583519d1..0836b1e7 100644 --- a/src/wallet/substrates/XDM.ts +++ b/src/wallet/substrates/XDM.ts @@ -38,7 +38,7 @@ import { CallType } from './WalletWireCalls.js' export default class XDMSubstrate implements WalletInterface { private readonly domain: string - constructor(domain: string = '*') { + constructor (domain: string = '*') { if (typeof window !== 'object') { throw new Error('The XDM substrate requires a global window object.') } @@ -50,7 +50,7 @@ export default class XDMSubstrate implements WalletInterface { this.domain = domain } - async invoke(call: CallType, args: any): Promise { + async invoke (call: CallType, args: any): Promise { return await new Promise((resolve, reject) => { const id = Utils.toBase64(Random(12)) const listener = (e: MessageEvent): void => { @@ -84,7 +84,7 @@ export default class XDMSubstrate implements WalletInterface { }) } - async createAction(args: { + async createAction (args: { description: DescriptionString5to50Bytes inputs?: Array<{ tx?: BEEF @@ -116,22 +116,22 @@ export default class XDMSubstrate implements WalletInterface { sendWith?: TXIDHexString[] } }): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - signableTransaction?: { tx: BEEF, reference: Base64String } - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + signableTransaction?: { tx: BEEF, reference: Base64String } + }> { return await this.invoke('createAction', args) } - async signAction(args: { + async signAction (args: { spends: Record< - PositiveIntegerOrZero, - { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } + PositiveIntegerOrZero, + { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } > reference: Base64String options?: { @@ -142,24 +142,24 @@ export default class XDMSubstrate implements WalletInterface { sendWith: TXIDHexString[] } }): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + }> { return await this.invoke('signAction', args) } - async abortAction(args: { + async abortAction (args: { reference: Base64String }): Promise<{ aborted: true }> { return await this.invoke('abortAction', args) } - async listActions(args: { + async listActions (args: { labels: LabelStringUnder300Bytes[] labelQueryMode?: 'any' | 'all' includeLabels?: BooleanDefaultFalse @@ -171,47 +171,47 @@ export default class XDMSubstrate implements WalletInterface { limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalActions: PositiveIntegerOrZero - actions: Array<{ - txid: TXIDHexString - satoshis: SatoshiValue - status: - | 'completed' - | 'unprocessed' - | 'sending' - | 'unproven' - | 'unsigned' - | 'nosend' - | 'nonfinal' - isOutgoing: boolean - description: DescriptionString5to50Bytes - labels?: LabelStringUnder300Bytes[] - version: PositiveIntegerOrZero - lockTime: PositiveIntegerOrZero - inputs?: Array<{ - sourceOutpoint: OutpointString - sourceSatoshis: SatoshiValue - sourceLockingScript?: HexString - unlockingScript?: HexString - inputDescription: DescriptionString5to50Bytes - sequenceNumber: PositiveIntegerOrZero - }> - outputs?: Array<{ - outputIndex: PositiveIntegerOrZero + totalActions: PositiveIntegerOrZero + actions: Array<{ + txid: TXIDHexString satoshis: SatoshiValue - lockingScript?: HexString - spendable: boolean - outputDescription: DescriptionString5to50Bytes - basket: BasketStringUnder300Bytes - tags: OutputTagStringUnder300Bytes[] - customInstructions?: string + status: + | 'completed' + | 'unprocessed' + | 'sending' + | 'unproven' + | 'unsigned' + | 'nosend' + | 'nonfinal' + isOutgoing: boolean + description: DescriptionString5to50Bytes + labels?: LabelStringUnder300Bytes[] + version: PositiveIntegerOrZero + lockTime: PositiveIntegerOrZero + inputs?: Array<{ + sourceOutpoint: OutpointString + sourceSatoshis: SatoshiValue + sourceLockingScript?: HexString + unlockingScript?: HexString + inputDescription: DescriptionString5to50Bytes + sequenceNumber: PositiveIntegerOrZero + }> + outputs?: Array<{ + outputIndex: PositiveIntegerOrZero + satoshis: SatoshiValue + lockingScript?: HexString + spendable: boolean + outputDescription: DescriptionString5to50Bytes + basket: BasketStringUnder300Bytes + tags: OutputTagStringUnder300Bytes[] + customInstructions?: string + }> }> - }> - }> { + }> { return await this.invoke('listActions', args) } - async internalizeAction(args: { + async internalizeAction (args: { tx: BEEF outputs: Array<{ outputIndex: PositiveIntegerOrZero @@ -233,7 +233,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('internalizeAction', args) } - async listOutputs(args: { + async listOutputs (args: { basket: BasketStringUnder300Bytes tags?: OutputTagStringUnder300Bytes[] tagQueryMode?: 'all' | 'any' @@ -244,29 +244,29 @@ export default class XDMSubstrate implements WalletInterface { limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalOutputs: PositiveIntegerOrZero - outputs: Array<{ - outpoint: OutpointString - satoshis: SatoshiValue - lockingScript?: HexString - tx?: BEEF - spendable: boolean - customInstructions?: string - tags?: OutputTagStringUnder300Bytes[] - labels?: LabelStringUnder300Bytes[] - }> - }> { + totalOutputs: PositiveIntegerOrZero + outputs: Array<{ + outpoint: OutpointString + satoshis: SatoshiValue + lockingScript?: HexString + tx?: BEEF + spendable: boolean + customInstructions?: string + tags?: OutputTagStringUnder300Bytes[] + labels?: LabelStringUnder300Bytes[] + }> + }> { return await this.invoke('listOutputs', args) } - async relinquishOutput(args: { + async relinquishOutput (args: { basket: BasketStringUnder300Bytes output: OutpointString }): Promise<{ relinquished: true }> { return await this.invoke('relinquishOutput', args) } - async getPublicKey(args: { + async getPublicKey (args: { identityKey?: true protocolID?: [SecurityLevel, ProtocolString5To400Bytes] keyID?: KeyIDStringUnder800Bytes @@ -278,23 +278,23 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('getPublicKey', args) } - async revealCounterpartyKeyLinkage(args: { + async revealCounterpartyKeyLinkage (args: { counterparty: PubKeyHex verifier: PubKeyHex privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - revelationTime: ISOTimestampString - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + revelationTime: ISOTimestampString + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + }> { return await this.invoke('revealCounterpartyKeyLinkage', args) } - async revealSpecificKeyLinkage(args: { + async revealSpecificKeyLinkage (args: { counterparty: PubKeyHex verifier: PubKeyHex protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -302,19 +302,19 @@ export default class XDMSubstrate implements WalletInterface { privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - protocolID: [SecurityLevel, ProtocolString5To400Bytes] - keyID: KeyIDStringUnder800Bytes - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - proofType: Byte - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + protocolID: [SecurityLevel, ProtocolString5To400Bytes] + keyID: KeyIDStringUnder800Bytes + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + proofType: Byte + }> { return await this.invoke('revealSpecificKeyLinkage', args) } - async encrypt(args: { + async encrypt (args: { plaintext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -325,7 +325,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('encrypt', args) } - async decrypt(args: { + async decrypt (args: { ciphertext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -336,7 +336,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('decrypt', args) } - async createHmac(args: { + async createHmac (args: { data: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -347,7 +347,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('createHmac', args) } - async verifyHmac(args: { + async verifyHmac (args: { data: Byte[] hmac: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -359,7 +359,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('verifyHmac', args) } - async createSignature(args: { + async createSignature (args: { data?: Byte[] hashToDirectlySign?: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -371,7 +371,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('createSignature', args) } - async verifySignature(args: { + async verifySignature (args: { data?: Byte[] hashToDirectlyVerify?: Byte[] signature: Byte[] @@ -385,7 +385,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('verifySignature', args) } - async acquireCertificate(args: { + async acquireCertificate (args: { type: Base64String subject: PubKeyHex serialNumber: Base64String @@ -398,18 +398,18 @@ export default class XDMSubstrate implements WalletInterface { acquisitionProtocol: 'direct' | 'issuance' certifierUrl?: string }): Promise<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> { + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> { return await this.invoke('acquireCertificate', args) } - async listCertificates(args: { + async listCertificates (args: { certifiers: PubKeyHex[] types: Base64String[] limit?: PositiveIntegerDefault10Max10000 @@ -417,21 +417,21 @@ export default class XDMSubstrate implements WalletInterface { privileged?: BooleanDefaultFalse privilegedReason?: DescriptionString5to50Bytes }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> - }> { + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> + }> { return await this.invoke('listCertificates', args) } - async proveCertificate(args: { + async proveCertificate (args: { certificate: { type: Base64String subject: PubKeyHex @@ -446,12 +446,12 @@ export default class XDMSubstrate implements WalletInterface { privileged?: BooleanDefaultFalse privilegedReason?: DescriptionString5to50Bytes }): Promise<{ - keyringForVerifier: Record - }> { + keyringForVerifier: Record + }> { return await this.invoke('proveCertificate', args) } - async relinquishCertificate(args: { + async relinquishCertificate (args: { type: Base64String serialNumber: Base64String certifier: PubKeyHex @@ -459,89 +459,89 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('relinquishCertificate', args) } - async discoverByIdentityKey(args: { + async discoverByIdentityKey (args: { identityKey: PubKeyHex limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.invoke('discoverByIdentityKey', args) } - async discoverByAttributes(args: { + async discoverByAttributes (args: { attributes: Record limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.invoke('discoverByAttributes', args) } - async isAuthenticated(args: {}): Promise<{ authenticated: true }> { + async isAuthenticated (args: {}): Promise<{ authenticated: true }> { return await this.invoke('isAuthenticated', args) } - async waitForAuthentication(args: {}): Promise<{ authenticated: true }> { + async waitForAuthentication (args: {}): Promise<{ authenticated: true }> { return await this.invoke('waitForAuthentication', args) } - async getHeight(args: {}): Promise<{ height: PositiveInteger }> { + async getHeight (args: {}): Promise<{ height: PositiveInteger }> { return await this.invoke('getHeight', args) } - async getHeaderForHeight(args: { + async getHeaderForHeight (args: { height: PositiveInteger }): Promise<{ header: HexString }> { return await this.invoke('getHeaderForHeight', args) } - async getNetwork(args: {}): Promise<{ network: 'mainnet' | 'testnet' }> { + async getNetwork (args: {}): Promise<{ network: 'mainnet' | 'testnet' }> { return await this.invoke('getNetwork', args) } - async getVersion(args: {}): Promise<{ version: VersionString7To30Bytes }> { + async getVersion (args: {}): Promise<{ version: VersionString7To30Bytes }> { return await this.invoke('getVersion', args) } } diff --git a/src/wallet/substrates/__tests/toOriginHeader.test.ts b/src/wallet/substrates/__tests/toOriginHeader.test.ts index 1832a5be..49ed7aaf 100644 --- a/src/wallet/substrates/__tests/toOriginHeader.test.ts +++ b/src/wallet/substrates/__tests/toOriginHeader.test.ts @@ -1,34 +1,34 @@ -import { toOriginHeader } from "../utils/toOriginHeader" +import { toOriginHeader } from '../utils/toOriginHeader' afterEach(() => jest.resetAllMocks()) type FetchMockCall = Parameters // alias for readability -function okJson(body: unknown = {}) { - return Promise.resolve({ +async function okJson (body: unknown = {}) { + return await Promise.resolve({ ok: true, status: 200, - json: () => Promise.resolve(body), + json: async () => await Promise.resolve(body) } as Response) } -describe("toOriginHeader()", () => { +describe('toOriginHeader()', () => { const vectors: Array<[originator: string, baseUrl: string, expected: string | undefined]> = [ /* originator, baseUrl, expected */ - ["localhost", "http://localhost:3321", "http://localhost"], - ["localhost:3000", "http://localhost:3321", "http://localhost:3000"], - ["example.com", "https://api.example.com", "https://example.com"], - ["https://example.com:8443", "http://localhost:3321", "https://example.com:8443"], + ['localhost', 'http://localhost:3321', 'http://localhost'], + ['localhost:3000', 'http://localhost:3321', 'http://localhost:3000'], + ['example.com', 'https://api.example.com', 'https://example.com'], + ['https://example.com:8443', 'http://localhost:3321', 'https://example.com:8443'] // ["metanet://somehost", "http://localhost:3321", "metanet://somehost"], // TODO: Consider adding support in the future ] - it.each(vectors)("originator=%p, baseUrl=%p → %p", (originator, baseUrl, expected) => { - const schemeFromBase = new URL(baseUrl).protocol.replace(":", "") + it.each(vectors)('originator=%p, baseUrl=%p → %p', (originator, baseUrl, expected) => { + const schemeFromBase = new URL(baseUrl).protocol.replace(':', '') const result = toOriginHeader(originator, schemeFromBase) expect(result).toBe(expected) }) - it("throws on clearly malformed input", () => { - expect(() => toOriginHeader("bad url^%", "http")).toThrow() + it('throws on clearly malformed input', () => { + expect(() => toOriginHeader('bad url^%', 'http')).toThrow() }) }) diff --git a/src/wallet/substrates/utils/toOriginHeader.ts b/src/wallet/substrates/utils/toOriginHeader.ts index 04efa0d9..efd86b7c 100644 --- a/src/wallet/substrates/utils/toOriginHeader.ts +++ b/src/wallet/substrates/utils/toOriginHeader.ts @@ -1,8 +1,8 @@ -export function toOriginHeader(originator: string, fallbackScheme = 'http'): string | undefined { +export function toOriginHeader (originator: string, fallbackScheme = 'http'): string | undefined { // If the caller already gave us a scheme, assume it’s fine if (/^[a-z][a-z0-9+.-]*:\/\//i.test(originator)) { try { - return new URL(originator).origin // trims any path/query + return new URL(originator).origin // trims any path/query } catch { /* fall through to fix-up */ } } diff --git a/src/wallet/substrates/window.CWI.ts b/src/wallet/substrates/window.CWI.ts index c67ae778..94a7948e 100644 --- a/src/wallet/substrates/window.CWI.ts +++ b/src/wallet/substrates/window.CWI.ts @@ -38,7 +38,7 @@ declare const window: { */ export default class WindowCWISubstrate implements WalletInterface { private readonly CWI: WalletInterface - constructor() { + constructor () { if (typeof window !== 'object') { throw new Error( 'The window.CWI substrate requires a global window object.' @@ -52,7 +52,7 @@ export default class WindowCWISubstrate implements WalletInterface { this.CWI = window.CWI // Binding CWI to prevent changes } - async createAction( + async createAction ( args: { description: DescriptionString5to50Bytes inputs?: Array<{ @@ -87,23 +87,23 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - signableTransaction?: { tx: BEEF, reference: Base64String } - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + signableTransaction?: { tx: BEEF, reference: Base64String } + }> { return await this.CWI.createAction(args, originator) } - async signAction( + async signAction ( args: { spends: Record< - PositiveIntegerOrZero, - { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } + PositiveIntegerOrZero, + { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } > reference: Base64String options?: { @@ -116,25 +116,25 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + }> { return await this.CWI.signAction(args, originator) } - async abortAction( + async abortAction ( args: { reference: Base64String }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ aborted: true }> { return await this.CWI.abortAction(args, originator) } - async listActions( + async listActions ( args: { labels: LabelStringUnder300Bytes[] labelQueryMode?: 'any' | 'all' @@ -149,48 +149,48 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - totalActions: PositiveIntegerOrZero - actions: Array<{ - txid: TXIDHexString - satoshis: SatoshiValue - status: - | 'completed' - | 'unprocessed' - | 'sending' - | 'unproven' - | 'unsigned' - | 'nosend' - | 'nonfinal' - | 'failed' - isOutgoing: boolean - description: DescriptionString5to50Bytes - labels?: LabelStringUnder300Bytes[] - version: PositiveIntegerOrZero - lockTime: PositiveIntegerOrZero - inputs?: Array<{ - sourceOutpoint: OutpointString - sourceSatoshis: SatoshiValue - sourceLockingScript?: HexString - unlockingScript?: HexString - inputDescription: DescriptionString5to50Bytes - sequenceNumber: PositiveIntegerOrZero - }> - outputs?: Array<{ - outputIndex: PositiveIntegerOrZero + totalActions: PositiveIntegerOrZero + actions: Array<{ + txid: TXIDHexString satoshis: SatoshiValue - lockingScript?: HexString - spendable: boolean - outputDescription: DescriptionString5to50Bytes - basket: BasketStringUnder300Bytes - tags: OutputTagStringUnder300Bytes[] - customInstructions?: string + status: + | 'completed' + | 'unprocessed' + | 'sending' + | 'unproven' + | 'unsigned' + | 'nosend' + | 'nonfinal' + | 'failed' + isOutgoing: boolean + description: DescriptionString5to50Bytes + labels?: LabelStringUnder300Bytes[] + version: PositiveIntegerOrZero + lockTime: PositiveIntegerOrZero + inputs?: Array<{ + sourceOutpoint: OutpointString + sourceSatoshis: SatoshiValue + sourceLockingScript?: HexString + unlockingScript?: HexString + inputDescription: DescriptionString5to50Bytes + sequenceNumber: PositiveIntegerOrZero + }> + outputs?: Array<{ + outputIndex: PositiveIntegerOrZero + satoshis: SatoshiValue + lockingScript?: HexString + spendable: boolean + outputDescription: DescriptionString5to50Bytes + basket: BasketStringUnder300Bytes + tags: OutputTagStringUnder300Bytes[] + customInstructions?: string + }> }> - }> - }> { + }> { return await this.CWI.listActions(args, originator) } - async internalizeAction( + async internalizeAction ( args: { tx: BEEF outputs: Array<{ @@ -215,7 +215,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.internalizeAction(args, originator) } - async listOutputs( + async listOutputs ( args: { basket: BasketStringUnder300Bytes tags?: OutputTagStringUnder300Bytes[] @@ -229,29 +229,29 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - totalOutputs: PositiveIntegerOrZero - outputs: Array<{ - outpoint: OutpointString - satoshis: SatoshiValue - lockingScript?: HexString - tx?: BEEF - spendable: boolean - customInstructions?: string - tags?: OutputTagStringUnder300Bytes[] - labels?: LabelStringUnder300Bytes[] - }> - }> { + totalOutputs: PositiveIntegerOrZero + outputs: Array<{ + outpoint: OutpointString + satoshis: SatoshiValue + lockingScript?: HexString + tx?: BEEF + spendable: boolean + customInstructions?: string + tags?: OutputTagStringUnder300Bytes[] + labels?: LabelStringUnder300Bytes[] + }> + }> { return await this.CWI.listOutputs(args, originator) } - async relinquishOutput( + async relinquishOutput ( args: { basket: BasketStringUnder300Bytes, output: OutpointString }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ relinquished: true }> { return await this.CWI.relinquishOutput(args, originator) } - async getPublicKey( + async getPublicKey ( args: { identityKey?: true protocolID?: [SecurityLevel, ProtocolString5To400Bytes] @@ -266,7 +266,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.getPublicKey(args, originator) } - async revealCounterpartyKeyLinkage( + async revealCounterpartyKeyLinkage ( args: { counterparty: PubKeyHex verifier: PubKeyHex @@ -275,17 +275,17 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - revelationTime: ISOTimestampString - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + revelationTime: ISOTimestampString + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + }> { return await this.CWI.revealCounterpartyKeyLinkage(args, originator) } - async revealSpecificKeyLinkage( + async revealSpecificKeyLinkage ( args: { counterparty: PubKeyHex verifier: PubKeyHex @@ -296,19 +296,19 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - protocolID: [SecurityLevel, ProtocolString5To400Bytes] - keyID: KeyIDStringUnder800Bytes - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - proofType: Byte - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + protocolID: [SecurityLevel, ProtocolString5To400Bytes] + keyID: KeyIDStringUnder800Bytes + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + proofType: Byte + }> { return await this.CWI.revealSpecificKeyLinkage(args, originator) } - async encrypt( + async encrypt ( args: { plaintext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -322,7 +322,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.encrypt(args, originator) } - async decrypt( + async decrypt ( args: { ciphertext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -336,7 +336,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.decrypt(args, originator) } - async createHmac( + async createHmac ( args: { data: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -350,7 +350,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.createHmac(args, originator) } - async verifyHmac( + async verifyHmac ( args: { data: Byte[] hmac: Byte[] @@ -365,7 +365,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.verifyHmac(args, originator) } - async createSignature( + async createSignature ( args: { data?: Byte[] hashToDirectlySign?: Byte[] @@ -380,7 +380,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.createSignature(args, originator) } - async verifySignature( + async verifySignature ( args: { data?: Byte[] hashToDirectlyVerify?: Byte[] @@ -397,7 +397,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.verifySignature(args, originator) } - async acquireCertificate( + async acquireCertificate ( args: { type: Base64String subject: PubKeyHex @@ -413,18 +413,18 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> { + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> { return await this.CWI.acquireCertificate(args, originator) } - async listCertificates( + async listCertificates ( args: { certifiers: PubKeyHex[] types: Base64String[] @@ -435,21 +435,21 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> - }> { + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> + }> { return await this.CWI.listCertificates(args, originator) } - async proveCertificate( + async proveCertificate ( args: { certificate: { type: Base64String @@ -467,12 +467,12 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - keyringForVerifier: Record - }> { + keyringForVerifier: Record + }> { return await this.CWI.proveCertificate(args, originator) } - async relinquishCertificate( + async relinquishCertificate ( args: { type: Base64String serialNumber: Base64String @@ -483,7 +483,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.relinquishCertificate(args, originator) } - async discoverByIdentityKey( + async discoverByIdentityKey ( args: { identityKey: PubKeyHex limit?: PositiveIntegerDefault10Max10000 @@ -491,32 +491,32 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.CWI.discoverByIdentityKey(args, originator) } - async discoverByAttributes( + async discoverByAttributes ( args: { attributes: Record limit?: PositiveIntegerDefault10Max10000 @@ -524,67 +524,67 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.CWI.discoverByAttributes(args, originator) } - async isAuthenticated( + async isAuthenticated ( args: object, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ authenticated: true }> { return await this.CWI.isAuthenticated(args, originator) } - async waitForAuthentication( + async waitForAuthentication ( args: object, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ authenticated: true }> { return await this.CWI.waitForAuthentication(args, originator) } - async getHeight( + async getHeight ( args: object, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ height: PositiveInteger }> { return await this.CWI.getHeight(args, originator) } - async getHeaderForHeight( + async getHeaderForHeight ( args: { height: PositiveInteger }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ header: HexString }> { return await this.CWI.getHeaderForHeight(args, originator) } - async getNetwork( + async getNetwork ( args: object, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ network: 'mainnet' | 'testnet' }> { return await this.CWI.getNetwork(args, originator) } - async getVersion( + async getVersion ( args: object, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ version: VersionString7To30Bytes }> { From 81939b74090c7e6be6cc4d2aceeeecf527da82df Mon Sep 17 00:00:00 2001 From: ChanceBarimbao Date: Tue, 9 Sep 2025 14:27:42 -0700 Subject: [PATCH 5/7] doc --- docs/reference/transaction.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/reference/transaction.md b/docs/reference/transaction.md index 002ee487..607bb087 100644 --- a/docs/reference/transaction.md +++ b/docs/reference/transaction.md @@ -985,6 +985,7 @@ verifyValid(allowTxidOnly?: boolean): { Returns + `valid` is true iff this Beef is structuraly valid. `roots` is a record where keys are block heights and values are the corresponding merkle roots to be validated. From 584923cab49bbc06e60722d1d6f26bd9c4f53225 Mon Sep 17 00:00:00 2001 From: Brayden Langley Date: Tue, 9 Sep 2025 14:41:51 -0700 Subject: [PATCH 6/7] Revert "lint" This reverts commit 4daa5a970f824c3499d5cdaa2e4ebe963280625a. --- src/auth/__tests/Peer.test.ts | 18 +- src/auth/certificates/Certificate.ts | 12 +- src/auth/certificates/MasterCertificate.ts | 26 +- .../certificates/VerifiableCertificate.ts | 8 +- .../__tests/CompletedProtoWallet.ts | 44 +- .../__tests/VerifiableCertificate.test.ts | 4 +- src/auth/clients/AuthFetch.ts | 45 +- src/auth/utils/createNonce.ts | 2 +- src/auth/utils/verifyNonce.ts | 2 +- src/identity/__tests/IdentityClient.test.ts | 66 ++- src/identity/types/index.ts | 2 +- src/kvstore/__tests/LocalKVStore.test.ts | 41 +- .../__tests/SymmetricKeyCompatibility.test.ts | 8 +- src/primitives/__tests/utils.test.ts | 14 +- src/registry/__tests/RegistryClient.test.ts | 61 +-- src/registry/types/index.ts | 2 +- src/script/templates/P2PKH.ts | 12 +- src/script/templates/PushDrop.ts | 16 +- src/script/templates/RPuzzle.ts | 24 +- src/storage/__tests/StorageDownloader.test.ts | 402 +++++++++--------- src/storage/__tests/StorageUploader.test.ts | 4 +- src/transaction/__tests/Beef.test.ts | 4 +- src/transaction/__tests/Transaction.test.ts | 30 +- src/transaction/broadcasters/ARC.ts | 14 +- .../broadcasters/DefaultBroadcaster.ts | 2 +- src/transaction/broadcasters/Teranode.ts | 4 +- .../broadcasters/WhatsOnChainBroadcaster.ts | 4 +- .../chaintrackers/BlockHeadersService.ts | 26 +- .../chaintrackers/DefaultChainTracker.ts | 2 +- src/transaction/chaintrackers/WhatsOnChain.ts | 8 +- .../fee-models/SatoshisPerKilobyte.ts | 4 +- src/transaction/http/BinaryFetchClient.ts | 10 +- src/transaction/http/DefaultHttpClient.ts | 4 +- src/transaction/http/FetchHttpClient.ts | 2 +- src/transaction/http/NodejsHttpClient.ts | 4 +- src/wallet/substrates/HTTPWalletJSON.ts | 94 ++-- src/wallet/substrates/HTTPWalletWire.ts | 4 +- src/wallet/substrates/ReactNativeWebView.ts | 349 +++++++-------- src/wallet/substrates/WalletWireProcessor.ts | 18 +- .../substrates/WalletWireTransceiver.ts | 110 ++--- src/wallet/substrates/XDM.ts | 346 +++++++-------- .../substrates/__tests/toOriginHeader.test.ts | 26 +- src/wallet/substrates/utils/toOriginHeader.ts | 4 +- src/wallet/substrates/window.CWI.ts | 346 +++++++-------- 44 files changed, 1115 insertions(+), 1113 deletions(-) diff --git a/src/auth/__tests/Peer.test.ts b/src/auth/__tests/Peer.test.ts index ba3edbc2..8c82339b 100644 --- a/src/auth/__tests/Peer.test.ts +++ b/src/auth/__tests/Peer.test.ts @@ -18,12 +18,12 @@ class LocalTransport implements Transport { private peerTransport?: LocalTransport private onDataCallback?: (message: AuthMessage) => void - connect (peerTransport: LocalTransport): void { + connect(peerTransport: LocalTransport): void { this.peerTransport = peerTransport peerTransport.peerTransport = this } - async send (message: AuthMessage): Promise { + async send(message: AuthMessage): Promise { if ( this.peerTransport?.onDataCallback !== undefined && this.peerTransport?.onDataCallback !== null @@ -37,18 +37,18 @@ class LocalTransport implements Transport { } } - async onData ( + async onData( callback: (message: AuthMessage) => void ): Promise { this.onDataCallback = callback } } -async function waitForNextGeneralMessage ( +function waitForNextGeneralMessage ( peer: Peer, handler?: (senderPublicKey: string, payload: number[]) => void ): Promise { - return await new Promise(resolve => { + return new Promise(resolve => { const listenerId = peer.listenForGeneralMessages((senderPublicKey, payload) => { peer.stopListeningForGeneralMessages(listenerId) if (handler !== undefined) handler(senderPublicKey, payload) @@ -84,7 +84,7 @@ describe('Peer class mutual authentication and certificate exchange', () => { libraryCardNumber: 'B654321' } - async function createMasterCertificate ( + async function createMasterCertificate( subjectWallet: WalletInterface, fields: Record ): Promise { @@ -111,7 +111,7 @@ describe('Peer class mutual authentication and certificate exchange', () => { return masterCertificate } - async function createVerifiableCertificate ( + async function createVerifiableCertificate( masterCertificate: MasterCertificate, wallet: WalletInterface, verifierIdentityKey: string, @@ -144,7 +144,7 @@ describe('Peer class mutual authentication and certificate exchange', () => { ) } - function setupPeers ( + function setupPeers( aliceRequests: boolean, bobRequests: boolean, options: { @@ -185,7 +185,7 @@ describe('Peer class mutual authentication and certificate exchange', () => { return { aliceReceivedCertificates, bobReceivedCertificates } } - async function mockGetVerifiableCertificates ( + async function mockGetVerifiableCertificates( aliceCertificate: VerifiableCertificate | undefined, bobCertificate: VerifiableCertificate | undefined, alicePubKey: string, diff --git a/src/auth/certificates/Certificate.ts b/src/auth/certificates/Certificate.ts index 3616954c..ff17e638 100644 --- a/src/auth/certificates/Certificate.ts +++ b/src/auth/certificates/Certificate.ts @@ -62,7 +62,7 @@ export default class Certificate { * @param {Record} fields - All the fields present in the certificate. * @param {HexString} signature - Certificate signature by the certifier's private key, DER encoded hex string. */ - constructor ( + constructor( type: Base64String, serialNumber: Base64String, subject: PubKeyHex, @@ -86,7 +86,7 @@ export default class Certificate { * @param {boolean} [includeSignature=true] - Whether to include the signature in the serialization. * @returns {number[]} - The serialized certificate in binary format. */ - toBinary (includeSignature: boolean = true): number[] { + toBinary(includeSignature: boolean = true): number[] { const writer = new Utils.Writer() // Write type (Base64String, 32 bytes) @@ -144,7 +144,7 @@ export default class Certificate { * @param {number[]} bin - The binary data representing the certificate. * @returns {Certificate} - The deserialized Certificate object. */ - static fromBinary (bin: number[]): Certificate { + static fromBinary(bin: number[]): Certificate { const reader = new Utils.Reader(bin) // Read type @@ -210,7 +210,7 @@ export default class Certificate { * * @returns {Promise} - A promise that resolves to true if the signature is valid. */ - async verify (): Promise { + async verify(): Promise { // A verifier can be any wallet capable of verifying signatures const verifier = new ProtoWallet('anyone') const verificationData = this.toBinary(false) // Exclude the signature from the verification data @@ -234,7 +234,7 @@ export default class Certificate { * @param {Wallet} certifierWallet - The wallet representing the certifier. * @returns {Promise} */ - async sign (certifierWallet: ProtoWallet): Promise { + async sign(certifierWallet: ProtoWallet): Promise { if (this.signature != null && this.signature.length > 0) { // ✅ Explicitly checking for null/undefined throw new Error( `Certificate has already been signed! Signature present: ${this.signature}` @@ -271,7 +271,7 @@ export default class Certificate { * - `keyID` (string): A unique key identifier. It is the `fieldName` if `serialNumber` is undefined, * otherwise it is a combination of `serialNumber` and `fieldName`. */ - static getCertificateFieldEncryptionDetails ( + static getCertificateFieldEncryptionDetails( fieldName: string, serialNumber?: string ): { protocolID: WalletProtocol, keyID: string } { diff --git a/src/auth/certificates/MasterCertificate.ts b/src/auth/certificates/MasterCertificate.ts index e57212df..89da9ee2 100644 --- a/src/auth/certificates/MasterCertificate.ts +++ b/src/auth/certificates/MasterCertificate.ts @@ -4,7 +4,7 @@ import { HexString, OutpointString, PubKeyHex, - WalletCounterparty + WalletCounterparty, } from '../../wallet/Wallet.interfaces.js' import Certificate from './Certificate.js' import * as Utils from '../../primitives/utils.js' @@ -36,7 +36,7 @@ export class MasterCertificate extends Certificate { masterKeyring: Record - constructor ( + constructor( type: Base64String, serialNumber: Base64String, subject: PubKeyHex, @@ -77,14 +77,14 @@ export class MasterCertificate extends Certificate { * @param {WalletCounterparty} certifierOrSubject - The certifier or subject who will validate the certificate fields. * @param {Record} fields - A record of certificate field names (under 50 bytes) mapped to their values. * @param {BooleanDefaultFalse} [privileged] - Whether this is a privileged request. - * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. * + * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. * * @returns {Promise} A promise resolving to an object containing: * - `certificateFields` {Record}: * The encrypted certificate fields. * - `masterKeyring` {Record}: * The master keyring containing encrypted revelation keys for each field. */ - static async createCertificateFields ( + static async createCertificateFields( creatorWallet: ProtoWallet, certifierOrSubject: WalletCounterparty, fields: Record, @@ -92,12 +92,12 @@ export class MasterCertificate extends Certificate { privilegedReason?: string ): Promise { const certificateFields: Record< - CertificateFieldNameUnder50Bytes, - Base64String + CertificateFieldNameUnder50Bytes, + Base64String > = {} const masterKeyring: Record< - CertificateFieldNameUnder50Bytes, - Base64String + CertificateFieldNameUnder50Bytes, + Base64String > = {} for (const [fieldName, fieldValue] of Object.entries(fields)) { const fieldSymmetricKey = SymmetricKey.fromRandom() @@ -139,13 +139,13 @@ export class MasterCertificate extends Certificate { * @param {string} [originator] - Optional originator identifier, used if additional context is needed for decryption and encryption operations. * @returns {Promise>} - A keyring mapping field names to encrypted field revelation keys, allowing the verifier to decrypt specified fields. * @param {BooleanDefaultFalse} [privileged] - Whether this is a privileged request. - * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. * + * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. * * @throws {Error} Throws an error if: * - fieldsToReveal is not an array of strings. * - A field in `fieldsToReveal` does not exist in the certificate. * - The decrypted master field key fails to decrypt the corresponding field (indicating an invalid key). */ - static async createKeyringForVerifier ( + static async createKeyringForVerifier( subjectWallet: ProtoWallet, certifier: WalletCounterparty, verifier: WalletCounterparty, @@ -225,7 +225,7 @@ export class MasterCertificate extends Certificate { * * @throws {Error} Throws an error if any operation (e.g., encryption, signing) fails during certificate issuance. */ - static async issueCertificateForSubject ( + static async issueCertificateForSubject( certifierWallet: ProtoWallet, subject: WalletCounterparty, fields: Record, @@ -281,7 +281,7 @@ export class MasterCertificate extends Certificate { * * @throws {Error} Throws an error if the `masterKeyring` is invalid or if decryption fails for any field. */ - static async decryptFields ( + static async decryptFields( subjectOrCertifierWallet: ProtoWallet, masterKeyring: Record, fields: Record, @@ -315,7 +315,7 @@ export class MasterCertificate extends Certificate { } } - static async decryptField ( + static async decryptField( subjectOrCertifierWallet: ProtoWallet, masterKeyring: Record, fieldName: Base64String, diff --git a/src/auth/certificates/VerifiableCertificate.ts b/src/auth/certificates/VerifiableCertificate.ts index 28b9278b..e9be8c0f 100644 --- a/src/auth/certificates/VerifiableCertificate.ts +++ b/src/auth/certificates/VerifiableCertificate.ts @@ -5,7 +5,7 @@ import type { HexString, OutpointString, WalletCertificate, - OriginatorDomainNameStringUnder250Bytes + OriginatorDomainNameStringUnder250Bytes, } from '../../wallet/Wallet.interfaces.js' import SymmetricKey from '../../primitives/SymmetricKey.js' import * as Utils from '../../primitives/utils.js' @@ -28,7 +28,7 @@ export class VerifiableCertificate extends Certificate { keyring: Record decryptedFields?: Record - constructor ( + constructor( type: Base64String, serialNumber: Base64String, subject: PubKeyHex, @@ -59,7 +59,7 @@ export class VerifiableCertificate extends Certificate { * @returns {VerifiableCertificate} – A fully-formed instance containing the * original certificate data plus the supplied keyring. */ - static fromCertificate ( + static fromCertificate( certificate: WalletCertificate, keyring: Record ): VerifiableCertificate { @@ -83,7 +83,7 @@ export class VerifiableCertificate extends Certificate { * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. * @throws {Error} Throws an error if any of the decryption operations fail, with a message indicating the failure context. */ - async decryptFields ( + async decryptFields( verifierWallet: ProtoWallet, privileged?: boolean, privilegedReason?: string, diff --git a/src/auth/certificates/__tests/CompletedProtoWallet.ts b/src/auth/certificates/__tests/CompletedProtoWallet.ts index 28a1d910..41ad6495 100644 --- a/src/auth/certificates/__tests/CompletedProtoWallet.ts +++ b/src/auth/certificates/__tests/CompletedProtoWallet.ts @@ -1,4 +1,4 @@ -// @ts-nocheck +//@ts-nocheck import PrivateKey from '../../../primitives/PrivateKey.js' import { ProtoWallet, @@ -33,7 +33,7 @@ export class CompletedProtoWallet extends ProtoWallet implements WalletInterface { keyDeriver: KeyDeriver - constructor (rootKeyOrKeyDeriver: PrivateKey | 'anyone' | KeyDeriverApi) { + constructor(rootKeyOrKeyDeriver: PrivateKey | 'anyone' | KeyDeriverApi) { super(rootKeyOrKeyDeriver) if (rootKeyOrKeyDeriver instanceof KeyDeriver) { @@ -48,30 +48,30 @@ export class CompletedProtoWallet } } - async isAuthenticated ( + async isAuthenticated( ): Promise { throw new Error('not implemented') } - async waitForAuthentication ( + async waitForAuthentication( ): Promise { throw new Error('not implemented') } - async getNetwork ( + async getNetwork( ): Promise { throw new Error('not implemented') } - async getVersion ( + async getVersion( ): Promise { throw new Error('not implemented') } - async getPublicKey ( + async getPublicKey( args: GetPublicKeyArgs ): Promise<{ publicKey: PubKeyHex }> { if (args.privileged === true) { @@ -110,91 +110,91 @@ export class CompletedProtoWallet } } - async createAction ( + async createAction( ): Promise { throw new Error('not implemented') } - async signAction ( + async signAction( ): Promise { throw new Error('not implemented') } - async abortAction ( + async abortAction( ): Promise { throw new Error('not implemented') } - async listActions ( + async listActions( ): Promise { throw new Error('not implemented') } - async internalizeAction ( + async internalizeAction( ): Promise { throw new Error('not implemented') } - async listOutputs ( + async listOutputs( ): Promise { throw new Error('not implemented') } - async relinquishOutput ( + async relinquishOutput( ): Promise { throw new Error('not implemented') } - async acquireCertificate ( + async acquireCertificate( ): Promise { throw new Error('not implemented') } - async listCertificates ( + async listCertificates( ): Promise { throw new Error('not implemented') } - async proveCertificate ( + async proveCertificate( ): Promise { throw new Error('not implemented') } - async relinquishCertificate ( + async relinquishCertificate( ): Promise { throw new Error('not implemented') } - async discoverByIdentityKey ( + async discoverByIdentityKey( ): Promise { throw new Error('not implemented') } - async discoverByAttributes ( + async discoverByAttributes( ): Promise { throw new Error('not implemented') } - async getHeight ( + async getHeight( ): Promise { throw new Error('not implemented') } - async getHeaderForHeight ( + async getHeaderForHeight( ): Promise { throw new Error('not implemented') diff --git a/src/auth/certificates/__tests/VerifiableCertificate.test.ts b/src/auth/certificates/__tests/VerifiableCertificate.test.ts index 7b1c0c2d..e3b8761b 100644 --- a/src/auth/certificates/__tests/VerifiableCertificate.test.ts +++ b/src/auth/certificates/__tests/VerifiableCertificate.test.ts @@ -150,7 +150,7 @@ describe('VerifiableCertificate', () => { expect(decrypted).toEqual(plaintextFields) }) }) - + describe('fromCertificate', () => { it('should create an equivalent VerifiableCertificate and decrypt correctly', async () => { const baseCert = new Certificate( @@ -160,7 +160,7 @@ describe('VerifiableCertificate', () => { verifiableCert.certifier, verifiableCert.revocationOutpoint, verifiableCert.fields, - verifiableCert.signature + verifiableCert.signature ) as WalletCertificate const verifiable = VerifiableCertificate.fromCertificate( diff --git a/src/auth/clients/AuthFetch.ts b/src/auth/clients/AuthFetch.ts index 0e3d6cb0..54a7dd84 100644 --- a/src/auth/clients/AuthFetch.ts +++ b/src/auth/clients/AuthFetch.ts @@ -33,7 +33,7 @@ const PAYMENT_VERSION = '1.0' * AuthFetch provides a lightweight fetch client for interacting with servers * over a simplified HTTP transport mechanism. It integrates session management, peer communication, * and certificate handling to enable secure and mutually-authenticated requests. - * + * * Additionally, it automatically handles 402 Payment Required responses by creating * and sending BSV payment transactions when necessary. */ @@ -51,7 +51,7 @@ export class AuthFetch { * @param wallet - The wallet instance for signing and authentication. * @param requestedCertificates - Optional set of certificates to request from peers. */ - constructor (wallet: WalletInterface, requestedCertificates?: RequestedCertificateSet, sessionManager?: SessionManager, originator?: OriginatorDomainNameStringUnder250Bytes) { + constructor(wallet: WalletInterface, requestedCertificates?: RequestedCertificateSet, sessionManager?: SessionManager, originator?: OriginatorDomainNameStringUnder250Bytes) { this.wallet = wallet this.requestedCertificates = requestedCertificates this.sessionManager = sessionManager ?? new SessionManager() @@ -60,18 +60,18 @@ export class AuthFetch { /** * Mutually authenticates and sends a HTTP request to a server. - * + * * 1) Attempt the request. * 2) If 402 Payment Required, automatically create and send payment. * 3) Return the final response. - * + * * @param url - The URL to send the request to. * @param config - Configuration options for the request, including method, headers, and body. * @returns A promise that resolves with the server's response, structured as a Response-like object. - * + * * @throws Will throw an error if unsupported headers are used or other validation fails. */ - async fetch (url: string, config: SimplifiedFetchRequestOptions = {}): Promise { + async fetch(url: string, config: SimplifiedFetchRequestOptions = {}): Promise { if (typeof config.retryCounter === 'number') { if (config.retryCounter <= 0) { throw new Error('Request failed after maximum number of retries.') @@ -189,7 +189,7 @@ export class AuthFetch { // Create the Response object const responseValue = new Response( - (responseBody != null) ? new Uint8Array(responseBody) : null, + responseBody ? new Uint8Array(responseBody) : null, { status: statusCode, statusText: `${statusCode}`, @@ -231,6 +231,7 @@ export class AuthFetch { try { const response = await this.handleFetchAndValidate(url, config, peerToUse) resolve(response) + return } catch (fetchError) { reject(fetchError) } @@ -253,14 +254,14 @@ export class AuthFetch { /** * Request Certificates from a Peer - * @param baseUrl - * @param certificatesToRequest + * @param baseUrl + * @param certificatesToRequest */ - async sendCertificateRequest (baseUrl: string, certificatesToRequest: RequestedCertificateSet): Promise { + async sendCertificateRequest(baseUrl: string, certificatesToRequest: RequestedCertificateSet): Promise { const parsedUrl = new URL(baseUrl) const baseURL = parsedUrl.origin - let peerToUse: { peer: Peer, identityKey?: string } + let peerToUse: { peer: Peer; identityKey?: string } if (typeof this.peers[baseURL] !== 'undefined') { peerToUse = { peer: this.peers[baseURL].peer } } else { @@ -299,7 +300,7 @@ export class AuthFetch { /** * Return any certificates we've collected thus far, then clear them out. */ - public consumeReceivedCertificates (): VerifiableCertificate[] { + public consumeReceivedCertificates(): VerifiableCertificate[] { return this.certificatesReceived.splice(0) } @@ -315,7 +316,7 @@ export class AuthFetch { * * @throws Will throw an error if unsupported headers are used or serialization fails. */ - private async serializeRequest ( + private async serializeRequest( method: string, headers: Record, body: any, @@ -398,7 +399,7 @@ export class AuthFetch { if (methodsThatTypicallyHaveBody.includes(method.toUpperCase()) && body === undefined) { // Check if content-type is application/json const contentTypeHeader = includedHeaders.find(([k]) => k === 'content-type') - if ((contentTypeHeader != null) && contentTypeHeader[1].includes('application/json')) { + if (contentTypeHeader && contentTypeHeader[1].includes('application/json')) { body = '{}' } else { body = '' @@ -416,10 +417,10 @@ export class AuthFetch { return writer } - /** + /** * Handles a non-authenticated fetch requests and validates that the server is not claiming to be authenticated. */ - private async handleFetchAndValidate (url: string, config: RequestInit, peerToUse: AuthPeer): Promise { + private async handleFetchAndValidate(url: string, config: RequestInit, peerToUse: AuthPeer): Promise { const response = await fetch(url, config) response.headers.forEach(header => { if (header.toLocaleLowerCase().startsWith('x-bsv')) { @@ -439,7 +440,7 @@ export class AuthFetch { * If we get 402 Payment Required, we build a transaction via wallet.createAction() * and re-attempt the request with an x-bsv-payment header. */ - private async handlePaymentAndRetry ( + private async handlePaymentAndRetry( url: string, config: SimplifiedFetchRequestOptions = {}, originalResponse: Response @@ -497,8 +498,10 @@ export class AuthFetch { } }, this.originator) + + // Attach the payment to the request headers - config.headers = (config.headers != null) || {} + config.headers = config.headers || {} config.headers['x-bsv-payment'] = JSON.stringify({ derivationPrefix, derivationSuffix, @@ -507,10 +510,10 @@ export class AuthFetch { config.retryCounter ??= 3 // Re-attempt request with payment attached - return await this.fetch(url, config) + return this.fetch(url, config) } - private async normalizeBodyToNumberArray (body: BodyInit | null | undefined): Promise { + private async normalizeBodyToNumberArray(body: BodyInit | null | undefined): Promise { // 0. Null / undefined if (body == null) { return [] @@ -545,7 +548,7 @@ export class AuthFetch { // 6. FormData if (body instanceof FormData) { - const entries: Array<[string, string]> = [] + const entries: [string, string][] = [] body.forEach((value, key) => { entries.push([key, value.toString()]) }) diff --git a/src/auth/utils/createNonce.ts b/src/auth/utils/createNonce.ts index 840275b0..1f4c9450 100644 --- a/src/auth/utils/createNonce.ts +++ b/src/auth/utils/createNonce.ts @@ -13,7 +13,7 @@ import Random from '../../primitives/Random.js' * @param counterparty - The counterparty to the nonce creation. Defaults to 'self'. * @returns A random nonce derived with a wallet */ -export async function createNonce ( +export async function createNonce( wallet: WalletInterface, counterparty: WalletCounterparty = 'self', originator?: OriginatorDomainNameStringUnder250Bytes diff --git a/src/auth/utils/verifyNonce.ts b/src/auth/utils/verifyNonce.ts index dad80805..a4835fc2 100644 --- a/src/auth/utils/verifyNonce.ts +++ b/src/auth/utils/verifyNonce.ts @@ -8,7 +8,7 @@ import { WalletInterface, WalletCounterparty, Base64String, OriginatorDomainName * @param counterparty - The counterparty to the nonce creation. Defaults to 'self'. * @returns The status of the validation */ -export async function verifyNonce ( +export async function verifyNonce( nonce: Base64String, wallet: WalletInterface, counterparty: WalletCounterparty = 'self', diff --git a/src/identity/__tests/IdentityClient.test.ts b/src/identity/__tests/IdentityClient.test.ts index a51b7f91..3d65f02f 100644 --- a/src/identity/__tests/IdentityClient.test.ts +++ b/src/identity/__tests/IdentityClient.test.ts @@ -256,7 +256,7 @@ describe('IdentityClient', () => { } // Mock ContactsManager to return contact for the specific identity key - const mockContactsManager = identityClient.contactsManager + const mockContactsManager = identityClient['contactsManager'] mockContactsManager.getContacts = jest.fn().mockResolvedValue([contact]) walletMock.discoverByIdentityKey = jest.fn().mockResolvedValue({ certificates: [discoveredCertificate] }) @@ -352,7 +352,7 @@ describe('IdentityClient', () => { } // Mock the ContactsManager's getContacts method instead of the IdentityClient method - const mockContactsManager = identityClient.contactsManager + const mockContactsManager = identityClient['contactsManager'] mockContactsManager.getContacts = jest.fn().mockResolvedValue([contact]) walletMock.discoverByAttributes = jest.fn().mockResolvedValue({ certificates: [discoveredCertificate] }) @@ -367,15 +367,11 @@ describe('IdentityClient', () => { { name: 'Alice Smith', identityKey: 'alice-key', - avatarURL: '', - abbreviatedKey: 'alice-i...', - badgeIconURL: '', - badgeLabel: '', - badgeClickURL: '' + avatarURL: '', abbreviatedKey: 'alice-i...', badgeIconURL: '', badgeLabel: '', badgeClickURL: '' } ] - const mockContactsManager = identityClient.contactsManager + const mockContactsManager = identityClient['contactsManager'] mockContactsManager.getContacts = jest.fn().mockResolvedValue(contacts) const identities = await identityClient.resolveByAttributes({ attributes: { name: '', email: ' ' } }) @@ -388,11 +384,7 @@ describe('IdentityClient', () => { { name: 'Alice Smith (Personal)', identityKey: 'alice-key', - avatarURL: '', - abbreviatedKey: 'alice-i...', - badgeIconURL: '', - badgeLabel: '', - badgeClickURL: '' + avatarURL: '', abbreviatedKey: 'alice-i...', badgeIconURL: '', badgeLabel: '', badgeClickURL: '' } ] @@ -410,7 +402,7 @@ describe('IdentityClient', () => { } } - const mockContactsManager = identityClient.contactsManager + const mockContactsManager = identityClient['contactsManager'] mockContactsManager.getContacts = jest.fn().mockResolvedValue(contacts) walletMock.discoverByAttributes = jest.fn().mockResolvedValue({ certificates: [discoveredCertificate] }) @@ -574,13 +566,13 @@ describe('IdentityClient', () => { } ; (walletMock.listOutputs as jest.Mock).mockResolvedValueOnce({ - outputs: [existingOutput], - BEEF: [1, 2, 3] - }) + outputs: [existingOutput], + BEEF: [1, 2, 3] + }) - ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ - plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) - }) + ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ + plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) + }) const updatedContact = { ...mockContact, name: 'Alice Updated' } await identityClient.saveContact(updatedContact) @@ -630,13 +622,13 @@ describe('IdentityClient', () => { } ; (walletMock.listOutputs as jest.Mock).mockResolvedValue({ - outputs: [mockOutput], - BEEF: [1, 2, 3] - }) + outputs: [mockOutput], + BEEF: [1, 2, 3] + }) - ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ - plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) - }) + ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ + plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) + }) const result = await identityClient.getContacts() @@ -664,11 +656,11 @@ describe('IdentityClient', () => { }) await identityClient.saveContact(mockContact) - // Mock empty result for force refresh - ; (walletMock.listOutputs as jest.Mock).mockResolvedValue({ - outputs: [], - BEEF: [] - }) + // Mock empty result for force refresh + ; (walletMock.listOutputs as jest.Mock).mockResolvedValue({ + outputs: [], + BEEF: [] + }) const result = await identityClient.getContacts(undefined, true) @@ -727,13 +719,13 @@ describe('IdentityClient', () => { } ; (walletMock.listOutputs as jest.Mock).mockResolvedValue({ - outputs: [mockOutput], - BEEF: [1, 2, 3] - }) + outputs: [mockOutput], + BEEF: [1, 2, 3] + }) - ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ - plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) - }) + ; (walletMock.decrypt as jest.Mock).mockResolvedValue({ + plaintext: new TextEncoder().encode(JSON.stringify(mockContact)) + }) await identityClient.removeContact(mockContact.identityKey) diff --git a/src/identity/types/index.ts b/src/identity/types/index.ts index 092539d6..5fae0150 100644 --- a/src/identity/types/index.ts +++ b/src/identity/types/index.ts @@ -1,4 +1,4 @@ -import { WalletProtocol } from '../../wallet/index.js' +import { WalletProtocol } from "../../wallet/index.js" export const defaultIdentity: DisplayableIdentity = { name: 'Unknown Identity', diff --git a/src/kvstore/__tests/LocalKVStore.test.ts b/src/kvstore/__tests/LocalKVStore.test.ts index abe5f547..839d73f1 100644 --- a/src/kvstore/__tests/LocalKVStore.test.ts +++ b/src/kvstore/__tests/LocalKVStore.test.ts @@ -157,15 +157,16 @@ describe('localKVStore', () => { BEEF: undefined } - const lookupValueReal = kvStore.lookupValue - kvStore.lookupValue = jest.fn().mockResolvedValue({ + const lookupValueReal = kvStore['lookupValue'] + kvStore['lookupValue'] = jest.fn().mockResolvedValue({ value: defaultValue, outpoint: undefined, lor: mockedLor }) + const result = await kvStore.get(testKey, defaultValue) - kvStore.lookupValue = lookupValueReal + kvStore['lookupValue'] = lookupValueReal expect(result).toBe(defaultValue) }) @@ -179,15 +180,16 @@ describe('localKVStore', () => { BEEF: undefined } - const lookupValueReal = kvStore.lookupValue - kvStore.lookupValue = jest.fn().mockResolvedValue({ + const lookupValueReal = kvStore['lookupValue'] + kvStore['lookupValue'] = jest.fn().mockResolvedValue({ value: defaultValue, outpoint: undefined, lor: mockedLor }) + const result = await kvStore.get(testKey, defaultValue) - kvStore.lookupValue = lookupValueReal + kvStore['lookupValue'] = lookupValueReal expect(result).toBe(defaultValue) }) @@ -231,7 +233,7 @@ describe('localKVStore', () => { testKey, 'self' ) - // expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions' }) + //expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions' }) // Verify createAction for NEW output expect(mockWallet.createAction).toHaveBeenCalledWith({ description: `Update ${testKey} in ${testContext}`, @@ -275,13 +277,13 @@ describe('localKVStore', () => { testKey, 'self' ) - // expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions' }) + //expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions' }) expect(mockWallet.createAction).toHaveBeenCalledWith({ description: `Update ${testKey} in ${testContext}`, inputBEEF: undefined, inputs: [], outputs: [{ - basket: 'test-kv-context', + basket: "test-kv-context", tags: ['myTestKey'], lockingScript: testLockingScriptHex, // From mock lock satoshis: 1, @@ -299,7 +301,7 @@ describe('localKVStore', () => { it('should update an existing output (spend and create)', async () => { const existingOutpoint = 'oldTxId.0' const existingOutput = { outpoint: existingOutpoint, txid: 'oldTxId', vout: 0, lockingScript: 'oldScriptHex' } // Added script - const mockBEEF = [1, 2, 3, 4, 5, 6] + const mockBEEF = [1,2,3,4,5,6] const signableRef = 'signableTxRef123' const signableTx = [] const updatedTxId = 'updatedTxId' @@ -335,8 +337,8 @@ describe('localKVStore', () => { BEEF: mockBEEF } - const lookupValueReal = kvStore.lookupValue - kvStore.lookupValue = jest.fn().mockResolvedValue({ + const lookupValueReal = kvStore['lookupValue'] + kvStore['lookupValue'] = jest.fn().mockResolvedValue({ value: 'oldValue', outpoint: existingOutpoint, lor: mockedLor @@ -348,7 +350,7 @@ describe('localKVStore', () => { */ const result = await kvStore.set(testKey, testValue) - kvStore.lookupValue = lookupValueReal + kvStore['lookupValue'] = lookupValueReal expect(result).toBe(`${updatedTxId}.0`) // Assuming output 0 is the new KV token expect(mockWallet.encrypt).toHaveBeenCalled() @@ -393,7 +395,7 @@ describe('localKVStore', () => { const existingOutpoint2 = 'oldTxId2.1' const existingOutput1 = { outpoint: existingOutpoint1, txid: 'oldTxId1', vout: 0, lockingScript: 's1' } const existingOutput2 = { outpoint: existingOutpoint2, txid: 'oldTxId2', vout: 1, lockingScript: 's2' } - const mockBEEF = [1, 2, 3, 4, 5, 6] + const mockBEEF = [1,2,3,4,5,6] const signableRef = 'signableTxRefMulti' const signableTx = [] const updatedTxId = 'updatedTxIdMulti' @@ -431,15 +433,15 @@ describe('localKVStore', () => { BEEF: mockBEEF } - const lookupValueReal = kvStore.lookupValue - kvStore.lookupValue = jest.fn().mockResolvedValue({ + const lookupValueReal = kvStore['lookupValue'] + kvStore['lookupValue'] = jest.fn().mockResolvedValue({ value: 'oldValue', outpoint: existingOutpoint2, lor: mockedLor }) const result = await kvStore.set(testKey, testValue) - kvStore.lookupValue = lookupValueReal + kvStore['lookupValue'] = lookupValueReal expect(result).toBe(`${updatedTxId}.0`) expect(mockWallet.encrypt).toHaveBeenCalled() @@ -534,7 +536,7 @@ describe('localKVStore', () => { const result = await kvStore.remove(testKey) expect(result).toEqual([removalTxId]) - // expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions', limit: undefined, tagsQueryMode: 'all' }) + //expect(mockWallet.listOutputs).toHaveBeenCalledWith({ basket: testContext, tags: [testKey], include: 'entire transactions', limit: undefined, tagsQueryMode: 'all' }) // Verify createAction for REMOVE (no outputs in the action) expect(mockWallet.createAction).toHaveBeenCalledWith({ @@ -602,10 +604,11 @@ describe('localKVStore', () => { expect(mockWallet.listOutputs).toHaveBeenCalled() expect(mockWallet.createAction).toHaveBeenCalled() // createAction called for removal attempt expect(MockedTransaction.fromAtomicBEEF).toHaveBeenCalled() - // expect(mockPDInstance.unlock).toHaveBeenCalledTimes(1) // unlock was called + //expect(mockPDInstance.unlock).toHaveBeenCalledTimes(1) // unlock was called const mockUnlocker = (mockPDInstance.unlock as jest.Mock).mock.results[0].value expect(mockUnlocker.sign).toHaveBeenCalledTimes(1) // sign was called expect(mockWallet.signAction).toHaveBeenCalled() // Called but failed + }) }) }) diff --git a/src/primitives/__tests/SymmetricKeyCompatibility.test.ts b/src/primitives/__tests/SymmetricKeyCompatibility.test.ts index bbd8b117..24e61b25 100644 --- a/src/primitives/__tests/SymmetricKeyCompatibility.test.ts +++ b/src/primitives/__tests/SymmetricKeyCompatibility.test.ts @@ -33,7 +33,7 @@ describe('Cross-SDK Compatibility Tests', () => { } ] - testCases.forEach(({ name, ciphertextHex }) => { + testCases.forEach(({name, ciphertextHex}) => { // Convert hex to byte array const ciphertext: number[] = [] for (let i = 0; i < ciphertextHex.length; i += 2) { @@ -79,7 +79,7 @@ describe('Cross-SDK Compatibility Tests', () => { } ] - testCases.forEach(({ name, ciphertextHex }) => { + testCases.forEach(({name, ciphertextHex}) => { // Convert hex to byte array const ciphertext: number[] = [] for (let i = 0; i < ciphertextHex.length; i += 2) { @@ -112,7 +112,7 @@ describe('Cross-SDK Compatibility Tests', () => { } ] - testCases.forEach(({ name, wif, expectedKeyLength, goCiphertext, tsCiphertext }) => { + testCases.forEach(({name, wif, expectedKeyLength, goCiphertext, tsCiphertext}) => { // Create symmetric key const privKey = PrivateKey.fromWif(wif) const pubKey = privKey.toPublicKey() @@ -147,4 +147,4 @@ describe('Cross-SDK Compatibility Tests', () => { }) }) }) -}) +}) \ No newline at end of file diff --git a/src/primitives/__tests/utils.test.ts b/src/primitives/__tests/utils.test.ts index 5e5f1852..a0303f81 100644 --- a/src/primitives/__tests/utils.test.ts +++ b/src/primitives/__tests/utils.test.ts @@ -159,33 +159,33 @@ describe('utils', () => { }) test('should return an empty array for an empty string', () => { - expect(toArray('')).toEqual([]) + expect(toArray("")).toEqual([]) }) test('should encode ASCII characters correctly', () => { - const input = 'Hello, World!' + const input = "Hello, World!" const expected = [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33] expect(toArray(input)).toEqual(expected) }) test('should encode 2-byte characters correctly', () => { // "é" (U+00E9) should encode to [0xC3, 0xA9] - expect(toArray('é')).toEqual([0xC3, 0xA9]) + expect(toArray("é")).toEqual([0xC3, 0xA9]) }) test('should encode 3-byte characters correctly', () => { // "€" (U+20AC) should encode to [0xE2, 0x82, 0xAC] - expect(toArray('€')).toEqual([0xE2, 0x82, 0xAC]) + expect(toArray("€")).toEqual([0xE2, 0x82, 0xAC]) }) test('should encode 4-byte characters correctly', () => { // "😃" (U+1F603) should encode to [0xF0, 0x9F, 0x98, 0x83] - expect(toArray('😃')).toEqual([0xF0, 0x9F, 0x98, 0x83]) + expect(toArray("😃")).toEqual([0xF0, 0x9F, 0x98, 0x83]) }) test('should encode mixed content correctly', () => { // "Hello, 😃! €" contains ASCII, an emoji, and a 3-byte character. - const input = 'Hello, 😃! €' + const input = "Hello, 😃! €" const expected = [ // "Hello, " => ASCII bytes: 72, 101, 108, 108, 111, 44, 32, @@ -202,7 +202,7 @@ describe('utils', () => { test('should replace lone surrogates with the replacement character', () => { // An unpaired high surrogate "\uD800" should be replaced with U+FFFD, // which is encoded in UTF-8 as [0xEF, 0xBF, 0xBD] - const input = '\uD800' + const input = "\uD800" const expected = [0xEF, 0xBF, 0xBD] expect(toArray(input)).toEqual(expected) }) diff --git a/src/registry/__tests/RegistryClient.test.ts b/src/registry/__tests/RegistryClient.test.ts index 73d9168f..18147eac 100644 --- a/src/registry/__tests/RegistryClient.test.ts +++ b/src/registry/__tests/RegistryClient.test.ts @@ -99,7 +99,7 @@ let walletMock: Partial /** * Build minimal valid DefinitionData for each type */ -function buildDefinitionData (type: DefinitionType): DefinitionData { +function buildDefinitionData(type: DefinitionType): DefinitionData { switch (type) { case 'basket': { const data: BasketDefinitionData = { @@ -288,23 +288,23 @@ describe('RegistryClient', () => { }) })) - // The code expects 7 fields for basket (6 definition fields + 1 extra signature field) - ; (PushDrop.decode as jest.Mock).mockReturnValue({ - fields: [ - [98], // 'b' - [97], // 'a' - [115], // 's' - [107], // 'k' - [101], // 'e' - [116], // 't' => operator - [111] // extra signature field - ] - }) + // The code expects 7 fields for basket (6 definition fields + 1 extra signature field) + ; (PushDrop.decode as jest.Mock).mockReturnValue({ + fields: [ + [98], // 'b' + [97], // 'a' + [115], // 's' + [107], // 'k' + [101], // 'e' + [116], // 't' => operator + [111] // extra signature field + ] + }) - // The final field must match the current wallet pubkey => 'mockPublicKey' - ; (walletMock.getPublicKey as jest.Mock).mockResolvedValueOnce({ - publicKey: 't' - }) + // The final field must match the current wallet pubkey => 'mockPublicKey' + ; (walletMock.getPublicKey as jest.Mock).mockResolvedValueOnce({ + publicKey: 't' + }) const result = await registryClient.resolve('basket', { basketID: 'whatever' }) expect(result).toHaveLength(1) @@ -330,10 +330,10 @@ describe('RegistryClient', () => { }) })) - // Return empty fields so parseLockingScript fails the length check - ; (PushDrop.decode as jest.Mock) - .mockReturnValueOnce({ fields: [] }) // fail - .mockReturnValueOnce({ fields: [] }) // fail again + // Return empty fields so parseLockingScript fails the length check + ; (PushDrop.decode as jest.Mock) + .mockReturnValueOnce({ fields: [] }) // fail + .mockReturnValueOnce({ fields: [] }) // fail again const result = await registryClient.resolve('basket', { name: 'fooAgain' }) expect(result).toEqual([]) @@ -376,34 +376,35 @@ describe('RegistryClient', () => { (PushDrop.decode as jest.Mock).mockImplementation((scriptObj) => { return { fields: [ - [98], // 'b' - [97], // 'a' + [98], // 'b' + [97], // 'a' [115], // 's' [107], // 'k' [101], // 'e' [116], // 't' - [111] // extra signature field + [111] // extra signature field ] } }); - (walletMock.getPublicKey as jest.Mock).mockResolvedValue({ publicKey: 't' }) // <-- Semicolon + (walletMock.getPublicKey as jest.Mock).mockResolvedValue({ publicKey: 't' }); // <-- Semicolon - const records = await registryClient.listOwnRegistryEntries('basket') + const records = await registryClient.listOwnRegistryEntries('basket'); expect(walletMock.listOutputs).toHaveBeenCalledWith({ basket: 'basketmap', include: 'entire transactions' - }) + }); // Only one spendable item should be returned if parsing succeeds. - expect(records).toHaveLength(1) + expect(records).toHaveLength(1); expect(records[0]).toMatchObject({ definitionType: 'basket', txid: 'skipMe', outputIndex: 2, satoshis: 200, lockingScript: 'decodedLockScript1AsHex' - }) - }) + }); + }); + }) // ------------------------------------------------------------------ diff --git a/src/registry/types/index.ts b/src/registry/types/index.ts index ce84bfd3..42132f7d 100644 --- a/src/registry/types/index.ts +++ b/src/registry/types/index.ts @@ -71,7 +71,7 @@ export interface TokenData { txid: string outputIndex: number satoshis: number - lockingScript: string + lockingScript: string, beef: BEEF } diff --git a/src/script/templates/P2PKH.ts b/src/script/templates/P2PKH.ts index bda8d7c0..aa567ff9 100644 --- a/src/script/templates/P2PKH.ts +++ b/src/script/templates/P2PKH.ts @@ -9,7 +9,7 @@ import TransactionSignature from '../../primitives/TransactionSignature.js' import { sha256 } from '../../primitives/Hash.js' import Script from '../Script.js' -function verifyTruthy (v: T | undefined): T { +function verifyTruthy(v: T | undefined): T { if (v == null) throw new Error('must have value') return v } @@ -26,7 +26,7 @@ export default class P2PKH implements ScriptTemplate { * @param {number[] | string} pubkeyhash or address - An array or address representing the public key hash. * @returns {LockingScript} - A P2PKH locking script. */ - lock (pubkeyhash: string | number[]): LockingScript { + lock(pubkeyhash: string | number[]): LockingScript { let data: number[] if (typeof pubkeyhash === 'string') { const hash = fromBase58Check(pubkeyhash) @@ -64,16 +64,16 @@ export default class P2PKH implements ScriptTemplate { * @param {Script} lockingScript - Optional. The lockinScript. Otherwise the input.sourceTransaction is required. * @returns {Object} - An object containing the `sign` and `estimateLength` functions. */ - unlock ( + unlock( privateKey: PrivateKey, signOutputs: 'all' | 'none' | 'single' = 'all', anyoneCanPay: boolean = false, sourceSatoshis?: number, lockingScript?: Script ): { - sign: (tx: Transaction, inputIndex: number) => Promise - estimateLength: () => Promise<108> - } { + sign: (tx: Transaction, inputIndex: number) => Promise + estimateLength: () => Promise<108> + } { return { sign: async (tx: Transaction, inputIndex: number) => { let signatureScope = TransactionSignature.SIGHASH_FORKID diff --git a/src/script/templates/PushDrop.ts b/src/script/templates/PushDrop.ts index 54dd7780..a2ac6cb9 100644 --- a/src/script/templates/PushDrop.ts +++ b/src/script/templates/PushDrop.ts @@ -9,7 +9,7 @@ import { import { WalletInterface, SecurityLevel } from '../../wallet/Wallet.interfaces.js' import { Transaction } from '../../transaction/index.js' -function verifyTruthy (v: T | undefined): T { +function verifyTruthy(v: T | undefined): T { if (v == null) throw new Error('must have value') return v } @@ -65,7 +65,7 @@ export default class PushDrop implements ScriptTemplate { * @param script PushDrop script to decode back into token fields * @returns An object containing PushDrop token fields and the locking public key. If a signature was included, it will be the last field. */ - static decode (script: LockingScript): { + static decode(script: LockingScript): { lockingPublicKey: PublicKey fields: number[][] } { @@ -108,7 +108,7 @@ export default class PushDrop implements ScriptTemplate { * @param {WalletInterface} wallet - The wallet interface used for creating signatures and accessing public keys. * @param {string} originator — The originator to use with Wallet requests */ - constructor (wallet: WalletInterface, originator?: string) { + constructor(wallet: WalletInterface, originator?: string) { this.wallet = wallet this.originator = originator } @@ -124,7 +124,7 @@ export default class PushDrop implements ScriptTemplate { * @param {boolean} [includeSignature=true] - Flag indicating if a signature should be included in the script (default yes). * @returns {Promise} The generated PushDrop locking script. */ - async lock ( + async lock( fields: number[][], protocolID: [SecurityLevel, string], keyID: string, @@ -187,7 +187,7 @@ export default class PushDrop implements ScriptTemplate { * @param {boolean} [anyoneCanPay=false] - Specifies if the anyone-can-pay flag is set. * @returns {Object} An object containing functions to sign the transaction and estimate the script length. */ - unlock ( + unlock( protocolID: [SecurityLevel, string], keyID: string, counterparty: string, @@ -196,9 +196,9 @@ export default class PushDrop implements ScriptTemplate { sourceSatoshis?: number, lockingScript?: LockingScript ): { - sign: (tx: Transaction, inputIndex: number) => Promise - estimateLength: () => Promise<73> - } { + sign: (tx: Transaction, inputIndex: number) => Promise + estimateLength: () => Promise<73> + } { return { sign: async ( tx: Transaction, diff --git a/src/script/templates/RPuzzle.ts b/src/script/templates/RPuzzle.ts index f4dd4ef5..993f32d1 100644 --- a/src/script/templates/RPuzzle.ts +++ b/src/script/templates/RPuzzle.ts @@ -24,14 +24,14 @@ export default class RPuzzle implements ScriptTemplate { * * @param {'raw'|'SHA1'|'SHA256'|'HASH256'|'RIPEMD160'|'HASH160'} type Denotes the type of puzzle to create */ - constructor ( + constructor( type: - | 'raw' - | 'SHA1' - | 'SHA256' - | 'HASH256' - | 'RIPEMD160' - | 'HASH160' = 'raw' + | 'raw' + | 'SHA1' + | 'SHA256' + | 'HASH256' + | 'RIPEMD160' + | 'HASH160' = 'raw' ) { this.type = type } @@ -42,7 +42,7 @@ export default class RPuzzle implements ScriptTemplate { * @param {number[]} value - An array representing the R value or its hash. * @returns {LockingScript} - An R puzzle locking script. */ - lock (value: number[]): LockingScript { + lock(value: number[]): LockingScript { const chunks: ScriptChunk[] = [ { op: OP.OP_OVER }, { op: OP.OP_3 }, @@ -79,15 +79,15 @@ export default class RPuzzle implements ScriptTemplate { * @param {boolean} anyoneCanPay - Flag indicating if the signature allows for other inputs to be added later. * @returns {Object} - An object containing the `sign` and `estimateLength` functions. */ - unlock ( + unlock( k: BigNumber, privateKey: PrivateKey, signOutputs: 'all' | 'none' | 'single' = 'all', anyoneCanPay: boolean = false ): { - sign: (tx: Transaction, inputIndex: number) => Promise - estimateLength: () => Promise<108> - } { + sign: (tx: Transaction, inputIndex: number) => Promise + estimateLength: () => Promise<108> + } { return { sign: async (tx: Transaction, inputIndex: number) => { if (typeof privateKey === 'undefined') { diff --git a/src/storage/__tests/StorageDownloader.test.ts b/src/storage/__tests/StorageDownloader.test.ts index 28bf1fe4..13fe769f 100644 --- a/src/storage/__tests/StorageDownloader.test.ts +++ b/src/storage/__tests/StorageDownloader.test.ts @@ -3,232 +3,234 @@ import { StorageUtils } from '../index.js' import { LookupResolver } from '../../overlay-tools/index.js' import Transaction from '../../transaction/Transaction.js' import PushDrop from '../../script/templates/PushDrop.js' -import { PublicKey, Utils } from '../../primitives/index.js' - +import { PublicKey } from '../../primitives/index.js' +import { Utils } from '../../primitives/index.js' import { ReadableStream } from 'stream/web' beforeEach(() => { - jest.restoreAllMocks() + jest.restoreAllMocks() }) describe('StorageDownloader', () => { - let downloader: StorageDownloader - - beforeEach(() => { - // Create a fresh instance - downloader = new StorageDownloader() - }) - - describe('resolve()', () => { - it('throws if the lookup response is not "output-list"', async () => { - // Mock the LookupResolver to return something invalid - jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ - type: 'something-else', - outputs: [] - } as any) - - await expect(downloader.resolve('fakeUhrpUrl')) - .rejects - .toThrow('Lookup answer must be an output list') - }) + let downloader: StorageDownloader - it('decodes each output with Transaction.fromBEEF and PushDrop.decode', async () => { - // 1) Mock lookup response - jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ - type: 'output-list', - outputs: [ - { beef: 'fake-beef-a', outputIndex: 0 }, - { beef: 'fake-beef-b', outputIndex: 1 } - ] - } as any) - - // 2) Mock Transaction.fromBEEF -> returns a dummy transaction - jest.spyOn(Transaction, 'fromBEEF').mockImplementation(() => { - // Each transaction might have multiple outputs; we only care about `outputIndex` - return { - outputs: [ - { lockingScript: {} }, // index 0 - { lockingScript: {} } // index 1 - ] - } as any - }) - - // 3) Mock PushDrop.decode -> returns { fields: number[][] } - jest.spyOn(PushDrop, 'decode').mockImplementation(() => { - // The decode function returns an object with `fields`, - return { - lockingPublicKey: {} as PublicKey, - fields: [ - [11], - [22], - [104, 116, 116, 112, 58, 47, 47, 97, 46, 99, 111, 109] - ] - } - }) - - // 4) Mock Utils.toUTF8 to convert that number[] to a string - jest.spyOn(Utils, 'toUTF8').mockReturnValue('http://a.com') - - const resolved = await downloader.resolve('fakeUhrpUrl') - expect(resolved).toEqual(['http://a.com', 'http://a.com']) + beforeEach(() => { + // Create a fresh instance + downloader = new StorageDownloader() }) - }) - describe('download()', () => { - it('throws if UHRP URL is invalid', async () => { - jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(false) + describe('resolve()', () => { + it('throws if the lookup response is not "output-list"', async () => { + // Mock the LookupResolver to return something invalid + jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ + type: 'something-else', + outputs: [] + } as any) + + await expect(downloader.resolve('fakeUhrpUrl')) + .rejects + .toThrow('Lookup answer must be an output list') + }) + + it('decodes each output with Transaction.fromBEEF and PushDrop.decode', async () => { + // 1) Mock lookup response + jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ + type: 'output-list', + outputs: [ + { beef: 'fake-beef-a', outputIndex: 0 }, + { beef: 'fake-beef-b', outputIndex: 1 } + ] + } as any) + + // 2) Mock Transaction.fromBEEF -> returns a dummy transaction + jest.spyOn(Transaction, 'fromBEEF').mockImplementation(() => { + // Each transaction might have multiple outputs; we only care about `outputIndex` + return { + outputs: [ + { lockingScript: {} }, // index 0 + { lockingScript: {} } // index 1 + ] + } as any + }) + + // 3) Mock PushDrop.decode -> returns { fields: number[][] } + jest.spyOn(PushDrop, 'decode').mockImplementation(() => { + // The decode function returns an object with `fields`, + return { + lockingPublicKey: {} as PublicKey, + fields: [ + [11], + [22], + [104, 116, 116, 112, 58, 47, 47, 97, 46, 99, 111, 109] + ] + } + }) + + // 4) Mock Utils.toUTF8 to convert that number[] to a string + jest.spyOn(Utils, 'toUTF8').mockReturnValue('http://a.com') + + const resolved = await downloader.resolve('fakeUhrpUrl') + expect(resolved).toEqual(['http://a.com', 'http://a.com']) + }) + - await expect(downloader.download('invalidUrl')) - .rejects - .toThrow('Invalid parameter UHRP url') }) - it('throws if no hosts are found', async () => { - // Valid UHRP URL - jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) - // Return some random 32-byte hash so we can pass the check - jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) + describe('download()', () => { + it('throws if UHRP URL is invalid', async () => { + jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(false) - // Force resolve() to return an empty array - jest.spyOn(downloader, 'resolve').mockResolvedValue([]) + await expect(downloader.download('invalidUrl')) + .rejects + .toThrow('Invalid parameter UHRP url') + }) - await expect(downloader.download('validButUnhostedUrl')) - .rejects - .toThrow('No one currently hosts this file!') - }) + it('throws if no hosts are found', async () => { + // Valid UHRP URL + jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) + // Return some random 32-byte hash so we can pass the check + jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) - it('downloads successfully from the first working host', async () => { - jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) - const knownHash = [ - 102, 104, 122, 173, 248, 98, 189, 119, 108, 143, - 193, 139, 142, 159, 142, 32, 8, 151, 20, 133, - 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, - 41, 37 - ] - jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(knownHash) - - // Suppose two possible download URLs - jest.spyOn(downloader, 'resolve').mockResolvedValue([ - 'http://host1/404', - 'http://host2/ok' - ]) - - // The first fetch -> 404, second fetch -> success - const fetchSpy = jest.spyOn(global, 'fetch') - .mockResolvedValueOnce(new Response(null, { status: 404 })) - .mockResolvedValueOnce(new Response(new Uint8Array(32).fill(0), { - status: 200, - headers: { 'Content-Type': 'application/test' } - })) - - const result = await downloader.download('validUrl') - expect(fetchSpy).toHaveBeenCalledTimes(2) - expect(result).toEqual({ - data: new Uint8Array(32).fill(0), - mimeType: 'application/test' - }) - }) + // Force resolve() to return an empty array + jest.spyOn(downloader, 'resolve').mockResolvedValue([]) - it('throws if content hash mismatches the UHRP hash', async () => { - jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) - // The expected hash is all zeros - jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) + await expect(downloader.download('validButUnhostedUrl')) + .rejects + .toThrow('No one currently hosts this file!') + }) - // One potential host - jest.spyOn(downloader, 'resolve').mockResolvedValue([ - 'http://bad-content.test' - ]) + it('downloads successfully from the first working host', async () => { + jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) + const knownHash = [ + 102, 104, 122, 173, 248, 98, 189, 119, 108, 143, + 193, 139, 142, 159, 142, 32, 8, 151, 20, 133, + 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, + 41, 37 + ] + jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(knownHash) + + // Suppose two possible download URLs + jest.spyOn(downloader, 'resolve').mockResolvedValue([ + 'http://host1/404', + 'http://host2/ok' + ]) + + // The first fetch -> 404, second fetch -> success + const fetchSpy = jest.spyOn(global, 'fetch') + .mockResolvedValueOnce(new Response(null, { status: 404 })) + .mockResolvedValueOnce(new Response(new Uint8Array(32).fill(0), { + status: 200, + headers: { 'Content-Type': 'application/test' } + })) + + const result = await downloader.download('validUrl') + expect(fetchSpy).toHaveBeenCalledTimes(2) + expect(result).toEqual({ + data: new Uint8Array(32).fill(0), + mimeType: 'application/test' + }) + }) - // The fetch returns 32 bytes of all 1's => hash mismatch - jest.spyOn(global, 'fetch').mockResolvedValue( - new Response(new Uint8Array(32).fill(1), { status: 200 }) - ) + it('throws if content hash mismatches the UHRP hash', async () => { + jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) + // The expected hash is all zeros + jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) - await expect(downloader.download('validButBadHashUrl')) - .rejects - .toThrow() - }) + // One potential host + jest.spyOn(downloader, 'resolve').mockResolvedValue([ + 'http://bad-content.test' + ]) - it('throws if all hosts fail or mismatch', async () => { - jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) - jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) + // The fetch returns 32 bytes of all 1's => hash mismatch + jest.spyOn(global, 'fetch').mockResolvedValue( + new Response(new Uint8Array(32).fill(1), { status: 200 }) + ) - jest.spyOn(downloader, 'resolve').mockResolvedValue([ - 'http://host1.test', - 'http://host2.test' - ]) + await expect(downloader.download('validButBadHashUrl')) + .rejects + .toThrow() + }) - // Both fetches fail with 500 or something >=400 - jest.spyOn(global, 'fetch').mockResolvedValue( - new Response(null, { status: 500 }) - ) + it('throws if all hosts fail or mismatch', async () => { + jest.spyOn(StorageUtils, 'isValidURL').mockReturnValue(true) + jest.spyOn(StorageUtils, 'getHashFromURL').mockReturnValue(new Array(32).fill(0)) - await expect(downloader.download('validButNoGoodHostUrl')) - .rejects - .toThrow('Unable to download content from validButNoGoodHostUrl') - }) + jest.spyOn(downloader, 'resolve').mockResolvedValue([ + 'http://host1.test', + 'http://host2.test' + ]) - it('throws if all entries are expired', async () => { - const currentTime = Math.floor(Date.now()) - - jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ - type: 'output-list', - outputs: [ - { beef: 'fake-beef-a', outputIndex: 0 }, - { beef: 'fake-beef-b', outputIndex: 1 } - ] - } as any) - - jest.spyOn(Transaction, 'fromBEEF').mockImplementation(() => { - return { - outputs: [ - { lockingScript: {} }, - { lockingScript: {} } - ] - } as any - }) - - jest.spyOn(PushDrop, 'decode').mockImplementation(() => { - return { - lockingPublicKey: {} as PublicKey, - fields: [[], [], [], [currentTime - 100]] - } - }) - - await expect(downloader.resolve('expiredUhrpUrl')) - .resolves - .toEqual(['', '']) - }) + // Both fetches fail with 500 or something >=400 + jest.spyOn(global, 'fetch').mockResolvedValue( + new Response(null, { status: 500 }) + ) + + await expect(downloader.download('validButNoGoodHostUrl')) + .rejects + .toThrow('Unable to download content from validButNoGoodHostUrl') + }) - it.skip('downloads and verifies large streamed content', async () => { - const size = 5 * 1024 * 1024 - const data = new Uint8Array(size) - for (let i = 0; i < size; i++) data[i] = i % 256 - const uhrpUrl = StorageUtils.getURLForFile(data) - - jest.spyOn(downloader, 'resolve').mockResolvedValue(['http://large-file']) - - const chunkSize = 64 * 1024 - const stream = new ReadableStream({ - start (controller) { - for (let offset = 0; offset < data.length; offset += chunkSize) { - controller.enqueue(data.subarray(offset, offset + chunkSize)) - } - controller.close() - } - }) - - jest.spyOn(global, 'fetch').mockResolvedValue( - new Response(stream as any, { - status: 200, - headers: { 'Content-Type': 'application/octet-stream' } + it('throws if all entries are expired', async () => { + const currentTime = Math.floor(Date.now()) + + jest.spyOn(LookupResolver.prototype, 'query').mockResolvedValue({ + type: 'output-list', + outputs: [ + { beef: 'fake-beef-a', outputIndex: 0 }, + { beef: 'fake-beef-b', outputIndex: 1 } + ] + } as any) + + jest.spyOn(Transaction, 'fromBEEF').mockImplementation(() => { + return { + outputs: [ + { lockingScript: {} }, + { lockingScript: {} } + ] + } as any + }) + + jest.spyOn(PushDrop, 'decode').mockImplementation(() => { + return { + lockingPublicKey: {} as PublicKey, + fields: [[], [], [], [currentTime - 100]] + } + }) + + await expect(downloader.resolve('expiredUhrpUrl')) + .resolves + .toEqual(["", ""]) }) - ) - const result = await downloader.download(uhrpUrl) - expect(result.mimeType).toBe('application/octet-stream') - expect(result.data.length).toBe(size) - expect(result.data).toEqual(data) + it.skip('downloads and verifies large streamed content', async () => { + const size = 5 * 1024 * 1024 + const data = new Uint8Array(size) + for (let i = 0; i < size; i++) data[i] = i % 256 + const uhrpUrl = StorageUtils.getURLForFile(data) + + jest.spyOn(downloader, 'resolve').mockResolvedValue(['http://large-file']) + + const chunkSize = 64 * 1024 + const stream = new ReadableStream({ + start (controller) { + for (let offset = 0; offset < data.length; offset += chunkSize) { + controller.enqueue(data.subarray(offset, offset + chunkSize)) + } + controller.close() + } + }) + + jest.spyOn(global, 'fetch').mockResolvedValue( + new Response(stream as any, { + status: 200, + headers: { 'Content-Type': 'application/octet-stream' } + }) + ) + + const result = await downloader.download(uhrpUrl) + expect(result.mimeType).toBe('application/octet-stream') + expect(result.data.length).toBe(size) + expect(result.data).toEqual(data) + }) }) - }) }) diff --git a/src/storage/__tests/StorageUploader.test.ts b/src/storage/__tests/StorageUploader.test.ts index 8aed612b..3b3cf87c 100644 --- a/src/storage/__tests/StorageUploader.test.ts +++ b/src/storage/__tests/StorageUploader.test.ts @@ -6,7 +6,7 @@ import { createHash } from 'crypto' /** * A helper for converting a string to a number[] of UTF-8 bytes */ -function stringToUtf8Array (str: string): number[] { +function stringToUtf8Array(str: string): number[] { return Array.from(new TextEncoder().encode(str)) } @@ -27,7 +27,7 @@ describe('StorageUploader Tests', () => { // 1) Spy on the "authFetch.fetch" calls for /find, /list, /renew authFetchSpy = jest - .spyOn(uploader.authFetch, 'fetch') + .spyOn(uploader['authFetch'], 'fetch') .mockResolvedValue(new Response(null, { status: 200 })) // 2) Spy on the global "fetch" calls for file upload (uploadFile) diff --git a/src/transaction/__tests/Beef.test.ts b/src/transaction/__tests/Beef.test.ts index 7db05bec..d07c8ee3 100644 --- a/src/transaction/__tests/Beef.test.ts +++ b/src/transaction/__tests/Beef.test.ts @@ -26,7 +26,7 @@ describe('Beef tests', () => { 875732: 'a19c54129ab996c72cda7721b4555b47d11b21e1fe67aa63c59843edb302b6c2', 1651724: - '0fa8e6a2a8860eaec7365217c1cf64a905dc7936342b36a86566f933187f8c62' + '0fa8e6a2a8860eaec7365217c1cf64a905dc7936342b36a86566f933187f8c62', } if (knownRoots[height] !== undefined) { @@ -497,4 +497,4 @@ const log2 = `BEEF with 1 BUMPS and 2 Transactions, isValid true const wrongBumpTxid = '0100beef01fe4e6d0c001002fd909002088a382ec07a8cf47c6158b68e5822852362102d8571482d1257e0b7527e1882fd91900065cb01218f2506bb51155d243e4d6b32d69d1b5f2221c52e26963cfd8cf7283201fd4948008d7a44ae384797b0ae84db0c857e8c1083425d64d09ef8bc5e2e9d270677260501fd25240060f38aa33631c8d70adbac1213e7a5b418c90414e919e3a12ced63dd152fd85a01fd1312005ff132ee64a7a0c79150a29f66ef861e552d3a05b47d6303f5d8a2b2a09bc61501fd080900cc0baf21cf06b9439dfe05dce9bdb14ddc2ca2d560b1138296ef5769851a84b301fd85040063ccb26232a6e1d3becdb47a0f19a67a562b754e8894155b3ae7bba10335ce5101fd430200e153fc455a0f2c8372885c11af70af904dcf44740b9ebf3b3e5b2234cce550bc01fd20010077d5ea69d1dcc379dde65d6adcebde1838190118a8fae928c037275e78bd87910191000263e4f31684a25169857f2788aeef603504931f92585f02c4c9e023b2aa43d1014900de72292e0b3e5eeacfa2b657bf4d46c885559b081ee78632a99b318c1148d85c01250068a5f831ca99b9e7f3720920d6ea977fd2ab52b83d1a6567dafa4c8cafd941ed0113006a0b91d83f9056b702d6a8056af6365c7da626fc3818b815dd4b0de22d05450f0108009876ce56b68545a75859e93d200bdde7880d46f39384818b259ed847a9664ddf010500990bc5e95cacbc927b5786ec39a183f983fe160d52829cf47521c7eb369771c30103004fe794e50305f590b6010a51d050bf47dfeaabfdb949c5ee0673f577a59537d70100004dad44a358aea4d8bc1917912539901f5ae44e07a4748e1a9d3018814b0759d00201000000027b0a1b12c7c9e48015e78d3a08a4d62e439387df7e0d7a810ebd4af37661daaa000000006a47304402207d972759afba7c0ffa6cfbbf39a31c2aeede1dae28d8841db56c6dd1197d56a20220076a390948c235ba8e72b8e43a7b4d4119f1a81a77032aa6e7b7a51be5e13845412103f78ec31cf94ca8d75fb1333ad9fc884e2d489422034a1efc9d66a3b72eddca0fffffffff7f36874f858fb43ffcf4f9e3047825619bad0e92d4b9ad4ba5111d1101cbddfe010000006a473044022043f048043d56eb6f75024808b78f18808b7ab45609e4c4c319e3a27f8246fc3002204b67766b62f58bf6f30ea608eaba76b8524ed49f67a90f80ac08a9b96a6922cd41210254a583c1c51a06e10fab79ddf922915da5f5c1791ef87739f40cb68638397248ffffffff03e8030000000000001976a914b08f70bc5010fb026de018f19e7792385a146b4a88acf3010000000000001976a9147d48635f889372c3da12d75ce246c59f4ab907ed88acf7000000000000001976a914b8fbd58685b6920d8f9a8f1b274d8696708b51b088ac00000000010001000000018ae36502fdc82837319362c488fb9cb978e064daf600bbfc48389663fc5c160c000000006a47304402204a04841f6f626d30e21200e1c404ea80e319b643fe86f08e709413a89a493a4b022038a2e3e25a813d8d540c1a572fa8ec5fa2d2434bcea78d17902dcccddcc1c9484121028fd1afeee81361e801800afb264e35cdce3037ec6f7dc4f1d1eaba7ad519c948ffffffff01c8000000000000001976a9148ce2d21f9a75e98600be76b25b91c4fef6b40bcd88ac0000000000' -const bumpIndexEncoding = '0100beef01fe6e621900010200008cdbd6fe227cfafa6be4500cae6140c84b2ead61318063e92bdb6974f869cf33010259617a9d17562f7c9765e5dfa6a9a393aa2809ca6166a3d7a31c09efcc50701402010000000159617a9d17562f7c9765e5dfa6a9a393aa2809ca6166a3d7a31c09efcc507014130000006b4830450221009399820c643e5f2699b07ffa3289b22c6124e1317fd1ec41fb2431047dcf552f02201b7ee3ee3422fe1c33d8869a34a28fadddb9b790b3c5b332b7fafaaa8d4b413c4121029b15053bc379e2378cd6a84fb40b761b4e400faa4efd09280443731d4b3f8a8cffffffff0201000000000000001976a91423f2562a8092ed24eddc77c74387b44c561692a188ac03000000000000001976a9144ed83e2b3aae481f7fa48321024eb3d8e1f7417888ac00000000000100000001ee353cb1f4cb2b19bf7d2328f3c0a5fa2bd1aa94d0795934dd1d63756583b0ac000000006b4830450221009e779c3f04bb056da180b50ad3972b6fd552c52bd6337f572f08ca656625a4530220648e1fc5872d9bc3846f78edd79b4dc406dfecbab359e46b53c7d478747141684121022280e60c665907fb88a97f5e74dd4e1db0eba60a4dad18158ea8eb9495e242daffffffff2005000000000000001976a914e073bf1bf7b6160f7f68403a374717fdc4cce86d88ac4a000000000000001976a9145bbe83249067ec745d8e270c121c651f56ec2cf188ac42030000000000001976a914983a29113517769da9eace0ec25b760ad09c5f5988ac05000000000000001976a91402c75f3ec99db76e6cd2658a7c83c8bf21a0d14b88ac05000000000000001976a914de454fbce4e1be341d11cd5545664771f72d184088ac25000000000000001976a914b5c2a6831b5cdbc8985517f5d912064449ad118088ac3d010000000000001976a914e4566d91c063f99f7418f12d670b5da320160c8188ac05000000000000001976a914616dc74c3945895eafdac8da9174f95b4d91d75b88ac03010000000000001976a91476ae1c3f2c01a9a5f2aa7696cc9b89ea55b0d01688ac0d000000000000001976a9146d805d21013cc20351e5cd55ecaa7dcee59f2fde88ac05000000000000001976a914613408f68bdde1ff3f77a96abd4956a472766acf88ac21000000000000001976a914d7f0bcfa5b5cad93574a960627db60af8dac277c88ac05000000000000001976a9147e088fe21413442569fa59b6a5bf7e8fe6db71e388ac05000000000000001976a914e5ff336cbffc4ffef544ff4d131de68bf9b0aa1488ac05000000000000001976a9142145b563cd2766ba08d33ca0ecb5a6679268dfb788ac05000000000000001976a914da990487dff4910c8891cebcd00a569011f4f05188ac05000000000000001976a914100daf8fa5add521fb87b46ff51657728626c5fe88ac07000000000000001976a914de900668ddecd73f498c8560b8770231bef9616b88ac05000000000000001976a914dd08ccc14ebdcc534bb2320e7d3dba624a7ecd5388ac05000000000000001976a9141c5b5915e67a840fdcefd0db0ca1a1dfaaf4f3cf88ac06000000000000001976a91441815c6352756937fe6b2b17586dd6b39560321188ac05000000000000001976a91471dca8f8631f145ad5721f8387a764ae0ef2599888ac1d000000000000001976a9147e2621372c66ca3c6e6fca8cdb7eac42405d37fe88ac05000000000000001976a914d745ec07218bde8d179d49e4a6feca7f744f57e388ac05000000000000001976a91499456246822c4270ae73d6c7d8e1af690d1d31dd88ac05000000000000001976a914176dc7f479059d28593021e63bcb66bae6c2cc5388ac05000000000000001976a914a48809ce3c763a0a34c24ab2646fdf10cffdbc6588ac05000000000000001976a914e314da9f12f6bd888da53faa616890a2dce9eeb488ac05000000000000001976a91418f9185bb0ca144d934bd4845b3968d545e7ec8188ac17010000000000001976a9149db831932668077f8eebf597976ec61fc6ab90d588ac09000000000000001976a91479b349601390a6216994d44ca618db71e6e811ef88ac06000000000000001976a91451d25ac626a4b7c281b4200a3dcf34caae43f0df88ac000000000100' +const bumpIndexEncoding = '0100beef01fe6e621900010200008cdbd6fe227cfafa6be4500cae6140c84b2ead61318063e92bdb6974f869cf33010259617a9d17562f7c9765e5dfa6a9a393aa2809ca6166a3d7a31c09efcc50701402010000000159617a9d17562f7c9765e5dfa6a9a393aa2809ca6166a3d7a31c09efcc507014130000006b4830450221009399820c643e5f2699b07ffa3289b22c6124e1317fd1ec41fb2431047dcf552f02201b7ee3ee3422fe1c33d8869a34a28fadddb9b790b3c5b332b7fafaaa8d4b413c4121029b15053bc379e2378cd6a84fb40b761b4e400faa4efd09280443731d4b3f8a8cffffffff0201000000000000001976a91423f2562a8092ed24eddc77c74387b44c561692a188ac03000000000000001976a9144ed83e2b3aae481f7fa48321024eb3d8e1f7417888ac00000000000100000001ee353cb1f4cb2b19bf7d2328f3c0a5fa2bd1aa94d0795934dd1d63756583b0ac000000006b4830450221009e779c3f04bb056da180b50ad3972b6fd552c52bd6337f572f08ca656625a4530220648e1fc5872d9bc3846f78edd79b4dc406dfecbab359e46b53c7d478747141684121022280e60c665907fb88a97f5e74dd4e1db0eba60a4dad18158ea8eb9495e242daffffffff2005000000000000001976a914e073bf1bf7b6160f7f68403a374717fdc4cce86d88ac4a000000000000001976a9145bbe83249067ec745d8e270c121c651f56ec2cf188ac42030000000000001976a914983a29113517769da9eace0ec25b760ad09c5f5988ac05000000000000001976a91402c75f3ec99db76e6cd2658a7c83c8bf21a0d14b88ac05000000000000001976a914de454fbce4e1be341d11cd5545664771f72d184088ac25000000000000001976a914b5c2a6831b5cdbc8985517f5d912064449ad118088ac3d010000000000001976a914e4566d91c063f99f7418f12d670b5da320160c8188ac05000000000000001976a914616dc74c3945895eafdac8da9174f95b4d91d75b88ac03010000000000001976a91476ae1c3f2c01a9a5f2aa7696cc9b89ea55b0d01688ac0d000000000000001976a9146d805d21013cc20351e5cd55ecaa7dcee59f2fde88ac05000000000000001976a914613408f68bdde1ff3f77a96abd4956a472766acf88ac21000000000000001976a914d7f0bcfa5b5cad93574a960627db60af8dac277c88ac05000000000000001976a9147e088fe21413442569fa59b6a5bf7e8fe6db71e388ac05000000000000001976a914e5ff336cbffc4ffef544ff4d131de68bf9b0aa1488ac05000000000000001976a9142145b563cd2766ba08d33ca0ecb5a6679268dfb788ac05000000000000001976a914da990487dff4910c8891cebcd00a569011f4f05188ac05000000000000001976a914100daf8fa5add521fb87b46ff51657728626c5fe88ac07000000000000001976a914de900668ddecd73f498c8560b8770231bef9616b88ac05000000000000001976a914dd08ccc14ebdcc534bb2320e7d3dba624a7ecd5388ac05000000000000001976a9141c5b5915e67a840fdcefd0db0ca1a1dfaaf4f3cf88ac06000000000000001976a91441815c6352756937fe6b2b17586dd6b39560321188ac05000000000000001976a91471dca8f8631f145ad5721f8387a764ae0ef2599888ac1d000000000000001976a9147e2621372c66ca3c6e6fca8cdb7eac42405d37fe88ac05000000000000001976a914d745ec07218bde8d179d49e4a6feca7f744f57e388ac05000000000000001976a91499456246822c4270ae73d6c7d8e1af690d1d31dd88ac05000000000000001976a914176dc7f479059d28593021e63bcb66bae6c2cc5388ac05000000000000001976a914a48809ce3c763a0a34c24ab2646fdf10cffdbc6588ac05000000000000001976a914e314da9f12f6bd888da53faa616890a2dce9eeb488ac05000000000000001976a91418f9185bb0ca144d934bd4845b3968d545e7ec8188ac17010000000000001976a9149db831932668077f8eebf597976ec61fc6ab90d588ac09000000000000001976a91479b349601390a6216994d44ca618db71e6e811ef88ac06000000000000001976a91451d25ac626a4b7c281b4200a3dcf34caae43f0df88ac000000000100' \ No newline at end of file diff --git a/src/transaction/__tests/Transaction.test.ts b/src/transaction/__tests/Transaction.test.ts index 151ef6d0..9182055d 100644 --- a/src/transaction/__tests/Transaction.test.ts +++ b/src/transaction/__tests/Transaction.test.ts @@ -743,7 +743,7 @@ describe('Transaction', () => { status: 200, statusText: 'OK', headers: { - get (key: string) { + get(key: string) { if (key === 'Content-Type') { return 'application/json' } @@ -844,7 +844,7 @@ describe('Transaction', () => { status: 200, statusText: 'OK', headers: { - get (key: string) { + get(key: string) { if (key === 'Content-Type') { return 'application/json' } @@ -1069,7 +1069,7 @@ describe('Transaction', () => { // Create two transactions, one depending on the other const privateKey = new PrivateKey(1) const publicKey = new Curve().g.mul(privateKey) - const publicKeyHash = hash160(publicKey.encode(true)) + const publicKeyHash = hash160(publicKey.encode(true)) as number[] const p2pkh = new P2PKH() const sourceTx = new Transaction( @@ -1166,7 +1166,7 @@ describe('Transaction', () => { it('should serialize a transaction to Atomic BEEF format correctly', async () => { const privateKey = new PrivateKey(1) const publicKey = new Curve().g.mul(privateKey) - const publicKeyHash = hash160(publicKey.encode(true)) + const publicKeyHash = hash160(publicKey.encode(true)) as number[] const p2pkh = new P2PKH() // Create a simple transaction @@ -1237,7 +1237,7 @@ describe('Transaction', () => { // Create two transactions, one depending on the other const privateKey = new PrivateKey(1) const publicKey = new Curve().g.mul(privateKey) - const publicKeyHash = hash160(publicKey.encode(true)) + const publicKeyHash = hash160(publicKey.encode(true)) as number[] const p2pkh = new P2PKH() const sourceTx = new Transaction(1, [], [{ @@ -1294,7 +1294,7 @@ describe('Transaction', () => { tx.addInput({ sourceTXID: '00'.repeat(32), sourceOutputIndex: 0, - unlockingScriptTemplate: new P2PKH().unlock(testPrivateKey) + unlockingScriptTemplate: new P2PKH().unlock(testPrivateKey), }) }) }) @@ -1305,11 +1305,11 @@ describe('Transaction', () => { sourceTransaction.addInput({ sourceTXID: '00'.repeat(32), sourceOutputIndex: 0, - unlockingScript: Script.fromASM('OP_TRUE') + unlockingScript: Script.fromASM('OP_TRUE'), }) sourceTransaction.addOutput({ satoshis: 2, - lockingScript: Script.fromASM('OP_2 OP_MUL ' + 'OP_DUP OP_MUL '.repeat(22) + 'OP_DROP') + lockingScript: Script.fromASM('OP_2 OP_MUL ' + 'OP_DUP OP_MUL '.repeat(22) + 'OP_DROP'), }) await sourceTransaction.sign() @@ -1328,7 +1328,7 @@ describe('Transaction', () => { }) tx.addOutput({ satoshis: 1, - lockingScript: Script.fromASM('OP_NOP') + lockingScript: Script.fromASM('OP_NOP'), }) await tx.fee() await tx.sign() @@ -1345,11 +1345,11 @@ describe('Transaction', () => { sourceTransaction.addInput({ sourceTXID: '00'.repeat(32), sourceOutputIndex: 0, - unlockingScript: Script.fromASM('OP_TRUE') + unlockingScript: Script.fromASM('OP_TRUE'), }) sourceTransaction.addOutput({ satoshis: 2, - lockingScript: new P2PKH().lock(key.toAddress()) + lockingScript: new P2PKH().lock(key.toAddress()), }) await sourceTransaction.sign() @@ -1368,7 +1368,7 @@ describe('Transaction', () => { }) tx.addOutput({ satoshis: 1, - lockingScript: Script.fromASM('OP_NOP') + lockingScript: Script.fromASM('OP_NOP'), }) await tx.fee() await tx.sign() @@ -1384,11 +1384,11 @@ describe('Transaction', () => { sourceTransaction.addInput({ sourceTXID: '00'.repeat(32), sourceOutputIndex: 0, - unlockingScript: Script.fromASM('OP_TRUE') + unlockingScript: Script.fromASM('OP_TRUE'), }) sourceTransaction.addOutput({ satoshis: 2, - lockingScript: Script.fromASM('OP_2 OP_MUL OP_DUP OP_MUL OP_DUP OP_MUL OP_DROP') + lockingScript: Script.fromASM('OP_2 OP_MUL OP_DUP OP_MUL OP_DUP OP_MUL OP_DROP'), }) await sourceTransaction.sign() @@ -1407,7 +1407,7 @@ describe('Transaction', () => { }) tx.addOutput({ satoshis: 1, - lockingScript: Script.fromASM('OP_NOP') + lockingScript: Script.fromASM('OP_NOP'), }) await tx.fee() await tx.sign() diff --git a/src/transaction/broadcasters/ARC.ts b/src/transaction/broadcasters/ARC.ts index 67b9776c..8b899f0e 100644 --- a/src/transaction/broadcasters/ARC.ts +++ b/src/transaction/broadcasters/ARC.ts @@ -25,7 +25,7 @@ export interface ArcConfig { headers?: Record } -function defaultDeploymentId (): string { +function defaultDeploymentId(): string { return `ts-sdk-${toHex(Random(16))}` } @@ -47,16 +47,16 @@ export default class ARC implements Broadcaster { * @param {string} URL - The URL endpoint for the ARC API. * @param {ArcConfig} config - Configuration options for the ARC broadcaster. */ - constructor (URL: string, config?: ArcConfig) + constructor(URL: string, config?: ArcConfig) /** * Constructs an instance of the ARC broadcaster. * * @param {string} URL - The URL endpoint for the ARC API. * @param {string} apiKey - The API key used for authorization with the ARC API. */ - constructor (URL: string, apiKey?: string) + constructor(URL: string, apiKey?: string) - constructor (URL: string, config?: string | ArcConfig) { + constructor(URL: string, config?: string | ArcConfig) { this.URL = URL if (typeof config === 'string') { this.apiKey = config @@ -86,7 +86,7 @@ export default class ARC implements Broadcaster { /** * Constructs a dictionary of the default & supplied request headers. */ - private requestHeaders (): Record { + private requestHeaders(): Record { const headers: Record = { 'Content-Type': 'application/json', 'XDeployment-ID': this.deploymentId @@ -119,7 +119,7 @@ export default class ARC implements Broadcaster { * @param {Transaction} tx - The transaction to be broadcasted. * @returns {Promise} A promise that resolves to either a success or failure response. */ - async broadcast ( + async broadcast( tx: Transaction ): Promise { let rawTx @@ -208,7 +208,7 @@ export default class ARC implements Broadcaster { * @param {Transaction[]} txs - Array of transactions to be broadcasted. * @returns {Promise>} A promise that resolves to an array of objects. */ - async broadcastMany (txs: Transaction[]): Promise { + async broadcastMany(txs: Transaction[]): Promise { const rawTxs = txs.map((tx) => { try { return { rawTx: tx.toHexEF() } diff --git a/src/transaction/broadcasters/DefaultBroadcaster.ts b/src/transaction/broadcasters/DefaultBroadcaster.ts index 6363bec4..89837d66 100644 --- a/src/transaction/broadcasters/DefaultBroadcaster.ts +++ b/src/transaction/broadcasters/DefaultBroadcaster.ts @@ -1,7 +1,7 @@ import { Broadcaster } from '../Broadcaster.js' import ARC, { ArcConfig } from './ARC.js' -export function defaultBroadcaster ( +export function defaultBroadcaster( isTestnet: boolean = false, config: ArcConfig = {} ): Broadcaster { diff --git a/src/transaction/broadcasters/Teranode.ts b/src/transaction/broadcasters/Teranode.ts index 75364685..cc8edf98 100644 --- a/src/transaction/broadcasters/Teranode.ts +++ b/src/transaction/broadcasters/Teranode.ts @@ -19,7 +19,7 @@ export default class Teranode implements Broadcaster { * @param {string} URL - The URL endpoint for the Teranode API. * @param {HttpClient} httpClient - The HTTP client used to make requests to the API, binaryHttpClient by default. */ - constructor ( + constructor( URL: string, httpClient: HttpClient = binaryHttpClient() ) { @@ -33,7 +33,7 @@ export default class Teranode implements Broadcaster { * @param {Transaction} tx - The transaction to be broadcasted. * @returns {Promise} A promise that resolves to either a success or failure response. */ - async broadcast ( + async broadcast( tx: Transaction ): Promise { const rawTx = tx.toEF() diff --git a/src/transaction/broadcasters/WhatsOnChainBroadcaster.ts b/src/transaction/broadcasters/WhatsOnChainBroadcaster.ts index e3a97bae..8217324c 100644 --- a/src/transaction/broadcasters/WhatsOnChainBroadcaster.ts +++ b/src/transaction/broadcasters/WhatsOnChainBroadcaster.ts @@ -21,7 +21,7 @@ export default class WhatsOnChainBroadcaster implements Broadcaster { * @param {'main' | 'test' | 'stn'} network - The BSV network to use when calling the WhatsOnChain API. * @param {HttpClient} httpClient - The HTTP client used to make requests to the API. */ - constructor ( + constructor( network: 'main' | 'test' | 'stn' = 'main', httpClient: HttpClient = defaultHttpClient() ) { @@ -36,7 +36,7 @@ export default class WhatsOnChainBroadcaster implements Broadcaster { * @param {Transaction} tx - The transaction to be broadcasted. * @returns {Promise} A promise that resolves to either a success or failure response. */ - async broadcast ( + async broadcast( tx: Transaction ): Promise { const rawTx = tx.toHex() diff --git a/src/transaction/chaintrackers/BlockHeadersService.ts b/src/transaction/chaintrackers/BlockHeadersService.ts index 1a6ceafd..0fb9d1ed 100644 --- a/src/transaction/chaintrackers/BlockHeadersService.ts +++ b/src/transaction/chaintrackers/BlockHeadersService.ts @@ -30,7 +30,7 @@ interface MerkleRootVerificationResponse { /** * Represents a chain tracker based on a BlockHeadersService API. - * + * * @example * ```typescript * const chainTracker = new BlockHeadersService('https://headers.spv.money', { @@ -45,11 +45,11 @@ export class BlockHeadersService implements ChainTracker { /** * Constructs an instance of the BlockHeadersService ChainTracker. - * + * * @param {string} baseUrl - The base URL for the BlockHeadersService API (e.g. https://headers.spv.money) * @param {BlockHeadersServiceConfig} config - Configuration options for the BlockHeadersService ChainTracker. */ - constructor ( + constructor( baseUrl: string, config: BlockHeadersServiceConfig = {} ) { @@ -61,18 +61,18 @@ export class BlockHeadersService implements ChainTracker { /** * Verifies if a given merkle root is valid for a specific block height. - * + * * @param {string} root - The merkle root to verify. * @param {number} height - The block height to check against. * @returns {Promise} - A promise that resolves to true if the merkle root is valid for the specified block height, false otherwise. */ - async isValidRootForHeight (root: string, height: number): Promise { + async isValidRootForHeight(root: string, height: number): Promise { const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json', - Accept: 'application/json', - Authorization: `Bearer ${this.apiKey}` + 'Accept': 'application/json', + 'Authorization': `Bearer ${this.apiKey}` }, data: [ { @@ -88,7 +88,7 @@ export class BlockHeadersService implements ChainTracker { requestOptions ) - if (response.ok) { + if (response.ok) { return response.data.confirmationState === 'CONFIRMED' } else { throw new Error( @@ -104,15 +104,15 @@ export class BlockHeadersService implements ChainTracker { /** * Gets the current block height from the BlockHeadersService API. - * + * * @returns {Promise} - A promise that resolves to the current block height. */ - async currentHeight (): Promise { + async currentHeight(): Promise { const requestOptions = { method: 'GET', headers: { - Accept: 'application/json', - Authorization: `Bearer ${this.apiKey}` + 'Accept': 'application/json', + 'Authorization': `Bearer ${this.apiKey}` } } @@ -121,7 +121,7 @@ export class BlockHeadersService implements ChainTracker { `${this.baseUrl}/api/v1/chain/tip/longest`, requestOptions ) - + if (response.ok && response.data && typeof response.data.height === 'number') { return response.data.height } else { diff --git a/src/transaction/chaintrackers/DefaultChainTracker.ts b/src/transaction/chaintrackers/DefaultChainTracker.ts index f5488744..3de887dd 100644 --- a/src/transaction/chaintrackers/DefaultChainTracker.ts +++ b/src/transaction/chaintrackers/DefaultChainTracker.ts @@ -1,6 +1,6 @@ import WhatsOnChain from './WhatsOnChain.js' import ChainTracker from '../ChainTracker.js' -export function defaultChainTracker (): ChainTracker { +export function defaultChainTracker(): ChainTracker { return new WhatsOnChain() } diff --git a/src/transaction/chaintrackers/WhatsOnChain.ts b/src/transaction/chaintrackers/WhatsOnChain.ts index 41041b52..4e615010 100644 --- a/src/transaction/chaintrackers/WhatsOnChain.ts +++ b/src/transaction/chaintrackers/WhatsOnChain.ts @@ -30,7 +30,7 @@ export default class WhatsOnChain implements ChainTracker { * @param {'main' | 'test' | 'stn'} network - The BSV network to use when calling the WhatsOnChain API. * @param {WhatsOnChainConfig} config - Configuration options for the WhatsOnChain ChainTracker. */ - constructor ( + constructor( network: 'main' | 'test' | 'stn' = 'main', config: WhatsOnChainConfig = {} ) { @@ -41,7 +41,7 @@ export default class WhatsOnChain implements ChainTracker { this.apiKey = apiKey ?? '' } - async isValidRootForHeight (root: string, height: number): Promise { + async isValidRootForHeight(root: string, height: number): Promise { const requestOptions = { method: 'GET', headers: this.getHttpHeaders() @@ -63,7 +63,7 @@ export default class WhatsOnChain implements ChainTracker { } } - async currentHeight (): Promise { + async currentHeight(): Promise { try { const requestOptions = { method: 'GET', @@ -88,7 +88,7 @@ export default class WhatsOnChain implements ChainTracker { } } - protected getHttpHeaders (): Record { + protected getHttpHeaders(): Record { const headers: Record = { Accept: 'application/json' } diff --git a/src/transaction/fee-models/SatoshisPerKilobyte.ts b/src/transaction/fee-models/SatoshisPerKilobyte.ts index 6cba8e6b..760f8dd3 100644 --- a/src/transaction/fee-models/SatoshisPerKilobyte.ts +++ b/src/transaction/fee-models/SatoshisPerKilobyte.ts @@ -16,7 +16,7 @@ export default class SatoshisPerKilobyte implements FeeModel { * * @param {number} value - The number of satoshis per kilobyte to charge as a fee. */ - constructor (value: number) { + constructor(value: number) { this.value = value } @@ -26,7 +26,7 @@ export default class SatoshisPerKilobyte implements FeeModel { * @param tx The transaction for which a fee is to be computed. * @returns The fee in satoshis for the transaction, as a BigNumber. */ - async computeFee (tx: Transaction): Promise { + async computeFee(tx: Transaction): Promise { const getVarIntSize = (i: number): number => { if (i > 2 ** 32) { return 9 diff --git a/src/transaction/http/BinaryFetchClient.ts b/src/transaction/http/BinaryFetchClient.ts index f0bd3613..58325ede 100644 --- a/src/transaction/http/BinaryFetchClient.ts +++ b/src/transaction/http/BinaryFetchClient.ts @@ -26,9 +26,9 @@ export interface BinaryNodejsHttpClientRequest { * Adapter for Node Https module to be used as HttpClient */ export class BinaryNodejsHttpClient implements HttpClient { - constructor (private readonly https: BinaryHttpsNodejs) { } + constructor(private readonly https: BinaryHttpsNodejs) { } - async request ( + async request( url: string, requestOptions: HttpClientRequestOptions ): Promise { @@ -91,7 +91,7 @@ export interface FetchOptions { * Adapter for Node Https module to be used as HttpClient */ export class BinaryFetchClient implements HttpClient { - constructor (private readonly fetch: Fetch) { } + constructor(private readonly fetch: Fetch) { } async request( url: string, @@ -115,9 +115,9 @@ export class BinaryFetchClient implements HttpClient { } } -export function binaryHttpClient (): HttpClient { +export function binaryHttpClient(): HttpClient { const noHttpClient: HttpClient = { - async request (..._): Promise { + async request(..._): Promise { throw new Error('No method available to perform HTTP request') } } diff --git a/src/transaction/http/DefaultHttpClient.ts b/src/transaction/http/DefaultHttpClient.ts index 92ae7b10..5d2be4d1 100644 --- a/src/transaction/http/DefaultHttpClient.ts +++ b/src/transaction/http/DefaultHttpClient.ts @@ -7,9 +7,9 @@ import { FetchHttpClient } from './FetchHttpClient.js' * This method will attempt to use `window.fetch` if available (in browser environments). * If running in a Node environment, it falls back to using the Node `https` module */ -export function defaultHttpClient (): HttpClient { +export function defaultHttpClient(): HttpClient { const noHttpClient: HttpClient = { - async request (..._): Promise { + async request(..._): Promise { throw new Error('No method available to perform HTTP request') } } diff --git a/src/transaction/http/FetchHttpClient.ts b/src/transaction/http/FetchHttpClient.ts index 9ce0a00e..61eaa86f 100644 --- a/src/transaction/http/FetchHttpClient.ts +++ b/src/transaction/http/FetchHttpClient.ts @@ -29,7 +29,7 @@ export interface FetchOptions { * Adapter for Node Https module to be used as HttpClient */ export class FetchHttpClient implements HttpClient { - constructor (private readonly fetch: Fetch) { } + constructor(private readonly fetch: Fetch) { } async request( url: string, diff --git a/src/transaction/http/NodejsHttpClient.ts b/src/transaction/http/NodejsHttpClient.ts index 09ebff1d..a27e0527 100644 --- a/src/transaction/http/NodejsHttpClient.ts +++ b/src/transaction/http/NodejsHttpClient.ts @@ -26,9 +26,9 @@ export interface NodejsHttpClientRequest { * Adapter for Node Https module to be used as HttpClient */ export class NodejsHttpClient implements HttpClient { - constructor (private readonly https: HttpsNodejs) { } + constructor(private readonly https: HttpsNodejs) { } - async request ( + async request( url: string, requestOptions: HttpClientRequestOptions ): Promise { diff --git a/src/wallet/substrates/HTTPWalletJSON.ts b/src/wallet/substrates/HTTPWalletJSON.ts index 6c13d0cb..20ab5d96 100644 --- a/src/wallet/substrates/HTTPWalletJSON.ts +++ b/src/wallet/substrates/HTTPWalletJSON.ts @@ -33,7 +33,7 @@ import { SecurityLevel, SignActionArgs, SignActionResult, - VersionString7To30Bytes + VersionString7To30Bytes, } from '../Wallet.interfaces.js' import { WERR_REVIEW_ACTIONS } from '../WERR_REVIEW_ACTIONS.js' import { toOriginHeader } from './utils/toOriginHeader.js' @@ -44,7 +44,7 @@ export default class HTTPWalletJSON implements WalletInterface { originator: OriginatorDomainNameStringUnder250Bytes | undefined api: (call: string, args: object) => Promise // Fixed `any` types - constructor ( + constructor( originator: OriginatorDomainNameStringUnder250Bytes | undefined, baseUrl: string = 'http://localhost:3321', httpClient = fetch @@ -74,7 +74,7 @@ export default class HTTPWalletJSON implements WalletInterface { Accept: 'application/json', 'Content-Type': 'application/json', ...(origin ? { Origin: origin } : {}), - ...(origin ? { Originator: origin } : {}) + ...(origin ? { Originator: origin } : {}), }, body: JSON.stringify(args) }) @@ -100,42 +100,42 @@ export default class HTTPWalletJSON implements WalletInterface { } } - async createAction (args: CreateActionArgs): Promise { + async createAction(args: CreateActionArgs): Promise { return await this.api('createAction', args) as CreateActionResult } - async signAction (args: SignActionArgs): Promise { + async signAction(args: SignActionArgs): Promise { return await this.api('signAction', args) as SignActionResult } - async abortAction (args: { + async abortAction(args: { reference: Base64String }): Promise<{ aborted: true }> { return await this.api('abortAction', args) as { aborted: true } } - async listActions (args: ListActionsArgs): Promise { + async listActions(args: ListActionsArgs): Promise { return await this.api('listActions', args) as ListActionsResult } - async internalizeAction ( + async internalizeAction( args: InternalizeActionArgs ): Promise<{ accepted: true }> { return await this.api('internalizeAction', args) as { accepted: true } } - async listOutputs (args: ListOutputsArgs): Promise { + async listOutputs(args: ListOutputsArgs): Promise { return await this.api('listOutputs', args) as ListOutputsResult } - async relinquishOutput (args: { + async relinquishOutput(args: { basket: BasketStringUnder300Bytes output: OutpointString }): Promise<{ relinquished: true }> { return await this.api('relinquishOutput', args) as { relinquished: true } } - async getPublicKey (args: { + async getPublicKey(args: { seekPermission?: BooleanDefaultTrue identityKey?: true protocolID?: [SecurityLevel, ProtocolString5To400Bytes] @@ -148,19 +148,19 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('getPublicKey', args) as { publicKey: PubKeyHex } } - async revealCounterpartyKeyLinkage (args: { + async revealCounterpartyKeyLinkage(args: { counterparty: PubKeyHex verifier: PubKeyHex privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - revelationTime: ISOTimestampString - encryptedLinkage: Byte[] - encryptedLinkageProof: number[] - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + revelationTime: ISOTimestampString + encryptedLinkage: Byte[] + encryptedLinkageProof: number[] + }> { return await this.api('revealCounterpartyKeyLinkage', args) as { prover: PubKeyHex verifier: PubKeyHex @@ -171,7 +171,7 @@ export default class HTTPWalletJSON implements WalletInterface { } } - async revealSpecificKeyLinkage (args: { + async revealSpecificKeyLinkage(args: { counterparty: PubKeyHex verifier: PubKeyHex protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -179,15 +179,15 @@ export default class HTTPWalletJSON implements WalletInterface { privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - protocolID: [SecurityLevel, ProtocolString5To400Bytes] - keyID: KeyIDStringUnder800Bytes - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - proofType: Byte - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + protocolID: [SecurityLevel, ProtocolString5To400Bytes] + keyID: KeyIDStringUnder800Bytes + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + proofType: Byte + }> { return await this.api('revealSpecificKeyLinkage', args) as { prover: PubKeyHex verifier: PubKeyHex @@ -200,7 +200,7 @@ export default class HTTPWalletJSON implements WalletInterface { } } - async encrypt (args: { + async encrypt(args: { seekPermission?: BooleanDefaultTrue plaintext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -212,7 +212,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('encrypt', args) as { ciphertext: Byte[] } } - async decrypt (args: { + async decrypt(args: { seekPermission?: BooleanDefaultTrue ciphertext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -224,7 +224,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('decrypt', args) as { plaintext: Byte[] } } - async createHmac (args: { + async createHmac(args: { seekPermission?: BooleanDefaultTrue data: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -236,7 +236,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('createHmac', args) as { hmac: Byte[] } } - async verifyHmac (args: { + async verifyHmac(args: { seekPermission?: BooleanDefaultTrue data: Byte[] hmac: Byte[] @@ -249,7 +249,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('verifyHmac', args) as { valid: true } } - async createSignature (args: { + async createSignature(args: { seekPermission?: BooleanDefaultTrue data?: Byte[] hashToDirectlySign?: Byte[] @@ -262,7 +262,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('createSignature', args) as { signature: Byte[] } } - async verifySignature (args: { + async verifySignature(args: { seekPermission?: BooleanDefaultTrue data?: Byte[] hashToDirectlyVerify?: Byte[] @@ -277,13 +277,13 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('verifySignature', args) as { valid: true } } - async acquireCertificate ( + async acquireCertificate( args: AcquireCertificateArgs ): Promise { return await this.api('acquireCertificate', args) as AcquireCertificateResult } - async listCertificates (args: { + async listCertificates(args: { certifiers: PubKeyHex[] types: Base64String[] limit?: PositiveIntegerDefault10Max10000 @@ -294,13 +294,13 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('listCertificates', args) as ListCertificatesResult } - async proveCertificate ( + async proveCertificate( args: ProveCertificateArgs ): Promise { return await this.api('proveCertificate', args) as ProveCertificateResult } - async relinquishCertificate (args: { + async relinquishCertificate(args: { type: Base64String serialNumber: Base64String certifier: PubKeyHex @@ -308,7 +308,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('relinquishCertificate', args) as { relinquished: true } } - async discoverByIdentityKey (args: { + async discoverByIdentityKey(args: { seekPermission?: BooleanDefaultTrue identityKey: PubKeyHex limit?: PositiveIntegerDefault10Max10000 @@ -317,7 +317,7 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('discoverByIdentityKey', args) as DiscoverCertificatesResult } - async discoverByAttributes (args: { + async discoverByAttributes(args: { seekPermission?: BooleanDefaultTrue attributes: Record limit?: PositiveIntegerDefault10Max10000 @@ -326,29 +326,29 @@ export default class HTTPWalletJSON implements WalletInterface { return await this.api('discoverByAttributes', args) as DiscoverCertificatesResult } - async isAuthenticated (args: object): Promise<{ authenticated: true }> { + async isAuthenticated(args: object): Promise<{ authenticated: true }> { return await this.api('isAuthenticated', args) as { authenticated: true } } - async waitForAuthentication (args: object): Promise<{ authenticated: true }> { + async waitForAuthentication(args: object): Promise<{ authenticated: true }> { return await this.api('waitForAuthentication', args) as { authenticated: true } } - async getHeight (args: object): Promise<{ height: PositiveInteger }> { + async getHeight(args: object): Promise<{ height: PositiveInteger }> { return await this.api('getHeight', args) as { height: PositiveInteger } } - async getHeaderForHeight (args: { + async getHeaderForHeight(args: { height: PositiveInteger }): Promise<{ header: HexString }> { return await this.api('getHeaderForHeight', args) as { header: HexString } } - async getNetwork (args: object): Promise<{ network: 'mainnet' | 'testnet' }> { + async getNetwork(args: object): Promise<{ network: 'mainnet' | 'testnet' }> { return await this.api('getNetwork', args) as { network: 'mainnet' | 'testnet' } } - async getVersion (args: object): Promise<{ version: VersionString7To30Bytes }> { + async getVersion(args: object): Promise<{ version: VersionString7To30Bytes }> { return await this.api('getVersion', args) as { version: VersionString7To30Bytes } } } diff --git a/src/wallet/substrates/HTTPWalletWire.ts b/src/wallet/substrates/HTTPWalletWire.ts index 7cf5f13b..d46fe7fd 100644 --- a/src/wallet/substrates/HTTPWalletWire.ts +++ b/src/wallet/substrates/HTTPWalletWire.ts @@ -7,7 +7,7 @@ export default class HTTPWalletWire implements WalletWire { httpClient: typeof fetch originator: string | undefined - constructor ( + constructor( originator: string | undefined, baseUrl: string = 'http://localhost:3301', httpClient = fetch @@ -17,7 +17,7 @@ export default class HTTPWalletWire implements WalletWire { this.originator = originator } - async transmitToWallet (message: number[]): Promise { + async transmitToWallet(message: number[]): Promise { const messageReader = new Utils.Reader(message) // Read call code const callCode = messageReader.readUInt8() diff --git a/src/wallet/substrates/ReactNativeWebView.ts b/src/wallet/substrates/ReactNativeWebView.ts index c5911acf..f6718aea 100644 --- a/src/wallet/substrates/ReactNativeWebView.ts +++ b/src/wallet/substrates/ReactNativeWebView.ts @@ -44,11 +44,12 @@ type ReactNativeWindow = Window & { export default class ReactNativeWebView implements WalletInterface { private readonly domain: string - constructor (domain: string = '*') { + + constructor(domain: string = '*') { if (typeof window !== 'object') { throw new Error('The XDM substrate requires a global window object.') } - if (!(window as unknown as ReactNativeWindow).hasOwnProperty('ReactNativeWebView')) { + if (!(window as unknown as ReactNativeWindow).hasOwnProperty("ReactNativeWebView")) { throw new Error( 'The window object does not have a ReactNativeWebView property.' ) @@ -61,7 +62,7 @@ export default class ReactNativeWebView implements WalletInterface { this.domain = domain } - async invoke (call: CallType, args: any): Promise { + async invoke(call: CallType, args: any): Promise { return await new Promise((resolve, reject) => { const id = Utils.toBase64(Random(12)) const listener = (e: MessageEvent): void => { @@ -96,7 +97,7 @@ export default class ReactNativeWebView implements WalletInterface { }) } - async createAction (args: { + async createAction(args: { description: DescriptionString5to50Bytes inputs?: Array<{ tx?: BEEF @@ -128,22 +129,22 @@ export default class ReactNativeWebView implements WalletInterface { sendWith?: TXIDHexString[] } }): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - signableTransaction?: { tx: BEEF, reference: Base64String } - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + signableTransaction?: { tx: BEEF, reference: Base64String } + }> { return await this.invoke('createAction', args) } - async signAction (args: { + async signAction(args: { spends: Record< - PositiveIntegerOrZero, - { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } + PositiveIntegerOrZero, + { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } > reference: Base64String options?: { @@ -154,24 +155,24 @@ export default class ReactNativeWebView implements WalletInterface { sendWith: TXIDHexString[] } }): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + }> { return await this.invoke('signAction', args) } - async abortAction (args: { + async abortAction(args: { reference: Base64String }): Promise<{ aborted: true }> { return await this.invoke('abortAction', args) } - async listActions (args: { + async listActions(args: { labels: LabelStringUnder300Bytes[] labelQueryMode?: 'any' | 'all' includeLabels?: BooleanDefaultFalse @@ -183,47 +184,47 @@ export default class ReactNativeWebView implements WalletInterface { limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalActions: PositiveIntegerOrZero - actions: Array<{ - txid: TXIDHexString + totalActions: PositiveIntegerOrZero + actions: Array<{ + txid: TXIDHexString + satoshis: SatoshiValue + status: + | 'completed' + | 'unprocessed' + | 'sending' + | 'unproven' + | 'unsigned' + | 'nosend' + | 'nonfinal' + isOutgoing: boolean + description: DescriptionString5to50Bytes + labels?: LabelStringUnder300Bytes[] + version: PositiveIntegerOrZero + lockTime: PositiveIntegerOrZero + inputs?: Array<{ + sourceOutpoint: OutpointString + sourceSatoshis: SatoshiValue + sourceLockingScript?: HexString + unlockingScript?: HexString + inputDescription: DescriptionString5to50Bytes + sequenceNumber: PositiveIntegerOrZero + }> + outputs?: Array<{ + outputIndex: PositiveIntegerOrZero satoshis: SatoshiValue - status: - | 'completed' - | 'unprocessed' - | 'sending' - | 'unproven' - | 'unsigned' - | 'nosend' - | 'nonfinal' - isOutgoing: boolean - description: DescriptionString5to50Bytes - labels?: LabelStringUnder300Bytes[] - version: PositiveIntegerOrZero - lockTime: PositiveIntegerOrZero - inputs?: Array<{ - sourceOutpoint: OutpointString - sourceSatoshis: SatoshiValue - sourceLockingScript?: HexString - unlockingScript?: HexString - inputDescription: DescriptionString5to50Bytes - sequenceNumber: PositiveIntegerOrZero - }> - outputs?: Array<{ - outputIndex: PositiveIntegerOrZero - satoshis: SatoshiValue - lockingScript?: HexString - spendable: boolean - outputDescription: DescriptionString5to50Bytes - basket: BasketStringUnder300Bytes - tags: OutputTagStringUnder300Bytes[] - customInstructions?: string - }> + lockingScript?: HexString + spendable: boolean + outputDescription: DescriptionString5to50Bytes + basket: BasketStringUnder300Bytes + tags: OutputTagStringUnder300Bytes[] + customInstructions?: string }> - }> { + }> + }> { return await this.invoke('listActions', args) } - async internalizeAction (args: { + async internalizeAction(args: { tx: BEEF outputs: Array<{ outputIndex: PositiveIntegerOrZero @@ -245,7 +246,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('internalizeAction', args) } - async listOutputs (args: { + async listOutputs(args: { basket: BasketStringUnder300Bytes tags?: OutputTagStringUnder300Bytes[] tagQueryMode?: 'all' | 'any' @@ -256,29 +257,29 @@ export default class ReactNativeWebView implements WalletInterface { limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalOutputs: PositiveIntegerOrZero - outputs: Array<{ - outpoint: OutpointString - satoshis: SatoshiValue - lockingScript?: HexString - tx?: BEEF - spendable: boolean - customInstructions?: string - tags?: OutputTagStringUnder300Bytes[] - labels?: LabelStringUnder300Bytes[] - }> - }> { + totalOutputs: PositiveIntegerOrZero + outputs: Array<{ + outpoint: OutpointString + satoshis: SatoshiValue + lockingScript?: HexString + tx?: BEEF + spendable: boolean + customInstructions?: string + tags?: OutputTagStringUnder300Bytes[] + labels?: LabelStringUnder300Bytes[] + }> + }> { return await this.invoke('listOutputs', args) } - async relinquishOutput (args: { + async relinquishOutput(args: { basket: BasketStringUnder300Bytes output: OutpointString }): Promise<{ relinquished: true }> { return await this.invoke('relinquishOutput', args) } - async getPublicKey (args: { + async getPublicKey(args: { identityKey?: true protocolID?: [SecurityLevel, ProtocolString5To400Bytes] keyID?: KeyIDStringUnder800Bytes @@ -290,23 +291,23 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('getPublicKey', args) } - async revealCounterpartyKeyLinkage (args: { + async revealCounterpartyKeyLinkage(args: { counterparty: PubKeyHex verifier: PubKeyHex privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - revelationTime: ISOTimestampString - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + revelationTime: ISOTimestampString + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + }> { return await this.invoke('revealCounterpartyKeyLinkage', args) } - async revealSpecificKeyLinkage (args: { + async revealSpecificKeyLinkage(args: { counterparty: PubKeyHex verifier: PubKeyHex protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -314,19 +315,19 @@ export default class ReactNativeWebView implements WalletInterface { privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - protocolID: [SecurityLevel, ProtocolString5To400Bytes] - keyID: KeyIDStringUnder800Bytes - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - proofType: Byte - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + protocolID: [SecurityLevel, ProtocolString5To400Bytes] + keyID: KeyIDStringUnder800Bytes + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + proofType: Byte + }> { return await this.invoke('revealSpecificKeyLinkage', args) } - async encrypt (args: { + async encrypt(args: { plaintext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -337,7 +338,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('encrypt', args) } - async decrypt (args: { + async decrypt(args: { ciphertext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -348,7 +349,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('decrypt', args) } - async createHmac (args: { + async createHmac(args: { data: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -359,7 +360,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('createHmac', args) } - async verifyHmac (args: { + async verifyHmac(args: { data: Byte[] hmac: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -371,7 +372,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('verifyHmac', args) } - async createSignature (args: { + async createSignature(args: { data?: Byte[] hashToDirectlySign?: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -383,7 +384,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('createSignature', args) } - async verifySignature (args: { + async verifySignature(args: { data?: Byte[] hashToDirectlyVerify?: Byte[] signature: Byte[] @@ -397,7 +398,7 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('verifySignature', args) } - async acquireCertificate (args: { + async acquireCertificate(args: { type: Base64String subject: PubKeyHex serialNumber: Base64String @@ -410,18 +411,18 @@ export default class ReactNativeWebView implements WalletInterface { acquisitionProtocol: 'direct' | 'issuance' certifierUrl?: string }): Promise<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> { + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> { return await this.invoke('acquireCertificate', args) } - async listCertificates (args: { + async listCertificates(args: { certifiers: PubKeyHex[] types: Base64String[] limit?: PositiveIntegerDefault10Max10000 @@ -429,21 +430,21 @@ export default class ReactNativeWebView implements WalletInterface { privileged?: BooleanDefaultFalse privilegedReason?: DescriptionString5to50Bytes }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> - }> { + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> + }> { return await this.invoke('listCertificates', args) } - async proveCertificate (args: { + async proveCertificate(args: { certificate: { type: Base64String subject: PubKeyHex @@ -458,12 +459,12 @@ export default class ReactNativeWebView implements WalletInterface { privileged?: BooleanDefaultFalse privilegedReason?: DescriptionString5to50Bytes }): Promise<{ - keyringForVerifier: Record - }> { + keyringForVerifier: Record + }> { return await this.invoke('proveCertificate', args) } - async relinquishCertificate (args: { + async relinquishCertificate(args: { type: Base64String serialNumber: Base64String certifier: PubKeyHex @@ -471,89 +472,89 @@ export default class ReactNativeWebView implements WalletInterface { return await this.invoke('relinquishCertificate', args) } - async discoverByIdentityKey (args: { + async discoverByIdentityKey(args: { identityKey: PubKeyHex limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.invoke('discoverByIdentityKey', args) } - async discoverByAttributes (args: { + async discoverByAttributes(args: { attributes: Record limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.invoke('discoverByAttributes', args) } - async isAuthenticated (args: {}): Promise<{ authenticated: true }> { + async isAuthenticated(args: {}): Promise<{ authenticated: true }> { return await this.invoke('isAuthenticated', args) } - async waitForAuthentication (args: {}): Promise<{ authenticated: true }> { + async waitForAuthentication(args: {}): Promise<{ authenticated: true }> { return await this.invoke('waitForAuthentication', args) } - async getHeight (args: {}): Promise<{ height: PositiveInteger }> { + async getHeight(args: {}): Promise<{ height: PositiveInteger }> { return await this.invoke('getHeight', args) } - async getHeaderForHeight (args: { + async getHeaderForHeight(args: { height: PositiveInteger }): Promise<{ header: HexString }> { return await this.invoke('getHeaderForHeight', args) } - async getNetwork (args: {}): Promise<{ network: 'mainnet' | 'testnet' }> { + async getNetwork(args: {}): Promise<{ network: 'mainnet' | 'testnet' }> { return await this.invoke('getNetwork', args) } - async getVersion (args: {}): Promise<{ version: VersionString7To30Bytes }> { + async getVersion(args: {}): Promise<{ version: VersionString7To30Bytes }> { return await this.invoke('getVersion', args) } } diff --git a/src/wallet/substrates/WalletWireProcessor.ts b/src/wallet/substrates/WalletWireProcessor.ts index 6d152e39..243400dd 100644 --- a/src/wallet/substrates/WalletWireProcessor.ts +++ b/src/wallet/substrates/WalletWireProcessor.ts @@ -10,18 +10,18 @@ import Certificate from '../../auth/certificates/Certificate.js' export default class WalletWireProcessor implements WalletWire { wallet: WalletInterface - constructor (wallet: WalletInterface) { + constructor(wallet: WalletInterface) { this.wallet = wallet } - private decodeOutpoint (reader: Utils.Reader): string { + private decodeOutpoint(reader: Utils.Reader): string { const txidBytes = reader.read(32) const txid = Utils.toHex(txidBytes) const index = reader.readVarIntNum() return `${txid}.${index}` } - private encodeOutpoint (outpoint: string): number[] { + private encodeOutpoint(outpoint: string): number[] { const writer = new Utils.Writer() const [txid, index] = outpoint.split('.') writer.write(Utils.toArray(txid, 'hex')) @@ -29,7 +29,7 @@ export default class WalletWireProcessor implements WalletWire { return writer.toArray() } - async transmitToWallet (message: number[]): Promise { + async transmitToWallet(message: number[]): Promise { const messageReader = new Utils.Reader(message) try { // Read call code @@ -2048,7 +2048,7 @@ export default class WalletWireProcessor implements WalletWire { } } - private decodeProtocolID (reader: Utils.Reader): [SecurityLevel, string] { + private decodeProtocolID(reader: Utils.Reader): [SecurityLevel, string] { const securityLevel = reader.readUInt8() as SecurityLevel const protocolLength = reader.readVarIntNum() const protocolBytes = reader.read(protocolLength) @@ -2056,13 +2056,13 @@ export default class WalletWireProcessor implements WalletWire { return [securityLevel, protocolString] } - private decodeString (reader: Utils.Reader): string { + private decodeString(reader: Utils.Reader): string { const length = reader.readVarIntNum() const bytes = reader.read(length) return Utils.toUTF8(bytes) } - private decodeCounterparty ( + private decodeCounterparty( reader: Utils.Reader ): string | 'self' | 'anyone' | undefined { const counterpartyFlag = reader.readUInt8() @@ -2078,7 +2078,7 @@ export default class WalletWireProcessor implements WalletWire { } } - private serializeDiscoveryResult (discoverResult: any): number[] { + private serializeDiscoveryResult(discoverResult: any): number[] { const resultWriter = new Utils.Writer() // totalCertificates @@ -2150,7 +2150,7 @@ export default class WalletWireProcessor implements WalletWire { return resultWriter.toArray() } - private decodeKeyRelatedParams (paramsReader: Utils.Reader): any { + private decodeKeyRelatedParams(paramsReader: Utils.Reader): any { const args: any = {} // Read protocolID diff --git a/src/wallet/substrates/WalletWireTransceiver.ts b/src/wallet/substrates/WalletWireTransceiver.ts index 67122a6f..7dcbdafd 100644 --- a/src/wallet/substrates/WalletWireTransceiver.ts +++ b/src/wallet/substrates/WalletWireTransceiver.ts @@ -58,11 +58,11 @@ import { WalletError } from '../WalletError.js' export default class WalletWireTransceiver implements WalletInterface { wire: WalletWire - constructor (wire: WalletWire) { + constructor(wire: WalletWire) { this.wire = wire } - private async transmit ( + private async transmit( call: CallType, originator: OriginatorDomainNameStringUnder250Bytes = '', params: number[] = [] @@ -99,7 +99,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async createAction ( + async createAction( args: CreateActionArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -399,7 +399,7 @@ export default class WalletWireTransceiver implements WalletInterface { return response } - async signAction ( + async signAction( args: SignActionArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -518,7 +518,7 @@ export default class WalletWireTransceiver implements WalletInterface { return response } - async abortAction ( + async abortAction( args: { reference: Base64String }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ aborted: true }> { @@ -530,7 +530,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { aborted: true } } - async listActions ( + async listActions( args: ListActionsArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -823,7 +823,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async internalizeAction ( + async internalizeAction( args: InternalizeActionArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ accepted: true }> { @@ -910,7 +910,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { accepted: true } } - async listOutputs ( + async listOutputs( args: ListOutputsArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -1053,7 +1053,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async relinquishOutput ( + async relinquishOutput( args: { basket: BasketStringUnder300Bytes, output: OutpointString }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ relinquished: true }> { @@ -1066,7 +1066,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { relinquished: true } } - private encodeOutpoint (outpoint: OutpointString): number[] { + private encodeOutpoint(outpoint: OutpointString): number[] { const writer = new Utils.Writer() const [txid, index] = outpoint.split('.') writer.write(Utils.toArray(txid, 'hex')) @@ -1074,13 +1074,13 @@ export default class WalletWireTransceiver implements WalletInterface { return writer.toArray() } - private readOutpoint (reader: Utils.Reader): OutpointString { + private readOutpoint(reader: Utils.Reader): OutpointString { const txid = Utils.toHex(reader.read(32)) const index = reader.readVarIntNum() return `${txid}.${index}` } - async getPublicKey ( + async getPublicKey( args: { seekPermission?: BooleanDefaultTrue identityKey?: true @@ -1135,7 +1135,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async revealCounterpartyKeyLinkage ( + async revealCounterpartyKeyLinkage( args: { counterparty: PubKeyHex verifier: PubKeyHex @@ -1144,13 +1144,13 @@ export default class WalletWireTransceiver implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - revelationTime: ISOTimestampString - encryptedLinkage: Byte[] - encryptedLinkageProof: number[] - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + revelationTime: ISOTimestampString + encryptedLinkage: Byte[] + encryptedLinkageProof: number[] + }> { const paramWriter = new Utils.Writer() paramWriter.write( this.encodePrivilegedParams(args.privileged, args.privilegedReason) @@ -1186,7 +1186,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async revealSpecificKeyLinkage ( + async revealSpecificKeyLinkage( args: { counterparty: PubKeyHex verifier: PubKeyHex @@ -1197,15 +1197,15 @@ export default class WalletWireTransceiver implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - protocolID: [SecurityLevel, ProtocolString5To400Bytes] - keyID: KeyIDStringUnder800Bytes - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - proofType: Byte - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + protocolID: [SecurityLevel, ProtocolString5To400Bytes] + keyID: KeyIDStringUnder800Bytes + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + proofType: Byte + }> { const paramWriter = new Utils.Writer() paramWriter.write( this.encodeKeyRelatedParams( @@ -1250,7 +1250,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async encrypt ( + async encrypt( args: { seekPermission?: BooleanDefaultTrue plaintext: Byte[] @@ -1291,7 +1291,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async decrypt ( + async decrypt( args: { seekPermission?: BooleanDefaultTrue ciphertext: Byte[] @@ -1332,7 +1332,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async createHmac ( + async createHmac( args: { seekPermission?: BooleanDefaultTrue data: Byte[] @@ -1373,7 +1373,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async verifyHmac ( + async verifyHmac( args: { seekPermission?: BooleanDefaultTrue data: Byte[] @@ -1411,7 +1411,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { valid: true } } - async createSignature ( + async createSignature( args: { seekPermission?: BooleanDefaultTrue data?: Byte[] @@ -1459,7 +1459,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async verifySignature ( + async verifySignature( args: { seekPermission?: BooleanDefaultTrue data?: Byte[] @@ -1511,7 +1511,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { valid: true } } - private encodeKeyRelatedParams ( + private encodeKeyRelatedParams( protocolID: [SecurityLevel, ProtocolString5To400Bytes], keyID: KeyIDStringUnder800Bytes, counterparty?: PubKeyHex | 'self' | 'anyone', @@ -1541,7 +1541,7 @@ export default class WalletWireTransceiver implements WalletInterface { return paramWriter.toArray() } - async acquireCertificate ( + async acquireCertificate( args: AcquireCertificateArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -1611,7 +1611,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - private encodePrivilegedParams ( + private encodePrivilegedParams( privileged?: boolean, privilegedReason?: string ): number[] { @@ -1631,7 +1631,7 @@ export default class WalletWireTransceiver implements WalletInterface { return paramWriter.toArray() } - async listCertificates ( + async listCertificates( args: { certifiers: PubKeyHex[] types: Base64String[] @@ -1696,7 +1696,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async proveCertificate ( + async proveCertificate( args: ProveCertificateArgs, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise { @@ -1760,7 +1760,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async relinquishCertificate ( + async relinquishCertificate( args: { type: Base64String serialNumber: Base64String @@ -1783,7 +1783,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { relinquished: true } } - private parseDiscoveryResult (result: number[]): { + private parseDiscoveryResult(result: number[]): { totalCertificates: number certificates: Array<{ type: Base64String @@ -1800,8 +1800,8 @@ export default class WalletWireTransceiver implements WalletInterface { trust: PositiveIntegerMax10 } publiclyRevealedKeyring: Record< - CertificateFieldNameUnder50Bytes, - Base64String + CertificateFieldNameUnder50Bytes, + Base64String > decryptedFields: Record }> @@ -1823,8 +1823,8 @@ export default class WalletWireTransceiver implements WalletInterface { trust: PositiveIntegerMax10 } publiclyRevealedKeyring: Record< - CertificateFieldNameUnder50Bytes, - Base64String + CertificateFieldNameUnder50Bytes, + Base64String > decryptedFields: Record }> = [] @@ -1871,7 +1871,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async discoverByIdentityKey ( + async discoverByIdentityKey( args: { seekPermission?: BooleanDefaultTrue identityKey: PubKeyHex @@ -1908,7 +1908,7 @@ export default class WalletWireTransceiver implements WalletInterface { return this.parseDiscoveryResult(result) } - async discoverByAttributes ( + async discoverByAttributes( args: { seekPermission?: BooleanDefaultTrue attributes: Record @@ -1954,7 +1954,7 @@ export default class WalletWireTransceiver implements WalletInterface { return this.parseDiscoveryResult(result) } - async isAuthenticated ( + async isAuthenticated( args: {}, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ authenticated: true }> { @@ -1963,7 +1963,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { authenticated: result[0] === 1 } } - async waitForAuthentication ( + async waitForAuthentication( args: {}, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ authenticated: true }> { @@ -1971,7 +1971,7 @@ export default class WalletWireTransceiver implements WalletInterface { return { authenticated: true } } - async getHeight ( + async getHeight( args: {}, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ height: PositiveInteger }> { @@ -1982,7 +1982,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async getHeaderForHeight ( + async getHeaderForHeight( args: { height: PositiveInteger }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ header: HexString }> { @@ -1998,7 +1998,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async getNetwork ( + async getNetwork( args: {}, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ network: 'mainnet' | 'testnet' }> { @@ -2008,7 +2008,7 @@ export default class WalletWireTransceiver implements WalletInterface { } } - async getVersion ( + async getVersion( args: {}, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ version: VersionString7To30Bytes }> { diff --git a/src/wallet/substrates/XDM.ts b/src/wallet/substrates/XDM.ts index 0836b1e7..583519d1 100644 --- a/src/wallet/substrates/XDM.ts +++ b/src/wallet/substrates/XDM.ts @@ -38,7 +38,7 @@ import { CallType } from './WalletWireCalls.js' export default class XDMSubstrate implements WalletInterface { private readonly domain: string - constructor (domain: string = '*') { + constructor(domain: string = '*') { if (typeof window !== 'object') { throw new Error('The XDM substrate requires a global window object.') } @@ -50,7 +50,7 @@ export default class XDMSubstrate implements WalletInterface { this.domain = domain } - async invoke (call: CallType, args: any): Promise { + async invoke(call: CallType, args: any): Promise { return await new Promise((resolve, reject) => { const id = Utils.toBase64(Random(12)) const listener = (e: MessageEvent): void => { @@ -84,7 +84,7 @@ export default class XDMSubstrate implements WalletInterface { }) } - async createAction (args: { + async createAction(args: { description: DescriptionString5to50Bytes inputs?: Array<{ tx?: BEEF @@ -116,22 +116,22 @@ export default class XDMSubstrate implements WalletInterface { sendWith?: TXIDHexString[] } }): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - signableTransaction?: { tx: BEEF, reference: Base64String } - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + signableTransaction?: { tx: BEEF, reference: Base64String } + }> { return await this.invoke('createAction', args) } - async signAction (args: { + async signAction(args: { spends: Record< - PositiveIntegerOrZero, - { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } + PositiveIntegerOrZero, + { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } > reference: Base64String options?: { @@ -142,24 +142,24 @@ export default class XDMSubstrate implements WalletInterface { sendWith: TXIDHexString[] } }): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + }> { return await this.invoke('signAction', args) } - async abortAction (args: { + async abortAction(args: { reference: Base64String }): Promise<{ aborted: true }> { return await this.invoke('abortAction', args) } - async listActions (args: { + async listActions(args: { labels: LabelStringUnder300Bytes[] labelQueryMode?: 'any' | 'all' includeLabels?: BooleanDefaultFalse @@ -171,47 +171,47 @@ export default class XDMSubstrate implements WalletInterface { limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalActions: PositiveIntegerOrZero - actions: Array<{ - txid: TXIDHexString + totalActions: PositiveIntegerOrZero + actions: Array<{ + txid: TXIDHexString + satoshis: SatoshiValue + status: + | 'completed' + | 'unprocessed' + | 'sending' + | 'unproven' + | 'unsigned' + | 'nosend' + | 'nonfinal' + isOutgoing: boolean + description: DescriptionString5to50Bytes + labels?: LabelStringUnder300Bytes[] + version: PositiveIntegerOrZero + lockTime: PositiveIntegerOrZero + inputs?: Array<{ + sourceOutpoint: OutpointString + sourceSatoshis: SatoshiValue + sourceLockingScript?: HexString + unlockingScript?: HexString + inputDescription: DescriptionString5to50Bytes + sequenceNumber: PositiveIntegerOrZero + }> + outputs?: Array<{ + outputIndex: PositiveIntegerOrZero satoshis: SatoshiValue - status: - | 'completed' - | 'unprocessed' - | 'sending' - | 'unproven' - | 'unsigned' - | 'nosend' - | 'nonfinal' - isOutgoing: boolean - description: DescriptionString5to50Bytes - labels?: LabelStringUnder300Bytes[] - version: PositiveIntegerOrZero - lockTime: PositiveIntegerOrZero - inputs?: Array<{ - sourceOutpoint: OutpointString - sourceSatoshis: SatoshiValue - sourceLockingScript?: HexString - unlockingScript?: HexString - inputDescription: DescriptionString5to50Bytes - sequenceNumber: PositiveIntegerOrZero - }> - outputs?: Array<{ - outputIndex: PositiveIntegerOrZero - satoshis: SatoshiValue - lockingScript?: HexString - spendable: boolean - outputDescription: DescriptionString5to50Bytes - basket: BasketStringUnder300Bytes - tags: OutputTagStringUnder300Bytes[] - customInstructions?: string - }> + lockingScript?: HexString + spendable: boolean + outputDescription: DescriptionString5to50Bytes + basket: BasketStringUnder300Bytes + tags: OutputTagStringUnder300Bytes[] + customInstructions?: string }> - }> { + }> + }> { return await this.invoke('listActions', args) } - async internalizeAction (args: { + async internalizeAction(args: { tx: BEEF outputs: Array<{ outputIndex: PositiveIntegerOrZero @@ -233,7 +233,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('internalizeAction', args) } - async listOutputs (args: { + async listOutputs(args: { basket: BasketStringUnder300Bytes tags?: OutputTagStringUnder300Bytes[] tagQueryMode?: 'all' | 'any' @@ -244,29 +244,29 @@ export default class XDMSubstrate implements WalletInterface { limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalOutputs: PositiveIntegerOrZero - outputs: Array<{ - outpoint: OutpointString - satoshis: SatoshiValue - lockingScript?: HexString - tx?: BEEF - spendable: boolean - customInstructions?: string - tags?: OutputTagStringUnder300Bytes[] - labels?: LabelStringUnder300Bytes[] - }> - }> { + totalOutputs: PositiveIntegerOrZero + outputs: Array<{ + outpoint: OutpointString + satoshis: SatoshiValue + lockingScript?: HexString + tx?: BEEF + spendable: boolean + customInstructions?: string + tags?: OutputTagStringUnder300Bytes[] + labels?: LabelStringUnder300Bytes[] + }> + }> { return await this.invoke('listOutputs', args) } - async relinquishOutput (args: { + async relinquishOutput(args: { basket: BasketStringUnder300Bytes output: OutpointString }): Promise<{ relinquished: true }> { return await this.invoke('relinquishOutput', args) } - async getPublicKey (args: { + async getPublicKey(args: { identityKey?: true protocolID?: [SecurityLevel, ProtocolString5To400Bytes] keyID?: KeyIDStringUnder800Bytes @@ -278,23 +278,23 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('getPublicKey', args) } - async revealCounterpartyKeyLinkage (args: { + async revealCounterpartyKeyLinkage(args: { counterparty: PubKeyHex verifier: PubKeyHex privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - revelationTime: ISOTimestampString - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + revelationTime: ISOTimestampString + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + }> { return await this.invoke('revealCounterpartyKeyLinkage', args) } - async revealSpecificKeyLinkage (args: { + async revealSpecificKeyLinkage(args: { counterparty: PubKeyHex verifier: PubKeyHex protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -302,19 +302,19 @@ export default class XDMSubstrate implements WalletInterface { privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - protocolID: [SecurityLevel, ProtocolString5To400Bytes] - keyID: KeyIDStringUnder800Bytes - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - proofType: Byte - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + protocolID: [SecurityLevel, ProtocolString5To400Bytes] + keyID: KeyIDStringUnder800Bytes + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + proofType: Byte + }> { return await this.invoke('revealSpecificKeyLinkage', args) } - async encrypt (args: { + async encrypt(args: { plaintext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -325,7 +325,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('encrypt', args) } - async decrypt (args: { + async decrypt(args: { ciphertext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -336,7 +336,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('decrypt', args) } - async createHmac (args: { + async createHmac(args: { data: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes @@ -347,7 +347,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('createHmac', args) } - async verifyHmac (args: { + async verifyHmac(args: { data: Byte[] hmac: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -359,7 +359,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('verifyHmac', args) } - async createSignature (args: { + async createSignature(args: { data?: Byte[] hashToDirectlySign?: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -371,7 +371,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('createSignature', args) } - async verifySignature (args: { + async verifySignature(args: { data?: Byte[] hashToDirectlyVerify?: Byte[] signature: Byte[] @@ -385,7 +385,7 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('verifySignature', args) } - async acquireCertificate (args: { + async acquireCertificate(args: { type: Base64String subject: PubKeyHex serialNumber: Base64String @@ -398,18 +398,18 @@ export default class XDMSubstrate implements WalletInterface { acquisitionProtocol: 'direct' | 'issuance' certifierUrl?: string }): Promise<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> { + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> { return await this.invoke('acquireCertificate', args) } - async listCertificates (args: { + async listCertificates(args: { certifiers: PubKeyHex[] types: Base64String[] limit?: PositiveIntegerDefault10Max10000 @@ -417,21 +417,21 @@ export default class XDMSubstrate implements WalletInterface { privileged?: BooleanDefaultFalse privilegedReason?: DescriptionString5to50Bytes }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> - }> { + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> + }> { return await this.invoke('listCertificates', args) } - async proveCertificate (args: { + async proveCertificate(args: { certificate: { type: Base64String subject: PubKeyHex @@ -446,12 +446,12 @@ export default class XDMSubstrate implements WalletInterface { privileged?: BooleanDefaultFalse privilegedReason?: DescriptionString5to50Bytes }): Promise<{ - keyringForVerifier: Record - }> { + keyringForVerifier: Record + }> { return await this.invoke('proveCertificate', args) } - async relinquishCertificate (args: { + async relinquishCertificate(args: { type: Base64String serialNumber: Base64String certifier: PubKeyHex @@ -459,89 +459,89 @@ export default class XDMSubstrate implements WalletInterface { return await this.invoke('relinquishCertificate', args) } - async discoverByIdentityKey (args: { + async discoverByIdentityKey(args: { identityKey: PubKeyHex limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.invoke('discoverByIdentityKey', args) } - async discoverByAttributes (args: { + async discoverByAttributes(args: { attributes: Record limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.invoke('discoverByAttributes', args) } - async isAuthenticated (args: {}): Promise<{ authenticated: true }> { + async isAuthenticated(args: {}): Promise<{ authenticated: true }> { return await this.invoke('isAuthenticated', args) } - async waitForAuthentication (args: {}): Promise<{ authenticated: true }> { + async waitForAuthentication(args: {}): Promise<{ authenticated: true }> { return await this.invoke('waitForAuthentication', args) } - async getHeight (args: {}): Promise<{ height: PositiveInteger }> { + async getHeight(args: {}): Promise<{ height: PositiveInteger }> { return await this.invoke('getHeight', args) } - async getHeaderForHeight (args: { + async getHeaderForHeight(args: { height: PositiveInteger }): Promise<{ header: HexString }> { return await this.invoke('getHeaderForHeight', args) } - async getNetwork (args: {}): Promise<{ network: 'mainnet' | 'testnet' }> { + async getNetwork(args: {}): Promise<{ network: 'mainnet' | 'testnet' }> { return await this.invoke('getNetwork', args) } - async getVersion (args: {}): Promise<{ version: VersionString7To30Bytes }> { + async getVersion(args: {}): Promise<{ version: VersionString7To30Bytes }> { return await this.invoke('getVersion', args) } } diff --git a/src/wallet/substrates/__tests/toOriginHeader.test.ts b/src/wallet/substrates/__tests/toOriginHeader.test.ts index 49ed7aaf..1832a5be 100644 --- a/src/wallet/substrates/__tests/toOriginHeader.test.ts +++ b/src/wallet/substrates/__tests/toOriginHeader.test.ts @@ -1,34 +1,34 @@ -import { toOriginHeader } from '../utils/toOriginHeader' +import { toOriginHeader } from "../utils/toOriginHeader" afterEach(() => jest.resetAllMocks()) type FetchMockCall = Parameters // alias for readability -async function okJson (body: unknown = {}) { - return await Promise.resolve({ +function okJson(body: unknown = {}) { + return Promise.resolve({ ok: true, status: 200, - json: async () => await Promise.resolve(body) + json: () => Promise.resolve(body), } as Response) } -describe('toOriginHeader()', () => { +describe("toOriginHeader()", () => { const vectors: Array<[originator: string, baseUrl: string, expected: string | undefined]> = [ /* originator, baseUrl, expected */ - ['localhost', 'http://localhost:3321', 'http://localhost'], - ['localhost:3000', 'http://localhost:3321', 'http://localhost:3000'], - ['example.com', 'https://api.example.com', 'https://example.com'], - ['https://example.com:8443', 'http://localhost:3321', 'https://example.com:8443'] + ["localhost", "http://localhost:3321", "http://localhost"], + ["localhost:3000", "http://localhost:3321", "http://localhost:3000"], + ["example.com", "https://api.example.com", "https://example.com"], + ["https://example.com:8443", "http://localhost:3321", "https://example.com:8443"], // ["metanet://somehost", "http://localhost:3321", "metanet://somehost"], // TODO: Consider adding support in the future ] - it.each(vectors)('originator=%p, baseUrl=%p → %p', (originator, baseUrl, expected) => { - const schemeFromBase = new URL(baseUrl).protocol.replace(':', '') + it.each(vectors)("originator=%p, baseUrl=%p → %p", (originator, baseUrl, expected) => { + const schemeFromBase = new URL(baseUrl).protocol.replace(":", "") const result = toOriginHeader(originator, schemeFromBase) expect(result).toBe(expected) }) - it('throws on clearly malformed input', () => { - expect(() => toOriginHeader('bad url^%', 'http')).toThrow() + it("throws on clearly malformed input", () => { + expect(() => toOriginHeader("bad url^%", "http")).toThrow() }) }) diff --git a/src/wallet/substrates/utils/toOriginHeader.ts b/src/wallet/substrates/utils/toOriginHeader.ts index efd86b7c..04efa0d9 100644 --- a/src/wallet/substrates/utils/toOriginHeader.ts +++ b/src/wallet/substrates/utils/toOriginHeader.ts @@ -1,8 +1,8 @@ -export function toOriginHeader (originator: string, fallbackScheme = 'http'): string | undefined { +export function toOriginHeader(originator: string, fallbackScheme = 'http'): string | undefined { // If the caller already gave us a scheme, assume it’s fine if (/^[a-z][a-z0-9+.-]*:\/\//i.test(originator)) { try { - return new URL(originator).origin // trims any path/query + return new URL(originator).origin // trims any path/query } catch { /* fall through to fix-up */ } } diff --git a/src/wallet/substrates/window.CWI.ts b/src/wallet/substrates/window.CWI.ts index 94a7948e..c67ae778 100644 --- a/src/wallet/substrates/window.CWI.ts +++ b/src/wallet/substrates/window.CWI.ts @@ -38,7 +38,7 @@ declare const window: { */ export default class WindowCWISubstrate implements WalletInterface { private readonly CWI: WalletInterface - constructor () { + constructor() { if (typeof window !== 'object') { throw new Error( 'The window.CWI substrate requires a global window object.' @@ -52,7 +52,7 @@ export default class WindowCWISubstrate implements WalletInterface { this.CWI = window.CWI // Binding CWI to prevent changes } - async createAction ( + async createAction( args: { description: DescriptionString5to50Bytes inputs?: Array<{ @@ -87,23 +87,23 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - signableTransaction?: { tx: BEEF, reference: Base64String } - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + signableTransaction?: { tx: BEEF, reference: Base64String } + }> { return await this.CWI.createAction(args, originator) } - async signAction ( + async signAction( args: { spends: Record< - PositiveIntegerOrZero, - { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } + PositiveIntegerOrZero, + { unlockingScript: HexString, sequenceNumber?: PositiveIntegerOrZero } > reference: Base64String options?: { @@ -116,25 +116,25 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - txid?: TXIDHexString - tx?: BEEF - noSendChange?: OutpointString[] - sendWithResults?: Array<{ - txid: TXIDHexString - status: 'unproven' | 'sending' | 'failed' - }> - }> { + txid?: TXIDHexString + tx?: BEEF + noSendChange?: OutpointString[] + sendWithResults?: Array<{ + txid: TXIDHexString + status: 'unproven' | 'sending' | 'failed' + }> + }> { return await this.CWI.signAction(args, originator) } - async abortAction ( + async abortAction( args: { reference: Base64String }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ aborted: true }> { return await this.CWI.abortAction(args, originator) } - async listActions ( + async listActions( args: { labels: LabelStringUnder300Bytes[] labelQueryMode?: 'any' | 'all' @@ -149,48 +149,48 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - totalActions: PositiveIntegerOrZero - actions: Array<{ - txid: TXIDHexString + totalActions: PositiveIntegerOrZero + actions: Array<{ + txid: TXIDHexString + satoshis: SatoshiValue + status: + | 'completed' + | 'unprocessed' + | 'sending' + | 'unproven' + | 'unsigned' + | 'nosend' + | 'nonfinal' + | 'failed' + isOutgoing: boolean + description: DescriptionString5to50Bytes + labels?: LabelStringUnder300Bytes[] + version: PositiveIntegerOrZero + lockTime: PositiveIntegerOrZero + inputs?: Array<{ + sourceOutpoint: OutpointString + sourceSatoshis: SatoshiValue + sourceLockingScript?: HexString + unlockingScript?: HexString + inputDescription: DescriptionString5to50Bytes + sequenceNumber: PositiveIntegerOrZero + }> + outputs?: Array<{ + outputIndex: PositiveIntegerOrZero satoshis: SatoshiValue - status: - | 'completed' - | 'unprocessed' - | 'sending' - | 'unproven' - | 'unsigned' - | 'nosend' - | 'nonfinal' - | 'failed' - isOutgoing: boolean - description: DescriptionString5to50Bytes - labels?: LabelStringUnder300Bytes[] - version: PositiveIntegerOrZero - lockTime: PositiveIntegerOrZero - inputs?: Array<{ - sourceOutpoint: OutpointString - sourceSatoshis: SatoshiValue - sourceLockingScript?: HexString - unlockingScript?: HexString - inputDescription: DescriptionString5to50Bytes - sequenceNumber: PositiveIntegerOrZero - }> - outputs?: Array<{ - outputIndex: PositiveIntegerOrZero - satoshis: SatoshiValue - lockingScript?: HexString - spendable: boolean - outputDescription: DescriptionString5to50Bytes - basket: BasketStringUnder300Bytes - tags: OutputTagStringUnder300Bytes[] - customInstructions?: string - }> + lockingScript?: HexString + spendable: boolean + outputDescription: DescriptionString5to50Bytes + basket: BasketStringUnder300Bytes + tags: OutputTagStringUnder300Bytes[] + customInstructions?: string }> - }> { + }> + }> { return await this.CWI.listActions(args, originator) } - async internalizeAction ( + async internalizeAction( args: { tx: BEEF outputs: Array<{ @@ -215,7 +215,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.internalizeAction(args, originator) } - async listOutputs ( + async listOutputs( args: { basket: BasketStringUnder300Bytes tags?: OutputTagStringUnder300Bytes[] @@ -229,29 +229,29 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - totalOutputs: PositiveIntegerOrZero - outputs: Array<{ - outpoint: OutpointString - satoshis: SatoshiValue - lockingScript?: HexString - tx?: BEEF - spendable: boolean - customInstructions?: string - tags?: OutputTagStringUnder300Bytes[] - labels?: LabelStringUnder300Bytes[] - }> - }> { + totalOutputs: PositiveIntegerOrZero + outputs: Array<{ + outpoint: OutpointString + satoshis: SatoshiValue + lockingScript?: HexString + tx?: BEEF + spendable: boolean + customInstructions?: string + tags?: OutputTagStringUnder300Bytes[] + labels?: LabelStringUnder300Bytes[] + }> + }> { return await this.CWI.listOutputs(args, originator) } - async relinquishOutput ( + async relinquishOutput( args: { basket: BasketStringUnder300Bytes, output: OutpointString }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ relinquished: true }> { return await this.CWI.relinquishOutput(args, originator) } - async getPublicKey ( + async getPublicKey( args: { identityKey?: true protocolID?: [SecurityLevel, ProtocolString5To400Bytes] @@ -266,7 +266,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.getPublicKey(args, originator) } - async revealCounterpartyKeyLinkage ( + async revealCounterpartyKeyLinkage( args: { counterparty: PubKeyHex verifier: PubKeyHex @@ -275,17 +275,17 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - revelationTime: ISOTimestampString - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + revelationTime: ISOTimestampString + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + }> { return await this.CWI.revealCounterpartyKeyLinkage(args, originator) } - async revealSpecificKeyLinkage ( + async revealSpecificKeyLinkage( args: { counterparty: PubKeyHex verifier: PubKeyHex @@ -296,19 +296,19 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - prover: PubKeyHex - verifier: PubKeyHex - counterparty: PubKeyHex - protocolID: [SecurityLevel, ProtocolString5To400Bytes] - keyID: KeyIDStringUnder800Bytes - encryptedLinkage: Byte[] - encryptedLinkageProof: Byte[] - proofType: Byte - }> { + prover: PubKeyHex + verifier: PubKeyHex + counterparty: PubKeyHex + protocolID: [SecurityLevel, ProtocolString5To400Bytes] + keyID: KeyIDStringUnder800Bytes + encryptedLinkage: Byte[] + encryptedLinkageProof: Byte[] + proofType: Byte + }> { return await this.CWI.revealSpecificKeyLinkage(args, originator) } - async encrypt ( + async encrypt( args: { plaintext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -322,7 +322,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.encrypt(args, originator) } - async decrypt ( + async decrypt( args: { ciphertext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -336,7 +336,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.decrypt(args, originator) } - async createHmac ( + async createHmac( args: { data: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] @@ -350,7 +350,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.createHmac(args, originator) } - async verifyHmac ( + async verifyHmac( args: { data: Byte[] hmac: Byte[] @@ -365,7 +365,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.verifyHmac(args, originator) } - async createSignature ( + async createSignature( args: { data?: Byte[] hashToDirectlySign?: Byte[] @@ -380,7 +380,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.createSignature(args, originator) } - async verifySignature ( + async verifySignature( args: { data?: Byte[] hashToDirectlyVerify?: Byte[] @@ -397,7 +397,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.verifySignature(args, originator) } - async acquireCertificate ( + async acquireCertificate( args: { type: Base64String subject: PubKeyHex @@ -413,18 +413,18 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> { + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> { return await this.CWI.acquireCertificate(args, originator) } - async listCertificates ( + async listCertificates( args: { certifiers: PubKeyHex[] types: Base64String[] @@ -435,21 +435,21 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - }> - }> { + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + }> + }> { return await this.CWI.listCertificates(args, originator) } - async proveCertificate ( + async proveCertificate( args: { certificate: { type: Base64String @@ -467,12 +467,12 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - keyringForVerifier: Record - }> { + keyringForVerifier: Record + }> { return await this.CWI.proveCertificate(args, originator) } - async relinquishCertificate ( + async relinquishCertificate( args: { type: Base64String serialNumber: Base64String @@ -483,7 +483,7 @@ export default class WindowCWISubstrate implements WalletInterface { return await this.CWI.relinquishCertificate(args, originator) } - async discoverByIdentityKey ( + async discoverByIdentityKey( args: { identityKey: PubKeyHex limit?: PositiveIntegerDefault10Max10000 @@ -491,32 +491,32 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.CWI.discoverByIdentityKey(args, originator) } - async discoverByAttributes ( + async discoverByAttributes( args: { attributes: Record limit?: PositiveIntegerDefault10Max10000 @@ -524,67 +524,67 @@ export default class WindowCWISubstrate implements WalletInterface { }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ - totalCertificates: PositiveIntegerOrZero - certificates: Array<{ - type: Base64String - subject: PubKeyHex - serialNumber: Base64String - certifier: PubKeyHex - revocationOutpoint: OutpointString - signature: HexString - fields: Record - certifierInfo: { - name: EntityNameStringMax100Bytes - iconUrl: EntityIconURLStringMax500Bytes - description: DescriptionString5to50Bytes - trust: PositiveIntegerMax10 - } - publiclyRevealedKeyring: Record< + totalCertificates: PositiveIntegerOrZero + certificates: Array<{ + type: Base64String + subject: PubKeyHex + serialNumber: Base64String + certifier: PubKeyHex + revocationOutpoint: OutpointString + signature: HexString + fields: Record + certifierInfo: { + name: EntityNameStringMax100Bytes + iconUrl: EntityIconURLStringMax500Bytes + description: DescriptionString5to50Bytes + trust: PositiveIntegerMax10 + } + publiclyRevealedKeyring: Record< CertificateFieldNameUnder50Bytes, Base64String - > - decryptedFields: Record - }> - }> { + > + decryptedFields: Record + }> + }> { return await this.CWI.discoverByAttributes(args, originator) } - async isAuthenticated ( + async isAuthenticated( args: object, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ authenticated: true }> { return await this.CWI.isAuthenticated(args, originator) } - async waitForAuthentication ( + async waitForAuthentication( args: object, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ authenticated: true }> { return await this.CWI.waitForAuthentication(args, originator) } - async getHeight ( + async getHeight( args: object, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ height: PositiveInteger }> { return await this.CWI.getHeight(args, originator) } - async getHeaderForHeight ( + async getHeaderForHeight( args: { height: PositiveInteger }, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ header: HexString }> { return await this.CWI.getHeaderForHeight(args, originator) } - async getNetwork ( + async getNetwork( args: object, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ network: 'mainnet' | 'testnet' }> { return await this.CWI.getNetwork(args, originator) } - async getVersion ( + async getVersion( args: object, originator?: OriginatorDomainNameStringUnder250Bytes ): Promise<{ version: VersionString7To30Bytes }> { From 77ff67704660601df921f5afbc00a7869154c7f2 Mon Sep 17 00:00:00 2001 From: Brayden Langley Date: Tue, 9 Sep 2025 14:42:54 -0700 Subject: [PATCH 7/7] doc --- docs/reference/transaction.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/reference/transaction.md b/docs/reference/transaction.md index 607bb087..002ee487 100644 --- a/docs/reference/transaction.md +++ b/docs/reference/transaction.md @@ -985,7 +985,6 @@ verifyValid(allowTxidOnly?: boolean): { Returns - `valid` is true iff this Beef is structuraly valid. `roots` is a record where keys are block heights and values are the corresponding merkle roots to be validated.