@branta-ops/branta 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,6 +18,7 @@ import { V2BrantaClient, BrantaServerBaseUrl } from "@branta-ops/branta";
18
18
 
19
19
  const client = new V2BrantaClient({
20
20
  baseUrl: BrantaServerBaseUrl.Production,
21
+ privacy: 'loose',
21
22
  });
22
23
 
23
24
  await client.getPayments("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
@@ -31,6 +32,7 @@ import { V2BrantaClient, BrantaServerBaseUrl } from "@branta-ops/branta";
31
32
  const client = new V2BrantaClient({
32
33
  baseUrl: BrantaServerBaseUrl.Production,
33
34
  defaultApiKey: "<default-api-key>",
35
+ privacy: 'loose',
34
36
  });
35
37
 
36
38
  await client.addPayment({
@@ -54,6 +56,7 @@ const client = new V2BrantaClient({
54
56
  baseUrl: BrantaServerBaseUrl.Production,
55
57
  defaultApiKey: "<default-api-key>",
56
58
  hmacSecret: "<hmac-secret>",
59
+ privacy: 'loose',
57
60
  });
58
61
 
59
62
  await client.addPayment({
@@ -68,6 +71,11 @@ await client.addPayment({
68
71
  });
69
72
  ```
70
73
 
74
+ ## Release
75
+ - npm login
76
+ - npm version major|minor|patch
77
+ - npm publish
78
+
71
79
  ## Feature Support
72
80
 
73
81
  - [X] Per Environment configuration
@@ -1,7 +1,22 @@
1
1
  import { ServerEnvironment } from "./brantaServerBaseUrl.js";
2
+ /**
3
+ * Controls the privacy posture for on-chain address lookups.
4
+ *
5
+ * - `'strict'` — Only ZK (zero-knowledge / encrypted) on-chain lookups are
6
+ * permitted. Calling `getPayments` directly will throw a
7
+ * `BrantaPaymentException`; plain-address branches inside
8
+ * `getPaymentByQrCode` will silently return `[]`. Lightning invoices and
9
+ * all POST operations are unaffected by this setting.
10
+ *
11
+ * - `'loose'` — Both plain and ZK on-chain lookups are allowed. No
12
+ * restrictions are enforced.
13
+ */
14
+ export type PrivacyMode = 'strict' | 'loose';
2
15
  export default interface BrantaClientOptions {
3
16
  baseUrl?: ServerEnvironment | string | null;
4
17
  defaultApiKey?: string | null;
5
18
  hmacSecret?: string | null;
6
19
  timeout?: number;
20
+ /** @see {@link PrivacyMode} */
21
+ privacy: PrivacyMode;
7
22
  }
@@ -11,7 +11,9 @@ export interface Payment {
11
11
  description?: string;
12
12
  metadata?: Record<string, string>;
13
13
  verifyUrl?: string;
14
+ platform?: string;
14
15
  platformLogoUrl?: string;
16
+ platformLogoLightUrl?: string;
15
17
  }
16
18
  interface PaymentResponse extends Payment {
17
19
  createdAt: Date;
@@ -28,10 +30,12 @@ export declare class V2BrantaClient {
28
30
  private _defaultOptions;
29
31
  constructor(brantaClientOptions: BrantaClientOptions);
30
32
  getPayments(address: string, options?: BrantaClientOptions | null): Promise<Payment[]>;
33
+ private _fetchPayments;
31
34
  getZKPayment(address: string, secret: string, options?: BrantaClientOptions | null): Promise<Payment[]>;
32
35
  addPayment(payment: Payment, options?: BrantaClientOptions | null): Promise<PaymentResult>;
33
36
  addZKPayment(payment: Payment, options?: BrantaClientOptions | null): Promise<ZKPaymentResult>;
34
37
  getPaymentsByQRCode(qrText: string, options?: BrantaClientOptions | null): Promise<Payment[]>;
38
+ private _getPlainPayments;
35
39
  isApiKeyValid(options?: BrantaClientOptions | null): Promise<boolean>;
36
40
  private _buildVerifyUrl;
37
41
  private _resolveBaseUrl;
package/dist/v2/client.js CHANGED
@@ -5,15 +5,23 @@ export class V2BrantaClient {
5
5
  this._defaultOptions = brantaClientOptions;
6
6
  }
7
7
  async getPayments(address, options = null) {
8
+ const privacy = options?.privacy ?? this._defaultOptions?.privacy;
9
+ if (privacy === 'strict') {
10
+ throw new BrantaPaymentException("privacy is set to 'strict': plain on-chain address lookups are not permitted");
11
+ }
12
+ return this._fetchPayments(address, options);
13
+ }
14
+ async _fetchPayments(address, options = null) {
8
15
  const httpClient = this._createClient(options);
9
16
  const response = await httpClient.get(`/v2/payments/${encodeURIComponent(address)}`);
10
17
  if (!response.ok || response.headers.get("content-length") === "0") {
11
18
  return [];
12
19
  }
13
20
  const raw = await response.json();
14
- const data = raw.map(({ platform_logo_url: platformLogoUrl, verify_url: verifyUrl, ...rest }) => ({
21
+ const data = raw.map(({ platform_logo_url: platformLogoUrl, platform_logo_light_url: platformLogoLightUrl, verify_url: verifyUrl, ...rest }) => ({
15
22
  ...rest,
16
23
  platformLogoUrl,
24
+ platformLogoLightUrl,
17
25
  verifyUrl,
18
26
  }));
19
27
  const baseUrl = this._resolveBaseUrl(options);
@@ -29,11 +37,20 @@ export class V2BrantaClient {
29
37
  if (!valid)
30
38
  throw new BrantaPaymentException("platformLogoUrl domain does not match the configured baseUrl domain");
31
39
  }
40
+ if (payment.platformLogoLightUrl) {
41
+ let valid = false;
42
+ try {
43
+ valid = new URL(payment.platformLogoLightUrl).origin === baseOrigin;
44
+ }
45
+ catch { /* invalid URL */ }
46
+ if (!valid)
47
+ throw new BrantaPaymentException("platformLogoLightUrl domain does not match the configured baseUrl domain");
48
+ }
32
49
  }
33
50
  return data;
34
51
  }
35
52
  async getZKPayment(address, secret, options = null) {
36
- const payments = await this.getPayments(address, options);
53
+ const payments = await this._fetchPayments(address, options);
37
54
  for (const payment of payments) {
38
55
  for (const destination of payment?.destinations || []) {
39
56
  if (destination.zk === false)
@@ -81,38 +98,44 @@ export class V2BrantaClient {
81
98
  url = new URL(text);
82
99
  }
83
100
  catch { /* not a URL */ }
84
- if (url) {
85
- const rawParams = new URLSearchParams(url.search.replace(/\+/g, '%2B'));
86
- const brantaId = rawParams.get('branta_id');
87
- const brantaSecret = rawParams.get('branta_secret');
88
- if (brantaId && brantaSecret) {
89
- return this.getZKPayment(brantaId, brantaSecret, options);
90
- }
91
- if (url.protocol === 'bitcoin:') {
92
- return this.getPayments(this._normalizeAddress(url.pathname), options);
101
+ if (!url)
102
+ return this._getPlainPayments(this._normalizeAddress(text), options);
103
+ const rawParams = new URLSearchParams(url.search.replace(/\+/g, '%2B'));
104
+ const brantaId = rawParams.get('branta_id');
105
+ const brantaSecret = rawParams.get('branta_secret');
106
+ if (brantaId && brantaSecret)
107
+ return this.getZKPayment(brantaId, brantaSecret, options);
108
+ if (url.protocol === 'bitcoin:') {
109
+ return this._getPlainPayments(this._normalizeAddress(url.pathname), options);
110
+ }
111
+ if (url.protocol === 'http:' || url.protocol === 'https:') {
112
+ const baseUrl = this._resolveBaseUrl(options);
113
+ if (!baseUrl || new URL(baseUrl).origin !== url.origin) {
114
+ return this._getPlainPayments(this._normalizeAddress(text), options);
93
115
  }
94
- if (url.protocol === 'http:' || url.protocol === 'https:') {
95
- const baseUrl = this._resolveBaseUrl(options);
96
- if (baseUrl && new URL(baseUrl).origin === url.origin) {
97
- const segments = url.pathname.split('/').filter(Boolean).map(decodeURIComponent);
98
- const [version, type, id] = segments;
99
- if (version === 'v2' && id) {
100
- if (type === 'verify')
101
- return this.getPayments(id, options);
102
- if (type === 'zk-verify') {
103
- const secret = new URLSearchParams(url.hash.slice(1)).get('secret');
104
- return secret
105
- ? this.getZKPayment(id, secret, options)
106
- : this.getPayments(id, options);
107
- }
108
- }
109
- const lastSegment = segments.at(-1);
110
- if (lastSegment)
111
- return this.getPayments(lastSegment, options);
116
+ const segments = url.pathname.split('/').filter(Boolean).map(decodeURIComponent);
117
+ const [version, type, id] = segments;
118
+ if (version === 'v2' && id) {
119
+ if (type === 'verify')
120
+ return this._getPlainPayments(id, options);
121
+ if (type === 'zk-verify') {
122
+ const secret = new URLSearchParams(url.hash.slice(1)).get('secret');
123
+ if (secret)
124
+ return this.getZKPayment(id, secret, options);
125
+ return this._getPlainPayments(id, options);
112
126
  }
113
127
  }
128
+ const lastSegment = segments.at(-1);
129
+ if (lastSegment)
130
+ return this._getPlainPayments(lastSegment, options);
114
131
  }
115
- return this.getPayments(this._normalizeAddress(text), options);
132
+ return this._getPlainPayments(this._normalizeAddress(text), options);
133
+ }
134
+ _getPlainPayments(address, options) {
135
+ const privacy = options?.privacy ?? this._defaultOptions?.privacy;
136
+ if (privacy === 'strict')
137
+ return Promise.resolve([]);
138
+ return this.getPayments(address, options);
116
139
  }
117
140
  async isApiKeyValid(options = null) {
118
141
  const httpClient = this._createClient(options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@branta-ops/branta",
3
- "version": "1.0.1",
3
+ "version": "2.0.0",
4
4
  "description": "A JavaScript SDK for the Branta API",
5
5
  "homepage": "https://github.com/BrantaOps/branta-js#readme",
6
6
  "bugs": {
@@ -1,11 +0,0 @@
1
- export interface ServerEnvironment {
2
- value: number;
3
- url: string;
4
- }
5
- export interface BrantaServerBaseUrlType {
6
- Staging: ServerEnvironment;
7
- Production: ServerEnvironment;
8
- Localhost: ServerEnvironment;
9
- }
10
- declare const BrantaServerBaseUrl: BrantaServerBaseUrlType;
11
- export default BrantaServerBaseUrl;
@@ -1,6 +0,0 @@
1
- const BrantaServerBaseUrl = {
2
- Staging: { value: 0, url: "https://staging.guardrail.branta.pro" },
3
- Production: { value: 1, url: "https://guardrail.branta.pro" },
4
- Localhost: { value: 2, url: "http://localhost:3000" },
5
- };
6
- export default BrantaServerBaseUrl;