@avacuscc/sdk 0.1.0 → 0.2.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
@@ -72,9 +72,29 @@ const client = new AvacusClient();
72
72
  const result = await client.sns.login({
73
73
  walletAddress,
74
74
  signMessage,
75
+ serviceName: 'connect', // optional: 'connect' | 'redirect' | 'gas-sponsor'
75
76
  });
77
+
78
+ `client.sns.login()` now uses `POST /v2/public/users/request_auth_token` and,
79
+ when `serviceName` is provided, builds the signed message with the matching base
80
+ message:
81
+
82
+ - omitted `serviceName`: Avacus Wallet message (`DEFAULT_BASE_SIGNED_MESSAGE`)
83
+ - `connect`: `BASE_CONNECT_SIGNED_MSG`
84
+ - `redirect`: `BASE_REDIRECT_SIGNED_MSG`
85
+ - `gas-sponsor`: `BASE_GAS_SPONSOR_SIGNED_MSG`
76
86
  ```
77
87
 
88
+ ## Services
89
+
90
+ `AvacusClient` exposes these service clients:
91
+
92
+ - `client.sns`
93
+ - `client.gasAccount`
94
+ - `client.balancer`
95
+
96
+ Most `gasAccount` APIs require a JWT token from `client.sns.login()` first.
97
+
78
98
  ### SNS create user
79
99
 
80
100
  ```ts
@@ -118,6 +138,232 @@ const profiles = await client.sns.getPublicProfiles({
118
138
  });
119
139
  ```
120
140
 
141
+ ## Gas Account service
142
+
143
+ ### Gas Account login prerequisite
144
+
145
+ Authenticated gas-account APIs require SNS login first:
146
+
147
+ ```ts
148
+ await client.sns.login({
149
+ walletAddress,
150
+ signMessage,
151
+ });
152
+ ```
153
+
154
+ ### Gas Account summary
155
+
156
+ ```ts
157
+ const summary = await client.gasAccount.getSummary();
158
+ ```
159
+
160
+ ### Gas Account stable tokens
161
+
162
+ ```ts
163
+ const tokens = await client.gasAccount.getStableTokens();
164
+ const bscTestnetTokens = await client.gasAccount.getStableTokens(97);
165
+ ```
166
+
167
+ ### Gas Account deposit vaults
168
+
169
+ ```ts
170
+ const vaults = await client.gasAccount.getDepositVaults();
171
+ ```
172
+
173
+ ### Gas Account whitelist spenders
174
+
175
+ Get current whitelist and nonce:
176
+
177
+ ```ts
178
+ const whitelist = await client.gasAccount.getWhitelistSpenders();
179
+ ```
180
+
181
+ Recommended helper for register flow:
182
+
183
+ ```ts
184
+ await client.gasAccount.registerWhitelistSpendersWithEthers({
185
+ owner: wallet.address,
186
+ spenders: [
187
+ {
188
+ address: '0x9876543210987654321098765432109876543210',
189
+ expiresAt: 0,
190
+ },
191
+ ],
192
+ signer: wallet,
193
+ });
194
+ ```
195
+
196
+ Generic signer helper when you do not want to couple app code to `ethers`:
197
+
198
+ ```ts
199
+ await client.gasAccount.registerWhitelistSpendersWithSignature({
200
+ owner: wallet.address,
201
+ spenders: [
202
+ {
203
+ address: '0x9876543210987654321098765432109876543210',
204
+ expiresAt: 0,
205
+ },
206
+ ],
207
+ signTypedData: (typedData) =>
208
+ wallet.signTypedData(
209
+ typedData.domain,
210
+ typedData.types,
211
+ typedData.message,
212
+ ),
213
+ });
214
+ ```
215
+
216
+ Low-level flow when you want full control:
217
+
218
+ ```ts
219
+ const { data } = await client.gasAccount.getWhitelistSpenders();
220
+
221
+ const typedData = client.gasAccount.buildRegisterWhitelistSpendersTypedData({
222
+ owner: wallet.address,
223
+ spenders: [
224
+ {
225
+ address: '0x9876543210987654321098765432109876543210',
226
+ expiresAt: 0,
227
+ },
228
+ ],
229
+ nonce: data.nonce,
230
+ deadline: Math.floor(Date.now() / 1000) + 600,
231
+ });
232
+
233
+ const signature = await wallet.signTypedData(
234
+ typedData.domain,
235
+ typedData.types,
236
+ typedData.message,
237
+ );
238
+
239
+ await client.gasAccount.registerWhitelistSpenders({
240
+ spenders: typedData.message.spenders,
241
+ nonce: typedData.message.nonce,
242
+ deadline: typedData.message.deadline,
243
+ signature,
244
+ });
245
+ ```
246
+
247
+ Remove spenders:
248
+
249
+ ```ts
250
+ await client.gasAccount.removeWhitelistSpenders({
251
+ spenders: ['0x9876543210987654321098765432109876543210'],
252
+ });
253
+ ```
254
+
255
+ ### Gas Account balances
256
+
257
+ ```ts
258
+ const balance = await client.gasAccount.getBalance();
259
+ const detailedBalance = await client.gasAccount.getDetailedBalance();
260
+ const stats = await client.gasAccount.getBalanceStats();
261
+ ```
262
+
263
+ Public batch balances:
264
+
265
+ ```ts
266
+ const balances = await client.gasAccount.getBalances({
267
+ addresses: [
268
+ '0x3a0430580303f4De9C5320aC013f14cd92192bfA',
269
+ '0x610b463d2f57d2e0d9e785a7ff423fbae36f0624',
270
+ ],
271
+ });
272
+ ```
273
+
274
+ ### Gas Account transactions
275
+
276
+ List transactions:
277
+
278
+ ```ts
279
+ const transactions = await client.gasAccount.listTransactions({
280
+ page: 1,
281
+ per: 10,
282
+ type: 'DEPOSIT',
283
+ status: 'CONFIRMED',
284
+ });
285
+ ```
286
+
287
+ Get transaction by ID:
288
+
289
+ ```ts
290
+ const transaction = await client.gasAccount.getTransactionById(transactionId);
291
+ ```
292
+
293
+ Create deposit:
294
+
295
+ ```ts
296
+ await client.gasAccount.createDeposit({
297
+ chainId: 97,
298
+ amount: '100.00000000',
299
+ tokenAddress: '0x5bF5121A17e3329D07Ba43f758dEC271D9105132',
300
+ txHash: '0xe3844e7bc420b2d409058e6bf5534fdba69b917907d691abf65862654df749d7',
301
+ actor: walletAddress,
302
+ notes: 'Deposit from wallet',
303
+ });
304
+ ```
305
+
306
+ Use balance for gas:
307
+
308
+ ```ts
309
+ await client.gasAccount.useBalance({
310
+ toAddress: '0x9876543210987654321098765432109876543210',
311
+ chainId: 97,
312
+ gasLimit: 21000,
313
+ gasPrice: 5,
314
+ notes: 'Gas for token transfer',
315
+ });
316
+ ```
317
+
318
+ Create sponsored transfer:
319
+
320
+ ```ts
321
+ await client.gasAccount.createSponsoredTransfer({
322
+ transactions: [
323
+ {
324
+ tokenAddress: '0x409E7b65eF7B243529e3F97be2A122123c55DE63',
325
+ from: '0x1234567890123456789012345678901234567890',
326
+ to: '0x9876543210987654321098765432109876543210',
327
+ value: '1000000000000000000',
328
+ validBefore: 1735689600,
329
+ validAfter: 0,
330
+ nonce: '0x0000000000000000000000000000000000000000000000000000000000000001',
331
+ signature: '0x...',
332
+ },
333
+ ],
334
+ chainId: 97,
335
+ type: 'ADMIN',
336
+ notes: 'JPYC transfer sponsorship',
337
+ });
338
+ ```
339
+
340
+ Cancel pending transaction:
341
+
342
+ ```ts
343
+ await client.gasAccount.cancelTransaction(transactionId);
344
+ ```
345
+
346
+ Internal funding request:
347
+
348
+ ```ts
349
+ await client.gasAccount.createFundingRequest({
350
+ sourceAddress: '0x610b463d2f57d2e0d9e785a7ff423fbae36f0624',
351
+ toAddress: '0x9876543210987654321098765432109876543210',
352
+ chainId: 97,
353
+ gasLimit: 21000,
354
+ gasPrice: 5,
355
+ notes: 'Gas for token transfer',
356
+ });
357
+ ```
358
+
359
+ ## Balancer service
360
+
361
+ ### Get balancer pools
362
+
363
+ ```ts
364
+ const pools = await client.balancer.getPools();
365
+ ```
366
+
121
367
  ### SNS-only import
122
368
 
123
369
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avacuscc/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "SDK for interacting with services in the Wakumo ecosystem",
5
5
  "main": "./packages/sdk/dist/index.js",
6
6
  "module": "./packages/sdk/dist/index.mjs",
@@ -69,6 +69,49 @@ var HttpAdapter = class {
69
69
  });
70
70
  return this.parseResponse(response, "POST", path);
71
71
  }
72
+ /**
73
+ * Sends an HTTP PUT request with a JSON body to a path relative to this adapter base URL.
74
+ *
75
+ * @param path Relative endpoint path.
76
+ * @param body Serializable request payload.
77
+ * @param options Request behavior such as auth requirement and extra headers.
78
+ */
79
+ async put(path, body, options = {}) {
80
+ const response = await fetch(this.buildUrl(path), {
81
+ method: "PUT",
82
+ headers: this.buildHeaders({
83
+ ...options,
84
+ headers: {
85
+ "Content-Type": "application/json",
86
+ ...options.headers
87
+ }
88
+ }),
89
+ body: body === void 0 ? void 0 : JSON.stringify(body)
90
+ });
91
+ return this.parseResponse(response, "PUT", path);
92
+ }
93
+ /**
94
+ * Sends an HTTP DELETE request with an optional JSON body to a path relative to this adapter base URL.
95
+ *
96
+ * @param path Relative endpoint path.
97
+ * @param body Optional serializable request payload.
98
+ * @param options Request behavior such as auth requirement and extra headers.
99
+ */
100
+ async delete(path, body, options = {}) {
101
+ const headers = body === void 0 ? this.buildHeaders(options) : this.buildHeaders({
102
+ ...options,
103
+ headers: {
104
+ "Content-Type": "application/json",
105
+ ...options.headers
106
+ }
107
+ });
108
+ const response = await fetch(this.buildUrl(path), {
109
+ method: "DELETE",
110
+ headers,
111
+ body: body === void 0 ? void 0 : JSON.stringify(body)
112
+ });
113
+ return this.parseResponse(response, "DELETE", path);
114
+ }
72
115
  /**
73
116
  * Builds the final request headers by combining default headers, per-request
74
117
  * headers, and an authorization header when the request requires auth.
@@ -143,6 +186,14 @@ function resolveServiceUrl(baseUrl, servicePath) {
143
186
 
144
187
  // packages/sdk/src/services/sns.ts
145
188
  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: ";
189
+ 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: ";
190
+ 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: ";
191
+ 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: ";
192
+ var BASE_SIGNED_MESSAGE_BY_SERVICE = {
193
+ connect: BASE_CONNECT_SIGNED_MSG,
194
+ redirect: BASE_REDIRECT_SIGNED_MSG,
195
+ "gas-sponsor": BASE_GAS_SPONSOR_SIGNED_MSG
196
+ };
146
197
  var SNS_SERVICE_PATH = "1/secure-chat/";
147
198
  var SnsService = class {
148
199
  /**
@@ -176,7 +227,7 @@ var SnsService = class {
176
227
  * @param params Payload expected by the SNS auth API.
177
228
  */
178
229
  async requestAuthToken(params) {
179
- return this.http.post("v1/public/users/request_auth_token", params);
230
+ return this.http.post("v2/public/users/request_auth_token", params);
180
231
  }
181
232
  /**
182
233
  * Returns public user profiles for a batch of wallet addresses and/or user IDs.
@@ -253,7 +304,8 @@ var SnsService = class {
253
304
  return this.requestAuthToken({
254
305
  wallet_address: params.walletAddress,
255
306
  message: params.message,
256
- signature: params.signature
307
+ signature: params.signature,
308
+ service_name: params.serviceName
257
309
  });
258
310
  }
259
311
  /**
@@ -267,14 +319,15 @@ var SnsService = class {
267
319
  * @param params Wallet address and async signing callback.
268
320
  */
269
321
  async login(params) {
270
- const { walletAddress, signMessage } = params;
322
+ const { walletAddress, signMessage, serviceName } = params;
271
323
  const { nonce } = await this.getNonce({ walletAddress });
272
- const message = this.buildLoginMessage(nonce);
324
+ const message = this.buildLoginMessage(nonce, serviceName);
273
325
  const signature = await signMessage(message);
274
326
  const result = await this.authenticate({
275
327
  walletAddress,
276
328
  message,
277
- signature
329
+ signature,
330
+ serviceName
278
331
  });
279
332
  const accessToken = extractAccessToken(result);
280
333
  if (accessToken) {
@@ -285,16 +338,16 @@ var SnsService = class {
285
338
  /**
286
339
  * Builds the exact message string that the wallet must sign during login.
287
340
  */
288
- buildLoginMessage(nonce) {
289
- return `${this.options.baseSignedMessage ?? DEFAULT_BASE_SIGNED_MESSAGE}${nonce}`;
341
+ buildLoginMessage(nonce, serviceName) {
342
+ const baseMessage = serviceName != null ? BASE_SIGNED_MESSAGE_BY_SERVICE[serviceName] : this.options.baseSignedMessage ?? DEFAULT_BASE_SIGNED_MESSAGE;
343
+ return `${baseMessage}${nonce}`;
290
344
  }
291
345
  };
292
346
  function extractAccessToken(result) {
293
- const candidateKeys = ["access_token", "accessToken", "token", "jwt"];
294
- for (const key of candidateKeys) {
295
- const value = result[key];
296
- if (typeof value === "string" && value.length > 0) {
297
- return value;
347
+ if ("data" in result && typeof result.data === "object" && result.data !== null) {
348
+ const token = result.data.token;
349
+ if (typeof token === "string" && token.length > 0) {
350
+ return token;
298
351
  }
299
352
  }
300
353
  return void 0;
@@ -335,6 +388,9 @@ export {
335
388
  resolveServiceUrl,
336
389
  HttpAdapter,
337
390
  DEFAULT_BASE_SIGNED_MESSAGE,
391
+ BASE_CONNECT_SIGNED_MSG,
392
+ BASE_REDIRECT_SIGNED_MSG,
393
+ BASE_GAS_SPONSOR_SIGNED_MSG,
338
394
  SNS_SERVICE_PATH,
339
395
  SnsService,
340
396
  loginWithSns,