UNPKG

@bsv/sdk

Version:

BSV Blockchain Software Development Kit

355 lines (318 loc) 11.7 kB
import { WalletInterface, CreateActionArgs, OriginatorDomainNameStringUnder250Bytes, CreateActionResult, BooleanDefaultTrue, AcquireCertificateArgs, AcquireCertificateResult, Base64String, BasketStringUnder300Bytes, BooleanDefaultFalse, Byte, CertificateFieldNameUnder50Bytes, DescriptionString5to50Bytes, DiscoverCertificatesResult, HexString, InternalizeActionArgs, ISOTimestampString, KeyIDStringUnder800Bytes, ListActionsArgs, ListActionsResult, ListCertificatesResult, ListOutputsArgs, ListOutputsResult, OutpointString, PositiveInteger, PositiveIntegerDefault10Max10000, PositiveIntegerOrZero, ProtocolString5To400Bytes, ProveCertificateArgs, ProveCertificateResult, PubKeyHex, SecurityLevel, SignActionArgs, SignActionResult, VersionString7To30Bytes, } from '../Wallet.interfaces.js' import { WERR_REVIEW_ACTIONS } from '../WERR_REVIEW_ACTIONS.js' import { toOriginHeader } from './utils/toOriginHeader.js' export default class HTTPWalletJSON implements WalletInterface { baseUrl: string httpClient: typeof fetch originator: OriginatorDomainNameStringUnder250Bytes | undefined api: (call: string, args: object) => Promise<unknown> // Fixed `any` types constructor( originator: OriginatorDomainNameStringUnder250Bytes | undefined, baseUrl: string = 'http://localhost:3321', httpClient = fetch ) { this.baseUrl = baseUrl this.originator = originator this.httpClient = httpClient // Detect if we're in a browser environment const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window?.origin !== 'file://' this.api = async (call: string, args: object) => { // In browser environments, let the browser handle Origin header automatically // In Node.js environments, we need to set it manually if originator is provided const origin = !isBrowser && this.originator ? toOriginHeader(this.originator, 'http') : undefined if (!isBrowser && origin === undefined) { console.error('Originator is required in Node.js environments') } const res = await ( await httpClient(`${this.baseUrl}/${call}`, { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', ...(origin ? { Origin: origin } : {}), ...(origin ? { Originator: origin } : {}), }, body: JSON.stringify(args) }) ) const data = await res.json() // Check the HTTP status on the original response if (!res.ok) { if (res.status === 400 && data.isError && data.code === 5) { const err = new WERR_REVIEW_ACTIONS(data.reviewActionResults, data.sendWithResults, data.txid, data.tx, data.noSendChange) throw err } else { const err = { call, args, message: data.message ?? `HTTP Client error ${res.status}` } throw new Error(JSON.stringify(err)) } } return data } } async createAction(args: CreateActionArgs): Promise<CreateActionResult> { return await this.api('createAction', args) as CreateActionResult } async signAction(args: SignActionArgs): Promise<SignActionResult> { return await this.api('signAction', args) as SignActionResult } async abortAction(args: { reference: Base64String }): Promise<{ aborted: true }> { return await this.api('abortAction', args) as { aborted: true } } async listActions(args: ListActionsArgs): Promise<ListActionsResult> { return await this.api('listActions', args) as ListActionsResult } async internalizeAction( args: InternalizeActionArgs ): Promise<{ accepted: true }> { return await this.api('internalizeAction', args) as { accepted: true } } async listOutputs(args: ListOutputsArgs): Promise<ListOutputsResult> { return await this.api('listOutputs', args) as ListOutputsResult } async relinquishOutput(args: { basket: BasketStringUnder300Bytes output: OutpointString }): Promise<{ relinquished: true }> { return await this.api('relinquishOutput', args) as { relinquished: true } } async getPublicKey(args: { seekPermission?: BooleanDefaultTrue identityKey?: true protocolID?: [SecurityLevel, ProtocolString5To400Bytes] keyID?: KeyIDStringUnder800Bytes privileged?: BooleanDefaultFalse privilegedReason?: DescriptionString5to50Bytes counterparty?: PubKeyHex | 'self' | 'anyone' forSelf?: BooleanDefaultFalse }): Promise<{ publicKey: PubKeyHex }> { return await this.api('getPublicKey', args) as { publicKey: PubKeyHex } } async revealCounterpartyKeyLinkage(args: { counterparty: PubKeyHex verifier: PubKeyHex privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ prover: PubKeyHex verifier: PubKeyHex counterparty: PubKeyHex revelationTime: ISOTimestampString encryptedLinkage: Byte[] encryptedLinkageProof: number[] }> { return await this.api('revealCounterpartyKeyLinkage', args) as { prover: PubKeyHex verifier: PubKeyHex counterparty: PubKeyHex revelationTime: ISOTimestampString encryptedLinkage: Byte[] encryptedLinkageProof: number[] } } async revealSpecificKeyLinkage(args: { counterparty: PubKeyHex verifier: PubKeyHex protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes privilegedReason?: DescriptionString5to50Bytes privileged?: BooleanDefaultFalse }): Promise<{ 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 counterparty: PubKeyHex protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes encryptedLinkage: Byte[] encryptedLinkageProof: Byte[] proofType: Byte } } async encrypt(args: { seekPermission?: BooleanDefaultTrue plaintext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes privilegedReason?: DescriptionString5to50Bytes counterparty?: PubKeyHex | 'self' | 'anyone' privileged?: BooleanDefaultFalse }): Promise<{ ciphertext: Byte[] }> { return await this.api('encrypt', args) as { ciphertext: Byte[] } } async decrypt(args: { seekPermission?: BooleanDefaultTrue ciphertext: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes privilegedReason?: DescriptionString5to50Bytes counterparty?: PubKeyHex | 'self' | 'anyone' privileged?: BooleanDefaultFalse }): Promise<{ plaintext: Byte[] }> { return await this.api('decrypt', args) as { plaintext: Byte[] } } async createHmac(args: { seekPermission?: BooleanDefaultTrue data: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes privilegedReason?: DescriptionString5to50Bytes counterparty?: PubKeyHex | 'self' | 'anyone' privileged?: BooleanDefaultFalse }): Promise<{ hmac: Byte[] }> { return await this.api('createHmac', args) as { hmac: Byte[] } } async verifyHmac(args: { seekPermission?: BooleanDefaultTrue data: Byte[] hmac: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes privilegedReason?: DescriptionString5to50Bytes counterparty?: PubKeyHex | 'self' | 'anyone' privileged?: BooleanDefaultFalse }): Promise<{ valid: true }> { return await this.api('verifyHmac', args) as { valid: true } } async createSignature(args: { seekPermission?: BooleanDefaultTrue data?: Byte[] hashToDirectlySign?: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes privilegedReason?: DescriptionString5to50Bytes counterparty?: PubKeyHex | 'self' | 'anyone' privileged?: BooleanDefaultFalse }): Promise<{ signature: Byte[] }> { return await this.api('createSignature', args) as { signature: Byte[] } } async verifySignature(args: { seekPermission?: BooleanDefaultTrue data?: Byte[] hashToDirectlyVerify?: Byte[] signature: Byte[] protocolID: [SecurityLevel, ProtocolString5To400Bytes] keyID: KeyIDStringUnder800Bytes privilegedReason?: DescriptionString5to50Bytes counterparty?: PubKeyHex | 'self' | 'anyone' forSelf?: BooleanDefaultFalse privileged?: BooleanDefaultFalse }): Promise<{ valid: true }> { return await this.api('verifySignature', args) as { valid: true } } async acquireCertificate( args: AcquireCertificateArgs ): Promise<AcquireCertificateResult> { return await this.api('acquireCertificate', args) as AcquireCertificateResult } async listCertificates(args: { certifiers: PubKeyHex[] types: Base64String[] limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero privileged?: BooleanDefaultFalse privilegedReason?: DescriptionString5to50Bytes }): Promise<ListCertificatesResult> { return await this.api('listCertificates', args) as ListCertificatesResult } async proveCertificate( args: ProveCertificateArgs ): Promise<ProveCertificateResult> { return await this.api('proveCertificate', args) as ProveCertificateResult } async relinquishCertificate(args: { type: Base64String serialNumber: Base64String certifier: PubKeyHex }): Promise<{ relinquished: true }> { return await this.api('relinquishCertificate', args) as { relinquished: true } } async discoverByIdentityKey(args: { seekPermission?: BooleanDefaultTrue identityKey: PubKeyHex limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<DiscoverCertificatesResult> { return await this.api('discoverByIdentityKey', args) as DiscoverCertificatesResult } async discoverByAttributes(args: { seekPermission?: BooleanDefaultTrue attributes: Record<CertificateFieldNameUnder50Bytes, string> limit?: PositiveIntegerDefault10Max10000 offset?: PositiveIntegerOrZero }): Promise<DiscoverCertificatesResult> { return await this.api('discoverByAttributes', args) as DiscoverCertificatesResult } async isAuthenticated(args: object): Promise<{ authenticated: true }> { return await this.api('isAuthenticated', args) as { 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 }> { return await this.api('getHeight', args) as { height: PositiveInteger } } 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' }> { return await this.api('getNetwork', args) as { network: 'mainnet' | 'testnet' } } async getVersion(args: object): Promise<{ version: VersionString7To30Bytes }> { return await this.api('getVersion', args) as { version: VersionString7To30Bytes } } }