@avacuscc/sdk 0.1.0 → 0.2.1

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.
@@ -1,16 +1,188 @@
1
- import {
2
- AVACUS_ENDPOINTS,
3
- DEFAULT_BASE_SIGNED_MESSAGE,
4
- HttpAdapter,
5
- SNS_SERVICE_PATH,
6
- SnsAuthClient,
7
- SnsService,
8
- isKnownAvacusBaseUrl,
9
- loginWithSns,
10
- resolveAvacusBaseUrl,
11
- resolveClientSettings,
12
- resolveServiceUrl
13
- } from "./chunk-T5BAFYHX.mjs";
1
+ // packages/sdk/src/config.ts
2
+ var AVACUS_ENDPOINTS = {
3
+ prod: "https://apis.avacus.cc/",
4
+ dev: "https://apis.d.avscc.unit-hosting.net/",
5
+ stg: "https://apis.avacus.cc/stg/"
6
+ };
7
+ function resolveAvacusBaseUrl(options) {
8
+ if (options.baseUrl) {
9
+ return options.baseUrl;
10
+ }
11
+ return AVACUS_ENDPOINTS[options.env ?? "prod"];
12
+ }
13
+ function resolveClientSettings(options = {}) {
14
+ return {
15
+ env: options.env ?? "prod",
16
+ baseUrl: resolveAvacusBaseUrl(options),
17
+ headers: options.headers
18
+ };
19
+ }
20
+ function isKnownAvacusBaseUrl(baseUrl) {
21
+ return Object.values(AVACUS_ENDPOINTS).includes(baseUrl);
22
+ }
23
+ function resolveServiceUrl(baseUrl, servicePath) {
24
+ const normalizedServicePath = servicePath.endsWith("/") ? servicePath : `${servicePath}/`;
25
+ return new URL(normalizedServicePath, baseUrl).toString();
26
+ }
27
+
28
+ // packages/sdk/src/adapters/http.ts
29
+ var HttpAdapter = class {
30
+ /**
31
+ * Creates a reusable HTTP transport bound to one service base URL.
32
+ *
33
+ * @param baseUrl Absolute base URL for the target service namespace.
34
+ * @param headers Default headers sent with every request.
35
+ * @param authState Shared mutable auth state so multiple adapters can reuse the same JWT.
36
+ */
37
+ constructor(baseUrl, headers = {}, authState = {}) {
38
+ this.baseUrl = baseUrl;
39
+ this.headers = headers;
40
+ this.authState = authState;
41
+ }
42
+ baseUrl;
43
+ headers;
44
+ authState;
45
+ /**
46
+ * Stores the JWT access token used by authenticated requests.
47
+ *
48
+ * @param accessToken JWT returned by the authentication flow.
49
+ */
50
+ setAccessToken(accessToken) {
51
+ this.authState.accessToken = accessToken;
52
+ }
53
+ /**
54
+ * Removes the currently stored JWT access token from shared auth state.
55
+ */
56
+ clearAccessToken() {
57
+ delete this.authState.accessToken;
58
+ }
59
+ /**
60
+ * Returns the currently stored JWT access token, if any.
61
+ */
62
+ getAccessToken() {
63
+ return this.authState.accessToken;
64
+ }
65
+ /**
66
+ * Sends an HTTP GET request to a path relative to this adapter base URL.
67
+ *
68
+ * @param path Relative endpoint path.
69
+ * @param options Request behavior such as auth requirement and extra headers.
70
+ */
71
+ async get(path, options = {}) {
72
+ const response = await fetch(this.buildUrl(path), {
73
+ method: "GET",
74
+ headers: this.buildHeaders(options)
75
+ });
76
+ return this.parseResponse(response, "GET", path);
77
+ }
78
+ /**
79
+ * Sends an HTTP POST request with a JSON body to a path relative to this adapter base URL.
80
+ *
81
+ * @param path Relative endpoint path.
82
+ * @param body Serializable request payload.
83
+ * @param options Request behavior such as auth requirement and extra headers.
84
+ */
85
+ async post(path, body, options = {}) {
86
+ const response = await fetch(this.buildUrl(path), {
87
+ method: "POST",
88
+ headers: this.buildHeaders({
89
+ ...options,
90
+ headers: {
91
+ "Content-Type": "application/json",
92
+ ...options.headers
93
+ }
94
+ }),
95
+ body: body === void 0 ? void 0 : JSON.stringify(body)
96
+ });
97
+ return this.parseResponse(response, "POST", path);
98
+ }
99
+ /**
100
+ * Sends an HTTP PUT request with a JSON body to a path relative to this adapter base URL.
101
+ *
102
+ * @param path Relative endpoint path.
103
+ * @param body Serializable request payload.
104
+ * @param options Request behavior such as auth requirement and extra headers.
105
+ */
106
+ async put(path, body, options = {}) {
107
+ const response = await fetch(this.buildUrl(path), {
108
+ method: "PUT",
109
+ headers: this.buildHeaders({
110
+ ...options,
111
+ headers: {
112
+ "Content-Type": "application/json",
113
+ ...options.headers
114
+ }
115
+ }),
116
+ body: body === void 0 ? void 0 : JSON.stringify(body)
117
+ });
118
+ return this.parseResponse(response, "PUT", path);
119
+ }
120
+ /**
121
+ * Sends an HTTP DELETE request with an optional JSON body to a path relative to this adapter base URL.
122
+ *
123
+ * @param path Relative endpoint path.
124
+ * @param body Optional serializable request payload.
125
+ * @param options Request behavior such as auth requirement and extra headers.
126
+ */
127
+ async delete(path, body, options = {}) {
128
+ const headers = body === void 0 ? this.buildHeaders(options) : this.buildHeaders({
129
+ ...options,
130
+ headers: {
131
+ "Content-Type": "application/json",
132
+ ...options.headers
133
+ }
134
+ });
135
+ const response = await fetch(this.buildUrl(path), {
136
+ method: "DELETE",
137
+ headers,
138
+ body: body === void 0 ? void 0 : JSON.stringify(body)
139
+ });
140
+ return this.parseResponse(response, "DELETE", path);
141
+ }
142
+ /**
143
+ * Builds the final request headers by combining default headers, per-request
144
+ * headers, and an authorization header when the request requires auth.
145
+ */
146
+ buildHeaders(options) {
147
+ const accessToken = this.authState.accessToken;
148
+ if (options.auth && !accessToken) {
149
+ throw new Error("This request requires authentication. Call login() first.");
150
+ }
151
+ return {
152
+ ...this.headers,
153
+ ...options.headers,
154
+ ...options.auth && accessToken ? {
155
+ Authorization: `Bearer ${accessToken}`
156
+ } : {}
157
+ };
158
+ }
159
+ /**
160
+ * Resolves a relative path against the adapter base URL.
161
+ */
162
+ buildUrl(path) {
163
+ const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
164
+ return new URL(normalizedPath, this.baseUrl);
165
+ }
166
+ /**
167
+ * Parses a JSON response and converts non-2xx responses into descriptive errors.
168
+ */
169
+ async parseResponse(response, method, path) {
170
+ const bodyText = await response.text();
171
+ if (!response.ok) {
172
+ throw new Error(
173
+ `HTTP ${response.status} ${response.statusText} for ${method} ${path}: ${bodyText}`
174
+ );
175
+ }
176
+ try {
177
+ return JSON.parse(bodyText);
178
+ } catch (error) {
179
+ throw new Error(
180
+ `Invalid JSON response for ${method} ${path}: ${bodyText}`,
181
+ { cause: error }
182
+ );
183
+ }
184
+ }
185
+ };
14
186
 
15
187
  // packages/sdk/src/services/balancer.ts
16
188
  var BalancerService = class {
@@ -18,6 +190,14 @@ var BalancerService = class {
18
190
  this.http = http;
19
191
  }
20
192
  http;
193
+ /**
194
+ * Returns the list of balancer pools.
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * const pools = await client.balancer.getPools();
199
+ * ```
200
+ */
21
201
  async getPools() {
22
202
  return this.http.get("balancer/pools");
23
203
  }
@@ -25,6 +205,30 @@ var BalancerService = class {
25
205
 
26
206
  // packages/sdk/src/services/gasAccount.ts
27
207
  var GAS_ACCOUNT_SERVICE_PATH = "1/gas-account/";
208
+ var DEFAULT_REGISTER_WHITELIST_SPENDERS_VERSION = "1";
209
+ var REGISTER_WHITELIST_SPENDERS_TYPED_DATA = {
210
+ domain: {
211
+ name: "AvacusGasAccount"
212
+ },
213
+ types: {
214
+ SpenderEntry: [
215
+ { name: "address", type: "address" },
216
+ { name: "expiresAt", type: "uint256" }
217
+ ],
218
+ RegisterSpenders: [
219
+ { name: "owner", type: "address" },
220
+ { name: "spenders", type: "SpenderEntry[]" },
221
+ { name: "nonce", type: "uint256" },
222
+ { name: "deadline", type: "uint256" }
223
+ ]
224
+ },
225
+ primaryType: "RegisterSpenders"
226
+ };
227
+ function toMutableTypedDataTypes(types) {
228
+ return Object.fromEntries(
229
+ Object.entries(types).map(([key, fields]) => [key, [...fields]])
230
+ );
231
+ }
28
232
  var GasAccountService = class {
29
233
  /**
30
234
  * Creates the gas-account service using a service-scoped HTTP adapter.
@@ -38,19 +242,614 @@ var GasAccountService = class {
38
242
  /**
39
243
  * Returns the deposit vault address mapping keyed by chain ID.
40
244
  * Requires a JWT token from a successful SNS login.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * await client.sns.login({
249
+ * walletAddress,
250
+ * signMessage,
251
+ * });
252
+ *
253
+ * const vaults = await client.gasAccount.getDepositVaults();
254
+ * ```
41
255
  */
42
256
  async getDepositVaults() {
43
257
  return this.http.get("deposit_vaults", { auth: true });
44
258
  }
45
259
  /**
46
- * Returns the authenticated gas-account service status payload.
47
- * Requires a JWT token from a successful SNS login.
260
+ * Returns the authenticated user's gas account summary, including balances,
261
+ * recent transactions, and pending transactions.
262
+ *
263
+ * @example
264
+ * ```ts
265
+ * const summary = await client.gasAccount.getSummary();
266
+ * ```
267
+ */
268
+ async getSummary() {
269
+ return this.http.get("summary", { auth: true });
270
+ }
271
+ /**
272
+ * Returns supported stable tokens, optionally filtered by chain ID.
273
+ *
274
+ * @param chainId Optional network chain ID used to filter supported tokens.
275
+ *
276
+ * @example
277
+ * ```ts
278
+ * const tokens = await client.gasAccount.getStableTokens();
279
+ * const bscTestnetTokens = await client.gasAccount.getStableTokens(97);
280
+ * ```
281
+ */
282
+ async getStableTokens(chainId) {
283
+ const searchParams = new URLSearchParams();
284
+ if (chainId !== void 0) {
285
+ searchParams.set("chainId", String(chainId));
286
+ }
287
+ const path = searchParams.size > 0 ? `stable_tokens?${searchParams.toString()}` : "stable_tokens";
288
+ return this.http.get(path, { auth: true });
289
+ }
290
+ /**
291
+ * Returns the authenticated user's current whitelist spender entries and nonce.
292
+ *
293
+ * @example
294
+ * ```ts
295
+ * const whitelist = await client.gasAccount.getWhitelistSpenders();
296
+ * ```
297
+ */
298
+ async getWhitelistSpenders() {
299
+ return this.http.get("whitelist-spenders", { auth: true });
300
+ }
301
+ /**
302
+ * Adds or updates whitelist spender entries using a signed EIP-712 payload.
303
+ *
304
+ * @param params Spenders, signature, nonce, and deadline for registration.
305
+ *
306
+ * @example
307
+ * ```ts
308
+ * const { data } = await client.gasAccount.getWhitelistSpenders();
309
+ * const typedData = client.gasAccount.buildRegisterWhitelistSpendersTypedData({
310
+ * owner: wallet.address,
311
+ * spenders,
312
+ * nonce: data.nonce,
313
+ * deadline: Math.floor(Date.now() / 1000) + 600,
314
+ * });
315
+ *
316
+ * const signature = await wallet.signTypedData(
317
+ * typedData.domain,
318
+ * typedData.types,
319
+ * typedData.message,
320
+ * );
321
+ *
322
+ * await client.gasAccount.registerWhitelistSpenders({
323
+ * spenders,
324
+ * nonce: data.nonce,
325
+ * deadline: typedData.message.deadline,
326
+ * signature,
327
+ * });
328
+ * ```
329
+ */
330
+ async registerWhitelistSpenders(params) {
331
+ return this.http.post("whitelist-spenders", params, {
332
+ auth: true
333
+ });
334
+ }
335
+ /**
336
+ * Convenience helper that fetches the current whitelist nonce, builds the
337
+ * typed-data payload, asks the caller to sign it, and submits the request.
338
+ *
339
+ * @param params Owner address, spender entries, optional deadline, and a typed-data signer.
340
+ *
341
+ * @example
342
+ * ```ts
343
+ * await client.gasAccount.registerWhitelistSpendersWithSignature({
344
+ * owner: wallet.address,
345
+ * spenders,
346
+ * signTypedData: (typedData) =>
347
+ * wallet.signTypedData(
348
+ * typedData.domain,
349
+ * typedData.types,
350
+ * typedData.message,
351
+ * ),
352
+ * });
353
+ * ```
354
+ */
355
+ async registerWhitelistSpendersWithSignature(params) {
356
+ const { data } = await this.getWhitelistSpenders();
357
+ const nonce = data.nonce;
358
+ const deadline = params.deadline ?? Math.floor(Date.now() / 1e3) + 600;
359
+ const typedData = this.buildRegisterWhitelistSpendersTypedData({
360
+ owner: params.owner,
361
+ spenders: params.spenders,
362
+ version: params.version,
363
+ nonce,
364
+ deadline
365
+ });
366
+ const signature = await params.signTypedData(typedData);
367
+ return this.registerWhitelistSpenders({
368
+ spenders: params.spenders,
369
+ signature,
370
+ nonce,
371
+ deadline
372
+ });
373
+ }
374
+ /**
375
+ * Convenience helper for ethers-compatible signers.
376
+ *
377
+ * @param params Owner address, spender entries, optional domain version/deadline, and an ethers-compatible signer.
378
+ *
379
+ * @example
380
+ * ```ts
381
+ * await client.gasAccount.registerWhitelistSpendersWithEthers({
382
+ * owner: wallet.address,
383
+ * spenders,
384
+ * signer: wallet,
385
+ * });
386
+ * ```
387
+ */
388
+ async registerWhitelistSpendersWithEthers(params) {
389
+ return this.registerWhitelistSpendersWithSignature({
390
+ owner: params.owner,
391
+ spenders: params.spenders,
392
+ version: params.version,
393
+ deadline: params.deadline,
394
+ signTypedData: (typedData) => params.signer.signTypedData(
395
+ typedData.domain,
396
+ toMutableTypedDataTypes(typedData.types),
397
+ typedData.message
398
+ )
399
+ });
400
+ }
401
+ /**
402
+ * Builds the EIP-712 typed-data payload required by whitelist registration.
403
+ *
404
+ * @param params Owner, spenders, nonce, and deadline used in the signature payload.
405
+ *
406
+ * @example
407
+ * ```ts
408
+ * const typedData = client.gasAccount.buildRegisterWhitelistSpendersTypedData({
409
+ * owner: wallet.address,
410
+ * spenders,
411
+ * nonce: 0,
412
+ * deadline: Math.floor(Date.now() / 1000) + 600,
413
+ * });
414
+ * ```
415
+ */
416
+ buildRegisterWhitelistSpendersTypedData(params) {
417
+ return {
418
+ ...REGISTER_WHITELIST_SPENDERS_TYPED_DATA,
419
+ domain: {
420
+ ...REGISTER_WHITELIST_SPENDERS_TYPED_DATA.domain,
421
+ version: params.version ?? DEFAULT_REGISTER_WHITELIST_SPENDERS_VERSION
422
+ },
423
+ message: {
424
+ owner: params.owner,
425
+ spenders: params.spenders,
426
+ nonce: params.nonce,
427
+ deadline: params.deadline
428
+ }
429
+ };
430
+ }
431
+ /**
432
+ * Removes one or more whitelist spender addresses from the authenticated account.
433
+ *
434
+ * @param params Spender addresses to revoke.
435
+ *
436
+ * @example
437
+ * ```ts
438
+ * await client.gasAccount.removeWhitelistSpenders({
439
+ * spenders: ['0x9876543210987654321098765432109876543210'],
440
+ * });
441
+ * ```
442
+ */
443
+ async removeWhitelistSpenders(params) {
444
+ return this.http.delete("whitelist-spenders", params, {
445
+ auth: true
446
+ });
447
+ }
448
+ /**
449
+ * Returns the authenticated user's balance summary.
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * const balance = await client.gasAccount.getBalance();
454
+ * ```
48
455
  */
49
- async getStatus() {
50
- return this.http.get("status", { auth: true });
456
+ async getBalance() {
457
+ return this.http.get("gas-account-balance", { auth: true });
458
+ }
459
+ /**
460
+ * Returns the authenticated user's balance summary with pending transaction lists.
461
+ *
462
+ * @example
463
+ * ```ts
464
+ * const detailedBalance = await client.gasAccount.getDetailedBalance();
465
+ * ```
466
+ */
467
+ async getDetailedBalance() {
468
+ return this.http.get("gas-account-balance/detailed", {
469
+ auth: true
470
+ });
471
+ }
472
+ /**
473
+ * Returns balance statistics for the authenticated user's gas account.
474
+ *
475
+ * @example
476
+ * ```ts
477
+ * const stats = await client.gasAccount.getBalanceStats();
478
+ * ```
479
+ */
480
+ async getBalanceStats() {
481
+ return this.http.get("gas-account-balance/stats", {
482
+ auth: true
483
+ });
484
+ }
485
+ /**
486
+ * Returns balances for a batch of addresses through the public balances endpoint.
487
+ *
488
+ * @param params Address batch to query.
489
+ *
490
+ * @example
491
+ * ```ts
492
+ * const balances = await client.gasAccount.getBalances({
493
+ * addresses: [
494
+ * '0x3a0430580303f4De9C5320aC013f14cd92192bfA',
495
+ * '0x610b463d2f57d2e0d9e785a7ff423fbae36f0624',
496
+ * ],
497
+ * });
498
+ * ```
499
+ */
500
+ async getBalances(params) {
501
+ return this.http.put("gas-account-balance/balances", params);
502
+ }
503
+ /**
504
+ * Returns a paginated transaction list for the authenticated user's gas account.
505
+ *
506
+ * @param params Optional pagination and filter parameters.
507
+ *
508
+ * @example
509
+ * ```ts
510
+ * const transactions = await client.gasAccount.listTransactions({
511
+ * page: 1,
512
+ * per: 10,
513
+ * type: 'DEPOSIT',
514
+ * status: 'CONFIRMED',
515
+ * });
516
+ * ```
517
+ */
518
+ async listTransactions(params = {}) {
519
+ const searchParams = new URLSearchParams();
520
+ if (params.page !== void 0) {
521
+ searchParams.set("page", String(params.page));
522
+ }
523
+ if (params.per !== void 0) {
524
+ searchParams.set("per", String(params.per));
525
+ }
526
+ if (params.type) {
527
+ searchParams.set("type", params.type);
528
+ }
529
+ if (params.status) {
530
+ searchParams.set("status", params.status);
531
+ }
532
+ const path = searchParams.size > 0 ? `gas-account-transaction?${searchParams.toString()}` : "gas-account-transaction";
533
+ return this.http.get(path, { auth: true });
534
+ }
535
+ /**
536
+ * Returns detailed data for a specific transaction ID.
537
+ *
538
+ * @param transactionId Transaction UUID.
539
+ *
540
+ * @example
541
+ * ```ts
542
+ * const transaction = await client.gasAccount.getTransactionById(transactionId);
543
+ * ```
544
+ */
545
+ async getTransactionById(transactionId) {
546
+ return this.http.get(
547
+ `gas-account-transaction/${transactionId}`,
548
+ { auth: true }
549
+ );
550
+ }
551
+ /**
552
+ * Creates a pending deposit transaction for the authenticated user.
553
+ *
554
+ * @param params Deposit payload.
555
+ *
556
+ * @example
557
+ * ```ts
558
+ * await client.gasAccount.createDeposit({
559
+ * chainId: 97,
560
+ * amount: '100.00000000',
561
+ * tokenAddress: '0x5bF5121A17e3329D07Ba43f758dEC271D9105132',
562
+ * txHash: '0xe3844e7bc420b2d409058e6bf5534fdba69b917907d691abf65862654df749d7',
563
+ * actor: walletAddress,
564
+ * notes: 'Deposit from wallet',
565
+ * });
566
+ * ```
567
+ */
568
+ async createDeposit(params) {
569
+ return this.http.post("gas-account-transaction/deposit", params, {
570
+ auth: true
571
+ });
572
+ }
573
+ /**
574
+ * Creates a gas-usage request against the caller's balance or a whitelisted source address.
575
+ * When `sourceAddress` is provided, the caller spends from another owner's
576
+ * gas account and therefore must already be registered as a whitelist spender
577
+ * for that source account.
578
+ *
579
+ * @param params Usage request payload.
580
+ *
581
+ * @example
582
+ * ```ts
583
+ * await client.gasAccount.useBalance({
584
+ * toAddress: '0x9876543210987654321098765432109876543210',
585
+ * chainId: 97,
586
+ * gasLimit: 21000,
587
+ * gasPrice: 5,
588
+ * notes: 'Gas for token transfer',
589
+ * });
590
+ *
591
+ * await client.gasAccount.useBalance({
592
+ * toAddress: '0x9876543210987654321098765432109876543210',
593
+ * chainId: 97,
594
+ * gasLimit: 21000,
595
+ * gasPrice: 5,
596
+ * sourceAddress: '0x610b463d2f57d2e0d9e785a7ff423fbae36f0624',
597
+ * notes: 'Use gas from delegated source account',
598
+ * });
599
+ * ```
600
+ */
601
+ async useBalance(params) {
602
+ return this.http.post("gas-account-transaction/use-balance", params, {
603
+ auth: true
604
+ });
605
+ }
606
+ /**
607
+ * Creates a sponsored transfer request.
608
+ *
609
+ * @param params Sponsored transfer payload.
610
+ *
611
+ * @example
612
+ * ```ts
613
+ * await client.gasAccount.createSponsoredTransfer({
614
+ * transactions: [
615
+ * {
616
+ * tokenAddress: '0x409E7b65eF7B243529e3F97be2A122123c55DE63',
617
+ * from: '0x1234567890123456789012345678901234567890',
618
+ * to: '0x9876543210987654321098765432109876543210',
619
+ * value: '1000000000000000000',
620
+ * validBefore: 1735689600,
621
+ * validAfter: 0,
622
+ * nonce: '0x0000000000000000000000000000000000000000000000000000000000000001',
623
+ * signature: '0x...',
624
+ * },
625
+ * ],
626
+ * chainId: 97,
627
+ * type: 'ADMIN',
628
+ * notes: 'JPYC transfer sponsorship',
629
+ * });
630
+ * ```
631
+ */
632
+ async createSponsoredTransfer(params) {
633
+ return this.http.post(
634
+ "gas-account-transaction/sponsored-transfers",
635
+ params,
636
+ { auth: true }
637
+ );
638
+ }
639
+ /**
640
+ * Cancels a pending gas-account transaction that has not yet been broadcast.
641
+ *
642
+ * @param transactionId Transaction UUID.
643
+ *
644
+ * @example
645
+ * ```ts
646
+ * await client.gasAccount.cancelTransaction(transactionId);
647
+ * ```
648
+ */
649
+ async cancelTransaction(transactionId) {
650
+ return this.http.put(
651
+ `gas-account-transaction/${transactionId}/cancel`,
652
+ void 0,
653
+ { auth: true }
654
+ );
655
+ }
656
+ /**
657
+ * Creates an internal funding request on behalf of another service.
658
+ *
659
+ * @param params Funding request payload.
660
+ *
661
+ * @example
662
+ * ```ts
663
+ * await client.gasAccount.createFundingRequest({
664
+ * sourceAddress: '0x610b463d2f57d2e0d9e785a7ff423fbae36f0624',
665
+ * toAddress: '0x9876543210987654321098765432109876543210',
666
+ * chainId: 97,
667
+ * gasLimit: 21000,
668
+ * gasPrice: 5,
669
+ * notes: 'Gas for token transfer',
670
+ * });
671
+ * ```
672
+ */
673
+ async createFundingRequest(params) {
674
+ return this.http.post(
675
+ "internal/gas-account-transaction/funding-requests",
676
+ params
677
+ );
51
678
  }
52
679
  };
53
680
 
681
+ // packages/sdk/src/services/sns.ts
682
+ var DEFAULT_BASE_SIGNED_MESSAGE = "Hi there from Avacus Wallet! Please sign this message to prove that you can access to secure chat. To stop hackers access to your secure chat, do not sign this message outside Avacus Wallet, and here's a unique message ID they can't guess: ";
683
+ var BASE_CONNECT_SIGNED_MSG = "Hi there from Avacus Connect! Please sign this message to prove that you can access our service. For security reasons, do not sign this message outside Avacus Connect, and here's a unique message ID they can't guess: ";
684
+ var BASE_REDIRECT_SIGNED_MSG = "Hi there from Avacus Redirect! Please sign this message to prove that you can access our service. For security reasons, do not sign this message outside Avacus Redirect, and here's a unique message ID they can't guess: ";
685
+ var BASE_GAS_SPONSOR_SIGNED_MSG = "Hi there from Avacus Gas Sponsor! Please sign this message to prove that you can access our service. For security reasons, do not sign this message outside Avacus Gas Sponsor, and here's a unique message ID they can't guess: ";
686
+ var BASE_SIGNED_MESSAGE_BY_SERVICE = {
687
+ connect: BASE_CONNECT_SIGNED_MSG,
688
+ redirect: BASE_REDIRECT_SIGNED_MSG,
689
+ "gas-sponsor": BASE_GAS_SPONSOR_SIGNED_MSG
690
+ };
691
+ var SNS_SERVICE_PATH = "1/secure-chat/";
692
+ var SnsService = class {
693
+ /**
694
+ * Creates the SNS service using a service-scoped HTTP adapter.
695
+ *
696
+ * @param http Adapter already configured for the SNS base path.
697
+ * @param options Optional SNS-specific behavior.
698
+ */
699
+ constructor(http, options = {}) {
700
+ this.http = http;
701
+ this.options = options;
702
+ }
703
+ http;
704
+ options;
705
+ /**
706
+ * Requests a one-time nonce used to construct the login signature message.
707
+ * This endpoint is public and does not require a JWT token.
708
+ *
709
+ * @param params Wallet identity used by the backend to mint a nonce.
710
+ */
711
+ async getNonce(params) {
712
+ const searchParams = new URLSearchParams({
713
+ wallet_address: params.walletAddress
714
+ });
715
+ return this.http.get(`v1/public/users/nonce?${searchParams.toString()}`);
716
+ }
717
+ /**
718
+ * Exchanges a signed message payload for an SNS auth token.
719
+ * This is the low-level authentication endpoint behind `login()`.
720
+ *
721
+ * @param params Payload expected by the SNS auth API.
722
+ */
723
+ async requestAuthToken(params) {
724
+ return this.http.post("v2/public/users/request_auth_token", params);
725
+ }
726
+ /**
727
+ * Returns public user profiles for a batch of wallet addresses and/or user IDs.
728
+ * This endpoint is public and does not require authentication.
729
+ *
730
+ * @param params Query payload with wallet addresses and/or user IDs.
731
+ */
732
+ async getPublicProfiles(params) {
733
+ return this.http.post("v1/public/users/profiles", {
734
+ wallets: params.wallets,
735
+ user_ids: params.userIds,
736
+ include_devices: params.includeDevices
737
+ });
738
+ }
739
+ /**
740
+ * Creates a new SNS user account using only the inputs the application already knows:
741
+ * wallet address, signer callback, and optional user profile metadata.
742
+ * The SDK internally fetches a nonce, builds the canonical message, requests
743
+ * the signature, and submits the create-user payload.
744
+ *
745
+ * @param params User creation payload in SDK-friendly camelCase format.
746
+ */
747
+ async createUser(params) {
748
+ const { walletAddress, signMessage } = params;
749
+ const { nonce } = await this.getNonce({ walletAddress });
750
+ const message = this.buildLoginMessage(nonce);
751
+ const signature = await signMessage(message);
752
+ return this.createUserWithSignature({
753
+ walletAddress,
754
+ message,
755
+ signature,
756
+ publicKey: params.publicKey,
757
+ displayName: params.displayName,
758
+ description: params.description,
759
+ device: params.device
760
+ });
761
+ }
762
+ /**
763
+ * Low-level create-user API for callers that already have a prepared message
764
+ * and signature and want direct control over the exact payload.
765
+ *
766
+ * @param params Signed create-user payload.
767
+ */
768
+ async createUserWithSignature(params) {
769
+ const result = await this.http.post(
770
+ "v1/public/users",
771
+ {
772
+ wallet_address: params.walletAddress,
773
+ message: params.message,
774
+ signature: params.signature,
775
+ public_key: params.publicKey,
776
+ display_name: params.displayName,
777
+ description: params.description,
778
+ device: params.device ? {
779
+ device_token: params.device.deviceToken,
780
+ app_name: params.device.appName,
781
+ app_version: params.device.appVersion,
782
+ platform: params.device.platform
783
+ } : void 0
784
+ }
785
+ );
786
+ const accessToken = extractAccessToken(result);
787
+ if (accessToken) {
788
+ this.http.setAccessToken(accessToken);
789
+ }
790
+ return result;
791
+ }
792
+ /**
793
+ * Adapts camelCase SDK parameters to the snake_case payload expected by the backend.
794
+ *
795
+ * @param params Wallet address, signed message, and signature returned by the signer.
796
+ */
797
+ async authenticate(params) {
798
+ return this.requestAuthToken({
799
+ wallet_address: params.walletAddress,
800
+ message: params.message,
801
+ signature: params.signature,
802
+ service_name: params.serviceName
803
+ });
804
+ }
805
+ /**
806
+ * Executes the full SNS login flow:
807
+ * 1. fetch nonce
808
+ * 2. build login message
809
+ * 3. sign message via injected signer callback
810
+ * 4. exchange signature for JWT
811
+ * 5. persist token in shared HTTP auth state
812
+ *
813
+ * @param params Wallet address and async signing callback.
814
+ */
815
+ async login(params) {
816
+ const { walletAddress, signMessage, serviceName } = params;
817
+ const { nonce } = await this.getNonce({ walletAddress });
818
+ const message = this.buildLoginMessage(nonce, serviceName);
819
+ const signature = await signMessage(message);
820
+ const result = await this.authenticate({
821
+ walletAddress,
822
+ message,
823
+ signature,
824
+ serviceName
825
+ });
826
+ const accessToken = extractAccessToken(result);
827
+ if (accessToken) {
828
+ this.http.setAccessToken(accessToken);
829
+ }
830
+ return result;
831
+ }
832
+ /**
833
+ * Builds the exact message string that the wallet must sign during login.
834
+ */
835
+ buildLoginMessage(nonce, serviceName) {
836
+ const baseMessage = serviceName != null ? BASE_SIGNED_MESSAGE_BY_SERVICE[serviceName] : this.options.baseSignedMessage ?? DEFAULT_BASE_SIGNED_MESSAGE;
837
+ return `${baseMessage}${nonce}`;
838
+ }
839
+ };
840
+ function extractAccessToken(result) {
841
+ if ("data" in result && typeof result.data === "object" && result.data !== null) {
842
+ const token = result.data.token;
843
+ if (typeof token === "string" && token.length > 0) {
844
+ return token;
845
+ }
846
+ }
847
+ return void 0;
848
+ }
849
+ async function loginWithSns(sns, params) {
850
+ return sns.login(params);
851
+ }
852
+
54
853
  // packages/sdk/src/core/client.ts
55
854
  var AvacusClient = class {
56
855
  http;
@@ -85,14 +884,41 @@ var AvacusClient = class {
85
884
  this.balancer = new BalancerService(this.http);
86
885
  }
87
886
  };
887
+
888
+ // packages/sdk/src/sns.ts
889
+ var SnsAuthClient = class extends SnsService {
890
+ settings;
891
+ usingCustomBaseUrl;
892
+ constructor(options = {}) {
893
+ const settings = resolveClientSettings(options);
894
+ const http = new HttpAdapter(
895
+ resolveServiceUrl(settings.baseUrl, "1/secure-chat/"),
896
+ settings.headers
897
+ );
898
+ super(http, {
899
+ baseSignedMessage: options.baseSignedMessage
900
+ });
901
+ this.settings = settings;
902
+ this.usingCustomBaseUrl = !isKnownAvacusBaseUrl(settings.baseUrl);
903
+ }
904
+ getSettings() {
905
+ return { ...this.settings };
906
+ }
907
+ isUsingCustomBaseUrl() {
908
+ return this.usingCustomBaseUrl;
909
+ }
910
+ };
88
911
  export {
89
912
  AVACUS_ENDPOINTS,
90
913
  AvacusClient,
914
+ BASE_CONNECT_SIGNED_MSG,
915
+ BASE_GAS_SPONSOR_SIGNED_MSG,
916
+ BASE_REDIRECT_SIGNED_MSG,
91
917
  BalancerService,
92
918
  DEFAULT_BASE_SIGNED_MESSAGE,
919
+ DEFAULT_REGISTER_WHITELIST_SPENDERS_VERSION,
93
920
  GAS_ACCOUNT_SERVICE_PATH,
94
921
  GasAccountService,
95
- HttpAdapter,
96
922
  SNS_SERVICE_PATH,
97
923
  SnsAuthClient,
98
924
  SnsService,