@bsv/sdk 1.7.3 → 1.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/auth/Peer.js +26 -25
  3. package/dist/cjs/src/auth/Peer.js.map +1 -1
  4. package/dist/cjs/src/auth/certificates/VerifiableCertificate.js +3 -3
  5. package/dist/cjs/src/auth/certificates/VerifiableCertificate.js.map +1 -1
  6. package/dist/cjs/src/auth/clients/AuthFetch.js +9 -9
  7. package/dist/cjs/src/auth/clients/AuthFetch.js.map +1 -1
  8. package/dist/cjs/src/auth/utils/createNonce.js +2 -2
  9. package/dist/cjs/src/auth/utils/createNonce.js.map +1 -1
  10. package/dist/cjs/src/auth/utils/getVerifiableCertificates.js +3 -3
  11. package/dist/cjs/src/auth/utils/getVerifiableCertificates.js.map +1 -1
  12. package/dist/cjs/src/auth/utils/validateCertificates.js +3 -3
  13. package/dist/cjs/src/auth/utils/validateCertificates.js.map +1 -1
  14. package/dist/cjs/src/auth/utils/verifyNonce.js +2 -2
  15. package/dist/cjs/src/auth/utils/verifyNonce.js.map +1 -1
  16. package/dist/cjs/src/identity/ContactsManager.js +12 -9
  17. package/dist/cjs/src/identity/ContactsManager.js.map +1 -1
  18. package/dist/cjs/src/identity/IdentityClient.js +3 -2
  19. package/dist/cjs/src/identity/IdentityClient.js.map +1 -1
  20. package/dist/cjs/src/storage/StorageDownloader.js +3 -3
  21. package/dist/cjs/src/storage/StorageDownloader.js.map +1 -1
  22. package/dist/cjs/src/wallet/ProtoWallet.js +1 -1
  23. package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -1
  24. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  25. package/dist/esm/src/auth/Peer.js +27 -25
  26. package/dist/esm/src/auth/Peer.js.map +1 -1
  27. package/dist/esm/src/auth/certificates/VerifiableCertificate.js +3 -3
  28. package/dist/esm/src/auth/certificates/VerifiableCertificate.js.map +1 -1
  29. package/dist/esm/src/auth/clients/AuthFetch.js +10 -9
  30. package/dist/esm/src/auth/clients/AuthFetch.js.map +1 -1
  31. package/dist/esm/src/auth/utils/createNonce.js +2 -2
  32. package/dist/esm/src/auth/utils/createNonce.js.map +1 -1
  33. package/dist/esm/src/auth/utils/getVerifiableCertificates.js +3 -3
  34. package/dist/esm/src/auth/utils/getVerifiableCertificates.js.map +1 -1
  35. package/dist/esm/src/auth/utils/validateCertificates.js +3 -3
  36. package/dist/esm/src/auth/utils/validateCertificates.js.map +1 -1
  37. package/dist/esm/src/auth/utils/verifyNonce.js +2 -2
  38. package/dist/esm/src/auth/utils/verifyNonce.js.map +1 -1
  39. package/dist/esm/src/identity/ContactsManager.js +13 -10
  40. package/dist/esm/src/identity/ContactsManager.js.map +1 -1
  41. package/dist/esm/src/identity/IdentityClient.js +3 -2
  42. package/dist/esm/src/identity/IdentityClient.js.map +1 -1
  43. package/dist/esm/src/storage/StorageDownloader.js +4 -3
  44. package/dist/esm/src/storage/StorageDownloader.js.map +1 -1
  45. package/dist/esm/src/wallet/ProtoWallet.js +1 -1
  46. package/dist/esm/src/wallet/ProtoWallet.js.map +1 -1
  47. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  48. package/dist/types/src/auth/Peer.d.ts +3 -2
  49. package/dist/types/src/auth/Peer.d.ts.map +1 -1
  50. package/dist/types/src/auth/certificates/VerifiableCertificate.d.ts +2 -2
  51. package/dist/types/src/auth/certificates/VerifiableCertificate.d.ts.map +1 -1
  52. package/dist/types/src/auth/clients/AuthFetch.d.ts +3 -2
  53. package/dist/types/src/auth/clients/AuthFetch.d.ts.map +1 -1
  54. package/dist/types/src/auth/utils/createNonce.d.ts +2 -2
  55. package/dist/types/src/auth/utils/createNonce.d.ts.map +1 -1
  56. package/dist/types/src/auth/utils/getVerifiableCertificates.d.ts +2 -2
  57. package/dist/types/src/auth/utils/getVerifiableCertificates.d.ts.map +1 -1
  58. package/dist/types/src/auth/utils/validateCertificates.d.ts +2 -2
  59. package/dist/types/src/auth/utils/validateCertificates.d.ts.map +1 -1
  60. package/dist/types/src/auth/utils/verifyNonce.d.ts +2 -2
  61. package/dist/types/src/auth/utils/verifyNonce.d.ts.map +1 -1
  62. package/dist/types/src/identity/ContactsManager.d.ts +2 -1
  63. package/dist/types/src/identity/ContactsManager.d.ts.map +1 -1
  64. package/dist/types/src/identity/IdentityClient.d.ts +2 -1
  65. package/dist/types/src/identity/IdentityClient.d.ts.map +1 -1
  66. package/dist/types/src/storage/StorageDownloader.d.ts +1 -0
  67. package/dist/types/src/storage/StorageDownloader.d.ts.map +1 -1
  68. package/dist/types/src/wallet/ProtoWallet.d.ts +1 -1
  69. package/dist/types/src/wallet/ProtoWallet.d.ts.map +1 -1
  70. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  71. package/dist/umd/bundle.js +2 -2
  72. package/dist/umd/bundle.js.map +1 -1
  73. package/docs/reference/auth.md +23 -23
  74. package/docs/reference/identity.md +8 -4
  75. package/docs/reference/wallet.md +1 -1
  76. package/package.json +1 -1
  77. package/src/auth/Peer.ts +34 -26
  78. package/src/auth/certificates/VerifiableCertificate.ts +5 -4
  79. package/src/auth/clients/AuthFetch.ts +13 -10
  80. package/src/auth/utils/__tests/getVerifiableCertificates.test.ts +3 -3
  81. package/src/auth/utils/__tests/validateCertificates.test.ts +3 -3
  82. package/src/auth/utils/createNonce.ts +5 -3
  83. package/src/auth/utils/getVerifiableCertificates.ts +5 -4
  84. package/src/auth/utils/validateCertificates.ts +5 -4
  85. package/src/auth/utils/verifyNonce.ts +4 -3
  86. package/src/identity/ContactsManager.ts +12 -10
  87. package/src/identity/IdentityClient.ts +3 -2
  88. package/src/identity/__tests/IdentityClient.test.ts +10 -4
  89. package/src/storage/StorageDownloader.ts +4 -3
  90. package/src/wallet/ProtoWallet.ts +1 -2
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  WalletInterface,
3
3
  WalletCounterparty,
4
- Base64String
4
+ Base64String,
5
+ OriginatorDomainNameStringUnder250Bytes
5
6
  } from '../../wallet/Wallet.interfaces.js'
6
7
  import * as Utils from '../../primitives/utils.js'
7
8
  import Random from '../../primitives/Random.js'
@@ -14,7 +15,8 @@ import Random from '../../primitives/Random.js'
14
15
  */
15
16
  export async function createNonce(
16
17
  wallet: WalletInterface,
17
- counterparty: WalletCounterparty = 'self'
18
+ counterparty: WalletCounterparty = 'self',
19
+ originator?: OriginatorDomainNameStringUnder250Bytes
18
20
  ): Promise<Base64String> {
19
21
  // Generate 16 random bytes for the first half of the data
20
22
  const firstHalf = Random(16)
@@ -24,7 +26,7 @@ export async function createNonce(
24
26
  keyID: Utils.toUTF8(firstHalf),
25
27
  data: firstHalf,
26
28
  counterparty
27
- })
29
+ }, originator)
28
30
  // Concatenate firstHalf and secondHalf as the nonce bytes
29
31
  const nonceBytes = [...firstHalf, ...hmac]
30
32
  return Utils.toBase64(nonceBytes)
@@ -1,5 +1,5 @@
1
1
  import { VerifiableCertificate } from '../certificates/VerifiableCertificate.js'
2
- import { WalletInterface } from '../../wallet/Wallet.interfaces.js'
2
+ import { OriginatorDomainNameStringUnder250Bytes, WalletInterface } from '../../wallet/Wallet.interfaces.js'
3
3
  import { RequestedCertificateSet } from '../types.js'
4
4
 
5
5
  /**
@@ -13,14 +13,15 @@ import { RequestedCertificateSet } from '../types.js'
13
13
  export const getVerifiableCertificates = async (
14
14
  wallet: WalletInterface,
15
15
  requestedCertificates: RequestedCertificateSet,
16
- verifierIdentityKey: string
16
+ verifierIdentityKey: string,
17
+ originator?: OriginatorDomainNameStringUnder250Bytes
17
18
  ): Promise<VerifiableCertificate[]> => {
18
19
  // Find matching certificates we have
19
20
  // Note: This may return multiple certificates that match the correct type.
20
21
  const matchingCertificates = await wallet.listCertificates({
21
22
  certifiers: requestedCertificates.certifiers,
22
23
  types: Object.keys(requestedCertificates.types)
23
- })
24
+ }, originator)
24
25
 
25
26
  // For each certificate requested, create a verifiable cert with selectively revealed fields
26
27
  return await Promise.all(
@@ -29,7 +30,7 @@ export const getVerifiableCertificates = async (
29
30
  certificate,
30
31
  fieldsToReveal: requestedCertificates.types[certificate.type],
31
32
  verifier: verifierIdentityKey
32
- })
33
+ }, originator)
33
34
  return new VerifiableCertificate(
34
35
  certificate.type,
35
36
  certificate.serialNumber,
@@ -1,4 +1,4 @@
1
- import { WalletInterface } from '../../wallet/index.js'
1
+ import { OriginatorDomainNameStringUnder250Bytes, WalletInterface } from '../../wallet/index.js'
2
2
  import { AuthMessage, RequestedCertificateSet } from '../types.js'
3
3
  import { VerifiableCertificate } from '../certificates/VerifiableCertificate.js'
4
4
 
@@ -13,7 +13,8 @@ import { VerifiableCertificate } from '../certificates/VerifiableCertificate.js'
13
13
  export const validateCertificates = async (
14
14
  verifierWallet: WalletInterface,
15
15
  message: AuthMessage,
16
- certificatesRequested?: RequestedCertificateSet
16
+ certificatesRequested?: RequestedCertificateSet,
17
+ originator?: OriginatorDomainNameStringUnder250Bytes
17
18
  ): Promise<void> => {
18
19
  if ((message.certificates == null) || message.certificates.length === 0) {
19
20
  throw new Error('No certificates were provided in the AuthMessage.')
@@ -58,7 +59,7 @@ export const validateCertificates = async (
58
59
 
59
60
  // Check type and fields match requested
60
61
  const requestedFields = types[certToVerify.type]
61
- if (requestedFields == null) { // ✅ Explicitly check for null or undefined
62
+ if (requestedFields == null) {
62
63
  throw new Error(
63
64
  `Certificate with type ${certToVerify.type} was not requested`
64
65
  )
@@ -66,7 +67,7 @@ export const validateCertificates = async (
66
67
  }
67
68
 
68
69
  // Attempt to decrypt fields
69
- await certToVerify.decryptFields(verifierWallet)
70
+ await certToVerify.decryptFields(verifierWallet, undefined, undefined, originator)
70
71
  })
71
72
  )
72
73
  }
@@ -1,5 +1,5 @@
1
1
  import * as Utils from '../../primitives/utils.js'
2
- import { WalletInterface, WalletCounterparty, Base64String } from '../../wallet/Wallet.interfaces.js'
2
+ import { WalletInterface, WalletCounterparty, Base64String, OriginatorDomainNameStringUnder250Bytes } from '../../wallet/Wallet.interfaces.js'
3
3
 
4
4
  /**
5
5
  * Verifies a nonce derived from a wallet
@@ -11,7 +11,8 @@ import { WalletInterface, WalletCounterparty, Base64String } from '../../wallet/
11
11
  export async function verifyNonce(
12
12
  nonce: Base64String,
13
13
  wallet: WalletInterface,
14
- counterparty: WalletCounterparty = 'self'
14
+ counterparty: WalletCounterparty = 'self',
15
+ originator?: OriginatorDomainNameStringUnder250Bytes
15
16
  ): Promise<boolean> {
16
17
  // Convert nonce from base64 string to Uint8Array
17
18
  const buffer = Utils.toArray(nonce, 'base64')
@@ -27,7 +28,7 @@ export async function verifyNonce(
27
28
  protocolID: [2, 'server hmac'],
28
29
  keyID: Utils.toUTF8(data),
29
30
  counterparty
30
- })
31
+ }, originator)
31
32
 
32
33
  return valid
33
34
  }
@@ -1,7 +1,7 @@
1
1
  import { PubKeyHex, WalletClient, WalletInterface, WalletProtocol } from '../wallet/index.js'
2
2
  import { Utils, Random } from '../primitives/index.js'
3
3
  import { DisplayableIdentity } from './types/index.js'
4
- import { PushDrop } from '../script/index.js'
4
+ import { LockingScript, PushDrop } from '../script/index.js'
5
5
  import { Transaction } from '../transaction/index.js'
6
6
  export type Contact = DisplayableIdentity & { metadata?: Record<string, any> }
7
7
 
@@ -41,9 +41,10 @@ export class ContactsManager {
41
41
  * Load all records from the contacts basket
42
42
  * @param identityKey Optional specific identity key to fetch
43
43
  * @param forceRefresh Whether to force a check for new contact data
44
+ * @param limit Maximum number of contacts to return
44
45
  * @returns A promise that resolves with an array of contacts
45
46
  */
46
- async getContacts (identityKey?: PubKeyHex, forceRefresh = false): Promise<Contact[]> {
47
+ async getContacts (identityKey?: PubKeyHex, forceRefresh = false, limit = 1000): Promise<Contact[]> {
47
48
  // Check in-memory cache first unless forcing refresh
48
49
  if (!forceRefresh) {
49
50
  const cached = this.cache.getItem(this.CONTACTS_CACHE_KEY)
@@ -74,9 +75,10 @@ export class ContactsManager {
74
75
  // Get all contact outputs from the contacts basket
75
76
  const outputs = await this.wallet.listOutputs({
76
77
  basket: 'contacts',
77
- include: 'entire transactions',
78
+ include: 'locking scripts',
78
79
  includeCustomInstructions: true,
79
- tags
80
+ tags,
81
+ limit
80
82
  })
81
83
 
82
84
  if (outputs.outputs == null || outputs.outputs.length === 0) {
@@ -89,12 +91,10 @@ export class ContactsManager {
89
91
  // Process each contact output
90
92
  for (const output of outputs.outputs) {
91
93
  try {
92
- const [txid, outputIndex] = output.outpoint.split('.')
93
- const tx = Transaction.fromBEEF(outputs.BEEF as number[], txid)
94
- const lockingScript = tx.outputs[Number(outputIndex)].lockingScript
94
+ if (output.lockingScript == null) continue
95
95
 
96
96
  // Decode the PushDrop data
97
- const decoded = PushDrop.decode(lockingScript)
97
+ const decoded = PushDrop.decode(LockingScript.fromHex(output.lockingScript))
98
98
  if (output.customInstructions == null) continue
99
99
  const keyID = JSON.parse(output.customInstructions).keyID
100
100
 
@@ -164,7 +164,8 @@ export class ContactsManager {
164
164
  basket: 'contacts',
165
165
  include: 'entire transactions',
166
166
  includeCustomInstructions: true,
167
- tags: [`identityKey ${Utils.toHex(hashedIdentityKey)}`]
167
+ tags: [`identityKey ${Utils.toHex(hashedIdentityKey)}`],
168
+ limit: 100 // Should only be one contact!
168
169
  })
169
170
 
170
171
  let existingOutput: any = null
@@ -309,7 +310,8 @@ export class ContactsManager {
309
310
  basket: 'contacts',
310
311
  include: 'entire transactions',
311
312
  includeCustomInstructions: true,
312
- tags
313
+ tags,
314
+ limit: 100 // Should only be one contact!
313
315
  })
314
316
 
315
317
  if (outputs.outputs == null) return
@@ -247,10 +247,11 @@ export class IdentityClient {
247
247
  * Load all records from the contacts basket
248
248
  * @param identityKey Optional specific identity key to fetch
249
249
  * @param forceRefresh Whether to force a check for new contact data
250
+ * @param limit Optional limit on number of contacts to fetch
250
251
  * @returns A promise that resolves with an array of contacts
251
252
  */
252
- public async getContacts (identityKey?: PubKeyHex, forceRefresh = false): Promise<Contact[]> {
253
- return await this.contactsManager.getContacts(identityKey, forceRefresh)
253
+ public async getContacts (identityKey?: PubKeyHex, forceRefresh = false, limit = 1000): Promise<Contact[]> {
254
+ return await this.contactsManager.getContacts(identityKey, forceRefresh, limit)
254
255
  }
255
256
 
256
257
  /**
@@ -54,7 +54,11 @@ jest.mock('../../script', () => {
54
54
  })
55
55
 
56
56
  return {
57
- PushDrop: mockPushDrop
57
+ PushDrop: mockPushDrop,
58
+ // Provide LockingScript.fromHex to satisfy ContactsManager.getContacts decode path
59
+ LockingScript: {
60
+ fromHex: jest.fn().mockImplementation((hex: string) => ({ toHex: () => hex }))
61
+ }
58
62
  }
59
63
  })
60
64
 
@@ -613,7 +617,8 @@ describe('IdentityClient', () => {
613
617
  it('should load contacts from wallet basket when cache is empty', async () => {
614
618
  const mockOutput = {
615
619
  outpoint: 'txid.0',
616
- customInstructions: JSON.stringify({ keyID: 'mockKeyID' })
620
+ customInstructions: JSON.stringify({ keyID: 'mockKeyID' }),
621
+ lockingScript: 'lockingScriptHex'
617
622
  }
618
623
 
619
624
  ; (walletMock.listOutputs as jest.Mock).mockResolvedValue({
@@ -630,9 +635,10 @@ describe('IdentityClient', () => {
630
635
  expect(result).toEqual([mockContact])
631
636
  expect(walletMock.listOutputs).toHaveBeenCalledWith({
632
637
  basket: 'contacts',
633
- include: 'entire transactions',
638
+ include: 'locking scripts',
634
639
  includeCustomInstructions: true,
635
- tags: []
640
+ tags: [],
641
+ limit: 1000
636
642
  })
637
643
 
638
644
  // Verify subsequent call uses cache
@@ -15,9 +15,11 @@ export interface DownloadResult {
15
15
 
16
16
  export class StorageDownloader {
17
17
  private readonly networkPreset?: 'mainnet' | 'testnet' | 'local' = 'mainnet'
18
+ private readonly lookupResolver: LookupResolver
18
19
 
19
20
  constructor (config?: DownloaderConfig) {
20
- this.networkPreset = config?.networkPreset
21
+ this.networkPreset = config?.networkPreset ?? 'mainnet'
22
+ this.lookupResolver = new LookupResolver({ networkPreset: this.networkPreset })
21
23
  }
22
24
 
23
25
  /**
@@ -27,8 +29,7 @@ export class StorageDownloader {
27
29
  */
28
30
  public async resolve (uhrpUrl: string): Promise<string[]> {
29
31
  // Use UHRP lookup service
30
- const lookupResolver = new LookupResolver({ networkPreset: this.networkPreset })
31
- const response = await lookupResolver.query({ service: 'ls_uhrp', query: { uhrpUrl } })
32
+ const response = await this.lookupResolver.query({ service: 'ls_uhrp', query: { uhrpUrl } })
32
33
  if (response.type !== 'output-list') {
33
34
  throw new Error('Lookup answer must be an output list')
34
35
  }
@@ -185,8 +185,7 @@ export class ProtoWallet {
185
185
  }
186
186
 
187
187
  async decrypt (
188
- args: WalletDecryptArgs
189
- ): Promise<WalletDecryptResult> {
188
+ args: WalletDecryptArgs, originator?: string): Promise<WalletDecryptResult> {
190
189
  if (this.keyDeriver == null) {
191
190
  throw new Error('keyDeriver is undefined')
192
191
  }