@gibs/common 1.13.1 → 1.17.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/dist/url.js ADDED
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Request addresses, built and read with plain string work.
3
+ *
4
+ * WHY THIS EXISTS: React Native 0.77 installs its own `URL` and
5
+ * `URLSearchParams` (react-native/Libraries/Blob/URL.js), and both are partial.
6
+ * `new URL(x).protocol`, `.host`, `.pathname` and `.search` throw "not
7
+ * implemented". `searchParams` is always a new, empty list, so a reader of it
8
+ * silently sees no parameters. `URLSearchParams` can only append and
9
+ * serialize: `get`, `set`, `has` and `delete` throw, and a string passed to
10
+ * its constructor is ignored. A package that uses either class needs a
11
+ * polyfill in a wallet. These functions need nothing from the runtime but
12
+ * `encodeURIComponent` and `decodeURIComponent`.
13
+ *
14
+ * Their output matches what the WHATWG classes produce for the addresses the
15
+ * Gibs packages build: a lowercase `http:` or `https:` origin with a plain
16
+ * path. A query is encoded exactly as `URLSearchParams` encodes it, as
17
+ * `application/x-www-form-urlencoded`: a space becomes `+`, and only letters,
18
+ * digits and `*-._` stay as they are. They do not normalize the address
19
+ * itself: an uppercase host or a `..` path segment passes through as written.
20
+ */
21
+ /** A surrogate pair, or a lone surrogate half. */
22
+ const surrogates = /[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDFFF]/g;
23
+ /** The characters `encodeURIComponent` keeps that a form encoder escapes. */
24
+ const formEscapedCharacters = /[!'()~]/g;
25
+ /** A run of percent-encoded bytes. */
26
+ const percentEncodedRun = /(?:%[0-9A-Fa-f]{2})+/g;
27
+ /** The port each special scheme leaves out of its host. */
28
+ const defaultPorts = Object.freeze({
29
+ http: '80',
30
+ https: '443',
31
+ ws: '80',
32
+ wss: '443',
33
+ ftp: '21',
34
+ });
35
+ /**
36
+ * Replaces each lone surrogate half with U+FFFD, as the WHATWG classes do
37
+ * before they encode. `encodeURIComponent` would throw on one instead.
38
+ *
39
+ * @param text - any string
40
+ * @returns the string, well formed
41
+ */
42
+ const toWellFormed = (text) => text.replace(surrogates, (match) => (match.length === 2 ? match : '�'));
43
+ /**
44
+ * Percent-encodes one character as two uppercase hex digits.
45
+ *
46
+ * @param character - a single ASCII character
47
+ * @returns the character as `%XX`
48
+ */
49
+ const percentEncodeCharacter = (character) => `%${character.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0')}`;
50
+ /**
51
+ * Encodes a query name or value exactly as `URLSearchParams.toString` does.
52
+ *
53
+ * @param text - the raw name or value
54
+ * @returns the encoded text
55
+ */
56
+ export const encodeQueryComponent = (text) => encodeURIComponent(toWellFormed(text))
57
+ .replace(formEscapedCharacters, percentEncodeCharacter)
58
+ .replace(/%20/g, '+');
59
+ /**
60
+ * Counts the continuation bytes a UTF-8 lead byte announces, and the bounds
61
+ * the first of them must fall in. The bounds reject overlong forms and
62
+ * surrogates, as the WHATWG decoder does.
63
+ *
64
+ * @param lead - the first byte of a sequence
65
+ * @returns the count, the lead byte's own bits, and the first continuation byte's bounds; null for a byte that cannot start one
66
+ */
67
+ const utf8Lead = (lead) => {
68
+ if (lead >= 0xc2 && lead <= 0xdf)
69
+ return { count: 1, bits: lead & 0x1f, lower: 0x80, upper: 0xbf };
70
+ if (lead === 0xe0)
71
+ return { count: 2, bits: lead & 0x0f, lower: 0xa0, upper: 0xbf };
72
+ if (lead === 0xed)
73
+ return { count: 2, bits: lead & 0x0f, lower: 0x80, upper: 0x9f };
74
+ if (lead >= 0xe1 && lead <= 0xef)
75
+ return { count: 2, bits: lead & 0x0f, lower: 0x80, upper: 0xbf };
76
+ if (lead === 0xf0)
77
+ return { count: 3, bits: lead & 0x07, lower: 0x90, upper: 0xbf };
78
+ if (lead === 0xf4)
79
+ return { count: 3, bits: lead & 0x07, lower: 0x80, upper: 0x8f };
80
+ if (lead >= 0xf1 && lead <= 0xf3)
81
+ return { count: 3, bits: lead & 0x07, lower: 0x80, upper: 0xbf };
82
+ return null;
83
+ };
84
+ /**
85
+ * Decodes UTF-8 bytes as the WHATWG decoder does: each malformed part becomes
86
+ * one U+FFFD, and a byte that ends a malformed part is read again as the
87
+ * start of the next. Only reached when `decodeURIComponent` refuses a run.
88
+ *
89
+ * @param bytes - the bytes
90
+ * @returns the decoded text
91
+ */
92
+ const decodeUtf8Leniently = (bytes) => {
93
+ const decode = (index, decoded) => {
94
+ if (index >= bytes.length)
95
+ return decoded;
96
+ const lead = bytes[index];
97
+ if (lead < 0x80)
98
+ return decode(index + 1, decoded + String.fromCharCode(lead));
99
+ const shape = utf8Lead(lead);
100
+ if (shape === null)
101
+ return decode(index + 1, `${decoded}�`);
102
+ const readContinuation = (offset, codePoint) => {
103
+ if (offset > shape.count)
104
+ return { codePoint, length: offset };
105
+ const byte = bytes[index + offset];
106
+ const lower = offset === 1 ? shape.lower : 0x80;
107
+ const upper = offset === 1 ? shape.upper : 0xbf;
108
+ if (byte === undefined || byte < lower || byte > upper)
109
+ return { codePoint: -1, length: offset };
110
+ return readContinuation(offset + 1, (codePoint << 6) | (byte & 0x3f));
111
+ };
112
+ const { codePoint, length } = readContinuation(1, shape.bits);
113
+ if (codePoint === -1)
114
+ return decode(index + length, `${decoded}�`);
115
+ return decode(index + length, decoded + String.fromCodePoint(codePoint));
116
+ };
117
+ return decode(0, '');
118
+ };
119
+ /**
120
+ * Decodes one run of `%XX` bytes.
121
+ *
122
+ * @param run - consecutive `%XX` sequences
123
+ * @returns the text they encode
124
+ */
125
+ const decodePercentRun = (run) => {
126
+ try {
127
+ return decodeURIComponent(run);
128
+ }
129
+ catch {
130
+ return decodeUtf8Leniently(run.slice(1).split('%').map((pair) => Number.parseInt(pair, 16)));
131
+ }
132
+ };
133
+ /**
134
+ * Decodes a query name or value as the WHATWG URL standard says
135
+ * `URLSearchParams` must: `+` is a space, a valid `%XX` is a byte, a `%` that
136
+ * starts no valid sequence stays as it is, and each malformed UTF-8 part, or
137
+ * lone surrogate half, becomes U+FFFD.
138
+ *
139
+ * @param text - the encoded name or value
140
+ * @returns the decoded text
141
+ */
142
+ export const decodeQueryComponent = (text) => toWellFormed(text).replace(/\+/g, ' ').replace(percentEncodedRun, decodePercentRun);
143
+ /**
144
+ * Lists the parameters of a query, decoded and in order.
145
+ *
146
+ * @param query - a query, with or without its leading `?`
147
+ * @returns each parameter's name and value; a parameter with no `=` has an empty value
148
+ */
149
+ export const parseQuery = (query) => query
150
+ .replace(/^\?/, '')
151
+ .split('&')
152
+ .filter((part) => part !== '')
153
+ .map((part) => {
154
+ const equalsAt = part.indexOf('=');
155
+ const name = equalsAt === -1 ? part : part.slice(0, equalsAt);
156
+ const value = equalsAt === -1 ? '' : part.slice(equalsAt + 1);
157
+ return [decodeQueryComponent(name), decodeQueryComponent(value)];
158
+ });
159
+ /**
160
+ * Turns query parameters into ordered pairs.
161
+ *
162
+ * @param parameters - a record or pairs; see {@link QueryParameters}
163
+ * @returns the pairs, with every `undefined` record value left out
164
+ */
165
+ const toEntries = (parameters) => {
166
+ if (Array.isArray(parameters))
167
+ return parameters;
168
+ return Object.entries(parameters).filter((entry) => entry[1] !== undefined);
169
+ };
170
+ /**
171
+ * Writes a query, as `new URLSearchParams(parameters).toString()` does.
172
+ *
173
+ * @param parameters - a record or pairs; see {@link QueryParameters}
174
+ * @returns the encoded query, with no leading `?`; empty for no parameters
175
+ */
176
+ export const buildQuery = (parameters) => toEntries(parameters)
177
+ .map(([name, value]) => `${encodeQueryComponent(name)}=${encodeQueryComponent(value)}`)
178
+ .join('&');
179
+ /**
180
+ * Sets one parameter in a query, as `URLSearchParams.set` does: the first
181
+ * parameter of that name takes the value and any later ones are removed, or
182
+ * the parameter is appended when none has the name.
183
+ *
184
+ * @param query - an encoded query, with or without its leading `?`
185
+ * @param name - the parameter's name
186
+ * @param value - its value
187
+ * @returns the encoded query, with no leading `?`
188
+ */
189
+ export const setQueryParameter = (query, name, value) => {
190
+ const entries = parseQuery(query);
191
+ const firstAt = entries.findIndex(([entryName]) => entryName === name);
192
+ if (firstAt === -1)
193
+ return buildQuery([...entries, [name, value]]);
194
+ return buildQuery(entries.flatMap((entry, index) => {
195
+ if (index === firstAt)
196
+ return [[name, value]];
197
+ return entry[0] === name ? [] : [entry];
198
+ }));
199
+ };
200
+ /**
201
+ * Splits an address at its first `#` and then at its first `?`.
202
+ *
203
+ * @param address - any address
204
+ * @returns everything before the query, the query and the fragment, each without its delimiter
205
+ */
206
+ const splitAtQuery = (address) => {
207
+ const fragmentAt = address.indexOf('#');
208
+ const beforeFragment = fragmentAt === -1 ? address : address.slice(0, fragmentAt);
209
+ const fragment = fragmentAt === -1 ? '' : address.slice(fragmentAt + 1);
210
+ const queryAt = beforeFragment.indexOf('?');
211
+ if (queryAt === -1)
212
+ return { beforeQuery: beforeFragment, query: '', fragment };
213
+ return { beforeQuery: beforeFragment.slice(0, queryAt), query: beforeFragment.slice(queryAt + 1), fragment };
214
+ };
215
+ /**
216
+ * Adds query parameters to an address, as `url.searchParams.set` does for
217
+ * each one in turn. A query already on the address is kept, and a fragment
218
+ * stays at the end.
219
+ *
220
+ * @param address - the address, with or without a query
221
+ * @param parameters - a record or pairs; see {@link QueryParameters}
222
+ * @returns the address with the parameters set; the address unchanged when there are none
223
+ */
224
+ export const buildUrl = (address, parameters) => {
225
+ const entries = toEntries(parameters);
226
+ if (entries.length === 0)
227
+ return address;
228
+ const { beforeQuery, query, fragment } = splitAtQuery(address);
229
+ const updated = entries.reduce((current, [name, value]) => setQueryParameter(current, name, value), query);
230
+ return `${beforeQuery}?${updated}${fragment === '' ? '' : `#${fragment}`}`;
231
+ };
232
+ /**
233
+ * Reads the host the WHATWG `URL` reports from an authority: lowercase, with
234
+ * any user name and password dropped, and the port dropped when it is the
235
+ * scheme's default.
236
+ *
237
+ * @param authority - the text between `//` and the path
238
+ * @param scheme - the lowercase scheme
239
+ * @returns the host
240
+ */
241
+ const hostOfAuthority = (authority, scheme) => {
242
+ const hostAndPort = authority.slice(authority.lastIndexOf('@') + 1).toLowerCase();
243
+ const port = /:(\d*)$/.exec(hostAndPort);
244
+ if (port === null)
245
+ return hostAndPort;
246
+ const hostname = hostAndPort.slice(0, port.index);
247
+ if (port[1] === '')
248
+ return hostname;
249
+ const portNumber = String(Number(port[1]));
250
+ return portNumber === defaultPorts[scheme] ? hostname : `${hostname}:${portNumber}`;
251
+ };
252
+ /**
253
+ * Splits an address into its parts, without the WHATWG `URL` class.
254
+ *
255
+ * @param address - any address; leading and trailing spaces and control characters are ignored, as the WHATWG parser ignores them
256
+ * @returns the parts; see {@link UrlParts}
257
+ */
258
+ export const splitUrl = (address) => {
259
+ const trimmed = address.replace(/^[\u0000- ]+|[\u0000- ]+$/g, '');
260
+ const { beforeQuery, query, fragment } = splitAtQuery(trimmed);
261
+ const schemeMatch = /^([A-Za-z][A-Za-z0-9+.-]*):/.exec(beforeQuery);
262
+ const scheme = schemeMatch === null ? '' : schemeMatch[1].toLowerCase();
263
+ const rest = schemeMatch === null ? beforeQuery : beforeQuery.slice(schemeMatch[0].length);
264
+ if (!rest.startsWith('//'))
265
+ return { scheme, host: '', path: rest, query, fragment };
266
+ const pathAt = rest.indexOf('/', 2);
267
+ const authority = pathAt === -1 ? rest.slice(2) : rest.slice(2, pathAt);
268
+ const path = pathAt === -1 ? '/' : rest.slice(pathAt);
269
+ return { scheme, host: hostOfAuthority(authority, scheme), path, query, fragment };
270
+ };
271
+ /**
272
+ * Says whether a value is an absolute `http:` or `https:` address with a host.
273
+ * It reads the scheme by its prefix, so it needs no `URL` class.
274
+ *
275
+ * @param value - any string
276
+ * @returns true for an absolute `http:` or `https:` address
277
+ */
278
+ export const isHttpUrl = (value) => {
279
+ const { scheme, host } = splitUrl(value);
280
+ return (scheme === 'http' || scheme === 'https') && host !== '';
281
+ };
@@ -0,0 +1,6 @@
1
+ {
2
+ "main": "../dist/cjs/erc20.js",
3
+ "module": "../dist/erc20.js",
4
+ "types": "../dist/erc20.d.ts",
5
+ "react-native": "../dist/cjs/erc20.js"
6
+ }
package/llms.txt CHANGED
@@ -8,9 +8,13 @@
8
8
  ## Install
9
9
 
10
10
  - Run `npm install @gibs/common viem`.
11
- - The package is ESM only. Use `import`, not `require`.
12
- - It needs Node 20 or later.
13
- - viem is a peer dependency. The range is `>=2.37.0 <3`.
11
+ - It runs on Node 20 or later, in browsers, and in React Native under Hermes.
12
+ - `import` loads the ECMAScript module build (`dist/`). `require` loads the CommonJS build (`dist/cjs/`).
13
+ - React Native 0.77 or later: Metro's default configuration and the React Native jest preset load it with no extra setup. Add no `resolveRequest` hook and no `transformIgnorePatterns`. The `react-native` condition gives an `import` statement the ECMAScript module build and a `require` call the CommonJS build.
14
+ - It needs no polyfill, not even for `URL`: React Native 0.77's own `URL` and `URLSearchParams` are partial, and no entry point reads them.
15
+ - Import from the narrowest subpath, for example `@gibs/common/cache`. Metro does not drop unused exports.
16
+ - It has no runtime dependency except viem.
17
+ - viem is a peer dependency. The range is `>=2.35.0 <3`.
14
18
  - Version note: 1.12.0 and older on npm are broken. 1.13.0 is the first usable version.
15
19
 
16
20
  ## Entry points
@@ -19,9 +23,10 @@
19
23
  - `@gibs/common/client`: `clientFromChain({ chain, urls })`, `chainKey`, `clientCache`.
20
24
  - `@gibs/common/erc20`: `multicallErc20`, `erc20MetadataCalls`.
21
25
  - `@gibs/common/multicall`: `multicallRead`.
22
- - `@gibs/common/cache`: `maxMemoize`, `ttlMemoizeSingle`.
26
+ - `@gibs/common/cache`: `maxMemoize`, `ttlMemoizeSingle`, `memoizeByKey`.
23
27
  - `@gibs/common/serialize`: `jsonAnyStringify`, `jsonAnyParse`, `isSerializedBigInt`.
24
28
  - `@gibs/common/types`: `Call`, `Erc20Metadata`.
29
+ - `@gibs/common/url`: `buildUrl`, `buildQuery`, `parseQuery`, `setQueryParameter`, `splitUrl`, `isHttpUrl`, `encodeQueryComponent`, `decodeQueryComponent`. They build and read request addresses with string work, never with `URL`, and encode a query exactly as `URLSearchParams` does.
25
30
 
26
31
  ## Read a token's name, symbol and decimals
27
32
 
@@ -56,6 +61,20 @@ const square = maxMemoize((x: number) => x * x, 100)
56
61
  const price = ttlMemoizeSingle(async (symbol: string) => symbol, 30_000)
57
62
  ```
58
63
 
64
+ `memoizeByKey` keys each answer by a resolver you supply, and exposes the
65
+ cache so you can evict one answer or clear them all.
66
+
67
+ ```ts
68
+ import { memoizeByKey } from '@gibs/common/cache'
69
+
70
+ const decimals = memoizeByKey(
71
+ async ({ chainId, address }: { chainId: number; address: string }) => (chainId === 1 ? 6 : 18),
72
+ ({ chainId, address }) => `${chainId}-${address.toLowerCase()}`,
73
+ )
74
+ decimals.cache.delete('1-0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48')
75
+ decimals.cache.clear()
76
+ ```
77
+
59
78
  ## Rules
60
79
 
61
80
  - `multicallRead` and `multicallErc20` need a chain object that carries a Multicall3 deployment. A chain without one fails.
@@ -66,5 +85,5 @@ const price = ttlMemoizeSingle(async (symbol: string) => symbol, 30_000)
66
85
 
67
86
  ## Links
68
87
 
69
- - [README](https://github.com/gibsfinance/bridge/blob/staging/packages/common/README.md)
88
+ - [README](https://www.npmjs.com/package/@gibs/common)
70
89
  - [Gibs Finance llms.txt](https://next.gibs.finance/llms.txt): the whole platform.
@@ -0,0 +1,6 @@
1
+ {
2
+ "main": "../dist/cjs/multicall.js",
3
+ "module": "../dist/multicall.js",
4
+ "types": "../dist/multicall.d.ts",
5
+ "react-native": "../dist/cjs/multicall.js"
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gibs/common",
3
- "version": "1.13.1",
3
+ "version": "1.17.0",
4
4
  "description": "Low-level blockchain helpers shared across the Gibs Finance packages: caching, multicall, and serialization.",
5
5
  "keywords": [
6
6
  "ethereum",
@@ -25,48 +25,236 @@
25
25
  },
26
26
  "type": "module",
27
27
  "sideEffects": false,
28
- "main": "./dist/index.js",
28
+ "main": "./dist/cjs/index.js",
29
+ "module": "./dist/index.js",
30
+ "react-native": "./dist/cjs/index.js",
29
31
  "types": "./dist/index.d.ts",
30
32
  "exports": {
31
33
  ".": {
32
34
  "gibs-source": "./src/index.ts",
35
+ "react-native": {
36
+ "import": {
37
+ "types": "./dist/index.d.ts",
38
+ "default": "./dist/index.js"
39
+ },
40
+ "require": {
41
+ "types": "./dist/cjs/index.d.ts",
42
+ "default": "./dist/cjs/index.js"
43
+ },
44
+ "default": {
45
+ "types": "./dist/cjs/index.d.ts",
46
+ "default": "./dist/cjs/index.js"
47
+ }
48
+ },
49
+ "import": {
50
+ "types": "./dist/index.d.ts",
51
+ "default": "./dist/index.js"
52
+ },
53
+ "require": {
54
+ "types": "./dist/cjs/index.d.ts",
55
+ "default": "./dist/cjs/index.js"
56
+ },
33
57
  "types": "./dist/index.d.ts",
34
58
  "default": "./dist/index.js"
35
59
  },
36
60
  "./erc20": {
37
61
  "gibs-source": "./src/erc20.ts",
62
+ "react-native": {
63
+ "import": {
64
+ "types": "./dist/erc20.d.ts",
65
+ "default": "./dist/erc20.js"
66
+ },
67
+ "require": {
68
+ "types": "./dist/cjs/erc20.d.ts",
69
+ "default": "./dist/cjs/erc20.js"
70
+ },
71
+ "default": {
72
+ "types": "./dist/cjs/erc20.d.ts",
73
+ "default": "./dist/cjs/erc20.js"
74
+ }
75
+ },
76
+ "import": {
77
+ "types": "./dist/erc20.d.ts",
78
+ "default": "./dist/erc20.js"
79
+ },
80
+ "require": {
81
+ "types": "./dist/cjs/erc20.d.ts",
82
+ "default": "./dist/cjs/erc20.js"
83
+ },
38
84
  "types": "./dist/erc20.d.ts",
39
85
  "default": "./dist/erc20.js"
40
86
  },
41
87
  "./cache": {
42
88
  "gibs-source": "./src/cache.ts",
89
+ "react-native": {
90
+ "import": {
91
+ "types": "./dist/cache.d.ts",
92
+ "default": "./dist/cache.js"
93
+ },
94
+ "require": {
95
+ "types": "./dist/cjs/cache.d.ts",
96
+ "default": "./dist/cjs/cache.js"
97
+ },
98
+ "default": {
99
+ "types": "./dist/cjs/cache.d.ts",
100
+ "default": "./dist/cjs/cache.js"
101
+ }
102
+ },
103
+ "import": {
104
+ "types": "./dist/cache.d.ts",
105
+ "default": "./dist/cache.js"
106
+ },
107
+ "require": {
108
+ "types": "./dist/cjs/cache.d.ts",
109
+ "default": "./dist/cjs/cache.js"
110
+ },
43
111
  "types": "./dist/cache.d.ts",
44
112
  "default": "./dist/cache.js"
45
113
  },
46
114
  "./serialize": {
47
115
  "gibs-source": "./src/serialize.ts",
116
+ "react-native": {
117
+ "import": {
118
+ "types": "./dist/serialize.d.ts",
119
+ "default": "./dist/serialize.js"
120
+ },
121
+ "require": {
122
+ "types": "./dist/cjs/serialize.d.ts",
123
+ "default": "./dist/cjs/serialize.js"
124
+ },
125
+ "default": {
126
+ "types": "./dist/cjs/serialize.d.ts",
127
+ "default": "./dist/cjs/serialize.js"
128
+ }
129
+ },
130
+ "import": {
131
+ "types": "./dist/serialize.d.ts",
132
+ "default": "./dist/serialize.js"
133
+ },
134
+ "require": {
135
+ "types": "./dist/cjs/serialize.d.ts",
136
+ "default": "./dist/cjs/serialize.js"
137
+ },
48
138
  "types": "./dist/serialize.d.ts",
49
139
  "default": "./dist/serialize.js"
50
140
  },
51
141
  "./types": {
52
142
  "gibs-source": "./src/types.ts",
143
+ "react-native": {
144
+ "import": {
145
+ "types": "./dist/types.d.ts",
146
+ "default": "./dist/types.js"
147
+ },
148
+ "require": {
149
+ "types": "./dist/cjs/types.d.ts",
150
+ "default": "./dist/cjs/types.js"
151
+ },
152
+ "default": {
153
+ "types": "./dist/cjs/types.d.ts",
154
+ "default": "./dist/cjs/types.js"
155
+ }
156
+ },
157
+ "import": {
158
+ "types": "./dist/types.d.ts",
159
+ "default": "./dist/types.js"
160
+ },
161
+ "require": {
162
+ "types": "./dist/cjs/types.d.ts",
163
+ "default": "./dist/cjs/types.js"
164
+ },
53
165
  "types": "./dist/types.d.ts",
54
166
  "default": "./dist/types.js"
55
167
  },
56
168
  "./multicall": {
57
169
  "gibs-source": "./src/multicall.ts",
170
+ "react-native": {
171
+ "import": {
172
+ "types": "./dist/multicall.d.ts",
173
+ "default": "./dist/multicall.js"
174
+ },
175
+ "require": {
176
+ "types": "./dist/cjs/multicall.d.ts",
177
+ "default": "./dist/cjs/multicall.js"
178
+ },
179
+ "default": {
180
+ "types": "./dist/cjs/multicall.d.ts",
181
+ "default": "./dist/cjs/multicall.js"
182
+ }
183
+ },
184
+ "import": {
185
+ "types": "./dist/multicall.d.ts",
186
+ "default": "./dist/multicall.js"
187
+ },
188
+ "require": {
189
+ "types": "./dist/cjs/multicall.d.ts",
190
+ "default": "./dist/cjs/multicall.js"
191
+ },
58
192
  "types": "./dist/multicall.d.ts",
59
193
  "default": "./dist/multicall.js"
60
194
  },
61
195
  "./client": {
62
196
  "gibs-source": "./src/client.ts",
197
+ "react-native": {
198
+ "import": {
199
+ "types": "./dist/client.d.ts",
200
+ "default": "./dist/client.js"
201
+ },
202
+ "require": {
203
+ "types": "./dist/cjs/client.d.ts",
204
+ "default": "./dist/cjs/client.js"
205
+ },
206
+ "default": {
207
+ "types": "./dist/cjs/client.d.ts",
208
+ "default": "./dist/cjs/client.js"
209
+ }
210
+ },
211
+ "import": {
212
+ "types": "./dist/client.d.ts",
213
+ "default": "./dist/client.js"
214
+ },
215
+ "require": {
216
+ "types": "./dist/cjs/client.d.ts",
217
+ "default": "./dist/cjs/client.js"
218
+ },
63
219
  "types": "./dist/client.d.ts",
64
220
  "default": "./dist/client.js"
65
221
  },
222
+ "./url": {
223
+ "gibs-source": "./src/url.ts",
224
+ "react-native": {
225
+ "import": {
226
+ "types": "./dist/url.d.ts",
227
+ "default": "./dist/url.js"
228
+ },
229
+ "require": {
230
+ "types": "./dist/cjs/url.d.ts",
231
+ "default": "./dist/cjs/url.js"
232
+ },
233
+ "default": {
234
+ "types": "./dist/cjs/url.d.ts",
235
+ "default": "./dist/cjs/url.js"
236
+ }
237
+ },
238
+ "import": {
239
+ "types": "./dist/url.d.ts",
240
+ "default": "./dist/url.js"
241
+ },
242
+ "require": {
243
+ "types": "./dist/cjs/url.d.ts",
244
+ "default": "./dist/cjs/url.js"
245
+ },
246
+ "types": "./dist/url.d.ts",
247
+ "default": "./dist/url.js"
248
+ },
66
249
  "./test-utils/fuzz": {
67
250
  "gibs-source": "./src/test-utils/fuzz.ts",
68
251
  "default": "./src/test-utils/fuzz.ts"
69
- }
252
+ },
253
+ "./test-utils/react-native-url": {
254
+ "gibs-source": "./src/test-utils/react-native-url.ts",
255
+ "default": "./src/test-utils/react-native-url.ts"
256
+ },
257
+ "./package.json": "./package.json"
70
258
  },
71
259
  "files": [
72
260
  "dist",
@@ -74,20 +262,28 @@
74
262
  "!dist/**/*.test-d.*",
75
263
  "!dist/test-utils",
76
264
  "LICENSE",
77
- "llms.txt"
265
+ "llms.txt",
266
+ "erc20",
267
+ "cache",
268
+ "serialize",
269
+ "types",
270
+ "multicall",
271
+ "client",
272
+ "url"
78
273
  ],
79
274
  "scripts": {
80
275
  "prepublishOnly": "npx tsc",
276
+ "prepack": "npm run build:cjs && npm run build:stubs",
277
+ "postpack": "node ../../scripts/subpath-stubs.mjs remove",
81
278
  "build": "npx tsc",
279
+ "build:cjs": "node ../../scripts/build-cjs.mjs",
280
+ "build:stubs": "node ../../scripts/subpath-stubs.mjs write",
82
281
  "test": "vitest run",
83
282
  "test:watch": "vitest",
84
283
  "test:coverage": "vitest run --coverage"
85
284
  },
86
- "dependencies": {
87
- "lodash-es": "^4.17.21"
88
- },
89
285
  "peerDependencies": {
90
- "viem": ">=2.37.0 <3"
286
+ "viem": ">=2.35.0 <3"
91
287
  },
92
288
  "devDependencies": {
93
289
  "@types/node": "^24",
@@ -0,0 +1,6 @@
1
+ {
2
+ "main": "../dist/cjs/serialize.js",
3
+ "module": "../dist/serialize.js",
4
+ "types": "../dist/serialize.d.ts",
5
+ "react-native": "../dist/cjs/serialize.js"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "main": "../dist/cjs/types.js",
3
+ "module": "../dist/types.js",
4
+ "types": "../dist/types.d.ts",
5
+ "react-native": "../dist/cjs/types.js"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "main": "../dist/cjs/url.js",
3
+ "module": "../dist/url.js",
4
+ "types": "../dist/url.d.ts",
5
+ "react-native": "../dist/cjs/url.js"
6
+ }