tapimo 0.4.0 → 0.4.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.
@@ -184,46 +184,9 @@ export declare namespace schema {
184
184
  export declare function transfers(): import("hono/hono-base").HonoBase<App.Environment, {
185
185
  "/v1/transfers": {
186
186
  $get: {
187
- output: {
188
- data: {
189
- attribution?: string | undefined;
190
- blockNumber: number;
191
- destinationToken?: {
192
- address: `0x${string}`;
193
- amount: string;
194
- currency?: string | undefined;
195
- decimals?: number | undefined;
196
- logoUri?: string | undefined;
197
- name?: string | undefined;
198
- symbol?: string | undefined;
199
- verified?: boolean | undefined;
200
- } | undefined;
201
- id: string;
202
- logIndex: number;
203
- memo?: string | undefined;
204
- recipient: `0x${string}`;
205
- sender: `0x${string}`;
206
- sourceToken: {
207
- address: `0x${string}`;
208
- amount: string;
209
- currency?: string | undefined;
210
- decimals?: number | undefined;
211
- logoUri?: string | undefined;
212
- name?: string | undefined;
213
- symbol?: string | undefined;
214
- verified?: boolean | undefined;
215
- };
216
- timestamp: string;
217
- transactionHash: `0x${string}`;
218
- }[];
219
- meta?: {
220
- totalCountCapped: boolean;
221
- totalCount: number;
222
- } | undefined;
223
- nextCursor: string | null;
224
- };
225
- outputFormat: "json";
226
- status: 200;
187
+ output: null;
188
+ outputFormat: "body";
189
+ status: 402;
227
190
  input: {
228
191
  query?: {
229
192
  recipient?: string | string[];
@@ -274,14 +237,14 @@ export declare function transfers(): import("hono/hono-base").HonoBase<App.Envir
274
237
  } | {
275
238
  output: {
276
239
  error: {
277
- code: "query_invalid";
240
+ code: "api_key_invalid" | "api_key_missing";
278
241
  details?: readonly Response.error.Detail[] | undefined;
279
242
  message: string;
280
243
  };
281
244
  requestId: string;
282
245
  };
283
246
  outputFormat: "json";
284
- status: 400;
247
+ status: 401;
285
248
  input: {
286
249
  query?: {
287
250
  recipient?: string | string[];
@@ -303,14 +266,14 @@ export declare function transfers(): import("hono/hono-base").HonoBase<App.Envir
303
266
  } | {
304
267
  output: {
305
268
  error: {
306
- code: "api_key_invalid" | "api_key_missing";
269
+ code: "api_key_forbidden";
307
270
  details?: readonly Response.error.Detail[] | undefined;
308
271
  message: string;
309
272
  };
310
273
  requestId: string;
311
274
  };
312
275
  outputFormat: "json";
313
- status: 401;
276
+ status: 403;
314
277
  input: {
315
278
  query?: {
316
279
  recipient?: string | string[];
@@ -330,9 +293,16 @@ export declare function transfers(): import("hono/hono-base").HonoBase<App.Envir
330
293
  } | undefined;
331
294
  };
332
295
  } | {
333
- output: null;
334
- outputFormat: "body";
335
- status: 402;
296
+ output: {
297
+ error: {
298
+ code: "payment_required" | "rate_limit_exceeded";
299
+ details?: readonly Response.error.Detail[] | undefined;
300
+ message: string;
301
+ };
302
+ requestId: string;
303
+ };
304
+ outputFormat: "json";
305
+ status: 429;
336
306
  input: {
337
307
  query?: {
338
308
  recipient?: string | string[];
@@ -354,14 +324,14 @@ export declare function transfers(): import("hono/hono-base").HonoBase<App.Envir
354
324
  } | {
355
325
  output: {
356
326
  error: {
357
- code: "api_key_forbidden";
327
+ code: "query_invalid";
358
328
  details?: readonly Response.error.Detail[] | undefined;
359
329
  message: string;
360
330
  };
361
331
  requestId: string;
362
332
  };
363
333
  outputFormat: "json";
364
- status: 403;
334
+ status: 400;
365
335
  input: {
366
336
  query?: {
367
337
  recipient?: string | string[];
@@ -383,14 +353,14 @@ export declare function transfers(): import("hono/hono-base").HonoBase<App.Envir
383
353
  } | {
384
354
  output: {
385
355
  error: {
386
- code: "payment_required" | "rate_limit_exceeded";
356
+ code: "upstream_error";
387
357
  details?: readonly Response.error.Detail[] | undefined;
388
358
  message: string;
389
359
  };
390
360
  requestId: string;
391
361
  };
392
362
  outputFormat: "json";
393
- status: 429;
363
+ status: 502;
394
364
  input: {
395
365
  query?: {
396
366
  recipient?: string | string[];
@@ -411,15 +381,45 @@ export declare function transfers(): import("hono/hono-base").HonoBase<App.Envir
411
381
  };
412
382
  } | {
413
383
  output: {
414
- error: {
415
- code: "upstream_error";
416
- details?: readonly Response.error.Detail[] | undefined;
417
- message: string;
418
- };
419
- requestId: string;
384
+ data: {
385
+ attribution?: string | undefined;
386
+ blockNumber: number;
387
+ destinationToken?: {
388
+ address: `0x${string}`;
389
+ amount: string;
390
+ currency?: string | undefined;
391
+ decimals?: number | undefined;
392
+ logoUri?: string | undefined;
393
+ name?: string | undefined;
394
+ symbol?: string | undefined;
395
+ verified?: boolean | undefined;
396
+ } | undefined;
397
+ id: string;
398
+ logIndex: number;
399
+ memo?: string | undefined;
400
+ recipient: `0x${string}`;
401
+ sender: `0x${string}`;
402
+ sourceToken: {
403
+ address: `0x${string}`;
404
+ amount: string;
405
+ currency?: string | undefined;
406
+ decimals?: number | undefined;
407
+ logoUri?: string | undefined;
408
+ name?: string | undefined;
409
+ symbol?: string | undefined;
410
+ verified?: boolean | undefined;
411
+ };
412
+ timestamp: string;
413
+ transactionHash: `0x${string}`;
414
+ }[];
415
+ meta?: {
416
+ totalCountCapped: boolean;
417
+ totalCount: number;
418
+ } | undefined;
419
+ nextCursor: string | null;
420
420
  };
421
421
  outputFormat: "json";
422
- status: 502;
422
+ status: 200;
423
423
  input: {
424
424
  query?: {
425
425
  recipient?: string | string[];
@@ -19,17 +19,6 @@ export declare namespace schema {
19
19
  export declare function me(): import("hono/hono-base").HonoBase<App.Environment, {
20
20
  "/v1/me": {
21
21
  $get: {
22
- output: {
23
- address?: string | undefined;
24
- createdAt: string;
25
- email?: string | undefined;
26
- id: string;
27
- updatedAt: string;
28
- };
29
- outputFormat: "json";
30
- status: 200;
31
- input: {};
32
- } | {
33
22
  output: {
34
23
  error: {
35
24
  code: "api_key_malformed";
@@ -56,38 +45,49 @@ export declare function me(): import("hono/hono-base").HonoBase<App.Environment,
56
45
  } | {
57
46
  output: {
58
47
  error: {
59
- code: "forbidden";
48
+ code: "upstream_error";
60
49
  details?: readonly Response.error.Detail[] | undefined;
61
50
  message: string;
62
51
  };
63
52
  requestId: string;
64
53
  };
65
54
  outputFormat: "json";
66
- status: 403;
55
+ status: 502;
67
56
  input: {};
68
57
  } | {
69
58
  output: {
70
59
  error: {
71
- code: "user_not_found";
60
+ code: "forbidden";
72
61
  details?: readonly Response.error.Detail[] | undefined;
73
62
  message: string;
74
63
  };
75
64
  requestId: string;
76
65
  };
77
66
  outputFormat: "json";
78
- status: 404;
67
+ status: 403;
79
68
  input: {};
80
69
  } | {
81
70
  output: {
82
71
  error: {
83
- code: "upstream_error";
72
+ code: "user_not_found";
84
73
  details?: readonly Response.error.Detail[] | undefined;
85
74
  message: string;
86
75
  };
87
76
  requestId: string;
88
77
  };
89
78
  outputFormat: "json";
90
- status: 502;
79
+ status: 404;
80
+ input: {};
81
+ } | {
82
+ output: {
83
+ address?: string | undefined;
84
+ createdAt: string;
85
+ email?: string | undefined;
86
+ id: string;
87
+ updatedAt: string;
88
+ };
89
+ outputFormat: "json";
90
+ status: 200;
91
91
  input: {};
92
92
  };
93
93
  };
@@ -43,17 +43,6 @@ export declare namespace schema {
43
43
  export declare function scopes(): import("hono/hono-base").HonoBase<App.Environment, {
44
44
  "/v1/scopes": {
45
45
  $get: {
46
- output: {
47
- data: {
48
- description: string;
49
- scope: "data:read" | "indexer:query" | "rpc-relay:read" | "rpc-relay:sponsor" | "webhooks:read" | "webhooks:write";
50
- selfServe: boolean;
51
- }[];
52
- };
53
- outputFormat: "json";
54
- status: 200;
55
- input: {};
56
- } | {
57
46
  output: {
58
47
  error: {
59
48
  code: "api_key_malformed";
@@ -101,6 +90,17 @@ export declare function scopes(): import("hono/hono-base").HonoBase<App.Environm
101
90
  outputFormat: "json";
102
91
  status: 429;
103
92
  input: {};
93
+ } | {
94
+ output: {
95
+ data: {
96
+ description: string;
97
+ scope: "data:read" | "indexer:query" | "rpc-relay:read" | "rpc-relay:sponsor" | "webhooks:read" | "webhooks:write";
98
+ selfServe: boolean;
99
+ }[];
100
+ };
101
+ outputFormat: "json";
102
+ status: 200;
103
+ input: {};
104
104
  };
105
105
  };
106
106
  }, "/", "/v1/scopes">;
@@ -12,9 +12,9 @@ import * as Sponsorship from './internal/sponsorship.js';
12
12
  *
13
13
  * @example
14
14
  * ```ts
15
- * import { Handler } from 'tempo-api/server'
15
+ * import { Handler } from 'tapimo'
16
16
  *
17
- * const handler = Handler.relay({ getClient })
17
+ * const handler = Handler.relay({ apiKey: process.env.TEMPO_API_KEY })
18
18
  *
19
19
  * // Plug handler into your server framework of choice:
20
20
  * createServer(handler.listener) // Node.js
@@ -31,10 +31,9 @@ import * as Sponsorship from './internal/sponsorship.js';
31
31
  *
32
32
  * ```ts
33
33
  * import { privateKeyToAccount } from 'viem/accounts'
34
- * import { Handler } from 'tempo-api/server'
34
+ * import { Handler } from 'tapimo'
35
35
  *
36
36
  * const handler = Handler.relay({
37
- * getClient,
38
37
  * feePayer: {
39
38
  * account: privateKeyToAccount('0x...'),
40
39
  * },
@@ -44,9 +43,14 @@ import * as Sponsorship from './internal/sponsorship.js';
44
43
  * @param options - Options.
45
44
  * @returns Request handler.
46
45
  */
47
- export declare function relay(options: relay.Options): Handler;
46
+ export declare function relay(options?: relay.Options): Handler;
48
47
  export declare namespace relay {
49
48
  type Options = from.Options & {
49
+ /**
50
+ * Tempo API key used by the default RPC clients and token resolver. When
51
+ * omitted, RPC clients use each chain's default transport.
52
+ */
53
+ apiKey?: string | undefined;
50
54
  /**
51
55
  * Auto-swap options.
52
56
  */
@@ -57,9 +61,9 @@ export declare namespace relay {
57
61
  /**
58
62
  * Resolves a viem client for a chain id. The handler resolves the client
59
63
  * from the `chainId` in the incoming transaction (falling back to the
60
- * client's default chain). Called with no argument for the default client.
64
+ * client's default chain). Defaults to Tempo mainnet and testnet clients.
61
65
  */
62
- getClient: (chainId?: number) => Client;
66
+ getClient?: ((chainId?: number) => Client) | undefined;
63
67
  /**
64
68
  * Fee payer / sponsor configuration. When provided, the relay will
65
69
  * sign `feePayerSignature` on the filled transaction.
@@ -113,9 +117,8 @@ export declare namespace relay {
113
117
  /** Path to use for the handler. @default "/" */
114
118
  path?: string | undefined;
115
119
  /**
116
- * Resolves the known fee-token candidates for a chain. The relay checks
117
- * the caller's balance for each candidate and picks the highest during
118
- * fee-token resolution. Omit to disable fee-token resolution.
120
+ * Resolves the known fee-token candidates for a chain. Defaults to the
121
+ * Tempo API verified token list for mainnet and testnet.
119
122
  */
120
123
  resolveTokens?: ((chainId: number) => readonly Address[] | Promise<readonly Address[]>) | undefined;
121
124
  };
@@ -1 +1 @@
1
- {"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../../src/handlers/relay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,UAAU,EAAe,MAAM,IAAI,CAAA;AAE3D,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,MAAM,EASZ,MAAM,MAAM,CAAA;AACb,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAMjD,OAAO,EAAE,KAAK,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,KAAK,KAAK,MAAM,sBAAsB,CAAA;AAC7C,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAA;AAClD,OAAO,KAAK,WAAW,MAAM,2BAA2B,CAAA;AAGxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAskBrD;AAED,yBAAiB,KAAK,CAAC;IACrB,KAAY,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG;QACnC;;WAEG;QACH,QAAQ,CAAC,EACL,KAAK,GACL;YACE,yDAAyD;YACzD,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;SAC9B,GACD,SAAS,CAAA;QACb;;;;WAIG;QACH,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;QACvC;;;WAGG;QACH,QAAQ,CAAC,EACL;YACE,uCAAuC;YACvC,OAAO,EAAE,YAAY,CAAA;YACrB,4DAA4D;YAC5D,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;YAC9B;;eAEG;YACH,WAAW,CAAC,EAAE,WAAW,CAAC,oBAAoB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;YACrE;;;eAGG;YACH,QAAQ,CAAC,EAAE,WAAW,CAAC,QAAQ,GAAG,SAAS,CAAA;YAC3C,gEAAgE;YAChE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YACzB,uDAAuD;YACvD,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;SACzB,GACD,SAAS,CAAA;QACb;;;;WAIG;QACH,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,SAAS,CAAA;QACvC;;;;;;WAMG;QACH,QAAQ,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;QAC5B;;;;WAIG;QACH,wBAAwB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;QAC9C;;;WAGG;QACH,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,CAAA;QAC/B,oDAAoD;QACpD,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,UAAU,CAAC,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAA;QAC3E,gDAAgD;QAChD,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QACzB;;;;WAIG;QACH,aAAa,CAAC,EACV,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC,GACvE,SAAS,CAAA;KACd,CAAA;CACF"}
1
+ {"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../../src/handlers/relay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,UAAU,EAAe,MAAM,IAAI,CAAA;AAE3D,OAAO,EACL,KAAK,OAAO,EAEZ,KAAK,MAAM,EASZ,MAAM,MAAM,CAAA;AACb,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAQjD,OAAO,EAAE,KAAK,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,KAAK,KAAK,MAAM,sBAAsB,CAAA;AAC7C,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAA;AAClD,OAAO,KAAK,WAAW,MAAM,2BAA2B,CAAA;AAKxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,KAAK,CAAC,OAAO,GAAE,KAAK,CAAC,OAAY,GAAG,OAAO,CAskB1D;AAmCD,yBAAiB,KAAK,CAAC;IACrB,KAAY,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG;QACnC;;;WAGG;QACH,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QAC3B;;WAEG;QACH,QAAQ,CAAC,EACL,KAAK,GACL;YACE,yDAAyD;YACzD,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;SAC9B,GACD,SAAS,CAAA;QACb;;;;WAIG;QACH,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAA;QACtD;;;WAGG;QACH,QAAQ,CAAC,EACL;YACE,uCAAuC;YACvC,OAAO,EAAE,YAAY,CAAA;YACrB,4DAA4D;YAC5D,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;YAC9B;;eAEG;YACH,WAAW,CAAC,EAAE,WAAW,CAAC,oBAAoB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;YACrE;;;eAGG;YACH,QAAQ,CAAC,EAAE,WAAW,CAAC,QAAQ,GAAG,SAAS,CAAA;YAC3C,gEAAgE;YAChE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YACzB,uDAAuD;YACvD,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;SACzB,GACD,SAAS,CAAA;QACb;;;;WAIG;QACH,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,SAAS,CAAA;QACvC;;;;;;WAMG;QACH,QAAQ,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;QAC5B;;;;WAIG;QACH,wBAAwB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;QAC9C;;;WAGG;QACH,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,SAAS,CAAA;QAC/B,oDAAoD;QACpD,SAAS,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,UAAU,CAAC,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAA;QAC3E,gDAAgD;QAChD,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QACzB;;;WAGG;QACH,aAAa,CAAC,EACV,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC,GACvE,SAAS,CAAA;KACd,CAAA;CACF"}
@@ -3,12 +3,15 @@ import { Transaction as core_Transaction } from 'ox/tempo';
3
3
  import { createClient, decodeFunctionData, formatUnits, http, isAddress, parseEventLogs, zeroAddress, } from 'viem';
4
4
  import { simulateCalls } from 'viem/actions';
5
5
  import { Abis, Actions, Addresses, Capabilities, VirtualAddress } from 'viem/tempo';
6
+ import { tempoMainnet, tempoTestnet } from 'viem/tempo/chains';
6
7
  import * as ExecutionError from './internal/executionError.js';
8
+ import * as TempoApi from '../Client.js';
7
9
  import { from } from '../Handler.js';
8
10
  import * as Store from '../internal/Store.js';
9
11
  import * as Multisig from './internal/multisig.js';
10
12
  import * as Sponsorship from './internal/sponsorship.js';
11
13
  import * as Utils from './internal/utils.js';
14
+ const defaultChains = [tempoMainnet, tempoTestnet];
12
15
  /**
13
16
  * Instantiates a relay handler that proxies `eth_fillTransaction`
14
17
  * with wallet-aware enrichment (fee token resolution, simulation,
@@ -16,9 +19,9 @@ import * as Utils from './internal/utils.js';
16
19
  *
17
20
  * @example
18
21
  * ```ts
19
- * import { Handler } from 'tempo-api/server'
22
+ * import { Handler } from 'tapimo'
20
23
  *
21
- * const handler = Handler.relay({ getClient })
24
+ * const handler = Handler.relay({ apiKey: process.env.TEMPO_API_KEY })
22
25
  *
23
26
  * // Plug handler into your server framework of choice:
24
27
  * createServer(handler.listener) // Node.js
@@ -35,10 +38,9 @@ import * as Utils from './internal/utils.js';
35
38
  *
36
39
  * ```ts
37
40
  * import { privateKeyToAccount } from 'viem/accounts'
38
- * import { Handler } from 'tempo-api/server'
41
+ * import { Handler } from 'tapimo'
39
42
  *
40
43
  * const handler = Handler.relay({
41
- * getClient,
42
44
  * feePayer: {
43
45
  * account: privateKeyToAccount('0x...'),
44
46
  * },
@@ -48,18 +50,17 @@ import * as Utils from './internal/utils.js';
48
50
  * @param options - Options.
49
51
  * @returns Request handler.
50
52
  */
51
- export function relay(options) {
52
- const { getClient, internal_allowUnsafeUrls = false, onRequest, path = '/', resolveTokens, ...rest } = options;
53
+ export function relay(options = {}) {
54
+ const { apiKey, getClient: getClient_, internal_allowUnsafeUrls = false, onRequest, path = '/', resolveTokens: resolveTokens_, ...rest } = options;
55
+ const getClient = getClient_ ?? defaultGetClient({ apiKey });
56
+ const resolveTokens = resolveTokens_ ?? defaultResolveTokens({ apiKey });
53
57
  const feePayerOptions = options.feePayer;
54
58
  // Adapt the state store into the multisig operation store once, up front.
55
59
  const multisigOptions = options.multisig
56
60
  ? { ...options.multisig, store: Multisig.fromStore(options.multisig.store) }
57
61
  : undefined;
58
- // Resolves the chain's fee-token candidates through the caller-provided
59
- // resolver. An unconfigured resolver (or a chain it has no list for) yields
60
- // an empty candidate set.
61
62
  const getTokens = async (chainId) => {
62
- if (!resolveTokens || chainId === undefined)
63
+ if (chainId === undefined)
63
64
  return [];
64
65
  return await resolveTokens(chainId);
65
66
  };
@@ -69,7 +70,7 @@ export function relay(options) {
69
70
  const store = options.cache;
70
71
  const features = {
71
72
  autoSwap: options.autoSwap ?? options.features === 'all',
72
- feeTokenResolution: options.features === 'all' || Boolean(resolveTokens),
73
+ feeTokenResolution: options.features === 'all' || Boolean(resolveTokens_),
73
74
  simulate: options.features === 'all',
74
75
  };
75
76
  const autoSwap = (() => {
@@ -130,13 +131,14 @@ export function relay(options) {
130
131
  let filled;
131
132
  let sponsored = false;
132
133
  let feeToken = sponsoredFeeToken;
134
+ const tokens = getTokens(chainId);
133
135
  // Lazily resolve a swap source token when autoSwap needs one.
134
136
  const resolveFeeTokenForSwap = from
135
137
  ? async (insufficientToken) => resolveFeeToken(client, {
136
138
  account: from,
137
139
  feeToken: undefined,
138
140
  store,
139
- tokens: (await getTokens(chainId)).filter((t) => t.toLowerCase() !== insufficientToken.toLowerCase()),
141
+ tokens: (await tokens).filter((t) => t.toLowerCase() !== insufficientToken.toLowerCase()),
140
142
  })
141
143
  : undefined;
142
144
  // When no sponsor will pay, prefer fee tokens the user actually
@@ -144,7 +146,7 @@ export function relay(options) {
144
146
  // the transaction is calling — typically the token being
145
147
  // transferred — so a user transferring USDC.e can pay gas in
146
148
  // USDC.e even when the configured list defaults to pathUSD.
147
- const configuredTokens = await getTokens(chainId);
149
+ const configuredTokens = await tokens;
148
150
  const unsponsoredTokens = [
149
151
  ...configuredTokens,
150
152
  ...callTargetTokens(baseTx).filter((t) => !configuredTokens.some((rt) => rt.toLowerCase() === t.toLowerCase())),
@@ -168,7 +170,7 @@ export function relay(options) {
168
170
  // Default to the chain's first token so the broadcast envelope
169
171
  // always carries a feeToken the chain can charge.
170
172
  if (!feeToken)
171
- feeToken = (await getTokens(chainId))[0];
173
+ feeToken = configuredTokens[0];
172
174
  const transaction = {
173
175
  ...baseTx,
174
176
  feePayer: true,
@@ -282,8 +284,7 @@ export function relay(options) {
282
284
  const transaction_filled = filled.transaction;
283
285
  const swap = 'swap' in filled ? filled.swap : undefined;
284
286
  if (!feeToken)
285
- feeToken =
286
- transaction_filled.feeToken ?? (await getTokens(chainId))[0];
287
+ feeToken = transaction_filled.feeToken ?? configuredTokens[0];
287
288
  // Parallelize: simulate, fee payer signing, and autoSwap metadata.
288
289
  const alreadySigned = 'feePayerSignature' in transaction_filled &&
289
290
  transaction_filled.feePayerSignature != null;
@@ -553,6 +554,35 @@ export function relay(options) {
553
554
  router.post(`${path === '/' ? '' : path}/:chainId`, handlePost);
554
555
  return router;
555
556
  }
557
+ function defaultGetClient(options) {
558
+ const clients = new Map();
559
+ for (const chain of defaultChains) {
560
+ const transport = options.apiKey
561
+ ? http(new URL(`/rpc/${chain.id}`, TempoApi.defaultUrl).toString(), {
562
+ fetchOptions: { headers: { 'tempo-api-key': options.apiKey } },
563
+ })
564
+ : http();
565
+ clients.set(chain.id, createClient({ batch: { multicall: { deployless: true } }, chain, transport }));
566
+ }
567
+ return (chainId = tempoMainnet.id) => {
568
+ const client = clients.get(chainId);
569
+ if (!client)
570
+ throw new Error(`Chain ${chainId} not configured`);
571
+ return client;
572
+ };
573
+ }
574
+ function defaultResolveTokens(options) {
575
+ const client = TempoApi.create({ apiKey: options.apiKey });
576
+ return async (chainId) => {
577
+ if (!defaultChains.some((chain) => chain.id === chainId))
578
+ return [];
579
+ const response = await client.v1.tokenlist.$get({ query: { chainId: String(chainId) } });
580
+ if (response.status !== 200)
581
+ return [];
582
+ const { tokens } = await response.json();
583
+ return tokens.map((token) => token.address);
584
+ };
585
+ }
556
586
  // TODO: cleanup
557
587
  async function fill(client, options) {
558
588
  const { autoSwap, feeToken, store, transaction: request } = options;